at protocol indexer with flexible filtering, xrpc queries, and a cursor-backed event stream, built on fjall
at-protocol atproto indexer rust fjall

[all] repo state holds pds & signing key, return those from /repos endpoints, and keep them fresh

ptr.pet b464adbb b4aed5ce

verified
+168 -79
+52 -45
Cargo.lock
··· 123 123 124 124 [[package]] 125 125 name = "aws-lc-rs" 126 - version = "1.16.0" 126 + version = "1.16.1" 127 127 source = "registry+https://github.com/rust-lang/crates.io-index" 128 - checksum = "d9a7b350e3bb1767102698302bc37256cbd48422809984b98d292c40e2579aa9" 128 + checksum = "94bffc006df10ac2a68c83692d734a465f8ee6c5b384d8545a636f81d858f4bf" 129 129 dependencies = [ 130 130 "aws-lc-sys", 131 131 "zeroize", ··· 133 133 134 134 [[package]] 135 135 name = "aws-lc-sys" 136 - version = "0.37.1" 136 + version = "0.38.0" 137 137 source = "registry+https://github.com/rust-lang/crates.io-index" 138 - checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" 138 + checksum = "4321e568ed89bb5a7d291a7f37997c2c0df89809d7b6d12062c81ddb54aa782e" 139 139 dependencies = [ 140 140 "cc", 141 141 "cmake", ··· 1041 1041 1042 1042 [[package]] 1043 1043 name = "fjall" 1044 - version = "3.0.3" 1044 + version = "3.0.4" 1045 1045 source = "registry+https://github.com/rust-lang/crates.io-index" 1046 - checksum = "5ce4b4c3a755bae832077657db2727b29b9acc535bb471c6d91ab4fe408fd805" 1046 + checksum = "0ebf22b812878dcd767879cb19e03124fd62563dce6410f96538175fba0c132d" 1047 1047 dependencies = [ 1048 1048 "byteorder-lite", 1049 1049 "byteview", ··· 1270 1270 "cfg-if", 1271 1271 "js-sys", 1272 1272 "libc", 1273 - "r-efi", 1273 + "r-efi 5.3.0", 1274 1274 "wasip2", 1275 1275 "wasm-bindgen", 1276 1276 ] 1277 1277 1278 1278 [[package]] 1279 1279 name = "getrandom" 1280 - version = "0.4.1" 1280 + version = "0.4.2" 1281 1281 source = "registry+https://github.com/rust-lang/crates.io-index" 1282 - checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" 1282 + checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" 1283 1283 dependencies = [ 1284 1284 "cfg-if", 1285 1285 "js-sys", 1286 1286 "libc", 1287 - "r-efi", 1287 + "r-efi 6.0.0", 1288 1288 "rand_core 0.10.0", 1289 1289 "wasip2", 1290 1290 "wasip3", ··· 1538 1538 "jacquard-repo", 1539 1539 "miette", 1540 1540 "mimalloc", 1541 + "multibase", 1541 1542 "rand 0.10.0", 1542 1543 "reqwest", 1543 1544 "rmp-serde", ··· 1615 1616 "libc", 1616 1617 "percent-encoding", 1617 1618 "pin-project-lite", 1618 - "socket2 0.6.2", 1619 + "socket2 0.6.3", 1619 1620 "system-configuration", 1620 1621 "tokio", 1621 1622 "tower-service", ··· 1816 1817 1817 1818 [[package]] 1818 1819 name = "ipnet" 1819 - version = "2.11.0" 1820 + version = "2.12.0" 1820 1821 source = "registry+https://github.com/rust-lang/crates.io-index" 1821 - checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" 1822 + checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" 1822 1823 1823 1824 [[package]] 1824 1825 name = "iri-string" ··· 1861 1862 [[package]] 1862 1863 name = "jacquard-api" 1863 1864 version = "0.9.5" 1864 - source = "git+https://tangled.org/ptr.pet/jacquard#da72566fde65f8cc76b8cb2bb99fc7f4d696dc05" 1865 + source = "git+https://tangled.org/ptr.pet/jacquard#681819111ac12a3c7ef92f1ec0b80c6f732d8b4a" 1865 1866 dependencies = [ 1866 1867 "bon", 1867 1868 "bytes", ··· 1880 1881 [[package]] 1881 1882 name = "jacquard-common" 1882 1883 version = "0.9.5" 1883 - source = "git+https://tangled.org/ptr.pet/jacquard#da72566fde65f8cc76b8cb2bb99fc7f4d696dc05" 1884 + source = "git+https://tangled.org/ptr.pet/jacquard#681819111ac12a3c7ef92f1ec0b80c6f732d8b4a" 1884 1885 dependencies = [ 1885 1886 "base64", 1886 1887 "bon", ··· 1891 1892 "cid", 1892 1893 "ed25519-dalek", 1893 1894 "getrandom 0.2.17", 1894 - "getrandom 0.4.1", 1895 + "getrandom 0.4.2", 1895 1896 "hashbrown 0.16.1", 1896 1897 "http", 1897 1898 "ipld-core", ··· 1928 1929 [[package]] 1929 1930 name = "jacquard-derive" 1930 1931 version = "0.9.5" 1931 - source = "git+https://tangled.org/ptr.pet/jacquard#da72566fde65f8cc76b8cb2bb99fc7f4d696dc05" 1932 + source = "git+https://tangled.org/ptr.pet/jacquard#681819111ac12a3c7ef92f1ec0b80c6f732d8b4a" 1932 1933 dependencies = [ 1933 1934 "heck 0.5.0", 1934 1935 "jacquard-lexicon", ··· 1940 1941 [[package]] 1941 1942 name = "jacquard-identity" 1942 1943 version = "0.9.5" 1943 - source = "git+https://tangled.org/ptr.pet/jacquard#da72566fde65f8cc76b8cb2bb99fc7f4d696dc05" 1944 + source = "git+https://tangled.org/ptr.pet/jacquard#681819111ac12a3c7ef92f1ec0b80c6f732d8b4a" 1944 1945 dependencies = [ 1945 1946 "bon", 1946 1947 "bytes", ··· 1967 1968 [[package]] 1968 1969 name = "jacquard-lexicon" 1969 1970 version = "0.9.5" 1970 - source = "git+https://tangled.org/ptr.pet/jacquard#da72566fde65f8cc76b8cb2bb99fc7f4d696dc05" 1971 + source = "git+https://tangled.org/ptr.pet/jacquard#681819111ac12a3c7ef92f1ec0b80c6f732d8b4a" 1971 1972 dependencies = [ 1972 1973 "cid", 1973 1974 "dashmap", ··· 1994 1995 [[package]] 1995 1996 name = "jacquard-repo" 1996 1997 version = "0.9.6" 1997 - source = "git+https://tangled.org/ptr.pet/jacquard#da72566fde65f8cc76b8cb2bb99fc7f4d696dc05" 1998 + source = "git+https://tangled.org/ptr.pet/jacquard#681819111ac12a3c7ef92f1ec0b80c6f732d8b4a" 1998 1999 dependencies = [ 1999 2000 "bytes", 2000 2001 "cid", ··· 2149 2150 2150 2151 [[package]] 2151 2152 name = "lsm-tree" 2152 - version = "3.0.3" 2153 + version = "3.0.4" 2153 2154 source = "registry+https://github.com/rust-lang/crates.io-index" 2154 - checksum = "341e13fa389d2e24023c2c2c110ae556b29fa59a2e734872de295863e11a6741" 2155 + checksum = "e9bfd2a6ea0c1d430c13643002f35800a87f200fc8ac4827f18a2db9d9fd0644" 2155 2156 dependencies = [ 2156 2157 "byteorder-lite", 2157 2158 "byteview", ··· 2663 2664 "quinn-udp", 2664 2665 "rustc-hash", 2665 2666 "rustls", 2666 - "socket2 0.6.2", 2667 + "socket2 0.6.3", 2667 2668 "thiserror 2.0.18", 2668 2669 "tokio", 2669 2670 "tracing", ··· 2701 2702 "cfg_aliases", 2702 2703 "libc", 2703 2704 "once_cell", 2704 - "socket2 0.6.2", 2705 + "socket2 0.6.3", 2705 2706 "tracing", 2706 2707 "windows-sys 0.60.2", 2707 2708 ] 2708 2709 2709 2710 [[package]] 2710 2711 name = "quote" 2711 - version = "1.0.44" 2712 + version = "1.0.45" 2712 2713 source = "registry+https://github.com/rust-lang/crates.io-index" 2713 - checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" 2714 + checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" 2714 2715 dependencies = [ 2715 2716 "proc-macro2", 2716 2717 ] ··· 2722 2723 checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" 2723 2724 2724 2725 [[package]] 2726 + name = "r-efi" 2727 + version = "6.0.0" 2728 + source = "registry+https://github.com/rust-lang/crates.io-index" 2729 + checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" 2730 + 2731 + [[package]] 2725 2732 name = "rand" 2726 2733 version = "0.9.2" 2727 2734 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2738 2745 checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" 2739 2746 dependencies = [ 2740 2747 "chacha20", 2741 - "getrandom 0.4.1", 2748 + "getrandom 0.4.2", 2742 2749 "rand_core 0.10.0", 2743 2750 ] 2744 2751 ··· 3049 3056 3050 3057 [[package]] 3051 3058 name = "scc" 3052 - version = "3.6.6" 3059 + version = "3.6.9" 3053 3060 source = "registry+https://github.com/rust-lang/crates.io-index" 3054 - checksum = "6012e652611b2fdcb557a7b4be8cee00d8be19397c70011906a68aa4dac2fe37" 3061 + checksum = "45bb5ce9efd4a6e7b0f86c2697fe4c1d78d1f4e6d988c54b752d577cafe22fe8" 3055 3062 dependencies = [ 3056 3063 "saa", 3057 3064 "sdd", ··· 3080 3087 3081 3088 [[package]] 3082 3089 name = "sdd" 3083 - version = "4.6.7" 3090 + version = "4.7.3" 3084 3091 source = "registry+https://github.com/rust-lang/crates.io-index" 3085 - checksum = "716318297c9f6208bda3eec88a9fdee0e2597be9461a1ab35f6ff68157527f99" 3092 + checksum = "b21a75f5913ab130e4b369fb8693be25f29b983e2ecad4279df9bfa5dd8aaf3e" 3086 3093 3087 3094 [[package]] 3088 3095 name = "sec1" ··· 3365 3372 3366 3373 [[package]] 3367 3374 name = "smol_str" 3368 - version = "0.3.5" 3375 + version = "0.3.6" 3369 3376 source = "registry+https://github.com/rust-lang/crates.io-index" 3370 - checksum = "0f7a918bd2a9951d18ee6e48f076843e8e73a9a5d22cf05bcd4b7a81bdd04e17" 3377 + checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" 3371 3378 dependencies = [ 3372 3379 "borsh", 3373 3380 "serde_core", ··· 3385 3392 3386 3393 [[package]] 3387 3394 name = "socket2" 3388 - version = "0.6.2" 3395 + version = "0.6.3" 3389 3396 source = "registry+https://github.com/rust-lang/crates.io-index" 3390 - checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" 3397 + checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" 3391 3398 dependencies = [ 3392 3399 "libc", 3393 - "windows-sys 0.60.2", 3400 + "windows-sys 0.61.2", 3394 3401 ] 3395 3402 3396 3403 [[package]] ··· 3528 3535 checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" 3529 3536 dependencies = [ 3530 3537 "fastrand", 3531 - "getrandom 0.4.1", 3538 + "getrandom 0.4.2", 3532 3539 "once_cell", 3533 3540 "rustix", 3534 3541 "windows-sys 0.61.2", ··· 3649 3656 3650 3657 [[package]] 3651 3658 name = "tokio" 3652 - version = "1.49.0" 3659 + version = "1.50.0" 3653 3660 source = "registry+https://github.com/rust-lang/crates.io-index" 3654 - checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" 3661 + checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" 3655 3662 dependencies = [ 3656 3663 "bytes", 3657 3664 "libc", ··· 3659 3666 "parking_lot", 3660 3667 "pin-project-lite", 3661 3668 "signal-hook-registry", 3662 - "socket2 0.6.2", 3669 + "socket2 0.6.3", 3663 3670 "tokio-macros", 3664 3671 "windows-sys 0.61.2", 3665 3672 ] 3666 3673 3667 3674 [[package]] 3668 3675 name = "tokio-macros" 3669 - version = "2.6.0" 3676 + version = "2.6.1" 3670 3677 source = "registry+https://github.com/rust-lang/crates.io-index" 3671 - checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" 3678 + checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" 3672 3679 dependencies = [ 3673 3680 "proc-macro2", 3674 3681 "quote", ··· 3964 3971 3965 3972 [[package]] 3966 3973 name = "uuid" 3967 - version = "1.21.0" 3974 + version = "1.22.0" 3968 3975 source = "registry+https://github.com/rust-lang/crates.io-index" 3969 - checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" 3976 + checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" 3970 3977 dependencies = [ 3971 - "getrandom 0.4.1", 3978 + "getrandom 0.4.2", 3972 3979 "js-sys", 3973 3980 "wasm-bindgen", 3974 3981 ]
+1
Cargo.toml
··· 45 45 arc-swap = "1.8.2" 46 46 rustls = { version = "0.23", features = ["aws-lc-rs"] } 47 47 tokio-tungstenite = { version = "0.28.0", features = ["rustls-tls-native-roots"] } 48 + multibase = "0.9.2" 48 49 49 50 [dev-dependencies] 50 51 tempfile = "3.26.0"
+1 -1
README.md
··· 96 96 - `limit`: max results (default 100, max 1000) 97 97 - `cursor`: opaque key for paginating. 98 98 - `partition`: `all` (default), `pending` (backfill queue), or `resync` (retries) 99 - - `GET /repos/{did}`: get the sync status and metadata of a specific repository. 99 + - `GET /repos/{did}`: get the sync status and metadata of a specific repository. also returns the handle, PDS URL and the atproto signing key (these won't be available before the repo has been backfilled once at least). 100 100 - `PUT /repos`: explicitly track repositories. accepts an NDJSON body of `{"did": "..."}` (or JSON array of the same). 101 101 - `DELETE /repos`: untrack repositories. accepts an NDJSON body of `{"did": "..."}` (or JSON array of the same). optionally include `"deleteData": true` to also purge the repository from the database. 102 102
+22 -14
src/api/repos.rs
··· 39 39 pub tracked: bool, 40 40 #[serde(skip_serializing_if = "Option::is_none")] 41 41 pub rev: Option<String>, 42 + #[serde(skip_serializing_if = "Option::is_none")] 43 + pub handle: Option<String>, 44 + #[serde(skip_serializing_if = "Option::is_none")] 45 + pub pds: Option<String>, 46 + // this does not have the did:key: prefix 47 + #[serde(skip_serializing_if = "Option::is_none")] 48 + pub signing_key: Option<String>, 42 49 pub last_updated_at: i64, 43 50 } 44 51 ··· 71 78 .map_err(internal)? 72 79 .to_did(); 73 80 74 - Ok(RepoResponse { 75 - did: did.to_string(), 76 - status: repo_state.status.to_string(), 77 - tracked: repo_state.tracked, 78 - rev: repo_state.rev.as_ref().map(|r| r.to_string()), 79 - last_updated_at: repo_state.last_updated_at, 80 - }) 81 + Ok(repo_state_to_response(did.to_string(), repo_state)) 81 82 }; 82 83 83 84 let results = match partition.as_str() { ··· 172 173 .transpose() 173 174 .map_err(internal)?; 174 175 175 - Ok(repo_state.map(|s| RepoResponse { 176 - did: did_str, 177 - status: s.status.to_string(), 178 - tracked: s.tracked, 179 - rev: s.rev.as_ref().map(|r| r.to_string()), 180 - last_updated_at: s.last_updated_at, 181 - })) 176 + Ok(repo_state.map(|s| repo_state_to_response(did_str, s))) 182 177 }) 183 178 .await 184 179 .map_err(internal)??; ··· 343 338 } 344 339 345 340 Ok(StatusCode::OK) 341 + } 342 + 343 + fn repo_state_to_response(did: String, s: RepoState<'_>) -> RepoResponse { 344 + RepoResponse { 345 + did, 346 + status: s.status.to_string(), 347 + tracked: s.tracked, 348 + rev: s.rev.as_ref().map(|r| r.to_string()), 349 + handle: s.handle.map(|h| h.to_string()), 350 + pds: s.pds.map(|p| p.to_string()), 351 + signing_key: s.signing_key.map(|k| k.encode()), 352 + last_updated_at: s.last_updated_at, 353 + } 346 354 } 347 355 348 356 async fn parse_body(req: axum::extract::Request) -> Result<Vec<RepoRequest>, (StatusCode, String)> {
+6 -6
src/backfill/mod.rs
··· 376 376 377 377 // 1. resolve pds 378 378 let start = Instant::now(); 379 - let (pds_url, handle) = app_state.resolver.resolve_identity_info(did).await?; 379 + let doc = app_state.resolver.resolve_doc(did).await?; 380 + let pds = doc.pds.clone(); 380 381 trace!( 381 382 did = %did, 382 - pds_url = %pds_url, 383 - ?handle, 383 + pds = %doc.pds, 384 + handle = ?doc.handle, 384 385 elapsed = ?start.elapsed(), 385 386 "resolved to pds" 386 387 ); 387 - 388 - state.handle = handle.map(|h| h.into_static()); 388 + state.update_from_doc(doc); 389 389 390 390 let emit_identity = |status: &RepoStatus| { 391 391 let evt = AccountEvt { ··· 410 410 // 2. fetch repo (car) 411 411 let start = Instant::now(); 412 412 let req = GetRepo::new().did(did.clone()).build(); 413 - let resp = http.xrpc(pds_url).send(&req).await?; 413 + let resp = http.xrpc(pds).send(&req).await?; 414 414 415 415 let car_bytes = match resp.into_output() { 416 416 Ok(o) => o,
+42
src/db/types.rs
··· 1 1 use data_encoding::BASE32_NOPAD; 2 2 use fjall::UserKey; 3 + use jacquard_common::types::crypto::{PublicKey, code_of, encode_uvarint}; 3 4 use jacquard_common::types::string::Did; 4 5 use jacquard_common::types::tid::Tid; 5 6 use jacquard_common::{CowStr, IntoStatic}; 7 + use miette::{Context, IntoDiagnostic}; 6 8 use serde::{Deserialize, Deserializer, Serialize, Serializer}; 7 9 use smol_str::{SmolStr, SmolStrBuilder, format_smolstr}; 10 + use std::borrow::Cow; 8 11 use std::fmt::Display; 9 12 10 13 const S32_CHAR: &str = "234567abcdefghijklmnopqrstuvwxyz"; ··· 353 356 impl Display for DbRkey { 354 357 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 355 358 write!(f, "{}", self.to_smolstr()) 359 + } 360 + } 361 + 362 + /// did:key:z... → raw multicodec public key bytes 363 + #[derive(Debug, Clone, Serialize, Deserialize, jacquard_derive::IntoStatic)] 364 + pub struct DidKey<'b>( 365 + #[serde(borrow)] 366 + #[serde(with = "serde_bytes")] 367 + pub Cow<'b, [u8]>, 368 + ); 369 + 370 + impl DidKey<'_> { 371 + pub fn from_did_key(s: &str) -> miette::Result<Self> { 372 + let multibase_str = s 373 + .strip_prefix("did:key:") 374 + .ok_or_else(|| miette::miette!("missing did:key: prefix in {s}"))?; 375 + let (_base, bytes) = multibase::decode(multibase_str) 376 + .into_diagnostic() 377 + .wrap_err("invalid multibase in did:key")?; 378 + Ok(Self(Cow::Owned(bytes))) 379 + } 380 + 381 + pub fn encode(&self) -> String { 382 + multibase::encode(multibase::Base::Base58Btc, &self.0) 383 + } 384 + } 385 + 386 + impl std::fmt::Display for DidKey<'_> { 387 + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 388 + write!(f, "did:key:{}", self.encode()) 389 + } 390 + } 391 + 392 + impl From<PublicKey<'_>> for DidKey<'static> { 393 + fn from(value: PublicKey<'_>) -> Self { 394 + let mut bytes = Vec::with_capacity(8 + value.bytes.len()); 395 + bytes.append(&mut encode_uvarint(code_of(value.codec))); 396 + bytes.extend_from_slice(&value.bytes); 397 + Self(bytes.into()) 356 398 } 357 399 } 358 400
+21 -6
src/ingest/worker.rs
··· 311 311 SubscribeReposMessage::Sync(sync) => { 312 312 debug!(did = %did, "processing buffered sync"); 313 313 314 - ctx.state.resolver.invalidate_sync(did); 314 + Self::refresh_doc(ctx, &mut repo_state, did)?; 315 315 316 316 match ops::verify_sync_event( 317 317 sync.blocks.as_ref(), ··· 360 360 // we invalidate only if no handle is sent since its like a 361 361 // "invalidate your caches" message then basically 362 362 ctx.state.resolver.invalidate_sync(did); 363 - let (_, handle) = ctx 364 - .handle 365 - .block_on(ctx.state.resolver.resolve_identity_info(did))?; 366 - repo_state.handle = handle; 363 + let doc = ctx.handle.block_on(ctx.state.resolver.resolve_doc(did))?; 364 + repo_state.update_from_doc(doc); 367 365 } 368 366 369 367 let handle = identity.handle.as_ref().map(|h| h.clone()); ··· 389 387 status: account.status.as_ref().map(|s| s.to_cowstr().into_static()), 390 388 }; 391 389 392 - ctx.state.resolver.invalidate_sync(did); 390 + Self::refresh_doc(ctx, &mut repo_state, did)?; 393 391 394 392 if !account.active { 395 393 use crate::ingest::stream::AccountStatus; ··· 683 681 } 684 682 685 683 Ok(RepoProcessResult::Ok(repo_state)) 684 + } 685 + 686 + // refreshes the handle, pds url and signing key of a did 687 + fn refresh_doc( 688 + ctx: &mut WorkerContext, 689 + repo_state: &mut RepoState, 690 + did: &Did, 691 + ) -> Result<(), IngestError> { 692 + ctx.state.resolver.invalidate_sync(did); 693 + let doc = ctx.handle.block_on(ctx.state.resolver.resolve_doc(did))?; 694 + repo_state.update_from_doc(doc); 695 + ctx.batch.insert( 696 + &ctx.state.db.repos, 697 + keys::repo_key(did), 698 + crate::db::ser_repo_state(&repo_state)?, 699 + ); 700 + Ok(()) 686 701 } 687 702 688 703 fn fetch_key(
+3 -3
src/resolver.rs
··· 49 49 50 50 #[derive(Clone)] 51 51 pub struct MiniDoc { 52 - pds: Url, 53 - handle: Option<Handle<'static>>, 54 - key: Option<PublicKey<'static>>, 52 + pub pds: Url, 53 + pub handle: Option<Handle<'static>>, 54 + pub key: Option<PublicKey<'static>>, 55 55 } 56 56 57 57 struct ResolverInner {
+20 -4
src/types.rs
··· 5 5 use jacquard_common::{CowStr, IntoStatic, types::string::Handle}; 6 6 use serde::{Deserialize, Serialize}; 7 7 use serde_json::Value; 8 - use smol_str::SmolStr; 8 + use smol_str::{SmolStr, ToSmolStr}; 9 9 10 - use crate::db::types::{DbAction, DbRkey, DbTid, TrimmedDid}; 10 + use crate::db::types::{DbAction, DbRkey, DbTid, DidKey, TrimmedDid}; 11 + use crate::resolver::MiniDoc; 11 12 12 13 #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] 13 14 pub enum RepoStatus { ··· 45 46 pub index_id: u64, 46 47 #[serde(default = "default_tracked")] 47 48 pub tracked: bool, 49 + #[serde(default)] 50 + pub signing_key: Option<DidKey<'i>>, 51 + #[serde(default)] 52 + pub pds: Option<CowStr<'i>>, 48 53 } 49 54 50 55 fn default_tracked() -> bool { ··· 59 64 data: None, 60 65 last_seq: None, 61 66 last_updated_at: chrono::Utc::now().timestamp(), 62 - handle: None, 67 + 63 68 index_id, 64 69 tracked: true, 70 + handle: None, 71 + pds: None, 72 + signing_key: None, 65 73 } 66 74 } 67 75 ··· 72 80 ..Self::backfilling(index_id) 73 81 } 74 82 } 83 + 84 + pub fn update_from_doc(&mut self, doc: MiniDoc) { 85 + self.pds = Some(CowStr::Owned(doc.pds.to_smolstr())); 86 + self.handle = doc.handle; 87 + self.signing_key = doc.key.map(From::from); 88 + } 75 89 } 76 90 77 91 impl<'i> IntoStatic for RepoState<'i> { ··· 84 98 data: self.data, 85 99 last_seq: self.last_seq, 86 100 last_updated_at: self.last_updated_at, 87 - handle: self.handle.map(|s| s.into_static()), 88 101 index_id: self.index_id, 89 102 tracked: self.tracked, 103 + handle: self.handle.map(IntoStatic::into_static), 104 + pds: self.pds.map(IntoStatic::into_static), 105 + signing_key: self.signing_key.map(IntoStatic::into_static), 90 106 } 91 107 } 92 108 }