this repo has no description

PDS Implementation TODOs#

Lewis' corrected big boy todofile

Server Infrastructure & Proxying#

  • Health Check
    • Implement GET /health endpoint (returns "OK").
    • Implement GET /xrpc/_health endpoint (returns "OK").
  • Server Description
    • Implement com.atproto.server.describeServer (returns available user domains).
  • XRPC Proxying
    • Implement strict forwarding for all app.bsky.* and chat.bsky.* requests to an appview.
    • Forward auth headers correctly.
    • Handle appview errors/timeouts gracefully.

Authentication & Account Management (com.atproto.server)#

  • Account Creation
    • Implement com.atproto.server.createAccount.
    • Validate handle format (reject invalid characters).
    • Create DID for new user (PLC directory).
    • Initialize user repository (Root commit).
    • Return access JWT and DID.
    • Create DID for new user (did:web).
  • Session Management
    • Implement com.atproto.server.createSession (Login).
    • Implement com.atproto.server.getSession.
    • Implement com.atproto.server.refreshSession.
    • Implement com.atproto.server.deleteSession (Logout).
    • Implement com.atproto.server.activateAccount.
    • Implement com.atproto.server.checkAccountStatus.
    • Implement com.atproto.server.createAppPassword.
    • Implement com.atproto.server.createInviteCode.
    • Implement com.atproto.server.createInviteCodes.
    • Implement com.atproto.server.deactivateAccount.
    • Implement com.atproto.server.deleteAccount (user-initiated, requires password + email token).
    • Implement com.atproto.server.getAccountInviteCodes.
    • Implement com.atproto.server.getServiceAuth (Cross-service auth).
    • Implement com.atproto.server.listAppPasswords.
    • Implement com.atproto.server.requestAccountDelete.
    • Implement com.atproto.server.requestEmailConfirmation / requestEmailUpdate.
    • Implement com.atproto.server.requestPasswordReset / resetPassword.
    • Implement com.atproto.server.reserveSigningKey.
    • Implement com.atproto.server.revokeAppPassword.
    • Implement com.atproto.server.updateEmail.
    • Implement com.atproto.server.confirmEmail.

Repository Operations (com.atproto.repo)#

  • Record CRUD
    • Implement com.atproto.repo.createRecord.
      • Generate rkey (TID) if not provided.
      • Handle MST (Merkle Search Tree) insertion.
      • Trigger Firehose Event.
    • Implement com.atproto.repo.putRecord.
    • Implement com.atproto.repo.getRecord.
    • Implement com.atproto.repo.deleteRecord.
    • Implement com.atproto.repo.listRecords.
    • Implement com.atproto.repo.describeRepo.
    • Implement com.atproto.repo.applyWrites (Batch writes).
    • Implement com.atproto.repo.importRepo (Migration).
    • Implement com.atproto.repo.listMissingBlobs.
  • Blob Management
    • Implement com.atproto.repo.uploadBlob.
      • Store blob (S3).
      • return blob ref (CID + MimeType).

Sync & Federation (com.atproto.sync)#

  • The Firehose (WebSocket)
    • Implement com.atproto.sync.subscribeRepos.
      • Broadcast real-time commit events.
      • Handle cursor replay (backfill).
  • Bulk Export
    • Implement com.atproto.sync.getRepo (Return full CAR file of repo).
    • Implement com.atproto.sync.getBlocks (Return specific blocks via CIDs).
    • Implement com.atproto.sync.getLatestCommit.
    • Implement com.atproto.sync.getRecord (Sync version, distinct from repo.getRecord).
    • Implement com.atproto.sync.getRepoStatus.
    • Implement com.atproto.sync.listRepos.
    • Implement com.atproto.sync.notifyOfUpdate.
  • Blob Sync
    • Implement com.atproto.sync.getBlob.
    • Implement com.atproto.sync.listBlobs.
  • Crawler Interaction
    • Implement com.atproto.sync.requestCrawl (Notify relays to index us).

Identity (com.atproto.identity)#

  • Resolution
    • Implement com.atproto.identity.resolveHandle (Can be internal or proxy to PLC).
    • Implement com.atproto.identity.updateHandle.
    • Implement com.atproto.identity.submitPlcOperation / signPlcOperation / requestPlcOperationSignature.
    • Implement com.atproto.identity.getRecommendedDidCredentials.
    • Implement /.well-known/did.json (Depends on supporting did:web).

