A better Rust ATProto crate
1# Changelog 2 3## [0.5.2] - 2025-10-14 4 5### Added 6 7**Value type deserialization** (`jacquard-common`) 8- `from_json_value()`: Deserialize typed data directly from `serde_json::Value` without borrowing 9- `from_data_owned()`, `from_raw_data_owned()`: Owned deserialization helpers 10- `Data::from_json_owned()`: Parse JSON into owned `Data<'static>` 11- `IntoStatic` implementation for `RawData` enabling owned conversions 12- Re-exported value types from crate root for easier imports 13- `Deserializer` trait implementations for `Data<'static>` and `RawData<'static>` 14- Owned deserializer helpers: `OwnedArrayDeserializer`, `OwnedObjectDeserializer`, `OwnedBlobDeserializer` 15 16**Service Auth** (`jacquard-axum`, `jacquard-common`) 17- Full service authentication implementation for inter-service JWT verification 18- `ExtractServiceAuth` Axum extractor for validating service auth tokens 19- Axum service auth middleware 20- JWT parsing and signature verification (ES256, ES256K) 21- Service auth claims validation (issuer, audience, expiration, method binding) 22- DID document resolution for signing key verification 23 24**XrpcRequest derive macro** (`jacquard-derive`) 25- `#[derive(XrpcRequest)]` for custom XRPC endpoints 26- Automatically generates response marker struct and trait implementations 27- Supports both client-side (`XrpcRequest`) and server-side (`XrpcEndpoint`) with `server` flag 28- Simplifies defining custom XRPC endpoints outside of generated API 29 30**Builder integration** (`jacquard-derive`) 31- `#[lexicon]` macro now detects `bon::Builder` derive 32- Automatically adds `#[builder(default)]` to `extra_data` field when Builder is present 33- Makes `extra_data` optional in generated builders 34 35### Fixed 36 37**String deserialization** (`jacquard-common`) 38- All string types (Did, Handle, Nsid, etc.) now properly handle URL-encoded values 39- `serde_html_form` correctly decodes percent-encoded characters during deserialization 40- Fixes issues with DIDs and other identifiers containing colons in query parameters 41 42**Axum extractor** (`jacquard-axum`) 43- Removed unnecessary URL-decoding workaround (now handled by improved string deserialization) 44- Added comprehensive tests for URL-encoded query parameters 45- Cleaner implementation with proper delegation to serde 46 47### Changed 48 49**Dependencies** 50- Moved `clap` to dev-dependencies in `jacquard` (only used in examples) 51- Moved `axum-macros` and `tracing-subscriber` to dev-dependencies in `jacquard-axum` (only used in examples) 52- Removed unused dependencies: `urlencoding` (jacquard, jacquard-axum), `uuid` (jacquard-oauth), `serde_with` (jacquard-common) 53- Removed `fancy` feature from `jacquard` (design smell for library crates) 54- Moved various proc-macro crate dependencies to dev-dependencies in `jacquard-derive` 55 56**Development tooling** 57- Improved justfile with dynamic example discovery 58- `just examples` now auto-discovers all examples 59- `just example <name>` auto-detects package without manual configuration 60- Better error messages when examples not found 61 62**Documentation** (`jacquard`, `jacquard-common`) 63- Improved lifetime pattern explanations 64- Better documentation of zero-copy deserialization approach 65- Links to docs.rs for generated documentation 66 67--- 68 69## [0.5.1] - 2025-10-13 70 71### Fixed 72 73**Trait bounds** (`jacquard-common`) 74- Removed lifetime parameter from `XrpcRequest` trait, simplifying trait bounds 75- Lifetime now only appears on `XrpcEndpoint::Request<'de>` associated type 76- Fixes issues with using XRPC types in async contexts like Axum extractors 77 78### Changed 79 80- Updated all workspace crates to 0.5.1 for consistency 81- `jacquard-axum` remains at 0.5.1 (unchanged) 82 83--- 84 85## `jacquard-axum` [0.5.1] - 2025-10-13 86 87### Fixed 88 89- Axum extractor now sets the correct Content-Type header during error path. 90 91--- 92 93## [0.5.0] - 2025-10-13 94 95### Added 96 97**Agent convenience methods** (`jacquard`) 98- New `AgentSessionExt` trait automatically implemented for `AgentSession + IdentityResolver` 99- **Basic CRUD**: `create_record()`, `get_record()`, `put_record()`, `delete_record()` 100- **Update patterns**: `update_record()` (fetch-modify-put), `update_vec()`, `update_vec_item()` 101- **Blob operations**: `upload_blob()` 102- All methods auto-fill repo from session or URI parameter as relevant, and collection from type's `Collection::NSID` 103 104**VecUpdate trait** (`jacquard`) 105- `VecUpdate` trait for fetch-modify-put patterns on array-based endpoints 106- `PreferencesUpdate` implementation for updating Bluesky user preferences 107- Enables simpler updates to preferences and other 'array of union' types 108 109**Typed record retrieval** (`jacquard-api`, `jacquard-common`, `jacquard-lexicon`) 110- Each collection generates `{Type}Record` marker struct implementing `XrpcResp` 111- `Collection::Record` associated type points to the marker 112- `get_record::<R>()` returns `Response<R::Record>` with zero-copy `.parse()` 113- Response transmutation enables type-safe record operations 114 115**Examples** 116- `create_post.rs`: Creating posts with Agent convenience methods 117- `update_profile.rs`: Updating profile with fetch-modify-put 118- `post_with_image.rs`: Uploading images and creating posts with embeds 119- `update_preferences.rs`: Using VecUpdate for preferences 120- `create_whitewind_post.rs`, `read_whitewind_post.rs`: Third-party lexicons 121- `read_tangled_repo.rs`: Reading git repo metadata from tangled.org 122- `resolve_did.rs`: Identity resolution examples 123- `public_atproto_feed.rs`: Unauthenticated feed access 124- `axum_server.rs`: Server-side XRPC handler 125 126 127**Documentation** (`jacquard`) 128- A whole host of examples added, as well as a lengthy explainer of the trait patterns. 129 130## [0.4.1] - 2025-10-13 131 132### Added 133 134**Collection trait improvements** (`jacquard-api`) 135- Generated `{Type}Record` marker structs for all record types 136- Each implements `XrpcResp` with `Output<'de> = {Type}<'de>` and `Err<'de> = RecordError<'de>` 137- Enables typed `get_record` returning `Response<R::Record>` 138 139### Changed 140 141- Minor improvements to derive macros (`jacquard-derive`) 142- Identity resolution refinements (`jacquard-identity`) 143- OAuth client improvements (`jacquard-oauth`) 144 145--- 146 147## [0.4.0] - 2025-10-11 148 149### Breaking Changes 150 151**Zero-copy deserialization** (`jacquard-common`, `jacquard-api`) 152- `XrpcRequest` now takes a `'de` lifetime parameter and requires `Deserialize<'de>` 153- For raw data, `Response::parse_data()` gives validated loosely-typed atproto data, while `Response::parse_raw()` gives the raw values, with minimal validation. 154 155**XRPC module moved** (`jacquard-common`) 156- `xrpc.rs` is now top-level instead of under `types` 157- Import from `jacquard_common::xrpc::*` not `jacquard_common::types::xrpc::*` 158 159**Response API changes** (`jacquard-common`) 160- `XrpcRequest::Output` and `XrpcRequest::Err` are associated types with lifetimes 161- Split response and request traits: `XrpcRequest<'de>` for client, `XrpcEndpoint` for server 162- Added `XrpcResp` marker trait 163 164**Various traits** (`jacquard`, `jacquard-common`, `jacquard-lexicon`, `jacquard-oauth`) 165- Removed #[async_trait] attribute macro usage in favour of `impl Future` return types with manual bounds. 166- Boxing imposed by asyc_trait negatively affected borrowing modes in async methods. 167- Currently no semver guarantees on API trait bounds, if they need to tighten, they will. 168 169### Added 170 171**New crate: `jacquard-axum`** 172- Server-side XRPC handlers for Axum 173- `ExtractXrpc<R>` deserializes incoming requests (query params for Query, body for Procedure) 174- Automatic error responses 175 176**Lexicon codegen fixes** (`jacquard-lexicon`) 177- Union variant collision detection: when multiple namespaces have similar type names, foreign ones get prefixed (e.g., `Images` vs `BskyImages`) 178- Token types generate unit structs with `Display` instead of being skipped 179- Namespace dependency tracking during union generation 180- `generate_cargo_features()` outputs Cargo.toml features with correct deps 181- `sanitize_name()` ensures valid Rust identifiers 182 183**Lexicons** (`jacquard-api`) 184 185Added 646 lexicon schemas. Highlights: 186 187Core ATProto: 188- `com.atproto.*` 189- `com.bad-example.*` for identity resolution 190 191Bluesky: 192- `app.bsky.*` bluesky app 193- `chat.bsky.*` chat client 194- `tools.ozone.*` moderation 195 196Third-party: 197- `sh.tangled.*` - git forge 198- `sh.weaver.*` - orual's WIP markdown blog platform 199- `pub.leaflet.*` - longform publishing 200- `net.anisota.*` - gamified and calming take on bluesky 201- `network.slices.*` - serverless atproto hosting 202- `tools.smokesignal.*` - automation 203- `com.whtwnd.*` - markdown blogging 204- `place.stream.*` - livestreaming 205- `blue.2048.*` - 2048 game 206- `community.lexicon.*` - community extensions (bookmarks, calendar, location, payments) 207- `my.skylights.*` - media tracking 208- `social.psky.*` - social extensions 209- `blue.linkat.*` - link boards 210 211Plus 30+ more experimental/community namespaces. 212 213**Value types** (`jacquard-common`) 214- `RawData` to `Data` conversion with type inference 215- `from_data`, `from_raw_data`, `to_data`, and `to_raw_data` to serialize to and deserialize from the loosely typed value data formats. Particularly useful for second-stage deserialization of type "unknown" fields in lexicons, such as `PostView.record`. 216 217### Changed 218 219- `generate_union()` takes current NSID for dependency tracking 220- Generated code uses `sanitize_name()` for identifiers more consistently 221- Added derive macro for IntoStatic trait implementation 222 223### Fixed 224 225- Methods to extract the output from an XRPC response now behave well with respect to lifetimes and borrowing. 226- Now possible to use jacquard types in places like axum extractors due to lifetime improvements 227- Union variants don't collide when multiple namespaces define similar types and another namespace includes them 228 229---