···8899It 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.
10101111-## 0.7.0 Release Highlights:
1111+## 0.8.0 Release Highlights:
12121313-- **Bluesky-style rich text support**
1414- - Parses from supplied text as well as explicit builder
1515- - Sanitizes input text
1616- - Also handles \[]() Markdown-style links
1717- - Optionally pulls out candidates for link/record embedding
1818- - Optionally fetches Opengraph link data for external links
1919-- **Moderation label application**
2020- - Generic implementation of atproto moderation/labeling client-side filtering/tagging via traits
2121- - Implementations for Bluesky and other types on best-effort basis
2222- - Demonstration options for use while avoiding Bluesky namespace or AppView infrastructure
2323-- **Websocket Subscriber-sent message control traits/code**
2424- - Primarily useful for Jetstream or other custom Websocket services
2525-- Fixed some `Data` value type deserialization issues
1313+**`jacquard-repo` crate**
1414+ - Complete implementation of the atproto repository spec
1515+ - [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
1616+ - repository CAR file read/write support
1717+ - 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)
1818+ - Big rewrite of all the errors in the crate, improvements to context and overall structure
26192720> [!WARNING]
2821> A lot of the streaming code is still pretty experimental. The examples work, though.\
···118111| `jacquard-api` | Autogenerated API bindings | [](https://crates.io/crates/jacquard-api) [](https://docs.rs/jacquard-api) |
119112| `jacquard-oauth` | atproto OAuth implementation | [](https://crates.io/crates/jacquard-oauth) [](https://docs.rs/jacquard-oauth) |
120113| `jacquard-identity` | Identity resolution | [](https://crates.io/crates/jacquard-identity) [](https://docs.rs/jacquard-identity) |
114114+| `jacquard-repo` | Repository primitives (MST, commits, CAR I/O) | [](https://crates.io/crates/jacquard-repo) [](https://docs.rs/jacquard-repo) |
121115| `jacquard-lexicon` | Lexicon parsing and code generation | [](https://crates.io/crates/jacquard-lexicon) [](https://docs.rs/jacquard-lexicon) |
122116| `jacquard-derive` | Macros for lexicon types | [](https://crates.io/crates/jacquard-derive) [](https://docs.rs/jacquard-derive) |
123117
···16161717[dependencies]
1818# Internal
1919-jacquard-common = { path = "../jacquard-common", version = "0.7.0", features = ["crypto-ed25519", "crypto-k256", "crypto-p256"] }
2020-jacquard-derive = { path = "../jacquard-derive", version = "0.7.0" }
1919+jacquard-common = { path = "../jacquard-common", version = "0.8.0", features = ["crypto-ed25519", "crypto-k256", "crypto-p256"] }
2020+jacquard-derive = { path = "../jacquard-derive", version = "0.8.0" }
21212222# Serialization
2323serde.workspace = true
+1-1
crates/jacquard-repo/src/lib.rs
···33//! This crate provides building blocks for working with AT Protocol repositories:
44//!
55//! - **MST (Merkle Search Tree)**: Immutable tree operations with deterministic structure
66-//! - **Commits**: Signed commit structures for Sync v1 (version 2) and v1.1 (version 3)
66+//! - **Commits**: Signed commit structures (versions 2 and 3) with signature verification
77//! - **CAR I/O**: Import and export repositories in CAR (Content Addressable aRchive) format
88//! - **Storage**: Pluggable block storage abstraction with in-memory and file-backed implementations
99//!
+2-9
crates/jacquard-repo/tests/mst_diff_suite.rs
···8282 Ok((parsed.root, parsed.blocks))
8383}
84848585-/// Convert base32 CID string to IpldCid
8686-fn parse_cid(cid_str: &str) -> anyhow::Result<IpldCid> {
8787- Ok(cid_str.parse()?)
8888-}
8989-9085/// Convert IpldCid to base32 string (for comparison)
9186fn cid_to_string(cid: &IpldCid) -> String {
9287 cid.to_string()
···139134140135 // Replicate create_commit's relevant_blocks logic (from repo.rs:276-290)
141136 let mut relevant_blocks = BTreeMap::new();
142142- let ops_count = diff.creates.len() + diff.updates.len() + diff.deletes.len();
143143-144137 // For each operation, collect blocks along the path in BOTH trees for inductive validation
145138 for (key, _cid) in &diff.creates {
146139 mst_b
···346339 Subset, // actual is subset of expected (missing blocks)
347340 Superset, // actual is superset of expected (extra blocks)
348341 Different, // neither subset nor superset
349349- NotImplemented,
350342}
351343352344/// Summary statistics across all tests
···481473 Ok(result) => {
482474 if let Some(ref info) = result.inductive_proof_nodes_info {
483475 if matches!(info.match_status, MatchStatus::Subset) {
484484- let missing: Vec<_> = info.expected.difference(&info.actual).cloned().collect();
476476+ let missing: Vec<_> =
477477+ info.expected.difference(&info.actual).cloned().collect();
485478 missing_block_cases.push((result.test_name, missing));
486479 }
487480 }