atprotocrates

Cat.

Catalogue

Twenty crates, shelved by layer. Plate marks run A at the data foundation to G at the tooling edge; within a band the order is the order you would reach for them.

§ 00

Reading the status column

Published version and workspace version are not the same number, and five crates have no published version at all. Every entry states both.

Status marks used in this catalogue
MarkMeansHow you depend on it
Published On crates.io at 0.14.5. The git workspace is ahead at 0.15.0-rc.5, unpublished. name = "0.14.5"
Git only Never published to crates.io. name = { git = "https://tangled.org/ngerakines.me/atproto-crates" }
Experimental The crate says so itself, in its own README. Interfaces and on-disk formats will move. Pin a revision.

A

Data foundation

Content addressing and the byte formats everything else is expressed in.

A.01

atproto-dasl

The DASL implementation the rest of the workspace is built on. Twelve public modules; nine of them carry the work: cid (three CID types — general, strictly-validated DaslCid, and unvalidated RawCid), drisl (deterministic DAG-CBOR with sorted keys, shortest-form integers, NaN and infinity rejected), car (streaming CAR v1 reader and writer with size and depth limits), storage (block-store trait with memory and disk backends, plus spillover), bdasl (BLAKE3/BAO for large files), masl, rasl, tiles and varint. The other three are errors, value and atproto_json.

B

Identity, records & schema

Who signed it, what it says, and which schema it claims to satisfy.

B.01

atproto-identity

Multi-method DID resolution for did:plc, did:web and did:key; handle resolution over both DNS TXT and the HTTPS well-known endpoint, with conflict detection when the two disagree; P-256, P-384 and K-256 key generation, signing and validation, with SignaturePolicy separating AT Protocol’s low-S rule from the any-S that JWS requires; LRU-cached DID document storage behind a pluggable trait. It also carries the PLC directory client, including an audit-log reader and fork resolution, both reachable from atpdid plc.

B.02

atproto-record

The small, unglamorous pieces every record touches: parsing and validating at:// URIs, generating microsecond-precision TIDs, RFC 3339 datetimes with the millisecond precision AT Protocol expects, base64 handling for binary fields, and typed records with lexicon $type validation. CID generation here goes through DAG-CBOR and SHA-256.

B.03

atproto-attestation

Creates and verifies record attestations using the CID-first workflow: prepare the record with $sig metadata, serialise to DAG-CBOR, hash to a CID, sign the CID bytes, then either embed the signature (inline) or emit a separate proof record holding a strongRef (remote). Signatures are normalised to low-S form so they cannot be malleated. The repository field inside $sig binds an attestation to one repo, which is what stops a record being lifted into somebody else’s.

B.04

atproto-lexicon

Implements the full resolution chain: NSID to a _lexicon.-prefixed DNS name, TXT lookup for the authoritative DID, DID document resolution, PDS endpoint extraction, then the XRPC fetch of the schema itself. Resolves referenced lexicons recursively with a depth limit, handles fragment-only references using the enclosing lexicon as context, and validates NSIDs on the way in.

C

Repository

The durable per-account store, the permissioned variant of it, and the client that reaches one.

C.01

atproto-repo

MST insert, get, delete, list and diff, with SHA-256 key-height calculation; AT Protocol commit structures with serialisation and validation; record path handling for collection/rkey; and CAR v1 reading and writing built on atproto-dasl. Storage is pluggable: in-memory with LRU eviction, disk-backed with a memory cache, and a spillable buffer for streaming large archives. Verification depth is configurable, so you can pay for full inductive verification or skip it.

C.02

atproto-space

Primitives for the 0016 Permissioned Data draft: the SetHash trait with LtHash as the production lattice hash, signed commits that sign only the per-commit context and bind the set-hash digest through an HKDF-keyed HMAC, so a leaked commit stays deniable, a SpaceRepo orchestrator for per-(user, space) record CRUD, and the two-step delegation-token to space-credential JWT exchange.

C.03

atproto-space-client

atproto-space is deliberately network-free, which is the right shape for a server and leaves a consumer with every type needed to read a space and no way to obtain one. This is that missing half, kept a sibling rather than a feature so the no-IO promise stays unconditional. It walks the three-call credential chain — getDelegationToken at the member’s own PDS, getSpaceCredential at the authority, registerNotify at the authority — and carries SpaceHosts, which exists because sending call two to the repo host instead of the authority fails in a way that never mentions hosts. Modules split by who may act: records (writes on an OAuth session, reads on either), sync (the repo host’s side — writer set, signed commit, oplog, CAR, blobs), and spaces for the com.atproto.simplespace management surface.

D

Authorisation

OAuth 2.0 with the AT Protocol extensions, plus framework bindings.

D.01

atproto-oauth

The OAuth crate, and since the removal of atproto-oauth-aip the only one you need for a client. Twelve modules. workflow drives the flow end to end — oauth_init pushes the authorization request and returns a request_uri, oauth_complete exchanges the code, oauth_refresh rotates the token. Underneath: JWT minting and verification across ES256, ES384 and ES256K; JWK generation for all three curves; PKCE per RFC 7636; DPoP per RFC 9449; resources for RFC 8414 discovery; and scopes, a typed parser for the AT Protocol scope grammar. Request storage is a trait with an LRU implementation behind the lru feature.

