Monorepo for Tangled tangled.org
1

Configure Feed

Select the types of activity you want to include in your feed.

bobbin: add jacquard identity resolver to AppState

Signed-off-by: Seongmin Lee <git@boltless.me>

author
Seongmin Lee
date (Jul 27, 2026, 7:22 PM +0900) commit 5448a3c3 parent ed5f1bdb change-id spktmqmu
+86
+53
Cargo.lock
··· 351 351 "clap", 352 352 "confique", 353 353 "futures", 354 + "jacquard-common", 355 + "jacquard-identity", 354 356 "serde", 355 357 "socket2", 356 358 "thiserror 2.0.18", ··· 586 588 "futures", 587 589 "http", 588 590 "jacquard-common", 591 + "jacquard-identity", 589 592 "serde", 590 593 "serde_json", 591 594 "thiserror 2.0.18", ··· 2105 2108 ] 2106 2109 2107 2110 [[package]] 2111 + name = "jacquard-identity" 2112 + version = "0.12.0-beta.2" 2113 + source = "registry+https://github.com/rust-lang/crates.io-index" 2114 + checksum = "49da1f0a0487051529a70891dac0d1c6699f47b95854514402b2642e66d96c7c" 2115 + dependencies = [ 2116 + "bon", 2117 + "bytes", 2118 + "http", 2119 + "jacquard-common", 2120 + "jacquard-lexicon", 2121 + "miette", 2122 + "mini-moka-wasm", 2123 + "n0-future", 2124 + "reqwest", 2125 + "serde", 2126 + "serde_html_form", 2127 + "serde_json", 2128 + "thiserror 2.0.18", 2129 + "tokio", 2130 + "trait-variant", 2131 + ] 2132 + 2133 + [[package]] 2108 2134 name = "jacquard-lexicon" 2109 2135 version = "0.12.0-beta.2" 2110 2136 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2362 2388 checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 2363 2389 2364 2390 [[package]] 2391 + name = "mini-moka-wasm" 2392 + version = "0.10.99" 2393 + source = "registry+https://github.com/rust-lang/crates.io-index" 2394 + checksum = "0102b9a2ad50fa47ca89eead2316c8222285ecfbd3f69ce99564fbe4253866e8" 2395 + dependencies = [ 2396 + "crossbeam-channel", 2397 + "crossbeam-utils", 2398 + "dashmap", 2399 + "smallvec", 2400 + "tagptr", 2401 + "triomphe", 2402 + "web-time", 2403 + ] 2404 + 2405 + [[package]] 2365 2406 name = "minimal-lexical" 2366 2407 version = "0.2.1" 2367 2408 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3864 3905 ] 3865 3906 3866 3907 [[package]] 3908 + name = "tagptr" 3909 + version = "0.2.0" 3910 + source = "registry+https://github.com/rust-lang/crates.io-index" 3911 + checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" 3912 + 3913 + [[package]] 3867 3914 name = "tantivy" 3868 3915 version = "0.26.1" 3869 3916 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4472 4519 "quote", 4473 4520 "syn", 4474 4521 ] 4522 + 4523 + [[package]] 4524 + name = "triomphe" 4525 + version = "0.1.16" 4526 + source = "registry+https://github.com/rust-lang/crates.io-index" 4527 + checksum = "b40688ea6389c8171614b25491f71d4a27946e0c7ce2da1c6de27e25abf1a0ae" 4475 4528 4476 4529 [[package]] 4477 4530 name = "try-lock"
+1
Cargo.toml
··· 45 45 jacquard-common = "0.12.0-beta.2" 46 46 jacquard-derive = "0.12.0-beta.2" 47 47 jacquard-lexicon = { version = "0.12.0-beta.2", default-features = false } 48 + jacquard-identity = { version = "0.12.0-beta.2", features = ["cache"] } 48 49 49 50 anyhow = "1" 50 51 miette = "7"
+2
bobbin/crates/bobbin/Cargo.toml
··· 19 19 bobbin-search = { workspace = true } 20 20 bobbin-slingshot-client = { workspace = true } 21 21 bobbin-xrpc = { workspace = true } 22 + jacquard-common = { workspace = true } 23 + jacquard-identity = { workspace = true } 22 24 23 25 axum = { workspace = true } 24 26 serde = { workspace = true, features = ["derive"] }
+17
bobbin/crates/bobbin/src/main.rs
··· 19 19 }; 20 20 use bobbin_search::{SearchIndex, SearchReader}; 21 21 use bobbin_slingshot_client::SlingshotClient; 22 + use bobbin_slingshot_client::default_http_client; 22 23 use bobbin_xrpc::{ 23 24 AppState, HeavyLimiter, MaxInFlight, PerRequestAnonBytes, ReservedFloor, router, 24 25 }; 26 + use jacquard_common::deps::fluent_uri::Uri; 27 + use jacquard_identity::JacquardResolver; 28 + use jacquard_identity::resolver::{DidStep, PlcSource, ResolverOptions}; 25 29 use clap::{Parser, Subcommand}; 26 30 use tokio::signal::unix::{SignalKind, signal}; 27 31 use tokio::task::JoinHandle; ··· 180 184 let records: Arc<dyn RecordStore> = 181 185 Arc::new(LruRecordStore::new(CacheCapacity::from_bytes(lru_cap))); 182 186 let slingshot = SlingshotClient::with_default_http(cfg.slingshot.url.clone())?; 187 + let mut resolver_opts = ResolverOptions::default(); 188 + // NOTE: see https://tangled.org/nonbinary.computer/jacquard/issues/39. 189 + resolver_opts.did_order = vec![DidStep::DidWebHttps, /* DidStep::PlcHttp, */ DidStep::PdsResolveDid]; 190 + let directory = Arc::new( 191 + JacquardResolver::new(default_http_client()?, resolver_opts) 192 + .with_plc_source(PlcSource::Slingshot { 193 + base: Uri::parse(cfg.slingshot.url.as_str()) 194 + .context("slingshot url is not a valid URI")? 195 + .to_owned(), 196 + }) 197 + .with_cache(), 198 + ); 183 199 let resolver = Arc::new(RepoIdResolver::with_slingshot( 184 200 slingshot.clone(), 185 201 clock.clone(), ··· 315 331 knots, 316 332 search as Arc<dyn SearchReader>, 317 333 resolver, 334 + directory, 318 335 ) 319 336 .with_limiter(limiter); 320 337 let app = router(state);
+1
bobbin/crates/xrpc/Cargo.toml
··· 15 15 bobbin-slingshot-client = { workspace = true } 16 16 bobbin-knot-proxy = { workspace = true } 17 17 jacquard-common = { workspace = true } 18 + jacquard-identity = { workspace = true } 18 19 19 20 axum = { workspace = true } 20 21 chrono = { workspace = true }
+4
bobbin/crates/xrpc/src/lib.rs
··· 33 33 SearchCursor, SearchError, SearchFilters, SearchHit, SearchOffset, SearchReader, 34 34 }; 35 35 use bobbin_slingshot_client::{SlingshotClient, SlingshotError}; 36 + use jacquard_identity::JacquardResolver; 36 37 use bobbin_types::ids::{EdgeKey, SubjectRef, nsid_static}; 37 38 use bobbin_types::knot_acl::{KnotOwnedSource, decode_knot_owned_source, knot_did_host}; 38 39 use bobbin_types::record::RecordBody; ··· 120 121 pub knots: Arc<KnotProxy>, 121 122 pub search: Arc<dyn SearchReader>, 122 123 pub resolver: Arc<RepoIdResolver>, 124 + pub directory: Arc<JacquardResolver>, 123 125 pub limiter: Option<Arc<HeavyLimiter>>, 124 126 enrich_router: Arc<std::sync::OnceLock<Router>>, 125 127 } ··· 136 138 knots: Arc<KnotProxy>, 137 139 search: Arc<dyn SearchReader>, 138 140 resolver: Arc<RepoIdResolver>, 141 + directory: Arc<JacquardResolver>, 139 142 ) -> Self { 140 143 Self { 141 144 records, ··· 147 150 knots, 148 151 search, 149 152 resolver, 153 + directory, 150 154 limiter: None, 151 155 enrich_router: Arc::new(std::sync::OnceLock::new()), 152 156 }
+1
bobbin/crates/xrpc/tests/aggregation.rs
··· 92 92 SearchIndex::new(DEFAULT_WRITER_HEAP_BYTES, Arc::new(SystemClock::new())).unwrap(), 93 93 ) as Arc<dyn SearchReader>, 94 94 Arc::new(RepoIdResolver::detached(RuntimeHasher::default())), 95 + Arc::new(jacquard_identity::JacquardResolver::default()), 95 96 ); 96 97 Self { 97 98 server,
+1
bobbin/crates/xrpc/tests/bulk.rs
··· 69 69 SearchIndex::new(DEFAULT_WRITER_HEAP_BYTES, Arc::new(SystemClock::new())).unwrap(), 70 70 ) as Arc<dyn SearchReader>, 71 71 Arc::new(RepoIdResolver::detached(RuntimeHasher::default())), 72 + Arc::new(jacquard_identity::JacquardResolver::default()), 72 73 ); 73 74 Self { server, state } 74 75 }
+1
bobbin/crates/xrpc/tests/cold_start.rs
··· 56 56 Arc::new(SearchIndex::new(DEFAULT_WRITER_HEAP_BYTES, Arc::new(SystemClock::new())).unwrap()) 57 57 as Arc<dyn SearchReader>, 58 58 Arc::new(RepoIdResolver::detached(RuntimeHasher::default())), 59 + Arc::new(jacquard_identity::JacquardResolver::default()), 59 60 ) 60 61 } 61 62
+1
bobbin/crates/xrpc/tests/coverage.rs
··· 44 44 SearchIndex::new(DEFAULT_WRITER_HEAP_BYTES, Arc::new(SystemClock::new())).unwrap(), 45 45 ) as Arc<dyn SearchReader>, 46 46 Arc::new(RepoIdResolver::detached(RuntimeHasher::default())), 47 + Arc::new(jacquard_identity::JacquardResolver::default()), 47 48 ); 48 49 Self { coverage, state } 49 50 }
+1
bobbin/crates/xrpc/tests/enrich.rs
··· 73 73 SearchIndex::new(DEFAULT_WRITER_HEAP_BYTES, Arc::new(SystemClock::new())).unwrap(), 74 74 ) as Arc<dyn SearchReader>, 75 75 Arc::new(RepoIdResolver::detached(RuntimeHasher::default())), 76 + Arc::new(jacquard_identity::JacquardResolver::default()), 76 77 ); 77 78 Self { 78 79 server,
+1
bobbin/crates/xrpc/tests/extended.rs
··· 81 81 SearchIndex::new(DEFAULT_WRITER_HEAP_BYTES, Arc::new(SystemClock::new())).unwrap(), 82 82 ) as Arc<dyn SearchReader>, 83 83 Arc::new(RepoIdResolver::detached(RuntimeHasher::default())), 84 + Arc::new(jacquard_identity::JacquardResolver::default()), 84 85 ); 85 86 Self { 86 87 server,
+1
bobbin/crates/xrpc/tests/knot_proxy.rs
··· 82 82 SearchIndex::new(DEFAULT_WRITER_HEAP_BYTES, Arc::new(SystemClock::new())).unwrap(), 83 83 ) as Arc<dyn SearchReader>, 84 84 Arc::new(RepoIdResolver::detached(RuntimeHasher::default())), 85 + Arc::new(jacquard_identity::JacquardResolver::default()), 85 86 ); 86 87 Self { 87 88 slingshot: slingshot_server,
+1
bobbin/crates/xrpc/tests/search.rs
··· 76 76 ), 77 77 search.clone() as Arc<dyn SearchReader>, 78 78 Arc::new(RepoIdResolver::detached(RuntimeHasher::default())), 79 + Arc::new(jacquard_identity::JacquardResolver::default()), 79 80 ); 80 81 Self { 81 82 server,