Admin Management (com.atproto.admin)#

  • Implement com.atproto.admin.deleteAccount.
  • Implement com.atproto.admin.disableAccountInvites.
  • Implement com.atproto.admin.disableInviteCodes.
  • Implement com.atproto.admin.enableAccountInvites.
  • Implement com.atproto.admin.getAccountInfo / getAccountInfos.
  • Implement com.atproto.admin.getInviteCodes.
  • Implement com.atproto.admin.getSubjectStatus.
  • Implement com.atproto.admin.sendEmail.
  • Implement com.atproto.admin.updateAccountEmail.
  • Implement com.atproto.admin.updateAccountHandle.
  • Implement com.atproto.admin.updateAccountPassword.
  • Implement com.atproto.admin.updateSubjectStatus.

Moderation (com.atproto.moderation)#

  • Implement com.atproto.moderation.createReport.

Temp Namespace (com.atproto.temp)#

  • Implement com.atproto.temp.checkSignupQueue (signup queue status for gated signups).

OAuth 2.1 Support#

Full OAuth 2.1 provider for ATProto native app authentication.

  • OAuth Provider Core
    • Implement /.well-known/oauth-protected-resource metadata endpoint.
    • Implement /.well-known/oauth-authorization-server metadata endpoint.
    • Implement /oauth/authorize authorization endpoint (headless JSON mode).
    • Implement /oauth/par Pushed Authorization Request endpoint.
    • Implement /oauth/token token endpoint (authorization_code + refresh_token grants).
    • Implement /oauth/jwks JSON Web Key Set endpoint.
    • Implement /oauth/revoke token revocation endpoint.
    • Implement /oauth/introspect token introspection endpoint.
  • OAuth Database Tables
    • Device table for tracking authorized devices.
    • Authorization request table.
    • Authorized client table.
    • Token table for OAuth tokens.
    • Used refresh token table (replay protection).
    • DPoP JTI tracking table.
  • DPoP (Demonstrating Proof-of-Possession) support.
  • Client metadata fetching and validation.
  • PKCE (S256) enforcement.
  • OAuth token verification extractor for protected resources.
  • Authorization UI templates (currently headless-only, returns JSON for programmatic flows).
  • Implement private_key_jwt signature verification (currently rejects with clear error).

OAuth Security Notes#

I've tried to ensure that this codebase is not vulnerable to the following:

  • Constant-time comparison for signature verification (prevents timing attacks)
  • HMAC-SHA256 for access token signing with configurable secret
  • Production secrets require 32+ character minimum
  • DPoP JTI replay protection via database
  • DPoP nonce validation with HMAC-based timestamps (5 min validity)
  • Refresh token rotation with reuse detection (revokes token family on reuse)
  • PKCE S256 enforced (plain not allowed)
  • Authorization code single-use enforcement
  • URL encoding for redirect parameters (prevents injection)
  • All database queries use parameterized statements (no SQL injection)
  • Deactivated/taken-down accounts blocked from OAuth authorization
  • Client ID validation on token exchange (defense-in-depth against cross-client attacks)

Auth Notes#

  • Algorithm choice: Using ES256K (secp256k1 ECDSA) with per-user keys. Ref PDS uses HS256 (HMAC) with single server key. Our approach provides better key isolation but differs from reference implementation.
    • Support the ref PDS HS256 system too.
  • Token storage: Now storing only token JTIs in session_tokens table (defense in depth against DB breaches). Refresh token family tracking enables detection of token reuse attacks.
  • Key encryption: User signing keys encrypted at rest using AES-256-GCM with keys derived via HKDF from MASTER_KEY environment variable. Migration-safe: supports both encrypted (version 1) and plaintext (version 0) keys.

PDS-Level App Endpoints#

These endpoints need to be implemented at the PDS level (not just proxied to appview).

Actor (app.bsky.actor)#

  • Implement app.bsky.actor.getPreferences (user preferences storage).
  • Implement app.bsky.actor.putPreferences (update user preferences).
  • Implement app.bsky.actor.getProfile (PDS-level with proxy fallback).
  • Implement app.bsky.actor.getProfiles (PDS-level with proxy fallback).

Feed (app.bsky.feed)#

These are implemented at PDS level to enable local-first reads:

  • Implement app.bsky.feed.getTimeline (PDS-level with proxy).
  • Implement app.bsky.feed.getAuthorFeed (PDS-level with proxy).
  • Implement app.bsky.feed.getActorLikes (PDS-level with proxy).
  • Implement app.bsky.feed.getPostThread (PDS-level with proxy).
  • Implement app.bsky.feed.getFeed (PDS-level with proxy).

Notification (app.bsky.notification)#

  • Implement app.bsky.notification.registerPush (push notification registration).

Deprecated Sync Endpoints (for compatibility)#

  • Implement com.atproto.sync.getCheckout (deprecated, still needed for compatibility).
  • Implement com.atproto.sync.getHead (deprecated, still needed for compatibility).