D.02

atproto-oauth-axum

The routes a confidential client has to publish anyway: the authorization callback, the JWKS endpoint, and client metadata. Drop them into an existing Axum router rather than re-deriving the JSON shapes from the specification.

D.03

atproto-oauth-dioxus

Components, hooks and server functions that carry the OAuth flow through a Dioxus fullstack application. The only crate directory that is not a workspace member. It is versioned at 0.15.0-alpha.2 and built on its own.

E

Clients & services

Talking to the network, and being something on it.

E.01

atproto-client

XRPC over reqwest with three authentication modes (DPoP-bound tokens, app-password bearer tokens, and classic sessions), plus typed repository operations under com::atproto::repo (create_record, put_record, and friends), session creation and refresh, and URL construction helpers that get the /xrpc/ prefixing right.

E.02

atproto-xrpcs

The server counterpart. An Authorization Axum extractor validates an inter-service JWT, resolves the issuer’s DID document, and verifies the signature against the key published there — so a handler receives a caller identity that has actually been proven, or None. No binaries of its own; atproto-pds is the worked example now that the hello-world service has been removed.

E.03

atpxrpc

A terminal client for XRPC calls with persistent session management, so you are not re-authenticating on every invocation while poking at an endpoint.

E.04

atproto-pds

A full PDS: the pds server binary and the atproto-pds-admin CLI. It serves com.atproto.repo.*, sync.* (including subscribeRepos and CAR streaming with ?since= diff slices), server.*, identity.*, admin.*, a complete OAuth 2.1 provider, and the simplespace/space permissioned realms. It is the second PDS implementation anywhere to ship Spaces, and the first in Rust. Two storage profiles, SQLite and fjall, chosen at compile time.

F

Event ingest

Three ways to read the network as it changes, in ascending order of how much you are willing to verify.

F.01

atproto-jetstream

Consumes the JSON view of the network: one WebSocket at /xrpc/network.bsky.jetstream.subscribeEvents, framed per proposal 0015, filtered server-side and already decoded — no CBOR, no CAR, no MST. Automatic reconnection, cursor resumption, Zstandard decompression against Bluesky’s published dictionary, and filtering by collection, DID and kind. Delivery goes through an EventSink you implement; shutdown runs through a CancellationToken, so a consumer drains rather than drops. v2 only — the v1 /subscribe endpoint is a different wire and remains served, wire-frozen, by the same hosts.

F.02

atproto-firehose

The workspace had a Jetstream consumer, a TAP consumer, and a subscribeRepos producer inside atproto-pds — so every app view that wanted full-fidelity verified events wrote the consumer itself. This is that consumer. wire holds the frame format, the five-member event union, and a two-stage decode that reads the header before paying for the body; verify proves a commit against the repository that claims to have made it, at a level the caller picks (Off, SignatureOnly, Full — signature, tree, and every tracked op’s inclusion in it); consumer is the WebSocket loop, its reconnect policy, and the cursor contract.

F.03

atproto-tap

Streams from a TAP service, which delivers events already MST-verified and signature-checked. Adds at-least-once delivery through an acknowledgment protocol that survives reconnects, exponential backoff, historical backfill flagged live: false, and an HTTP management API for adding and removing tracked DIDs. Events are Arc-wrapped and small strings are CompactString, because the working set is the whole point.

G

Tooling & utilities

The edges: rich text, and a bridge for AI assistants.

G.01

atproto-extras

Extracts mentions, URLs and hashtags from plain text and emits facets with correct UTF-8 byte offsets. Implementations written against character indices get this wrong. Optionally resolves mention handles to DIDs during the parse.

G.02

atpmcp

A local Model Context Protocol server speaking JSON-RPC 2.0 over stdio, so an assistant can compute a real CID rather than guess at one — and, since it grew past that, resolve identities, fetch records and lexicons, validate XRPC calls against a schema, mint TIDs, parse facets, and move blobs. Twelve tools: create_record_cid, validate_lexicon_schema, resolve_handle_to_did, resolve_identity, parse_facets, get_record, get_lexicon, validate_xrpc, invoke_xrpc, generate_tid, upload_blob and download_blob. Blobs are also readable as resources at atpmcp://public/blob/{did}/{cid}, fetched from the repository’s PDS, verified against the CID, and cached.

§ 99

Removed from the workspace

Two crates were dropped in b8ff044. Both are still resolvable on crates.io at 0.14.5, so a build that depends on them keeps working — it is just building against code that no longer exists upstream and will not be released again.

What went, and what to use instead
CrateWasReplacement
atproto-oauth-aip The workflow layer above atproto-oauth: oauth_init, oauth_complete, session_exchange. atproto-oauth, module workflow. oauth_init and oauth_complete live there now, alongside a new oauth_refresh. There is no session_exchange — see the rewritten guide.
atproto-xrpcs-helloworld A runnable example service demonstrating did:web identity, service documents and JWT auth. No direct replacement. atproto-pds is the worked example of an XRPC service built on atproto-xrpcs, at considerably larger scale.