Changelog#
[0.12.0-beta.1] - 2026-03-23#
Breaking changes#
Borrow-or-share (BOS) type system (all crates)
- All validated string types (
Did,Handle,Nsid,Rkey,AtUri,AtIdentifier,MimeType,Cid,CidLink,Blob,BlobRef,Data,Array,Object,DidDocument,RecordUri,UriValue,RepoPath) are now parameterised onS: BosStr = DefaultStrinstead of lifetimes DefaultStr = SmolStr: owned, inline ≤23 bytes,DeserializeOwned&str,CowStr<'a>,Stringall work as backing types via theBosStrtraitSmolStr-backed types satisfyDeserializeOwned, enabling use in async contexts, collections, and across thread boundaries withoutIntoStaticconversion- New
.borrow()method onDid,Handle,Nsid,Rkey,RecordKeyreturnsType<&str>for cheap borrowing (analogous toUri::borrow()) - New
.convert::<B>()method for cross-backing-type conversion
XRPC trait changes (jacquard-common)
XrpcResp::Output<S: BosStr>: GAT parameterised on backing type S, not lifetimeXrpcResp::Err: plain associated type, alwaysSmolStr-backed andDeserializeOwnedXrpcRequestnow requiresSerializeboundXrpcEndpoint::Request<S: BosStr>: GAT for server-side extractionSubscriptionResp::Message<S: BosStr>,SubscriptionEndpoint::Params<S: BosStr>: updated GATsXrpcProcedureStream::Frame<S: BosStr>,XrpcStreamResp::Frame<S: BosStr>: streaming frame GATs updated
Response parsing (jacquard-common)
Response::parse::<S>(): caller chooses backing type via turbofishResponse::into_output(): returnsSmolStr-backed owned types viaDeserializeOwned- Zero-copy:
response.parse::<CowStr<'_>>(); owned:response.into_output()
Generated API types (jacquard-api, jacquard-lexicon)
- All generated structs/enums:
Foo<S: BosStr = DefaultStr>with#[serde(bound(deserialize = "S: Deserialize<'de> + BosStr"))] #[serde(borrow)]removed from all generated code- String field defaults use
FromStaticStr::from_static()for zero-alloc construction - Error enums:
SmolStrmessage fields, no lifetime parameters - Type aliases:
<S = DefaultStr>(no bounds, per rust type checker limitation)
OAuth types (jacquard-oauth)
- All session, metadata, token, scope, and JWT types parameterised on
S: BosStr = DefaultStr OAuthMetadata<S>parameterised so callers can borrow from stored metadataDpopDataSourcetrait methods returnOption<&str>(wasOption<CowStr<'_>>)- DPoP proof building uses
&strfor zero-copy JWT construction build_dpop_prooftakes&strparameters, returnsSmolStr
Identity resolution (jacquard-identity)
IdentityResolver::resolve_handle<S: BosStr + Sync>(&self, handle: &Handle<S>): generic over handle backing typeIdentityResolver::resolve_did_doc<S: BosStr + Sync>(&self, did: &Did<S>): generic over DID backing type
Repository types (jacquard-repo)
Commit<S: BosStr = DefaultStr>,UnsignedCommit<S>,RecordClaim<S>,VerifyProofsOutput<S>parameterised on SRecordWriteOpnow parameterised on both S (for string fields) and BS (for BlockStore)RawData<'a>intentionally remains lifetime-based
Derive macros (jacquard-derive)
#[lexicon]detects type param S, emitsData<S>forextra_data#[open_union]detects type param S, emitsUnknown(Data<S>)#[derive(IntoStatic)]handles S-parameterised types#[derive(XrpcRequest)]generates newOutput<S: BosStr>andErr(not GAT) impls
Client types (jacquard)
AtpSessionfieldsaccess_jwt/refresh_jwtare nowSmolStr(wasCowStr<'static>)SessionKeyusesDidandSmolStr(wasDid<'static>andCowStr<'static>)AgentSessionExtrecord methods (get_record,update_record, etc.) takeAtUri<S>/RecordUri<S, R>with generic S- Moderation types (
ModerationPrefs,LabelerDefs,Labeledtrait, etc.) parameterised on S
Removed#
jacquard-axumtemporarily removed from workspace (extractor needs redesign for BOS type params)
Changed#
Codegen (jacquard-lexicon)
- Generated
XrpcRespimpls emitOutput<S: BosStr>andErr(plain type, not GAT) - Generated
XrpcEndpointimpls emitRequest<S: BosStr>
[0.11.0] - 2026-03-21#
Breaking changes#
Code generation pipeline overhaul (jacquard-lexicon, jacquard-lexgen)
- Jacquard's codegen output already was nice to use. now it's going to be nice to read.
- New code generation tracks the types used, makes an import block for the file, and then organizes the file with stuff you care about at the top and internal stuff, like the builders, at the bottom.
- Import resolution pass now conditionally generates short paths when types are unambiguous within a module, falling back to fully-qualified paths when collisions exist
- Improved default value handling in generated code, reducing unnecessary boilerplate
Added#
Hand-written XRPC bootstrap types (jacquard-common)
- Added minimal XRPC endpoint types for
com.atproto.repo.listRecords,com.atproto.repo.getRecord,com.atproto.identity.resolveHandle, andcom.atproto.identity.resolveDid - These types break circular dependencies between
jacquard-lexgen/jacquard-identityandjacquard-api, allowing the codegen tooling and identity resolver to function without depending on the generated API crate
Changed#
Regenerated API crate (jacquard-api)
- All generated code regenerated with the new codegen pipeline
- Shorter import paths where unambiguous, cleaner builder output, better formatting throughout
[0.10.1] - 2026-03-20#
Fixed#
CID deserialization (jacquard-common)
- Fixed
CidLinkdeserialization from CBOR tag-42 bytes through internally-tagged enums (reported by @natalie.sh, fixed by adorable robot) serde_ipld_dagcborbuffers tag-42 CIDs as a newtype struct wrapping raw bytes when deserializing throughContent; the visitor now handlesvisit_bytes,visit_byte_buf, andvisit_newtype_structto cover this path
Lexicon code generation (jacquard-lexicon, jacquard-api)
- Fixed
BlobRefgeneration producing incorrect code in certain lexicon schemas
Identity resolution (jacquard-identity)
- Error message when handle resolution exhausts all resolution methods no longer misleading
[0.10.0] - 2026-03-20#
Breaking changes#
URL type migration (jacquard-common, jacquard, jacquard-oauth, jacquard-identity, jacquard-api)
- Migrated from
urlcrate tofluent_urifor validated URL/URI types - All
Urltypes are nowUrifromfluent_uri - Affects any code that constructs, passes, or pattern-matches on endpoint URLs
Re-exported crate paths (jacquard-api, jacquard-common)
- Re-exported crates (including non-proc-macro dependencies of the generated API crate) are now centralized into a distinct module
- Import paths for re-exported types have changed as a result
Added#
no_std groundwork (jacquard-common, jacquard-api)
- Initial steps toward
no_stdsupport for core types jacquard-apigains feature gating forstd/no_stdusage
Datetime improvements (jacquard-common)
- PR from @blyoom.dev exposing timestamps directly on
Datetimetype - Naming aligned with
chronoconventions
Handle normalization (jacquard-common)
- Handles are now lowercase-normalized on construction
Embedded PDS primitives (jacquard-repo)
- Initial lazy disk-spilling collection types for embedded PDS use cases
- Repo firehose types now use generated API types instead of hand-written equivalents
Lexicon codegen improvements (jacquard-lexicon, jacquard-api)
knownValuesgeneration now aligned with AT Protocol spec and triggers more frequently- Improved feature dependency tracking for API crate features
Additional signing algorithms (jacquard-oauth)
- Keyset signing now supports ES384 (P-384), ES256K (secp256k1), and EdDSA (Ed25519) in addition to ES256
Keyset::create_jwtnow accepts&[Signing](fromjose_jwa) instead of string-based algorithm names
Documentation (jacquard-oauth, jacquard-identity)
- Doc comments across all public items in both crates (thanks Claude, but I played editor pretty heavily)
Fixed#
Identity resolution (jacquard-identity)
- PR from @alephcubed.com fixing
DidDocument::handles()always failing when parsed fromMiniDoc
Error handling (jacquard-common, jacquard, jacquard-oauth)
- Big error quality-of-life pass with richer, more actionable diagnostics
- More resilient error parsing for auth errors
- Better lexicon parsing error messages
WASM (jacquard-common)
- Fixed WASM CI smoke test compilation
Changed#
Lexicons (jacquard-api)
- Large batch of lexicon schema updates with manual cleanup
[0.9.6] - 2025-12-19#
Changed#
Logging (jacquard, jacquard-axum)
- PR from @nekomimi.pet cleaning up more debug logs, and adding tracing feature gate to jacquard-axum
Fixed#
Repo commit signatures (jacquard-repo)
- commit signatures generated by
jacquard-reposhould now be consistent with other implementations - previously, they included an empty
sigbytes field in the signed struct, which has a different CBOR serialization from the canonical relay implementation expectations.
[0.9.5] - 2025-12-19#
Fixed#
docs.rs configuration
- Fixed typo in
jacquard-commondocs.rs features (crypto-ed22519→crypto-ed25519) that was causing documentation builds to fail - Moved
loopbackfeature documentation tojacquard-oauthwhere the feature is defined
OAuth flow (jacquard-oauth)
- Minor OAuth flow compatibility improvements
Serialization (jacquard-common, jacquard-identity)
- Fixed CID deserialization edge cases in
DataandRawDatatypes - Fixed DID document serialization when optional fields are absent
Lexicon code generation (jacquard-lexicon, jacquard-api)
- Fixed nullable field handling in generated code
- Fixed lifetime handling in codegen of binary xrpc outputs
- Fixed lifetime handling in unions
- Fixed incorrectly unescaped rust keywords in module paths
Observability (jacquard)
- Fixed tracing span issues associated with some build failures
Added#
mini-moka-wasm (mini-moka-wasm, jacquard-identity)
- Publishing vendored version of mini-moka with wasm browser compat fix to make usage easier
Service authentication (jacquard-axum)
- Optional service auth extractor option
Data handling (jacquard-common)
- Serde bytes helpers for JSON fields
- Made PLC source fields public for library consumers
Lexicons (jacquard-api)
- Updated to latest AT Protocol lexicon schemas
- API regeneration with builder fixes
Changed#
Logging (jacquard)
- Improved client error logging with better context
[0.9.3] - 2025-11-17 (jacquard)#
Fixed#
- 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
[0.9.2] - 2025-11-17#
Added#
WASM compatibility improvements (jacquard-common, jacquard-identity)
- Vendored mini-moka implementation with WASM support for caching
- regex-lite usage on WASM targets for reduced binary size
- Schema resolver now works on WASM targets
Data query improvements (jacquard-common)
- Mutable path query access and setting for
Datavalues
Changed#
URL handling (jacquard-common)
- Rework of some internal URL handling for better compatibility
- Includes a minor change to the return type of the endpoint() method of XrpcClient and equivalents.
OAuth improvements (jacquard-oauth)
- Fixed OAuth scope handling in loopback flow
- OAuth metadata resolution improvements
- Various OAuth flow enhancements and bug fixes
Identity resolution (jacquard-identity)
- Fixed non-DNS lexicon and did:web resolution using Cloudflare DoH
- Reduced noisy logging in identity resolution
Lexicons (jacquard-api)
- Updated to latest AT Protocol lexicons
Fixed#
Data deserialization (jacquard-common)
- Fixed CID deserialization edge cases for better spec compliance
- More permissive JSON shape handling for better interoperability with varied implementations
[0.9.1] - 2025-11-04 (jacquard-identity, jacquard-lexicon)#
Fixed#
- slingshot resolver no longer spuriously warns when cross-validating handles
[0.9.0] - 2025-11-03#
Added#
Runtime schema validation (jacquard-lexicon)
SchemaValidatorfor validatingDatavalues against lexicon schemas- CID-based validation caching for efficient repeated validation
ValidationResultwith structural and constraint error separation- Comprehensive error types:
StructuralError(type mismatches, missing fields, union errors) andConstraintError(length, grapheme, numeric bounds) ValidationPathfor precise error location reporting- Ref cycle detection with configurable max depth
- Support for validating partial/malformed data without full deserialization
Value query DSL (jacquard-common)
- Pattern-based querying of nested
Datastructures data.query(pattern)with expressive syntax:field.nested- exact path navigation[..]- wildcard over collections (array elements or object values)field..nested- scoped recursion (find nested within field, expect one)...field- global recursion (find all occurrences anywhere)
QueryResultenum withSingle,Multiple, andNonevariantsQueryMatchwith path tracking for multiple results- Iterator support via
.values(),.first(),.single(),.multiple()
Data value enhancements (jacquard-common)
get_at_path()for simple path-based field access onDataandRawData- Path syntax:
embed.images[0].altfor navigating nested structures type_discriminator()helper methods for AT Protocol union discrimination- Returns
$typefield value for objects with type discriminators - Added on
Data,Object, andRawDatatypes - Collection helper methods:
get(),contains_key(),len(),is_empty(),iter(),keys(),values() - Index operator support:
obj["key"]andarr[0]
Lexicon resolution (jacquard-identity)
LexiconResolverfor fetching lexicon schemas from AT Protocol services- Resolves lexicons from PDS instances and lexicon hosts
resolve_lexicon()fetches and parses lexicon schemasresolve_lexicon_raw()fetches raw schema JSON- New example:
resolve_lexicon.rs
Identity resolver caching (jacquard-identity)
- Optional
cachefeature with configurable in-memory caching JacquardResolver::with_cache()constructor for cached resolver- Separate TTLs for handle→DID, DID→doc, and lexicon resolution
XRPC client improvements (jacquard-common, jacquard, jacquard-oauth)
set_options()andset_endpoint()methods onXrpcClienttrait- Default no-op implementations for stateless clients
- Enables runtime reconfiguration of stateful clients
- Better support for custom endpoint and option overrides
Lexicon schema generation from Rust types (jacquard-derive, jacquard-lexicon)
- New
#[derive(LexiconSchema)]macro for generating lexicon schemas from Rust structs - New
#[lexicon_union]attribute macro for lexicon union types (tagged enums) - Automatic schema generation for custom lexicons without writing JSON manually
- Field-level attributes:
reffor explicit type references,unionfor union fields - Fragment support for multi-def lexicons via
fragment = "..."attribute - Generates
LexiconDocat compile time for runtime validation - Enables type-safe custom lexicon development
Lexicon codegen improvements (jacquard-lexicon, jacquard-api)
- Vendored in an implementation of the typed builder pattern from
bonto substantially improve compile times - Feature-gated heavy code generation features so
jacquard-apiand other consumers of the validation capabilities don't pay thesyntax as badly. - LexiconSchema trait generated implementations for runtime validation
Session store improvements (jacquard)
- Improved trait bounds for
SessionStoreimplementations - Better ergonomics for credential session types
- Memory-based credential session helpers
New crate: jacquard-lexgen
- Lexicon code generation tooling extracted from
jacquard-lexicon - Separates binary/CLI tools from library code
- Contains lexicon fetching and code generation binaries
jacquard-lexiconremains as pure library for lexicon parsing, code generation, and validation
Examples
app_password_create_post.rs: App password authentication example
Changed#
Feature gating (jacquard-identity)
- Better conditional compilation for platform-specific features
- Improved WASM target support
Dependency updates
- Updated to latest lexicons from atproto/bluesky
- Added workspace dependencies: sha2, multihash, dashmap, cid
- Various minor dependency version updates
Fixed#
File auth store (jacquard)
- Fixed serialization/deserialization bugs in
FileAuthStoreimplementation
Packaging (jacquard-lexgen)
- Added Nix flake apps for lexicon tools
[0.8.0] - 2025-10-23#
Breaking Changes#
Error type refactor (jacquard-common, jacquard-identity, jacquard-oauth, jacquard)
- Better error messages with contextual information and help text
- Breaking: Error variant names and structures changed across all crates
Added#
New crate: jacquard-repo
- AT Protocol repository primitives for working with atproto data structures
- MST (Merkle Search Tree): Immutable, deterministic tree operations with proper fanout
- Optimized block allocation (4.5% oversupply, validated against retr0id's test suite)
- Diff operations with protocol limit enforcement
- Cursor-based traversal
- Commits:
- Proof generation and validation for Sync v1 and v1.1 Relay protocol
- CAR I/O:
- Proof CAR validation with MST path verification
- Storage: Pluggable block storage abstraction
MemoryBlockStore: In-memory storage for testingFileBlockStore: Persistent file-based storageLayeredBlockStore: Layered read-through cache (memory over file, etc.)
Changed#
- Dependency updates (upgraded various crypto and serialization dependencies)
- Documentation improvements throughout
- 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).
[0.7.0] - 2025-10-19#
Added#
Bluesky-style rich text utilities (jacquard)
- Rich text parsing with automatic facet detection (mentions, links, hashtags)
- Compatible with Bluesky, with the addition of support for markdown-style links (
[display](url)syntax) - Embed candidate detection from URLs and at-URIs
- Record embeds (posts, lists, starter packs, feeds)
- External embeds with optional OpenGraph metadata fetching
- Configurable embed domains for at-URI extraction (default: bsky.app, deer.social, blacksky.community, catsky.social)
- Overlap detection and validation for facet byte ranges
Moderation/labeling client utilities (jacquard)
- Trait-based content moderation with
LabeledandModerateabletraits - Generic moderation decision making via
moderate()andmoderate_all() - User preference handling (
ModerationPrefs) with global and per-labeler overrides ModerationIterExttrait for filtering/mapping moderation over iteratorsLabeledimplementations for Bluesky types (PostView, ProfileView, ListView, Generator, Notification, etc.)Labeledimplementations for community lexicons (net.anisota, social.grain)fetch_labels()andfetch_labeled_record()helpers for retrieving labels via XRPCfetch_labeler_defs()andfetch_labeler_defs_direct()for fetching labeler definitions
Subscription control (jacquard-common)
SubscriptionControlMessagetrait for dynamic subscription configurationSubscriptionControllerfor sending control messages to active WebSocket subscriptions- Enables runtime reconfiguration of subscriptions (e.g., Jetstream filtering)
Lexicons (jacquard-api)
- teal.fm alpha lexicons for music sharing (fm.teal.alpha.*)
- Actor profiles with music service status
- Feed generation from play history
- Statistics endpoints (top artists, top releases, user stats)
Examples
- Updated
create_post.rsto demonstrate richtext parsing with automatic facet detection - New
moderated_timeline.rsto demonstrate fetching timeline with labelers enabled and applying moderation decisions
Fixed#
Data deserialization (jacquard-common)
- Fixed
Option<Vec<T>>deserialization fromDatavalues - Implemented explicit
deserialize_optionforDataandRawDatadeserializers - Properly handles null vs present array values when deserializing into optional fields
[0.6.0] - 2025-10-18#
Added#
HTTP streaming support (jacquard-common, jacquard)
HttpClientExttrait for streaming HTTP requests/responsessend_http_streaming()for streaming response bodiessend_http_bidirectional()for streaming both request and responseStreamingResponsewrapper type with parts +ByteStreamXrpcResponseStream<R>for typed XRPC streaming responsesByteStream/ByteSinkplatform-agnostic stream wrappers (uses n0-future)StreamErrorconcrete error type with kind enum (Transport, Closed, Protocol)- Native support via reqwest's
bytes_stream()andBody::wrap_stream() - WASM compatibility via n0-future (no Send bounds required)
WebSocket subscription support (jacquard-common)
- Full XRPC WebSocket subscription infrastructure
SubscriptionResptrait for defining subscription message/error typesXrpcSubscriptiontrait for subscription parametersSubscriptionStream<S>typed wrapper with automatic message decodingSubscriptionClientstateful trait +TungsteniteSubscriptionClientimplementationSubscriptionExtfor stateless subscription calls- Support for both JSON and DAG-CBOR message encodings
- Custom path support via
CUSTOM_PATHconstant for non-XRPC endpoints - WebSocket integration into
Agentstruct (agents can now subscribe) into_stream(),into_raw_data_stream(),into_data_stream()methods for different deserialization modes
Framed DAG-CBOR message decoding (jacquard-common, jacquard-api, jacquard-lexicon)
- Two-stage deserialization for AT Protocol event streams (header + body)
EventHeaderstruct andparse_event_header()functiondecode_framed()methods generated for all DAG-CBOR subscription message enumsdecode_message()override inSubscriptionResptrait for custom decodingUnknownEventTypevariant inDecodeErrorfor unknown discriminators- Fixes "TrailingData" errors when consuming subscribeRepos and subscribeLabels
Jetstream support (jacquard-common)
- Full typed support for Jetstream JSON firehose
JetstreamMessageenum withCommit,Identity,AccountvariantsJetstreamCommit,JetstreamIdentity,JetstreamAccountdetail structsCommitOperationenum for create/update/delete operationsJetstreamParamswith filtering options (collections, DIDs, cursor, compression)- Uses proper AT Protocol types (
Did,Handle,Datetime,Data)
Zstd compression (jacquard-common)
- Optional
zstdfeature for Jetstream message decompression - Automatic detection and decompression of zstd-compressed binary frames
- Includes official Bluesky Jetstream zstd dictionary
- Transparent fallback to uncompressed when zstd unavailable
- Works across all JSON stream methods (
into_stream(),into_raw_data_stream(),into_data_stream())
Typed AT URI wrapper (jacquard-common, jacquard-api, jacquard-lexicon)
AtUri<'a>newtype wrapper forat://URIs with proper validation- Generated
fetch_uri()method on all record types for fetching by AT URI AtUri::from_parts()constructor for building URIs from components- Proper Display and FromStr implementations
Memory-based credential session helpers (jacquard) (ty @vielle.dev)
Axum improvements (jacquard-axum)
XrpcErrornow implementsIntoResponsefor better error handling- Proper typed error responses without manual conversion
- Better integration with Axum's response system
Examples
subscribe_repos.rs: Subscribe to PDS firehose with typed DAG-CBOR messagessubscribe_jetstream.rs: Subscribe to Jetstream with typed JSON messages and optional compressionstream_get_blob.rs: Download blobs using HTTP streamingapp_password_example.rs: App password authentication example (ty @vielle.dev)
CID deserialization improvements (jacquard-common)
- Fixed
Cidtype to properly deserialize CBOR tag 42 viaIpldCid::deserialize - Separate handling for JSON (string) vs CBOR (tag 42) formats
CidLinkcorrectly delegates toCidfor both formats
Changed#
Default features (jacquard-common)
- Added
zstdto default features for better Jetstream experience - Jetstream compression enabled by default when using the full feature set
Generated code (jacquard-lexicon, jacquard-api)
- All DAG-CBOR subscriptions (subscribeRepos, subscribeLabels) now use framed decoding
- Generated
decode_framed()implementations match on event type discriminator - Override
decode_message()in trait impls to use framed decoding - All record types now have
fetch_uri()andfetch_record()methods generated
Dependencies (jacquard-axum) (ty @thoth.ptnote.dev)
- Disabled default features for
jacquarddependency to reduce bloat
Fixed#
Blob upload (jacquard) (ty @vielle.dev for reporting this one)
- Fixed
upload_blob()authentication issues - Properly authenticates while allowing custom Content-Type headers
XRPC client (jacquard-common, jacquard-oauth, jacquard)
- Added
send_with_options()method for per-request option overrides - Stateful clients can now override options while preserving internal auth
jacquard-api [0.5.5], jacquard-lexicon [0.5.4] - 2025-10-16#
Fixed#
- events.smokesignal.invokeWebhook lexicon now generates valid code
- lexicon code generation now uses
Datafor blank objects, rather than naming and then failing to generate a struct
[0.5.4] - 2025-10-16#
Added#
Initial streaming client support (jacquard-common)
- First primitives for streamed requests and responses
send_with_options() method on XrpcClient (jacquard-common, jacquard-oauth, jacquard)
- allows setting custom options per request in stateful client
- updated oauth and credential session clients to use it
- implementations should generally override provided auth with own internal auth
Prelude providing common traits into scope
Fixed#
AgentSessionExt::upload_blob() failed to authenticate (jacquard)
- new
XrpcClient::send_with_options()method now allows properly overriding the content-type header while still handling auth internally
[0.5.3] - 2025-10-15#
Added#
Experimental WASM Support (jacquard-common, jacquard-api, jacquard-identity, jacquard-oauth)
- Core crates now compile for
wasm32-unknown-unknowntarget - Traits use
trait-variantto conditionally excludeSendbounds on WASM - Platform-specific trait method implementations for methods with
Self: Syncbounds - DNS-based handle resolution remains gated behind
dnsfeature (unavailable on WASM) - HTTPS well-known and PDS resolution work on all platforms
Fixed#
OAuth client (jacquard-oauth)
- Fixed tokio runtime detection for non-WASM targets
- Conditional compilation for tokio-specific features
[0.5.2] - 2025-10-14#
Added#
Value type deserialization (jacquard-common)
from_json_value(): Deserialize typed data directly fromserde_json::Valuewithout borrowingfrom_data_owned(),from_raw_data_owned(): Owned deserialization helpersData::from_json_owned(): Parse JSON into ownedData<'static>IntoStaticimplementation forRawDataenabling owned conversions- Re-exported value types from crate root for easier imports
Deserializertrait implementations forData<'static>andRawData<'static>- Owned deserializer helpers:
OwnedArrayDeserializer,OwnedObjectDeserializer,OwnedBlobDeserializer
Service Auth (jacquard-axum, jacquard-common)
- Full service authentication implementation for inter-service JWT verification
ExtractServiceAuthAxum extractor for validating service auth tokens- Axum service auth middleware
- JWT parsing and signature verification (ES256, ES256K)
- Service auth claims validation (issuer, audience, expiration, method binding)
- DID document resolution for signing key verification
XrpcRequest derive macro (jacquard-derive)
#[derive(XrpcRequest)]for custom XRPC endpoints- Automatically generates response marker struct and trait implementations
- Supports both client-side (
XrpcRequest) and server-side (XrpcEndpoint) withserverflag - Simplifies defining custom XRPC endpoints outside of generated API
Builder integration (jacquard-derive)
#[lexicon]macro now detectsbon::Builderderive- Automatically adds
#[builder(default)]toextra_datafield when Builder is present - Makes
extra_dataoptional in generated builders
Fixed#
String deserialization (jacquard-common)
- All string types (Did, Handle, Nsid, etc.) now properly handle URL-encoded values
serde_html_formcorrectly decodes percent-encoded characters during deserialization- Fixes issues with DIDs and other identifiers containing colons in query parameters
Axum extractor (jacquard-axum)
- Removed unnecessary URL-decoding workaround (now handled by improved string deserialization)
- Added comprehensive tests for URL-encoded query parameters
- Cleaner implementation with proper delegation to serde
Changed#
Dependencies
- Moved
clapto dev-dependencies injacquard(only used in examples) - Moved
axum-macrosandtracing-subscriberto dev-dependencies injacquard-axum(only used in examples) - Removed unused dependencies:
urlencoding(jacquard, jacquard-axum),uuid(jacquard-oauth),serde_with(jacquard-common) - Removed
fancyfeature fromjacquard(design smell for library crates) - Moved various proc-macro crate dependencies to dev-dependencies in
jacquard-derive
Development tooling
- Improved justfile with dynamic example discovery
just examplesnow auto-discovers all examplesjust example <name>auto-detects package without manual configuration- Better error messages when examples not found
Documentation (jacquard, jacquard-common)
- Improved lifetime pattern explanations
- Better documentation of zero-copy deserialization approach
- Links to docs.rs for generated documentation
[0.5.1] - 2025-10-13#
Fixed#
Trait bounds (jacquard-common)
- Removed lifetime parameter from
XrpcRequesttrait, simplifying trait bounds - Lifetime now only appears on
XrpcEndpoint::Request<'de>associated type - Fixes issues with using XRPC types in async contexts like Axum extractors
Changed#
- Updated all workspace crates to 0.5.1 for consistency
jacquard-axumremains at 0.5.1 (unchanged)
jacquard-axum [0.5.1] - 2025-10-13#
Fixed#
- Axum extractor now sets the correct Content-Type header during error path.
[0.5.0] - 2025-10-13#
Added#
Agent convenience methods (jacquard)
- New
AgentSessionExttrait automatically implemented forAgentSession + IdentityResolver - Basic CRUD:
create_record(),get_record(),put_record(),delete_record() - Update patterns:
update_record()(fetch-modify-put),update_vec(),update_vec_item() - Blob operations:
upload_blob() - All methods auto-fill repo from session or URI parameter as relevant, and collection from type's
Collection::NSID
VecUpdate trait (jacquard)
VecUpdatetrait for fetch-modify-put patterns on array-based endpointsPreferencesUpdateimplementation for updating Bluesky user preferences- Enables simpler updates to preferences and other 'array of union' types
Typed record retrieval (jacquard-api, jacquard-common, jacquard-lexicon)
- Each collection generates
{Type}Recordmarker struct implementingXrpcResp Collection::Recordassociated type points to the markerget_record::<R>()returnsResponse<R::Record>with zero-copy.parse()- Response transmutation enables type-safe record operations
Examples
create_post.rs: Creating posts with Agent convenience methodsupdate_profile.rs: Updating profile with fetch-modify-putpost_with_image.rs: Uploading images and creating posts with embedsupdate_preferences.rs: Using VecUpdate for preferencescreate_whitewind_post.rs,read_whitewind_post.rs: Third-party lexiconsread_tangled_repo.rs: Reading git repo metadata from tangled.orgresolve_did.rs: Identity resolution examplespublic_atproto_feed.rs: Unauthenticated feed accessaxum_server.rs: Server-side XRPC handler
Documentation (jacquard)
- A whole host of examples added, as well as a lengthy explainer of the trait patterns.
[0.4.1] - 2025-10-13#
Added#
Collection trait improvements (jacquard-api)
- Generated
{Type}Recordmarker structs for all record types - Each implements
XrpcRespwithOutput<'de> = {Type}<'de>andErr<'de> = RecordError<'de> - Enables typed
get_recordreturningResponse<R::Record>
Changed#
- Minor improvements to derive macros (
jacquard-derive) - Identity resolution refinements (
jacquard-identity) - OAuth client improvements (
jacquard-oauth)
[0.4.0] - 2025-10-11#
Breaking Changes#
Zero-copy deserialization (jacquard-common, jacquard-api)
XrpcRequestnow takes a'delifetime parameter and requiresDeserialize<'de>- For raw data,
Response::parse_data()gives validated loosely-typed atproto data, whileResponse::parse_raw()gives the raw values, with minimal validation.
XRPC module moved (jacquard-common)
xrpc.rsis now top-level instead of undertypes- Import from
jacquard_common::xrpc::*notjacquard_common::types::xrpc::*
Response API changes (jacquard-common)
XrpcRequest::OutputandXrpcRequest::Errare associated types with lifetimes- Split response and request traits:
XrpcRequest<'de>for client,XrpcEndpointfor server - Added
XrpcRespmarker trait
Various traits (jacquard, jacquard-common, jacquard-lexicon, jacquard-oauth)
- Removed #[async_trait] attribute macro usage in favour of
impl Futurereturn types with manual bounds. - Boxing imposed by asyc_trait negatively affected borrowing modes in async methods.
- Currently no semver guarantees on API trait bounds, if they need to tighten, they will.
Added#
New crate: jacquard-axum
- Server-side XRPC handlers for Axum
ExtractXrpc<R>deserializes incoming requests (query params for Query, body for Procedure)- Automatic error responses
Lexicon codegen fixes (jacquard-lexicon)
- Union variant collision detection: when multiple namespaces have similar type names, foreign ones get prefixed (e.g.,
ImagesvsBskyImages) - Token types generate unit structs with
Displayinstead of being skipped - Namespace dependency tracking during union generation
generate_cargo_features()outputs Cargo.toml features with correct depssanitize_name()ensures valid Rust identifiers
Lexicons (jacquard-api)
Added 646 lexicon schemas. Highlights:
Core ATProto:
com.atproto.*com.bad-example.*for identity resolution
Bluesky:
app.bsky.*bluesky appchat.bsky.*chat clienttools.ozone.*moderation
Third-party:
sh.tangled.*- git forgesh.weaver.*- orual's WIP markdown blog platformpub.leaflet.*- longform publishingnet.anisota.*- gamified and calming take on blueskynetwork.slices.*- serverless atproto hostingtools.smokesignal.*- automationcom.whtwnd.*- markdown bloggingplace.stream.*- livestreamingblue.2048.*- 2048 gamecommunity.lexicon.*- community extensions (bookmarks, calendar, location, payments)my.skylights.*- media trackingsocial.psky.*- social extensionsblue.linkat.*- link boards
Plus 30+ more experimental/community namespaces.
Value types (jacquard-common)
RawDatatoDataconversion with type inferencefrom_data,from_raw_data,to_data, andto_raw_datato serialize to and deserialize from the loosely typed value data formats. Particularly useful for second-stage deserialization of type "unknown" fields in lexicons, such asPostView.record.
Changed#
generate_union()takes current NSID for dependency tracking- Generated code uses
sanitize_name()for identifiers more consistently - Added derive macro for IntoStatic trait implementation
Fixed#
- Methods to extract the output from an XRPC response now behave well with respect to lifetimes and borrowing.
- Now possible to use jacquard types in places like axum extractors due to lifetime improvements
- Union variants don't collide when multiple namespaces define similar types and another namespace includes them