Misc HTTP Endpoints#

  • Implement /robots.txt endpoint.

Record Schema Validation#

  • Handle this generically.

Preference Storage#

User preferences (for app.bsky.actor.getPreferences/putPreferences):

  • Create preferences table for storing user app preferences.
  • Implement app.bsky.actor.getPreferences handler (read from postgres, proxy fallback).
  • Implement app.bsky.actor.putPreferences handler (write to postgres).

Infrastructure & Core Components#

  • Sequencer (Event Log)
    • Implement a Sequencer (backed by repo_seq table).
    • Implement event formatting (commit, handle, identity, account).
    • Implement database polling / event emission mechanism.
    • Implement cursor-based event replay (requestSeqRange).
  • Repo Storage & Consistency (in postgres)
    • Implement RepoStorage for postgres (replaces per-user SQLite).
      • Read/Write IPLD blocks to blocks table (global deduplication).
      • Manage Repo Root in repos table.
    • Implement Atomic Repo Transactions.
      • Ensure blocks write, repo_root update, records index update, and sequencer event are committed in a single transaction.
    • Implement concurrency control (row-level locking on repos table) to prevent concurrent writes to the same repo.
  • DID Cache
    • Implement caching layer for DID resolution (Redis or in-memory).
    • Handle cache invalidation/expiry.
  • Background Jobs
    • Implement Crawlers service (debounce notifications to relays).
  • Notification Service
    • Queue-based notification system with database table
    • Background worker polling for pending notifications
    • Extensible sender trait for multiple channels
    • Email sender via OS sendmail/msmtp
    • Discord bot sender
    • Telegram bot sender
    • Signal bot sender
    • Helper functions for common notification types (welcome, password reset, email verification, etc.)
    • Respect user's preferred_notification_channel setting for non-email-specific notifications
  • Image Processing
    • Implement image resize/formatting pipeline (for blob uploads).
  • IPLD & MST
    • Implement Merkle Search Tree logic for repo signing.
    • Implement CAR (Content Addressable Archive) encoding/decoding.
  • Validation
    • DID PLC Operations (Sign rotation keys).
  • Fix any remaining TODOs in the code, everywhere, full stop.

Web Management UI#

A single-page web app for account management. The frontend (JS framework) calls existing ATProto XRPC endpoints - no server-side rendering or bespoke HTML form handlers.

Architecture#

  • Static SPA served from PDS (or separate static host)
  • Frontend authenticates via OAuth 2.1 flow (same as any ATProto client)
  • All operations use standard XRPC endpoints (existing + new PDS-specific ones below)
  • No server-side sessions or CSRF - pure API client

PDS-Specific XRPC Endpoints (new)#

Absolutely subject to change, "bspds" isn't even the real name of this pds thus far :D Anyway... endpoints for PDS settings not covered by standard ATProto:

  • com.bspds.account.getNotificationPrefs - get preferred channel, verified channels
  • com.bspds.account.updateNotificationPrefs - set preferred channel
  • com.bspds.account.getNotificationHistory - list past notifications
  • com.bspds.account.verifyChannel - initiate verification for Discord/Telegram/Signal
  • com.bspds.account.confirmChannelVerification - confirm with code
  • com.bspds.admin.getServerStats - user count, storage usage, etc.

Frontend Views#

Uses existing ATProto endpoints where possible:

User Dashboard

  • Account overview (uses com.atproto.server.getSession, com.atproto.admin.getAccountInfo)
  • Active sessions view (needs new endpoint or extend existing)
  • App passwords (uses com.atproto.server.listAppPasswords, createAppPassword, revokeAppPassword)
  • Invite codes (uses com.atproto.server.getAccountInviteCodes, createInviteCode)

Notification Preferences

  • Channel selector (uses com.bspds.account.* endpoints above)
  • Verification flows for Discord/Telegram/Signal
  • Notification history view

Account Settings

  • Email change (uses com.atproto.server.requestEmailUpdate, updateEmail)
  • Password change (uses com.atproto.server.requestPasswordReset, resetPassword)
  • Handle change (uses com.atproto.identity.updateHandle)
  • Account deletion (uses com.atproto.server.requestAccountDelete, deleteAccount)
  • Data export (uses com.atproto.sync.getRepo)

Admin Dashboard (privileged users only)

  • User list (uses com.atproto.admin.getAccountInfos with pagination)
  • User detail/actions (uses com.atproto.admin.* endpoints)
  • Invite management (uses com.atproto.admin.getInviteCodes, disableInviteCodes)
  • Server stats (uses com.bspds.admin.getServerStats)