Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol. wisp.place

finally found good scopes

Changed files
+103 -39
cli
hosting-service
src
+63 -34
cli/Cargo.lock
··· 113 113 114 114 [[package]] 115 115 name = "anstyle-query" 116 - version = "1.1.4" 116 + version = "1.1.5" 117 117 source = "registry+https://github.com/rust-lang/crates.io-index" 118 - checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" 118 + checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" 119 119 dependencies = [ 120 - "windows-sys 0.60.2", 120 + "windows-sys 0.61.2", 121 121 ] 122 122 123 123 [[package]] 124 124 name = "anstyle-wincon" 125 - version = "3.0.10" 125 + version = "3.0.11" 126 126 source = "registry+https://github.com/rust-lang/crates.io-index" 127 - checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" 127 + checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" 128 128 dependencies = [ 129 129 "anstyle", 130 130 "once_cell_polyfill", 131 - "windows-sys 0.60.2", 131 + "windows-sys 0.61.2", 132 132 ] 133 133 134 134 [[package]] ··· 407 407 408 408 [[package]] 409 409 name = "bytes" 410 - version = "1.10.1" 410 + version = "1.11.0" 411 411 source = "registry+https://github.com/rust-lang/crates.io-index" 412 - checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 412 + checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" 413 413 dependencies = [ 414 414 "serde", 415 415 ] ··· 425 425 426 426 [[package]] 427 427 name = "cc" 428 - version = "1.2.45" 428 + version = "1.2.46" 429 429 source = "registry+https://github.com/rust-lang/crates.io-index" 430 - checksum = "35900b6c8d709fb1d854671ae27aeaa9eec2f8b01b364e1619a40da3e6fe2afe" 430 + checksum = "b97463e1064cb1b1c1384ad0a0b9c8abd0988e2a91f52606c80ef14aadb63e36" 431 431 dependencies = [ 432 432 "find-msvc-tools", 433 433 "shlex", ··· 996 996 997 997 [[package]] 998 998 name = "find-msvc-tools" 999 - version = "0.1.4" 999 + version = "0.1.5" 1000 1000 source = "registry+https://github.com/rust-lang/crates.io-index" 1001 - checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" 1001 + checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" 1002 1002 1003 1003 [[package]] 1004 1004 name = "flate2" ··· 1209 1209 checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" 1210 1210 1211 1211 [[package]] 1212 + name = "gloo-storage" 1213 + version = "0.3.0" 1214 + source = "registry+https://github.com/rust-lang/crates.io-index" 1215 + checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a" 1216 + dependencies = [ 1217 + "gloo-utils", 1218 + "js-sys", 1219 + "serde", 1220 + "serde_json", 1221 + "thiserror 1.0.69", 1222 + "wasm-bindgen", 1223 + "web-sys", 1224 + ] 1225 + 1226 + [[package]] 1227 + name = "gloo-utils" 1228 + version = "0.2.0" 1229 + source = "registry+https://github.com/rust-lang/crates.io-index" 1230 + checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" 1231 + dependencies = [ 1232 + "js-sys", 1233 + "serde", 1234 + "serde_json", 1235 + "wasm-bindgen", 1236 + "web-sys", 1237 + ] 1238 + 1239 + [[package]] 1212 1240 name = "group" 1213 1241 version = "0.13.0" 1214 1242 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1428 1456 1429 1457 [[package]] 1430 1458 name = "hyper" 1431 - version = "1.8.0" 1459 + version = "1.8.1" 1432 1460 source = "registry+https://github.com/rust-lang/crates.io-index" 1433 - checksum = "1744436df46f0bde35af3eda22aeaba453aada65d8f1c171cd8a5f59030bd69f" 1461 + checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" 1434 1462 dependencies = [ 1435 1463 "atomic-waker", 1436 1464 "bytes", ··· 1468 1496 1469 1497 [[package]] 1470 1498 name = "hyper-util" 1471 - version = "0.1.17" 1499 + version = "0.1.18" 1472 1500 source = "registry+https://github.com/rust-lang/crates.io-index" 1473 - checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" 1501 + checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56" 1474 1502 dependencies = [ 1475 1503 "base64 0.22.1", 1476 1504 "bytes", ··· 1725 1753 [[package]] 1726 1754 name = "jacquard" 1727 1755 version = "0.9.0" 1728 - source = "git+https://tangled.org/@nonbinary.computer/jacquard#5c79bb76de544cbd4fa8d5d8b01ba6e828f8ba65" 1756 + source = "git+https://tangled.org/@nonbinary.computer/jacquard#d853091d7de59e18746a78532dc28cfc017079b0" 1729 1757 dependencies = [ 1730 1758 "bytes", 1731 1759 "getrandom 0.2.16", 1760 + "gloo-storage", 1732 1761 "http", 1733 1762 "jacquard-api", 1734 1763 "jacquard-common", ··· 1753 1782 [[package]] 1754 1783 name = "jacquard-api" 1755 1784 version = "0.9.0" 1756 - source = "git+https://tangled.org/@nonbinary.computer/jacquard#5c79bb76de544cbd4fa8d5d8b01ba6e828f8ba65" 1785 + source = "git+https://tangled.org/@nonbinary.computer/jacquard#d853091d7de59e18746a78532dc28cfc017079b0" 1757 1786 dependencies = [ 1758 1787 "bon", 1759 1788 "bytes", ··· 1771 1800 [[package]] 1772 1801 name = "jacquard-common" 1773 1802 version = "0.9.0" 1774 - source = "git+https://tangled.org/@nonbinary.computer/jacquard#5c79bb76de544cbd4fa8d5d8b01ba6e828f8ba65" 1803 + source = "git+https://tangled.org/@nonbinary.computer/jacquard#d853091d7de59e18746a78532dc28cfc017079b0" 1775 1804 dependencies = [ 1776 1805 "base64 0.22.1", 1777 1806 "bon", ··· 1812 1841 [[package]] 1813 1842 name = "jacquard-derive" 1814 1843 version = "0.9.0" 1815 - source = "git+https://tangled.org/@nonbinary.computer/jacquard#5c79bb76de544cbd4fa8d5d8b01ba6e828f8ba65" 1844 + source = "git+https://tangled.org/@nonbinary.computer/jacquard#d853091d7de59e18746a78532dc28cfc017079b0" 1816 1845 dependencies = [ 1817 1846 "heck 0.5.0", 1818 1847 "jacquard-lexicon", ··· 1824 1853 [[package]] 1825 1854 name = "jacquard-identity" 1826 1855 version = "0.9.1" 1827 - source = "git+https://tangled.org/@nonbinary.computer/jacquard#5c79bb76de544cbd4fa8d5d8b01ba6e828f8ba65" 1856 + source = "git+https://tangled.org/@nonbinary.computer/jacquard#d853091d7de59e18746a78532dc28cfc017079b0" 1828 1857 dependencies = [ 1829 1858 "bon", 1830 1859 "bytes", ··· 1850 1879 [[package]] 1851 1880 name = "jacquard-lexicon" 1852 1881 version = "0.9.1" 1853 - source = "git+https://tangled.org/@nonbinary.computer/jacquard#5c79bb76de544cbd4fa8d5d8b01ba6e828f8ba65" 1882 + source = "git+https://tangled.org/@nonbinary.computer/jacquard#d853091d7de59e18746a78532dc28cfc017079b0" 1854 1883 dependencies = [ 1855 1884 "cid", 1856 1885 "dashmap", ··· 1876 1905 [[package]] 1877 1906 name = "jacquard-oauth" 1878 1907 version = "0.9.0" 1879 - source = "git+https://tangled.org/@nonbinary.computer/jacquard#5c79bb76de544cbd4fa8d5d8b01ba6e828f8ba65" 1908 + source = "git+https://tangled.org/@nonbinary.computer/jacquard#d853091d7de59e18746a78532dc28cfc017079b0" 1880 1909 dependencies = [ 1881 1910 "base64 0.22.1", 1882 1911 "bytes", ··· 3076 3105 3077 3106 [[package]] 3078 3107 name = "rsa" 3079 - version = "0.9.8" 3108 + version = "0.9.9" 3080 3109 source = "registry+https://github.com/rust-lang/crates.io-index" 3081 - checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" 3110 + checksum = "40a0376c50d0358279d9d643e4bf7b7be212f1f4ff1da9070a7b54d22ef75c88" 3082 3111 dependencies = [ 3083 3112 "const-oid", 3084 3113 "digest", ··· 3395 3424 3396 3425 [[package]] 3397 3426 name = "serde_with" 3398 - version = "3.15.1" 3427 + version = "3.16.0" 3399 3428 source = "registry+https://github.com/rust-lang/crates.io-index" 3400 - checksum = "aa66c845eee442168b2c8134fec70ac50dc20e760769c8ba0ad1319ca1959b04" 3429 + checksum = "10574371d41b0d9b2cff89418eda27da52bcaff2cc8741db26382a77c29131f1" 3401 3430 dependencies = [ 3402 3431 "base64 0.22.1", 3403 3432 "chrono", ··· 3414 3443 3415 3444 [[package]] 3416 3445 name = "serde_with_macros" 3417 - version = "3.15.1" 3446 + version = "3.16.0" 3418 3447 source = "registry+https://github.com/rust-lang/crates.io-index" 3419 - checksum = "b91a903660542fced4e99881aa481bdbaec1634568ee02e0b8bd57c64cb38955" 3448 + checksum = "08a72d8216842fdd57820dc78d840bef99248e35fb2554ff923319e60f2d686b" 3420 3449 dependencies = [ 3421 3450 "darling", 3422 3451 "proc-macro2", ··· 4550 4579 4551 4580 [[package]] 4552 4581 name = "windows-registry" 4553 - version = "0.5.3" 4582 + version = "0.6.1" 4554 4583 source = "registry+https://github.com/rust-lang/crates.io-index" 4555 - checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" 4584 + checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" 4556 4585 dependencies = [ 4557 - "windows-link 0.1.3", 4558 - "windows-result 0.3.4", 4559 - "windows-strings 0.4.2", 4586 + "windows-link 0.2.1", 4587 + "windows-result 0.4.1", 4588 + "windows-strings 0.5.1", 4560 4589 ] 4561 4590 4562 4591 [[package]]
+37 -3
cli/src/main.rs
··· 114 114 async fn main() -> miette::Result<()> { 115 115 let args = Args::parse(); 116 116 117 - match args.command { 117 + let result = match args.command { 118 118 Some(Commands::Deploy { input, path, site, store, password }) => { 119 119 // Dispatch to appropriate authentication method 120 120 if let Some(password) = password { ··· 134 134 if let Some(input) = args.input { 135 135 let path = args.path.unwrap_or_else(|| PathBuf::from(".")); 136 136 let store = args.store.unwrap_or_else(|| "/tmp/wisp-oauth-session.json".to_string()); 137 - 137 + 138 138 // Dispatch to appropriate authentication method 139 139 if let Some(password) = args.password { 140 140 run_with_app_password(input, password, path, args.site).await ··· 148 148 Ok(()) 149 149 } 150 150 } 151 + }; 152 + 153 + // Force exit to avoid hanging on background tasks/connections 154 + match result { 155 + Ok(_) => std::process::exit(0), 156 + Err(e) => { 157 + eprintln!("{:?}", e); 158 + std::process::exit(1) 159 + } 151 160 } 152 161 } 153 162 ··· 173 182 path: PathBuf, 174 183 site: Option<String>, 175 184 ) -> miette::Result<()> { 176 - let oauth = OAuthClient::with_default_config(FileAuthStore::new(&store)); 185 + use jacquard::oauth::scopes::Scope; 186 + use jacquard::oauth::atproto::AtprotoClientMetadata; 187 + use jacquard::oauth::session::ClientData; 188 + use url::Url; 189 + 190 + // Request the necessary scopes for wisp.place 191 + let scopes = Scope::parse_multiple("atproto repo:place.wisp.fs repo:place.wisp.subfs blob:*/*") 192 + .map_err(|e| miette::miette!("Failed to parse scopes: {:?}", e))?; 193 + 194 + // Create redirect URIs that match the loopback server (port 4000, path /oauth/callback) 195 + let redirect_uris = vec![ 196 + Url::parse("http://127.0.0.1:4000/oauth/callback").into_diagnostic()?, 197 + Url::parse("http://[::1]:4000/oauth/callback").into_diagnostic()?, 198 + ]; 199 + 200 + // Create client metadata with matching redirect URIs and scopes 201 + let client_data = ClientData { 202 + keyset: None, 203 + config: AtprotoClientMetadata::new_localhost( 204 + Some(redirect_uris), 205 + Some(scopes), 206 + ), 207 + }; 208 + 209 + let oauth = OAuthClient::new(FileAuthStore::new(&store), client_data); 210 + 177 211 let session = oauth 178 212 .login_with_local_server(input, Default::default(), LoopbackConfig::default()) 179 213 .await?;
+1
hosting-service/bun.lock
··· 1 1 { 2 2 "lockfileVersion": 1, 3 + "configVersion": 0, 3 4 "workspaces": { 4 5 "": { 5 6 "name": "wisp-hosting-service",
+2 -2
src/lib/oauth-client.ts
··· 110 110 // Loopback client for local development 111 111 // For loopback, scopes and redirect_uri must be in client_id query string 112 112 const redirectUri = 'http://127.0.0.1:8000/api/auth/callback'; 113 - const scope = 'atproto repo:place.wisp.fs repo:place.wisp.domain repo:place.wisp.subfs blob:*/* blob?maxSize=100000000 rpc:*?aud=did:web:api.bsky.app#bsky_appview'; 113 + const scope = 'atproto repo:place.wisp.fs repo:place.wisp.domain repo:place.wisp.subfs blob:*/* rpc:app.bsky.actor.getProfile?aud=did:web:api.bsky.app#bsky_appview'; 114 114 const params = new URLSearchParams(); 115 115 params.append('redirect_uri', redirectUri); 116 116 params.append('scope', scope); ··· 145 145 application_type: 'web', 146 146 token_endpoint_auth_method: 'private_key_jwt', 147 147 token_endpoint_auth_signing_alg: "ES256", 148 - scope: "atproto repo:place.wisp.fs repo:place.wisp.domain repo:place.wisp.subfs blob:*/* blob?maxSize=100000000 rpc:*?aud=did:web:api.bsky.app#bsky_appview", 148 + scope: "atproto repo:place.wisp.fs repo:place.wisp.domain repo:place.wisp.subfs blob:*/* rpc:app.bsky.actor.getProfile?aud=did:web:api.bsky.app#bsky_appview", 149 149 dpop_bound_access_tokens: true, 150 150 jwks_uri: `${config.domain}/jwks.json`, 151 151 subject_type: 'public',