A better Rust ATProto crate

version bump, changelog updates

Orual 46f8b7fe 3f2c672b

Changed files
+118 -99
crates
jacquard
jacquard-api
jacquard-axum
jacquard-common
jacquard-derive
jacquard-identity
jacquard-lexicon
jacquard-oauth
jacquard-repo
+31
CHANGELOG.md
··· 1 1 # Changelog 2 2 3 + ## [0.8.0] - 2025-10-23 4 + 5 + ### Breaking Changes 6 + 7 + **Error type refactor** (`jacquard-common`, `jacquard-identity`, `jacquard-oauth`, `jacquard`) 8 + - Better error messages with contextual information and help text 9 + - Breaking: Error variant names and structures changed across all crates 10 + 11 + ### Added 12 + 13 + **New crate: `jacquard-repo`** 14 + - AT Protocol repository primitives for working with atproto data structures 15 + - **MST (Merkle Search Tree)**: Immutable, deterministic tree operations with proper fanout 16 + - Optimized block allocation (4.5% oversupply, validated against retr0id's test suite) 17 + - Diff operations with protocol limit enforcement 18 + - Cursor-based traversal 19 + - **Commits**: 20 + - Proof generation and validation for Sync v1 and v1.1 Relay protocol 21 + - **CAR I/O**: 22 + - Proof CAR validation with MST path verification 23 + - **Storage**: Pluggable block storage abstraction 24 + - `MemoryBlockStore`: In-memory storage for testing 25 + - `FileBlockStore`: Persistent file-based storage 26 + - `LayeredBlockStore`: Layered read-through cache (memory over file, etc.) 27 + 28 + ### Changed 29 + 30 + - Import cleanup across all crates 31 + - Dependency updates (upgraded various crypto and serialization dependencies) 32 + - Documentation improvements throughout 33 + 3 34 ## [0.7.0] - 2025-10-19 4 35 5 36 ### Added
+48 -48
Cargo.lock
··· 2262 2262 2263 2263 [[package]] 2264 2264 name = "jacquard" 2265 - version = "0.7.0" 2265 + version = "0.8.0" 2266 2266 dependencies = [ 2267 2267 "bon", 2268 2268 "bytes", ··· 2271 2271 "getrandom 0.2.16", 2272 2272 "http", 2273 2273 "image", 2274 - "jacquard-api 0.7.1", 2275 - "jacquard-common 0.7.0", 2276 - "jacquard-derive 0.7.0", 2277 - "jacquard-identity 0.7.0", 2274 + "jacquard-api 0.8.0", 2275 + "jacquard-common 0.8.0", 2276 + "jacquard-derive 0.8.0", 2277 + "jacquard-identity 0.8.0", 2278 2278 "jacquard-oauth", 2279 2279 "jose-jwk", 2280 2280 "miette", ··· 2306 2306 dependencies = [ 2307 2307 "bon", 2308 2308 "bytes", 2309 - "jacquard-common 0.7.0 (git+https://tangled.org/@nonbinary.computer/jacquard)", 2310 - "jacquard-derive 0.7.0 (git+https://tangled.org/@nonbinary.computer/jacquard)", 2309 + "jacquard-common 0.7.0", 2310 + "jacquard-derive 0.7.0", 2311 2311 "miette", 2312 2312 "serde", 2313 2313 "serde_ipld_dagcbor", ··· 2316 2316 2317 2317 [[package]] 2318 2318 name = "jacquard-api" 2319 - version = "0.7.1" 2319 + version = "0.8.0" 2320 2320 dependencies = [ 2321 2321 "bon", 2322 2322 "bytes", 2323 - "jacquard-common 0.7.0", 2324 - "jacquard-derive 0.7.0", 2323 + "jacquard-common 0.8.0", 2324 + "jacquard-derive 0.8.0", 2325 2325 "miette", 2326 2326 "serde", 2327 2327 "serde_ipld_dagcbor", ··· 2330 2330 2331 2331 [[package]] 2332 2332 name = "jacquard-axum" 2333 - version = "0.6.0" 2333 + version = "0.8.0" 2334 2334 dependencies = [ 2335 2335 "axum", 2336 2336 "axum-macros", ··· 2339 2339 "bytes", 2340 2340 "chrono", 2341 2341 "jacquard", 2342 - "jacquard-common 0.7.0", 2343 - "jacquard-derive 0.7.0", 2344 - "jacquard-identity 0.7.0", 2342 + "jacquard-common 0.8.0", 2343 + "jacquard-derive 0.8.0", 2344 + "jacquard-identity 0.8.0", 2345 2345 "k256", 2346 2346 "miette", 2347 2347 "multibase", ··· 2362 2362 [[package]] 2363 2363 name = "jacquard-common" 2364 2364 version = "0.7.0" 2365 + source = "git+https://tangled.org/@nonbinary.computer/jacquard#ef09feb782cf34eda616c9511fa12e439e1062c6" 2365 2366 dependencies = [ 2366 2367 "base64 0.22.1", 2367 2368 "bon", 2368 2369 "bytes", 2369 2370 "chrono", 2370 - "ciborium", 2371 2371 "cid", 2372 - "ed25519-dalek", 2373 - "futures", 2374 - "futures-lite", 2375 - "getrandom 0.2.16", 2372 + "genawaiter", 2376 2373 "getrandom 0.3.4", 2377 2374 "http", 2378 2375 "ipld-core", ··· 2381 2378 "miette", 2382 2379 "multibase", 2383 2380 "multihash", 2384 - "n0-future", 2385 2381 "ouroboros", 2386 2382 "p256", 2387 2383 "rand 0.9.2", ··· 2395 2391 "smol_str", 2396 2392 "thiserror 2.0.17", 2397 2393 "tokio", 2398 - "tokio-tungstenite-wasm", 2399 2394 "tokio-util", 2400 - "tracing", 2401 2395 "trait-variant", 2402 2396 "url", 2403 - "zstd", 2404 2397 ] 2405 2398 2406 2399 [[package]] 2407 2400 name = "jacquard-common" 2408 - version = "0.7.0" 2409 - source = "git+https://tangled.org/@nonbinary.computer/jacquard#ef09feb782cf34eda616c9511fa12e439e1062c6" 2401 + version = "0.8.0" 2410 2402 dependencies = [ 2411 2403 "base64 0.22.1", 2412 2404 "bon", 2413 2405 "bytes", 2414 2406 "chrono", 2407 + "ciborium", 2415 2408 "cid", 2416 - "genawaiter", 2409 + "ed25519-dalek", 2410 + "futures", 2411 + "futures-lite", 2412 + "getrandom 0.2.16", 2417 2413 "getrandom 0.3.4", 2418 2414 "http", 2419 2415 "ipld-core", ··· 2422 2418 "miette", 2423 2419 "multibase", 2424 2420 "multihash", 2421 + "n0-future", 2425 2422 "ouroboros", 2426 2423 "p256", 2427 2424 "rand 0.9.2", ··· 2435 2432 "smol_str", 2436 2433 "thiserror 2.0.17", 2437 2434 "tokio", 2435 + "tokio-tungstenite-wasm", 2438 2436 "tokio-util", 2437 + "tracing", 2439 2438 "trait-variant", 2440 2439 "url", 2440 + "zstd", 2441 2441 ] 2442 2442 2443 2443 [[package]] 2444 2444 name = "jacquard-derive" 2445 2445 version = "0.7.0" 2446 + source = "git+https://tangled.org/@nonbinary.computer/jacquard#ef09feb782cf34eda616c9511fa12e439e1062c6" 2446 2447 dependencies = [ 2447 - "jacquard-common 0.7.0", 2448 2448 "proc-macro2", 2449 2449 "quote", 2450 - "serde", 2451 - "serde_json", 2452 2450 "syn 2.0.106", 2453 2451 ] 2454 2452 2455 2453 [[package]] 2456 2454 name = "jacquard-derive" 2457 - version = "0.7.0" 2458 - source = "git+https://tangled.org/@nonbinary.computer/jacquard#ef09feb782cf34eda616c9511fa12e439e1062c6" 2455 + version = "0.8.0" 2459 2456 dependencies = [ 2457 + "jacquard-common 0.8.0", 2460 2458 "proc-macro2", 2461 2459 "quote", 2460 + "serde", 2461 + "serde_json", 2462 2462 "syn 2.0.106", 2463 2463 ] 2464 2464 2465 2465 [[package]] 2466 2466 name = "jacquard-identity" 2467 2467 version = "0.7.0" 2468 + source = "git+https://tangled.org/@nonbinary.computer/jacquard#ef09feb782cf34eda616c9511fa12e439e1062c6" 2468 2469 dependencies = [ 2469 2470 "bon", 2470 2471 "bytes", 2471 - "hickory-resolver", 2472 2472 "http", 2473 - "jacquard-api 0.7.1", 2473 + "jacquard-api 0.7.0", 2474 2474 "jacquard-common 0.7.0", 2475 2475 "miette", 2476 - "n0-future", 2477 2476 "percent-encoding", 2478 2477 "reqwest", 2479 2478 "serde", ··· 2481 2480 "serde_json", 2482 2481 "thiserror 2.0.17", 2483 2482 "tokio", 2484 - "tracing", 2485 2483 "trait-variant", 2486 2484 "url", 2487 2485 "urlencoding", ··· 2489 2487 2490 2488 [[package]] 2491 2489 name = "jacquard-identity" 2492 - version = "0.7.0" 2493 - source = "git+https://tangled.org/@nonbinary.computer/jacquard#ef09feb782cf34eda616c9511fa12e439e1062c6" 2490 + version = "0.8.0" 2494 2491 dependencies = [ 2495 2492 "bon", 2496 2493 "bytes", 2494 + "hickory-resolver", 2497 2495 "http", 2498 - "jacquard-api 0.7.0", 2499 - "jacquard-common 0.7.0 (git+https://tangled.org/@nonbinary.computer/jacquard)", 2496 + "jacquard-api 0.8.0", 2497 + "jacquard-common 0.8.0", 2500 2498 "miette", 2499 + "n0-future", 2501 2500 "percent-encoding", 2502 2501 "reqwest", 2503 2502 "serde", ··· 2505 2504 "serde_json", 2506 2505 "thiserror 2.0.17", 2507 2506 "tokio", 2507 + "tracing", 2508 2508 "trait-variant", 2509 2509 "url", 2510 2510 "urlencoding", ··· 2512 2512 2513 2513 [[package]] 2514 2514 name = "jacquard-lexicon" 2515 - version = "0.7.0" 2515 + version = "0.8.0" 2516 2516 dependencies = [ 2517 2517 "async-trait", 2518 2518 "clap", ··· 2521 2521 "glob", 2522 2522 "heck 0.5.0", 2523 2523 "jacquard-api 0.7.0", 2524 - "jacquard-common 0.7.0 (git+https://tangled.org/@nonbinary.computer/jacquard)", 2525 - "jacquard-identity 0.7.0 (git+https://tangled.org/@nonbinary.computer/jacquard)", 2524 + "jacquard-common 0.7.0", 2525 + "jacquard-identity 0.7.0", 2526 2526 "kdl", 2527 2527 "miette", 2528 2528 "prettyplease", ··· 2542 2542 2543 2543 [[package]] 2544 2544 name = "jacquard-oauth" 2545 - version = "0.7.0" 2545 + version = "0.8.0" 2546 2546 dependencies = [ 2547 2547 "base64 0.22.1", 2548 2548 "bytes", ··· 2550 2550 "dashmap", 2551 2551 "elliptic-curve", 2552 2552 "http", 2553 - "jacquard-common 0.7.0", 2554 - "jacquard-identity 0.7.0", 2553 + "jacquard-common 0.8.0", 2554 + "jacquard-identity 0.8.0", 2555 2555 "jose-jwa", 2556 2556 "jose-jwk", 2557 2557 "miette", ··· 2577 2577 2578 2578 [[package]] 2579 2579 name = "jacquard-repo" 2580 - version = "0.7.0" 2580 + version = "0.8.0" 2581 2581 dependencies = [ 2582 2582 "anyhow", 2583 2583 "bytes", ··· 2586 2586 "hex", 2587 2587 "ipld-core", 2588 2588 "iroh-car", 2589 - "jacquard-common 0.7.0", 2590 - "jacquard-derive 0.7.0", 2589 + "jacquard-common 0.8.0", 2590 + "jacquard-derive 0.8.0", 2591 2591 "k256", 2592 2592 "miette", 2593 2593 "multihash",
+1 -1
Cargo.toml
··· 5 5 6 6 [workspace.package] 7 7 edition = "2024" 8 - version = "0.7.0" 8 + version = "0.8.0" 9 9 authors = ["Orual <orual@nonbinary.computer>"] 10 10 #repository = "https://github.com/rsform/jacquard" 11 11 repository = "https://tangled.org/@nonbinary.computer/jacquard"
+8 -14
README.md
··· 8 8 9 9 It is also designed around zero-copy/borrowed deserialization: types like [`Post<'_>`](https://tangled.org/@nonbinary.computer/jacquard/blob/main/crates/jacquard-api/src/app_bsky/feed/post.rs) can borrow data (via the [`CowStr<'_>`](https://docs.rs/jacquard/latest/jacquard/cowstr/enum.CowStr.html) type and a host of other types built on top of it) directly from the response buffer instead of allocating owned copies. Owned versions are themselves mostly inlined or reference-counted pointers and are therefore still quite efficient. The `IntoStatic` trait (which is derivable) makes it easy to get an owned version and avoid worrying about lifetimes. 10 10 11 - ## 0.7.0 Release Highlights: 11 + ## 0.8.0 Release Highlights: 12 12 13 - - **Bluesky-style rich text support** 14 - - Parses from supplied text as well as explicit builder 15 - - Sanitizes input text 16 - - Also handles \[]() Markdown-style links 17 - - Optionally pulls out candidates for link/record embedding 18 - - Optionally fetches Opengraph link data for external links 19 - - **Moderation label application** 20 - - Generic implementation of atproto moderation/labeling client-side filtering/tagging via traits 21 - - Implementations for Bluesky and other types on best-effort basis 22 - - Demonstration options for use while avoiding Bluesky namespace or AppView infrastructure 23 - - **Websocket Subscriber-sent message control traits/code** 24 - - Primarily useful for Jetstream or other custom Websocket services 25 - - Fixed some `Data` value type deserialization issues 13 + **`jacquard-repo` crate** 14 + - Complete implementation of the atproto repository spec 15 + - [Sync v1.1](https://github.com/bluesky-social/proposals/blob/main/0006-sync-iteration/README.md#commit-validation-mst-operation-inversion) commit event support (both proof production and verification), well-validated in testing 16 + - repository CAR file read/write support 17 + - CAR file write order compatible with streaming mode from the [sync iteration proposal](https://github.com/bluesky-social/proposals/blob/main/0006-sync-iteration/README.md#streaming-car-processing) 18 + - Big rewrite of all the errors in the crate, improvements to context and overall structure 26 19 27 20 > [!WARNING] 28 21 > A lot of the streaming code is still pretty experimental. The examples work, though.\ ··· 118 111 | `jacquard-api` | Autogenerated API bindings | [![Crates.io](https://img.shields.io/crates/v/jacquard-api.svg)](https://crates.io/crates/jacquard-api) [![Documentation](https://docs.rs/jacquard-api/badge.svg)](https://docs.rs/jacquard-api) | 119 112 | `jacquard-oauth` | atproto OAuth implementation | [![Crates.io](https://img.shields.io/crates/v/jacquard-oauth.svg)](https://crates.io/crates/jacquard-oauth) [![Documentation](https://docs.rs/jacquard-oauth/badge.svg)](https://docs.rs/jacquard-oauth) | 120 113 | `jacquard-identity` | Identity resolution | [![Crates.io](https://img.shields.io/crates/v/jacquard-identity.svg)](https://crates.io/crates/jacquard-identity) [![Documentation](https://docs.rs/jacquard-identity/badge.svg)](https://docs.rs/jacquard-identity) | 114 + | `jacquard-repo` | Repository primitives (MST, commits, CAR I/O) | [![Crates.io](https://img.shields.io/crates/v/jacquard-repo.svg)](https://crates.io/crates/jacquard-repo) [![Documentation](https://docs.rs/jacquard-repo/badge.svg)](https://docs.rs/jacquard-repo) | 121 115 | `jacquard-lexicon` | Lexicon parsing and code generation | [![Crates.io](https://img.shields.io/crates/v/jacquard-lexicon.svg)](https://crates.io/crates/jacquard-lexicon) [![Documentation](https://docs.rs/jacquard-lexicon/badge.svg)](https://docs.rs/jacquard-lexicon) | 122 116 | `jacquard-derive` | Macros for lexicon types | [![Crates.io](https://img.shields.io/crates/v/jacquard-derive.svg)](https://crates.io/crates/jacquard-derive) [![Documentation](https://docs.rs/jacquard-derive/badge.svg)](https://docs.rs/jacquard-derive) | 123 117
+3 -3
crates/jacquard-api/Cargo.toml
··· 2 2 name = "jacquard-api" 3 3 description = "Generated AT Protocol API bindings for Jacquard" 4 4 edition.workspace = true 5 - version = "0.7.1" 5 + version = "0.8.0" 6 6 authors.workspace = true 7 7 repository.workspace = true 8 8 keywords.workspace = true ··· 17 17 [dependencies] 18 18 bon.workspace = true 19 19 bytes = { workspace = true, features = ["serde"] } 20 - jacquard-common = { version = "0.7", path = "../jacquard-common" } 21 - jacquard-derive = { version = "0.7", path = "../jacquard-derive" } 20 + jacquard-common = { version = "0.8", path = "../jacquard-common" } 21 + jacquard-derive = { version = "0.8", path = "../jacquard-derive" } 22 22 miette.workspace = true 23 23 serde.workspace = true 24 24 serde_ipld_dagcbor.workspace = true
+5 -5
crates/jacquard-axum/Cargo.toml
··· 1 1 [package] 2 2 name = "jacquard-axum" 3 3 edition.workspace = true 4 - version = "0.6.0" 4 + version = "0.8.0" 5 5 authors.workspace = true 6 6 repository.workspace = true 7 7 keywords.workspace = true ··· 22 22 [dependencies] 23 23 axum = "0.8.6" 24 24 bytes.workspace = true 25 - jacquard = { version = "0.7", path = "../jacquard", default-features = false, features = ["api"] } 26 - jacquard-common = { version = "0.7", path = "../jacquard-common", features = ["reqwest-client"] } 27 - jacquard-derive = { version = "0.7", path = "../jacquard-derive" } 28 - jacquard-identity = { version = "0.7", path = "../jacquard-identity", optional = true } 25 + jacquard = { version = "0.8", path = "../jacquard", default-features = false, features = ["api"] } 26 + jacquard-common = { version = "0.8", path = "../jacquard-common", features = ["reqwest-client"] } 27 + jacquard-derive = { version = "0.8", path = "../jacquard-derive" } 28 + jacquard-identity = { version = "0.8", path = "../jacquard-identity", optional = true } 29 29 miette.workspace = true 30 30 multibase = { version = "0.9.1", optional = true } 31 31 serde.workspace = true
+1 -1
crates/jacquard-common/Cargo.toml
··· 2 2 name = "jacquard-common" 3 3 description = "Core AT Protocol types and utilities for Jacquard" 4 4 edition.workspace = true 5 - version = "0.7.0" 5 + version = "0.8.0" 6 6 authors.workspace = true 7 7 repository.workspace = true 8 8 keywords.workspace = true
+1 -1
crates/jacquard-derive/Cargo.toml
··· 20 20 syn.workspace = true 21 21 22 22 [dev-dependencies] 23 - jacquard-common = { version = "0.7", path = "../jacquard-common" } 23 + jacquard-common = { version = "0.8", path = "../jacquard-common" } 24 24 serde.workspace = true 25 25 serde_json.workspace = true
+3 -3
crates/jacquard-identity/Cargo.toml
··· 1 1 [package] 2 2 name = "jacquard-identity" 3 3 edition.workspace = true 4 - version = "0.7.0" 4 + version = "0.8.0" 5 5 authors.workspace = true 6 6 repository.workspace = true 7 7 keywords.workspace = true ··· 21 21 trait-variant.workspace = true 22 22 bon.workspace = true 23 23 bytes.workspace = true 24 - jacquard-common = { version = "0.7", path = "../jacquard-common", features = ["reqwest-client"] } 25 - jacquard-api = { version = "0.7", path = "../jacquard-api", default-features = false, features = ["minimal"] } 24 + jacquard-common = { version = "0.8", path = "../jacquard-common", features = ["reqwest-client"] } 25 + jacquard-api = { version = "0.8", path = "../jacquard-api", default-features = false, features = ["minimal"] } 26 26 percent-encoding.workspace = true 27 27 reqwest.workspace = true 28 28 url.workspace = true
+3 -3
crates/jacquard-lexicon/Cargo.toml
··· 25 25 glob = "0.3" 26 26 heck.workspace = true 27 27 #itertools.workspace = true 28 - jacquard-api = { version = "0.7", git = "https://tangled.org/@nonbinary.computer/jacquard" } 29 - jacquard-common = { version = "0.7", features = [ "reqwest-client" ], git = "https://tangled.org/@nonbinary.computer/jacquard" } 30 - jacquard-identity = { version = "0.7", git = "https://tangled.org/@nonbinary.computer/jacquard" } 28 + jacquard-api = { version = "0.8", git = "https://tangled.org/@nonbinary.computer/jacquard" } 29 + jacquard-common = { version = "0.8", features = [ "reqwest-client" ], git = "https://tangled.org/@nonbinary.computer/jacquard" } 30 + jacquard-identity = { version = "0.8", git = "https://tangled.org/@nonbinary.computer/jacquard" } 31 31 kdl = "6" 32 32 miette = { workspace = true, features = ["fancy"] } 33 33 prettyplease.workspace = true
+3 -3
crates/jacquard-oauth/Cargo.toml
··· 1 1 [package] 2 2 name = "jacquard-oauth" 3 - version = "0.7.0" 3 + version = "0.8.0" 4 4 edition.workspace = true 5 5 description = "AT Protocol OAuth 2.1 core types and helpers for Jacquard" 6 6 authors.workspace = true ··· 21 21 streaming = ["jacquard-common/streaming", "dep:n0-future"] 22 22 23 23 [dependencies] 24 - jacquard-common = { version = "0.7", path = "../jacquard-common", features = ["reqwest-client"] } 25 - jacquard-identity = { version = "0.7", path = "../jacquard-identity" } 24 + jacquard-common = { version = "0.8", path = "../jacquard-common", features = ["reqwest-client"] } 25 + jacquard-identity = { version = "0.8", path = "../jacquard-identity" } 26 26 serde = { workspace = true, features = ["derive"] } 27 27 serde_json = { workspace = true } 28 28 url = { workspace = true }
+2 -2
crates/jacquard-repo/Cargo.toml
··· 16 16 17 17 [dependencies] 18 18 # Internal 19 - jacquard-common = { path = "../jacquard-common", version = "0.7.0", features = ["crypto-ed25519", "crypto-k256", "crypto-p256"] } 20 - jacquard-derive = { path = "../jacquard-derive", version = "0.7.0" } 19 + jacquard-common = { path = "../jacquard-common", version = "0.8.0", features = ["crypto-ed25519", "crypto-k256", "crypto-p256"] } 20 + jacquard-derive = { path = "../jacquard-derive", version = "0.8.0" } 21 21 22 22 # Serialization 23 23 serde.workspace = true
+1 -1
crates/jacquard-repo/src/lib.rs
··· 3 3 //! This crate provides building blocks for working with AT Protocol repositories: 4 4 //! 5 5 //! - **MST (Merkle Search Tree)**: Immutable tree operations with deterministic structure 6 - //! - **Commits**: Signed commit structures for Sync v1 (version 2) and v1.1 (version 3) 6 + //! - **Commits**: Signed commit structures (versions 2 and 3) with signature verification 7 7 //! - **CAR I/O**: Import and export repositories in CAR (Content Addressable aRchive) format 8 8 //! - **Storage**: Pluggable block storage abstraction with in-memory and file-backed implementations 9 9 //!
+2 -9
crates/jacquard-repo/tests/mst_diff_suite.rs
··· 82 82 Ok((parsed.root, parsed.blocks)) 83 83 } 84 84 85 - /// Convert base32 CID string to IpldCid 86 - fn parse_cid(cid_str: &str) -> anyhow::Result<IpldCid> { 87 - Ok(cid_str.parse()?) 88 - } 89 - 90 85 /// Convert IpldCid to base32 string (for comparison) 91 86 fn cid_to_string(cid: &IpldCid) -> String { 92 87 cid.to_string() ··· 139 134 140 135 // Replicate create_commit's relevant_blocks logic (from repo.rs:276-290) 141 136 let mut relevant_blocks = BTreeMap::new(); 142 - let ops_count = diff.creates.len() + diff.updates.len() + diff.deletes.len(); 143 - 144 137 // For each operation, collect blocks along the path in BOTH trees for inductive validation 145 138 for (key, _cid) in &diff.creates { 146 139 mst_b ··· 346 339 Subset, // actual is subset of expected (missing blocks) 347 340 Superset, // actual is superset of expected (extra blocks) 348 341 Different, // neither subset nor superset 349 - NotImplemented, 350 342 } 351 343 352 344 /// Summary statistics across all tests ··· 481 473 Ok(result) => { 482 474 if let Some(ref info) = result.inductive_proof_nodes_info { 483 475 if matches!(info.match_status, MatchStatus::Subset) { 484 - let missing: Vec<_> = info.expected.difference(&info.actual).cloned().collect(); 476 + let missing: Vec<_> = 477 + info.expected.difference(&info.actual).cloned().collect(); 485 478 missing_block_cases.push((result.test_name, missing)); 486 479 } 487 480 }
+5 -5
crates/jacquard/Cargo.toml
··· 126 126 required-features = ["api_bluesky", "loopback"] 127 127 128 128 [dependencies] 129 - jacquard-api = { version = "0.7", path = "../jacquard-api" } 130 - jacquard-common = { version = "0.7", path = "../jacquard-common", features = [ 129 + jacquard-api = { version = "0.8", path = "../jacquard-api" } 130 + jacquard-common = { version = "0.8", path = "../jacquard-common", features = [ 131 131 "reqwest-client", 132 132 ] } 133 - jacquard-oauth = { version = "0.7", path = "../jacquard-oauth" } 134 - jacquard-derive = { version = "0.7", path = "../jacquard-derive", optional = true } 135 - jacquard-identity = { version = "0.7", path = "../jacquard-identity" } 133 + jacquard-oauth = { version = "0.8", path = "../jacquard-oauth" } 134 + jacquard-derive = { version = "0.8", path = "../jacquard-derive", optional = true } 135 + jacquard-identity = { version = "0.8", path = "../jacquard-identity" } 136 136 137 137 bon.workspace = true 138 138 trait-variant.workspace = true
+1
crates/jacquard/src/lib.rs
··· 96 96 //! - [`jacquard-axum`](https://docs.rs/jacquard-axum/latest/jacquard_axum/index.html) - Server-side XRPC handler extractors for Axum framework (not re-exported, depends on jacquard) 97 97 //! - [`jacquard-oauth`](https://docs.rs/jacquard-oauth/latest/jacquard_oauth/index.html) - OAuth/DPoP flow implementation with session management 98 98 //! - [`jacquard-identity`](https://docs.rs/jacquard-identity/latest/jacquard_identity/index.html) - Identity resolution (handle → DID, DID → Doc, OAuth metadata) 99 + //! - [`jacquard-repo`](https://docs.rs/jacquard-repo/latest/jacquard_repo/index.html) - Repository primitives (MST, commits, CAR I/O, block storage) 99 100 //! - [`jacquard-lexicon`](https://docs.rs/jacquard-lexicon/latest/jacquard_lexicon/index.html) - Lexicon resolution, fetching, parsing and Rust code generation from schemas 100 101 //! - [`jacquard-derive`](https://docs.rs/jacquard-derive/latest/jacquard_derive/index.html) - Macros (`#[lexicon]`, `#[open_union]`, `#[derive(IntoStatic)]`) 101 102 //!