ANProto over ATProto -- using Bluesky PDSes to store ANProto messages and blobs

Work Order: ANProto Messages on Bluesky PDS#

Scope#

  • Store ANProto-signed messages (and blobs) in a Bluesky PDS using the existing Node OAuth backend. APDS remains frontend-only.
  • Use custom collections com.anproto.message.v1 (messages) and optional com.anproto.blob if we need standalone blob records.

First Steps#

  • Lexicons: com.anproto.message.v1 has anmsg (full ANProto message), optional anblob, anhash (base64 ANProto hash), and blobhash (hash of the attached blob). PDS rkey uses a base64url form of anhash (replace +-, /_, strip =) to satisfy record-key rules. IDs must match the collection names exactly. com.anproto.blob is optional if blobs stay in anblob.
  • OAuth/scopes: Keep Node OAuth flow; request repo read/write + blob upload (atproto for now). Continue storing DID in cookies and tokens server-side.
  • Signing/validation: Frontend APDS signs messages; send backend {anmsg, blob?, blobMime?}. Backend recomputes anhash via ANProto, converts to base64url rkey, and rejects mismatches.
  • Persistence: Upload blobs via com.atproto.repo.uploadBlob; create com.anproto.message.v1 records with rkey = base64url(anhash), storing anmsg, anhash, optional anblob, and optional blobhash.
  • Retrieval/indexing: Add backend endpoints to fetch by rkey/anhash/DID; optional local index (DB) for search/filter; fallback to repo reads by rkey.
  • Safety: Enforce size limits on content/blobs, rate-limit publish, reject tampered/duplicate/invalid signatures, log verification failures.

Client UI (Frontend)#

  • Auth status: “Connect Bluesky” button; show connected DID/handle; disable publish until connected.
  • Key management: Display ANProto pubkey; controls to generate/import/export (avoid leaking private key in production).
  • Composer: Text area for content, optional “previous” hash, blob uploader, live display of computed hash/signature.
  • Publish flow: “Sign & Save to Bluesky” runs APDS sign then POSTs to backend; show progress/errors.
  • Viewer: Fetch by hash, display content, author pubkey, timestamp, previous chain, blob previews; simple search/filter if backend index exists.
  • Notifications: Inline status/toasts for auth, signing, upload, and save failures.