Expand description
The atproto identity + PDS record layer.
FeatherReader’s defining bet is that a user’s feed
subscriptions, folders, saved items, and batched read-state live as records
in the user’s own atproto PDS under the open community.lexicon.rss.*
community lexicon — not in the app’s database. This module is the client that
reads and writes those records.
It has three layers:
- Identity resolution (
resolve_handle,resolve_did_to_pds) — turn a handle (alice.example.com) into a DID (did:plc:…), then resolve the DID document to the PDS service endpoint. Handles resolve via the account’s PDScom.atproto.identity.resolveHandle(or the well-known/.well-known/atproto-did); DIDs resolve via the PLC directory (did:plc:*) or thedid:webwell-known document. - A lightweight
PdsClient— holds the resolved DID, the PDS base URL, and anAuthtoken, and exposes typed calls overcom.atproto.repo.*:list_records,create_record,put_record,delete_record, andapply_writes(the batch call the read-state flusher uses to coalesce many per-feed cursor writes into one round-trip). - Typed convenience wrappers wired to the
crate::lexiconrecord types (list/createSubscription/Folder/Saved, putReadState, batch-flush manyReadStatecursors).
§Auth — the OAuth sidecar is the live path
Auth is a trait/enum boundary so the mechanism can vary without touching call sites. There are two paths:
- The live path — the atproto OAuth confidential client, via
SidecarClient. atproto OAuth (DPoP, PAR, token refresh) is fiddly and is not hand-rolled in Rust: it runs in a small, supported@atproto/oauth-client-nodesidecar. The Rust server never holds PDS tokens — it POSTs everycom.atproto.repo.*op to the sidecar’s/internal/repoendpoint (gated by a sharedX-Internal-Secret), and the sidecar restores the DID’s OAuth session (transparent DPoP + token refresh) and runs the matching XRPC call.SidecarClientis that client; the typed convenience wrappers (list/create/put/delete subscriptions, batch-flush read-state) live on it and map 1:1 to the oldPdsClientsurface. - The interim path —
Auth::Session(app password). A session obtained fromcom.atproto.server.createSession. Kept behind theAuthseam as a fallback for local runs without the sidecar, but it is no longer the live path:PdsClientandlogin_with_app_passwordremain for tests and dev, whileSidecarClientis what the web layer routes through.
All network I/O is reqwest (rustls, no OpenSSL); every fallible path returns
anyhow::Result or the typed AtProtoError — nothing panics.
Structs§
- DidDocument
- The subset of a DID document FeatherReader needs: its services, so it can
find the
#atproto_pdsendpoint. - DidService
- One service entry in a
DidDocument. - List
Records Response - The
com.atproto.repo.listRecordsresponse envelope. - Oauth
Placeholder - Placeholder for the OAuth variant of
Auth. - PdsClient
- A lightweight client for one user’s PDS repo.
- Record
Entry - A single record as returned in a
listRecords/getRecordresponse. - Revoke
Result - The sidecar’s
/internal/revokeresponse body:{ ok:true, did, revoked, hadSession }. - Session
Auth - A session obtained from
com.atproto.server.createSession(interim app-password auth). Holds the DID + tokens + handle the server returned. - Sidecar
Client - A client for the atproto OAuth sidecar’s internal API.
- Sidecar
Session - The
{did, handle}a session-id resolves to (the sidecar’s/internal/session/:idbody). - Write
Result - The
com.atproto.repo.createRecord/putRecordresponse (a strong ref to the written record).
Enums§
- AtProto
Error - Errors from the atproto identity + PDS layer.
- Auth
- The auth material a
PdsClientcarries. - Repo
Action - The action verbs the sidecar’s
/internal/repoendpoint dispatches on. - WriteOp
- One operation in a
PdsClient::apply_writesbatch.
Constants§
- DEFAULT_
PLC_ DIRECTORY - The public PLC directory, used to resolve
did:plc:*DIDs to their DID document (and thus their PDS service endpoint). - DEFAULT_
RESOLVER_ HOST - The default appview/entryway used only as a bootstrap host for handle
resolution when the caller has no PDS hint yet. Handle resolution ultimately
works against any atproto host that implements
com.atproto.identity.resolveHandle;bsky.socialis a reliable default.
Traits§
- Token
Source - A source of atproto access tokens.
Functions§
- login_
with_ app_ password - Create a session with an app password via
com.atproto.server.createSession. - resolve_
did_ to_ pds - Resolve a DID to its PDS service endpoint by fetching + parsing its DID document.
- resolve_
handle - Resolve an atproto handle to its DID.