A better Rust ATProto crate
1# Changelog
2
3## [0.9.6] - 2025-12-19
4
5### Changed
6
7**Logging** (`jacquard`, `jacquard-axum`)
8- [PR from @nekomimi.pet](https://tangled.org/nonbinary.computer/jacquard/pulls/5) cleaning up more debug logs, and adding tracing feature gate to jacquard-axum
9
10## [0.9.5] - 2025-12-19
11
12### Fixed
13
14**docs.rs configuration**
15- Fixed typo in `jacquard-common` docs.rs features (`crypto-ed22519` → `crypto-ed25519`) that was causing documentation builds to fail
16- Moved `loopback` feature documentation to `jacquard-oauth` where the feature is defined
17
18**OAuth flow** (`jacquard-oauth`)
19- Minor OAuth flow compatibility improvements
20
21**Serialization** (`jacquard-common`, `jacquard-identity`)
22- Fixed CID deserialization edge cases in `Data` and `RawData` types
23- Fixed DID document serialization when optional fields are absent
24
25**Lexicon code generation** (`jacquard-lexicon`, `jacquard-api`)
26- Fixed nullable field handling in generated code
27- Fixed lifetime handling in codegen of binary xrpc outputs
28- Fixed lifetime handling in unions
29- Fixed incorrectly unescaped rust keywords in module paths
30
31**Observability** (`jacquard`)
32- Fixed tracing span issues associated with some build failures
33
34### Added
35
36**mini-moka-wasm** (`mini-moka-wasm`, `jacquard-identity`)
37- Publishing vendored version of mini-moka with wasm browser compat fix to make usage easier
38
39**Service authentication** (`jacquard-axum`)
40- Optional service auth extractor option
41
42**Data handling** (`jacquard-common`)
43- Serde bytes helpers for JSON fields
44- Made PLC source fields public for library consumers
45
46**Lexicons** (`jacquard-api`)
47- Updated to latest AT Protocol lexicon schemas
48- API regeneration with builder fixes
49
50### Changed
51
52**Logging** (`jacquard`)
53- Improved client error logging with better context
54
55## [0.9.3] - 2025-11-17 (`jacquard`)
56
57### Fixed
58
59- SessionKey is now a proper tuple struct and not a type alias, which should help rustc not freak out when you do things like put MemoryCredentialSession in an Arc
60
61## [0.9.2] - 2025-11-17
62
63### Added
64
65**WASM compatibility improvements** (`jacquard-common`, `jacquard-identity`)
66- Vendored mini-moka implementation with WASM support for caching
67- regex-lite usage on WASM targets for reduced binary size
68- Schema resolver now works on WASM targets
69
70**Data query improvements** (`jacquard-common`)
71- Mutable path query access and setting for `Data` values
72
73### Changed
74
75**URL handling** (`jacquard-common`)
76- Rework of some internal URL handling for better compatibility
77- Includes a minor change to the return type of the endpoint() method of XrpcClient and equivalents.
78
79**OAuth improvements** (`jacquard-oauth`)
80- Fixed OAuth scope handling in loopback flow
81- OAuth metadata resolution improvements
82- Various OAuth flow enhancements and bug fixes
83
84**Identity resolution** (`jacquard-identity`)
85- Fixed non-DNS lexicon and did:web resolution using Cloudflare DoH
86- Reduced noisy logging in identity resolution
87
88**Lexicons** (`jacquard-api`)
89- Updated to latest AT Protocol lexicons
90
91### Fixed
92
93**Data deserialization** (`jacquard-common`)
94- Fixed CID deserialization edge cases for better spec compliance
95- More permissive JSON shape handling for better interoperability with varied implementations
96
97## [0.9.1] - 2025-11-04 (`jacquard-identity`, `jacquard-lexicon`)
98
99### Fixed
100
101- slingshot resolver no longer spuriously warns when cross-validating handles
102
103## [0.9.0] - 2025-11-03
104
105### Added
106
107**Runtime schema validation** (`jacquard-lexicon`)
108- `SchemaValidator` for validating `Data` values against lexicon schemas
109- CID-based validation caching for efficient repeated validation
110- `ValidationResult` with structural and constraint error separation
111- Comprehensive error types: `StructuralError` (type mismatches, missing fields, union errors) and `ConstraintError` (length, grapheme, numeric bounds)
112- `ValidationPath` for precise error location reporting
113- Ref cycle detection with configurable max depth
114- Support for validating partial/malformed data without full deserialization
115
116**Value query DSL** (`jacquard-common`)
117- Pattern-based querying of nested `Data` structures
118- `data.query(pattern)` with expressive syntax:
119 - `field.nested` - exact path navigation
120 - `[..]` - wildcard over collections (array elements or object values)
121 - `field..nested` - scoped recursion (find nested within field, expect one)
122 - `...field` - global recursion (find all occurrences anywhere)
123- `QueryResult` enum with `Single`, `Multiple`, and `None` variants
124- `QueryMatch` with path tracking for multiple results
125- Iterator support via `.values()`, `.first()`, `.single()`, `.multiple()`
126
127**Data value enhancements** (`jacquard-common`)
128- `get_at_path()` for simple path-based field access on `Data` and `RawData`
129- Path syntax: `embed.images[0].alt` for navigating nested structures
130- `type_discriminator()` helper methods for AT Protocol union discrimination
131- Returns `$type` field value for objects with type discriminators
132- Added on `Data`, `Object`, and `RawData` types
133- Collection helper methods: `get()`, `contains_key()`, `len()`, `is_empty()`, `iter()`, `keys()`, `values()`
134- Index operator support: `obj["key"]` and `arr[0]`
135
136**Lexicon resolution** (`jacquard-identity`)
137- `LexiconResolver` for fetching lexicon schemas from AT Protocol services
138- Resolves lexicons from PDS instances and lexicon hosts
139- `resolve_lexicon()` fetches and parses lexicon schemas
140- `resolve_lexicon_raw()` fetches raw schema JSON
141- New example: `resolve_lexicon.rs`
142
143**Identity resolver caching** (`jacquard-identity`)
144- Optional `cache` feature with configurable in-memory caching
145- `JacquardResolver::with_cache()` constructor for cached resolver
146- Separate TTLs for handle→DID, DID→doc, and lexicon resolution
147
148**XRPC client improvements** (`jacquard-common`, `jacquard`, `jacquard-oauth`)
149- `set_options()` and `set_endpoint()` methods on `XrpcClient` trait
150- Default no-op implementations for stateless clients
151- Enables runtime reconfiguration of stateful clients
152- Better support for custom endpoint and option overrides
153
154**Lexicon schema generation from Rust types** (`jacquard-derive`, `jacquard-lexicon`)
155- New `#[derive(LexiconSchema)]` macro for generating lexicon schemas from Rust structs
156- New `#[lexicon_union]` attribute macro for lexicon union types (tagged enums)
157- Automatic schema generation for custom lexicons without writing JSON manually
158- Field-level attributes: `ref` for explicit type references, `union` for union fields
159- Fragment support for multi-def lexicons via `fragment = "..."` attribute
160- Generates `LexiconDoc` at compile time for runtime validation
161- Enables type-safe custom lexicon development
162
163**Lexicon codegen improvements** (`jacquard-lexicon`, `jacquard-api`)
164- Vendored in an implementation of the typed builder pattern from `bon` to **substantially** improve compile times
165- Feature-gated heavy code generation features so `jacquard-api` and other consumers of the validation capabilities don't pay the `syn` tax as badly.
166- LexiconSchema trait generated implementations for runtime validation
167
168**Session store improvements** (`jacquard`)
169- Improved trait bounds for `SessionStore` implementations
170- Better ergonomics for credential session types
171- Memory-based credential session helpers
172
173**New crate: `jacquard-lexgen`**
174- Lexicon code generation tooling extracted from `jacquard-lexicon`
175- Separates binary/CLI tools from library code
176- Contains lexicon fetching and code generation binaries
177- `jacquard-lexicon` remains as pure library for lexicon parsing, code generation, and validation
178
179**Examples**
180- `app_password_create_post.rs`: App password authentication example
181
182### Changed
183
184**Feature gating** (`jacquard-identity`)
185- Better conditional compilation for platform-specific features
186- Improved WASM target support
187
188**Dependency updates**
189- Updated to latest lexicons from atproto/bluesky
190- Added workspace dependencies: sha2, multihash, dashmap, cid
191- Various minor dependency version updates
192
193### Fixed
194
195**File auth store** (`jacquard`)
196- Fixed serialization/deserialization bugs in `FileAuthStore` implementation
197
198**Packaging** (`jacquard-lexgen`)
199- Added Nix flake apps for lexicon tools
200
201## [0.8.0] - 2025-10-23
202
203### Breaking Changes
204
205**Error type refactor** (`jacquard-common`, `jacquard-identity`, `jacquard-oauth`, `jacquard`)
206- Better error messages with contextual information and help text
207- Breaking: Error variant names and structures changed across all crates
208
209### Added
210
211**New crate: `jacquard-repo`**
212- AT Protocol repository primitives for working with atproto data structures
213- **MST (Merkle Search Tree)**: Immutable, deterministic tree operations with proper fanout
214 - Optimized block allocation (4.5% oversupply, validated against retr0id's test suite)
215 - Diff operations with protocol limit enforcement
216 - Cursor-based traversal
217- **Commits**:
218 - Proof generation and validation for Sync v1 and v1.1 Relay protocol
219- **CAR I/O**:
220 - Proof CAR validation with MST path verification
221- **Storage**: Pluggable block storage abstraction
222 - `MemoryBlockStore`: In-memory storage for testing
223 - `FileBlockStore`: Persistent file-based storage
224 - `LayeredBlockStore`: Layered read-through cache (memory over file, etc.)
225
226### Changed
227
228- Dependency updates (upgraded various crypto and serialization dependencies)
229- Documentation improvements throughout
230- Made handle parsing a bit more permissive for a common case ('handle.invalid' when someone has a messed up handle), added a method to confirm syntactic validity (the correct way to confirm validity is resolve_handle() from IdentityResolver, and comparing to the DID document).
231
232## [0.7.0] - 2025-10-19
233
234### Added
235
236**Bluesky-style rich text utilities** (`jacquard`)
237- Rich text parsing with automatic facet detection (mentions, links, hashtags)
238- Compatible with Bluesky, with the addition of support for markdown-style links (`[display](url)` syntax)
239- Embed candidate detection from URLs and at-URIs
240 - Record embeds (posts, lists, starter packs, feeds)
241 - External embeds with optional OpenGraph metadata fetching
242- Configurable embed domains for at-URI extraction (default: bsky.app, deer.social, blacksky.community, catsky.social)
243- Overlap detection and validation for facet byte ranges
244
245**Moderation/labeling client utilities** (`jacquard`)
246- Trait-based content moderation with `Labeled` and `Moderateable` traits
247- Generic moderation decision making via `moderate()` and `moderate_all()`
248- User preference handling (`ModerationPrefs`) with global and per-labeler overrides
249- `ModerationIterExt` trait for filtering/mapping moderation over iterators
250- `Labeled` implementations for Bluesky types (PostView, ProfileView, ListView, Generator, Notification, etc.)
251- `Labeled` implementations for community lexicons (net.anisota, social.grain)
252- `fetch_labels()` and `fetch_labeled_record()` helpers for retrieving labels via XRPC
253- `fetch_labeler_defs()` and `fetch_labeler_defs_direct()` for fetching labeler definitions
254
255**Subscription control** (`jacquard-common`)
256- `SubscriptionControlMessage` trait for dynamic subscription configuration
257- `SubscriptionController` for sending control messages to active WebSocket subscriptions
258- Enables runtime reconfiguration of subscriptions (e.g., Jetstream filtering)
259
260**Lexicons** (`jacquard-api`)
261- teal.fm alpha lexicons for music sharing (fm.teal.alpha.*)
262 - Actor profiles with music service status
263 - Feed generation from play history
264 - Statistics endpoints (top artists, top releases, user stats)
265
266**Examples**
267- Updated `create_post.rs` to demonstrate richtext parsing with automatic facet detection
268- New `moderated_timeline.rs` to demonstrate fetching timeline with labelers enabled and applying moderation decisions
269
270### Fixed
271
272**Data deserialization** (`jacquard-common`)
273- Fixed `Option<Vec<T>>` deserialization from `Data` values
274- Implemented explicit `deserialize_option` for `Data` and `RawData` deserializers
275- Properly handles null vs present array values when deserializing into optional fields
276
277
278## [0.6.0] - 2025-10-18
279
280### Added
281
282**HTTP streaming support** (`jacquard-common`, `jacquard`)
283- `HttpClientExt` trait for streaming HTTP requests/responses
284- `send_http_streaming()` for streaming response bodies
285- `send_http_bidirectional()` for streaming both request and response
286- `StreamingResponse` wrapper type with parts + `ByteStream`
287- `XrpcResponseStream<R>` for typed XRPC streaming responses
288- `ByteStream` / `ByteSink` platform-agnostic stream wrappers (uses n0-future)
289- `StreamError` concrete error type with kind enum (Transport, Closed, Protocol)
290- Native support via reqwest's `bytes_stream()` and `Body::wrap_stream()`
291- WASM compatibility via n0-future (no Send bounds required)
292
293
294**WebSocket subscription support** (`jacquard-common`)
295- Full XRPC WebSocket subscription infrastructure
296- `SubscriptionResp` trait for defining subscription message/error types
297- `XrpcSubscription` trait for subscription parameters
298- `SubscriptionStream<S>` typed wrapper with automatic message decoding
299- `SubscriptionClient` stateful trait + `TungsteniteSubscriptionClient` implementation
300- `SubscriptionExt` for stateless subscription calls
301- Support for both JSON and DAG-CBOR message encodings
302- Custom path support via `CUSTOM_PATH` constant for non-XRPC endpoints
303- WebSocket integration into `Agent` struct (agents can now subscribe)
304- `into_stream()`, `into_raw_data_stream()`, `into_data_stream()` methods for different deserialization modes
305
306**Framed DAG-CBOR message decoding** (`jacquard-common`, `jacquard-api`, `jacquard-lexicon`)
307- Two-stage deserialization for AT Protocol event streams (header + body)
308- `EventHeader` struct and `parse_event_header()` function
309- `decode_framed()` methods generated for all DAG-CBOR subscription message enums
310- `decode_message()` override in `SubscriptionResp` trait for custom decoding
311- `UnknownEventType` variant in `DecodeError` for unknown discriminators
312- Fixes "TrailingData" errors when consuming subscribeRepos and subscribeLabels
313
314**Jetstream support** (`jacquard-common`)
315- Full typed support for Jetstream JSON firehose
316- `JetstreamMessage` enum with `Commit`, `Identity`, `Account` variants
317- `JetstreamCommit`, `JetstreamIdentity`, `JetstreamAccount` detail structs
318- `CommitOperation` enum for create/update/delete operations
319- `JetstreamParams` with filtering options (collections, DIDs, cursor, compression)
320- Uses proper AT Protocol types (`Did`, `Handle`, `Datetime`, `Data`)
321
322**Zstd compression** (`jacquard-common`)
323- Optional `zstd` feature for Jetstream message decompression
324- Automatic detection and decompression of zstd-compressed binary frames
325- Includes official Bluesky Jetstream zstd dictionary
326- Transparent fallback to uncompressed when zstd unavailable
327- Works across all JSON stream methods (`into_stream()`, `into_raw_data_stream()`, `into_data_stream()`)
328
329**Typed AT URI wrapper** (`jacquard-common`, `jacquard-api`, `jacquard-lexicon`)
330- `AtUri<'a>` newtype wrapper for `at://` URIs with proper validation
331- Generated `fetch_uri()` method on all record types for fetching by AT URI
332- `AtUri::from_parts()` constructor for building URIs from components
333- Proper Display and FromStr implementations
334
335**Memory-based credential session helpers** (`jacquard`) (ty [@vielle.dev](https://tangled.org/@vielle.dev))
336
337**Axum improvements** (`jacquard-axum`)
338- `XrpcError` now implements `IntoResponse` for better error handling
339- Proper typed error responses without manual conversion
340- Better integration with Axum's response system
341
342**Examples**
343- `subscribe_repos.rs`: Subscribe to PDS firehose with typed DAG-CBOR messages
344- `subscribe_jetstream.rs`: Subscribe to Jetstream with typed JSON messages and optional compression
345- `stream_get_blob.rs`: Download blobs using HTTP streaming
346- `app_password_example.rs`: App password authentication example (ty [@vielle.dev](https://tangled.org/@vielle.dev))
347
348**CID deserialization improvements** (`jacquard-common`)
349- Fixed `Cid` type to properly deserialize CBOR tag 42 via `IpldCid::deserialize`
350- Separate handling for JSON (string) vs CBOR (tag 42) formats
351- `CidLink` correctly delegates to `Cid` for both formats
352
353### Changed
354
355**Default features** (`jacquard-common`)
356- Added `zstd` to default features for better Jetstream experience
357- Jetstream compression enabled by default when using the full feature set
358
359**Generated code** (`jacquard-lexicon`, `jacquard-api`)
360- All DAG-CBOR subscriptions (subscribeRepos, subscribeLabels) now use framed decoding
361- Generated `decode_framed()` implementations match on event type discriminator
362- Override `decode_message()` in trait impls to use framed decoding
363- All record types now have `fetch_uri()` and `fetch_record()` methods generated
364
365**Dependencies** (`jacquard-axum`) (ty [@thoth.ptnote.dev](https://tangled.org/@thoth.ptnote.dev))
366- Disabled default features for `jacquard` dependency to reduce bloat
367
368### Fixed
369
370**Blob upload** (`jacquard`) (ty [@vielle.dev](https://tangled.org/@vielle.dev) for reporting this one)
371- Fixed `upload_blob()` authentication issues
372- Properly authenticates while allowing custom Content-Type headers
373
374**XRPC client** (`jacquard-common`, `jacquard-oauth`, `jacquard`)
375- Added `send_with_options()` method for per-request option overrides
376- Stateful clients can now override options while preserving internal auth
377
378
379---
380
381## `jacquard-api` [0.5.5], `jacquard-lexicon` [0.5.4] - 2025-10-16
382
383### Fixed
384
385- events.smokesignal.invokeWebhook lexicon now generates valid code
386- lexicon code generation now uses `Data` for blank objects, rather than naming and then failing to generate a struct
387
388## [0.5.4] - 2025-10-16
389
390### Added
391
392**Initial streaming client support** (`jacquard-common`)
393- First primitives for streamed requests and responses
394
395**`send_with_options()` method on XrpcClient** (`jacquard-common`, `jacquard-oauth`, `jacquard`)
396- allows setting custom options per request in stateful client
397- updated oauth and credential session clients to use it
398- implementations should generally override provided auth with own internal auth
399
400**Prelude providing common traits into scope**
401
402### Fixed
403
404**`AgentSessionExt::upload_blob()` failed to authenticate** (`jacquard`)
405- new `XrpcClient::send_with_options()` method now allows properly overriding the content-type header while still handling auth internally
406
407## [0.5.3] - 2025-10-15
408
409### Added
410
411**Experimental WASM Support** (`jacquard-common`, `jacquard-api`, `jacquard-identity`, `jacquard-oauth`)
412- Core crates now compile for `wasm32-unknown-unknown` target
413- Traits use `trait-variant` to conditionally exclude `Send` bounds on WASM
414- Platform-specific trait method implementations for methods with `Self: Sync` bounds
415- DNS-based handle resolution remains gated behind `dns` feature (unavailable on WASM)
416- HTTPS well-known and PDS resolution work on all platforms
417
418### Fixed
419
420**OAuth client** (`jacquard-oauth`)
421- Fixed tokio runtime detection for non-WASM targets
422- Conditional compilation for tokio-specific features
423
424
425---
426
427## [0.5.2] - 2025-10-14
428
429### Added
430
431**Value type deserialization** (`jacquard-common`)
432- `from_json_value()`: Deserialize typed data directly from `serde_json::Value` without borrowing
433- `from_data_owned()`, `from_raw_data_owned()`: Owned deserialization helpers
434- `Data::from_json_owned()`: Parse JSON into owned `Data<'static>`
435- `IntoStatic` implementation for `RawData` enabling owned conversions
436- Re-exported value types from crate root for easier imports
437- `Deserializer` trait implementations for `Data<'static>` and `RawData<'static>`
438- Owned deserializer helpers: `OwnedArrayDeserializer`, `OwnedObjectDeserializer`, `OwnedBlobDeserializer`
439
440**Service Auth** (`jacquard-axum`, `jacquard-common`)
441- Full service authentication implementation for inter-service JWT verification
442- `ExtractServiceAuth` Axum extractor for validating service auth tokens
443- Axum service auth middleware
444- JWT parsing and signature verification (ES256, ES256K)
445- Service auth claims validation (issuer, audience, expiration, method binding)
446- DID document resolution for signing key verification
447
448**XrpcRequest derive macro** (`jacquard-derive`)
449- `#[derive(XrpcRequest)]` for custom XRPC endpoints
450- Automatically generates response marker struct and trait implementations
451- Supports both client-side (`XrpcRequest`) and server-side (`XrpcEndpoint`) with `server` flag
452- Simplifies defining custom XRPC endpoints outside of generated API
453
454**Builder integration** (`jacquard-derive`)
455- `#[lexicon]` macro now detects `bon::Builder` derive
456- Automatically adds `#[builder(default)]` to `extra_data` field when Builder is present
457- Makes `extra_data` optional in generated builders
458
459### Fixed
460
461**String deserialization** (`jacquard-common`)
462- All string types (Did, Handle, Nsid, etc.) now properly handle URL-encoded values
463- `serde_html_form` correctly decodes percent-encoded characters during deserialization
464- Fixes issues with DIDs and other identifiers containing colons in query parameters
465
466**Axum extractor** (`jacquard-axum`)
467- Removed unnecessary URL-decoding workaround (now handled by improved string deserialization)
468- Added comprehensive tests for URL-encoded query parameters
469- Cleaner implementation with proper delegation to serde
470
471### Changed
472
473**Dependencies**
474- Moved `clap` to dev-dependencies in `jacquard` (only used in examples)
475- Moved `axum-macros` and `tracing-subscriber` to dev-dependencies in `jacquard-axum` (only used in examples)
476- Removed unused dependencies: `urlencoding` (jacquard, jacquard-axum), `uuid` (jacquard-oauth), `serde_with` (jacquard-common)
477- Removed `fancy` feature from `jacquard` (design smell for library crates)
478- Moved various proc-macro crate dependencies to dev-dependencies in `jacquard-derive`
479
480**Development tooling**
481- Improved justfile with dynamic example discovery
482- `just examples` now auto-discovers all examples
483- `just example <name>` auto-detects package without manual configuration
484- Better error messages when examples not found
485
486**Documentation** (`jacquard`, `jacquard-common`)
487- Improved lifetime pattern explanations
488- Better documentation of zero-copy deserialization approach
489- Links to docs.rs for generated documentation
490
491---
492
493## [0.5.1] - 2025-10-13
494
495### Fixed
496
497**Trait bounds** (`jacquard-common`)
498- Removed lifetime parameter from `XrpcRequest` trait, simplifying trait bounds
499- Lifetime now only appears on `XrpcEndpoint::Request<'de>` associated type
500- Fixes issues with using XRPC types in async contexts like Axum extractors
501
502### Changed
503
504- Updated all workspace crates to 0.5.1 for consistency
505- `jacquard-axum` remains at 0.5.1 (unchanged)
506
507---
508
509## `jacquard-axum` [0.5.1] - 2025-10-13
510
511### Fixed
512
513- Axum extractor now sets the correct Content-Type header during error path.
514
515---
516
517## [0.5.0] - 2025-10-13
518
519### Added
520
521**Agent convenience methods** (`jacquard`)
522- New `AgentSessionExt` trait automatically implemented for `AgentSession + IdentityResolver`
523- **Basic CRUD**: `create_record()`, `get_record()`, `put_record()`, `delete_record()`
524- **Update patterns**: `update_record()` (fetch-modify-put), `update_vec()`, `update_vec_item()`
525- **Blob operations**: `upload_blob()`
526- All methods auto-fill repo from session or URI parameter as relevant, and collection from type's `Collection::NSID`
527
528**VecUpdate trait** (`jacquard`)
529- `VecUpdate` trait for fetch-modify-put patterns on array-based endpoints
530- `PreferencesUpdate` implementation for updating Bluesky user preferences
531- Enables simpler updates to preferences and other 'array of union' types
532
533**Typed record retrieval** (`jacquard-api`, `jacquard-common`, `jacquard-lexicon`)
534- Each collection generates `{Type}Record` marker struct implementing `XrpcResp`
535- `Collection::Record` associated type points to the marker
536- `get_record::<R>()` returns `Response<R::Record>` with zero-copy `.parse()`
537- Response transmutation enables type-safe record operations
538
539**Examples**
540- `create_post.rs`: Creating posts with Agent convenience methods
541- `update_profile.rs`: Updating profile with fetch-modify-put
542- `post_with_image.rs`: Uploading images and creating posts with embeds
543- `update_preferences.rs`: Using VecUpdate for preferences
544- `create_whitewind_post.rs`, `read_whitewind_post.rs`: Third-party lexicons
545- `read_tangled_repo.rs`: Reading git repo metadata from tangled.org
546- `resolve_did.rs`: Identity resolution examples
547- `public_atproto_feed.rs`: Unauthenticated feed access
548- `axum_server.rs`: Server-side XRPC handler
549
550
551**Documentation** (`jacquard`)
552- A whole host of examples added, as well as a lengthy explainer of the trait patterns.
553
554## [0.4.1] - 2025-10-13
555
556### Added
557
558**Collection trait improvements** (`jacquard-api`)
559- Generated `{Type}Record` marker structs for all record types
560- Each implements `XrpcResp` with `Output<'de> = {Type}<'de>` and `Err<'de> = RecordError<'de>`
561- Enables typed `get_record` returning `Response<R::Record>`
562
563### Changed
564
565- Minor improvements to derive macros (`jacquard-derive`)
566- Identity resolution refinements (`jacquard-identity`)
567- OAuth client improvements (`jacquard-oauth`)
568
569---
570
571## [0.4.0] - 2025-10-11
572
573### Breaking Changes
574
575**Zero-copy deserialization** (`jacquard-common`, `jacquard-api`)
576- `XrpcRequest` now takes a `'de` lifetime parameter and requires `Deserialize<'de>`
577- For raw data, `Response::parse_data()` gives validated loosely-typed atproto data, while `Response::parse_raw()` gives the raw values, with minimal validation.
578
579**XRPC module moved** (`jacquard-common`)
580- `xrpc.rs` is now top-level instead of under `types`
581- Import from `jacquard_common::xrpc::*` not `jacquard_common::types::xrpc::*`
582
583**Response API changes** (`jacquard-common`)
584- `XrpcRequest::Output` and `XrpcRequest::Err` are associated types with lifetimes
585- Split response and request traits: `XrpcRequest<'de>` for client, `XrpcEndpoint` for server
586- Added `XrpcResp` marker trait
587
588**Various traits** (`jacquard`, `jacquard-common`, `jacquard-lexicon`, `jacquard-oauth`)
589- Removed #[async_trait] attribute macro usage in favour of `impl Future` return types with manual bounds.
590- Boxing imposed by asyc_trait negatively affected borrowing modes in async methods.
591- Currently no semver guarantees on API trait bounds, if they need to tighten, they will.
592
593### Added
594
595**New crate: `jacquard-axum`**
596- Server-side XRPC handlers for Axum
597- `ExtractXrpc<R>` deserializes incoming requests (query params for Query, body for Procedure)
598- Automatic error responses
599
600**Lexicon codegen fixes** (`jacquard-lexicon`)
601- Union variant collision detection: when multiple namespaces have similar type names, foreign ones get prefixed (e.g., `Images` vs `BskyImages`)
602- Token types generate unit structs with `Display` instead of being skipped
603- Namespace dependency tracking during union generation
604- `generate_cargo_features()` outputs Cargo.toml features with correct deps
605- `sanitize_name()` ensures valid Rust identifiers
606
607**Lexicons** (`jacquard-api`)
608
609Added 646 lexicon schemas. Highlights:
610
611Core ATProto:
612- `com.atproto.*`
613- `com.bad-example.*` for identity resolution
614
615Bluesky:
616- `app.bsky.*` bluesky app
617- `chat.bsky.*` chat client
618- `tools.ozone.*` moderation
619
620Third-party:
621- `sh.tangled.*` - git forge
622- `sh.weaver.*` - orual's WIP markdown blog platform
623- `pub.leaflet.*` - longform publishing
624- `net.anisota.*` - gamified and calming take on bluesky
625- `network.slices.*` - serverless atproto hosting
626- `tools.smokesignal.*` - automation
627- `com.whtwnd.*` - markdown blogging
628- `place.stream.*` - livestreaming
629- `blue.2048.*` - 2048 game
630- `community.lexicon.*` - community extensions (bookmarks, calendar, location, payments)
631- `my.skylights.*` - media tracking
632- `social.psky.*` - social extensions
633- `blue.linkat.*` - link boards
634
635Plus 30+ more experimental/community namespaces.
636
637**Value types** (`jacquard-common`)
638- `RawData` to `Data` conversion with type inference
639- `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`.
640
641### Changed
642
643- `generate_union()` takes current NSID for dependency tracking
644- Generated code uses `sanitize_name()` for identifiers more consistently
645- Added derive macro for IntoStatic trait implementation
646
647### Fixed
648
649- Methods to extract the output from an XRPC response now behave well with respect to lifetimes and borrowing.
650- Now possible to use jacquard types in places like axum extractors due to lifetime improvements
651- Union variants don't collide when multiple namespaces define similar types and another namespace includes them
652
653---