commits
- Add notifyCrawlers() to notify relays after writes via requestCrawl
- Add worker-level routing for sync endpoints (getLatestCommit, getRepoStatus, getRepo, getRecord)
- Fix /init to register handles in default DO's handleMap
- Add self-contained E2E test suite (23 tests) covering:
- Server basics, identity, authentication
- Repo CRUD, applyWrites batch operations
- Sync endpoints (CAR file retrieval)
- Error handling (401, 403, 404)
- Move test credentials to .dev.vars (gitignored)
- Update .env.example with all config options
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement full authentication system for ATProto PDS:
- JWT helpers: base64url encode/decode, HMAC-SHA256 signing
- Access tokens (2hr) and refresh tokens (90 days)
- createSession endpoint with password validation
- getSession endpoint with token verification
- Auth middleware protecting write endpoints (createRecord, deleteRecord, putRecord, applyWrites)
- AppView proxy with ES256 service auth for app.bsky.* endpoints
- Local storage for user preferences (getPreferences, putPreferences)
- resolveHandle XRPC endpoint
Refactoring:
- Consolidated 4 CBOR encoders into 2
- Added errorResponse() helper for consistent ATProto error format
- Extracted handleAuthenticatedRepoWrite() to reduce duplication
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements record deletion with proper ATProto event emission:
- Removes record from database and rebuilds MST
- Creates signed commit with updated repo state
- Emits delete event to firehose for relay/indexer propagation
- Routes POST requests with repo in body to correct Durable Object
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ATProto MST spec: "Layers are counted from the bottom of the tree,
starting with zero." This means:
- Layer 0 is at the BOTTOM
- Root is at the HIGHEST layer (max depth of any key)
- Subtrees go DOWN to lower layers
Previous implementation had this inverted, causing "depths are out of
order" validation errors in pdsls.
Also includes:
- MST nodes must include l and t fields (even when null) per ATProto schema
- handleGetRepo now only includes blocks reachable from current commit
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add scripts/update-did.js for updating PLC DID handle and PDS endpoint
- Fix handle resolution to work with bare domain handles (not just subdomains)
- This allows workers.dev deployments where nested subdomains aren't supported
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add handle -> DID mapping storage in default DO
- Route /.well-known/atproto-did based on subdomain
- Update setup script to register handle mappings
- Bare domain returns 404 for handle resolution (use subdomain)
Works with custom domains that have wildcard SSL certs.
Note: workers.dev doesn't support nested subdomains (SSL limitation).
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add CBOR tag 42 decoding for CID links in cborDecode
- Use DAG-CBOR encoding for records (length-first key sorting)
- Return full proof chain in sync.getRecord (commit + MST + record)
- Skip CORS wrapping for WebSocket upgrade responses (status 101)
- Simplify setup script to use PDS hostname as handle
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Plan covers: CBOR constants, shared encodeHead, JSDoc on exports,
route table pattern, and protocol-specific "why" comments.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add explicit CID wrapper class for reliable DAG-CBOR tag 42 encoding
instead of heuristic detection. Fix 32-bit signed integer overflow
when encoding large lengths by using Math.floor instead of bitshift.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The PLC spec requires the DID to be derived from the hash of the
complete signed operation, not just the unsigned operation.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Covers handle resolution, DID:PLC registration, and relay notification.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
SQLite BLOBs are returned as ArrayBuffer in Cloudflare Workers.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Removed /test/* endpoints, added proper 404 JSON response.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Broadcasts events to connected WebSocket clients on record creation
- Supports cursor parameter for event replay
- AT Protocol frame format with CBOR header + body
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Converts ArrayBuffer from SQLite BLOB to Uint8Array before building CAR.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add createCid, cidToString, base32Encode utilities
- Set up Node.js built-in test runner (zero dependencies)
- Add comprehensive tests for CBOR encoding and CID generation
- Export utility functions for testing
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add notifyCrawlers() to notify relays after writes via requestCrawl
- Add worker-level routing for sync endpoints (getLatestCommit, getRepoStatus, getRepo, getRecord)
- Fix /init to register handles in default DO's handleMap
- Add self-contained E2E test suite (23 tests) covering:
- Server basics, identity, authentication
- Repo CRUD, applyWrites batch operations
- Sync endpoints (CAR file retrieval)
- Error handling (401, 403, 404)
- Move test credentials to .dev.vars (gitignored)
- Update .env.example with all config options
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement full authentication system for ATProto PDS:
- JWT helpers: base64url encode/decode, HMAC-SHA256 signing
- Access tokens (2hr) and refresh tokens (90 days)
- createSession endpoint with password validation
- getSession endpoint with token verification
- Auth middleware protecting write endpoints (createRecord, deleteRecord, putRecord, applyWrites)
- AppView proxy with ES256 service auth for app.bsky.* endpoints
- Local storage for user preferences (getPreferences, putPreferences)
- resolveHandle XRPC endpoint
Refactoring:
- Consolidated 4 CBOR encoders into 2
- Added errorResponse() helper for consistent ATProto error format
- Extracted handleAuthenticatedRepoWrite() to reduce duplication
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements record deletion with proper ATProto event emission:
- Removes record from database and rebuilds MST
- Creates signed commit with updated repo state
- Emits delete event to firehose for relay/indexer propagation
- Routes POST requests with repo in body to correct Durable Object
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ATProto MST spec: "Layers are counted from the bottom of the tree,
starting with zero." This means:
- Layer 0 is at the BOTTOM
- Root is at the HIGHEST layer (max depth of any key)
- Subtrees go DOWN to lower layers
Previous implementation had this inverted, causing "depths are out of
order" validation errors in pdsls.
Also includes:
- MST nodes must include l and t fields (even when null) per ATProto schema
- handleGetRepo now only includes blocks reachable from current commit
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add scripts/update-did.js for updating PLC DID handle and PDS endpoint
- Fix handle resolution to work with bare domain handles (not just subdomains)
- This allows workers.dev deployments where nested subdomains aren't supported
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add handle -> DID mapping storage in default DO
- Route /.well-known/atproto-did based on subdomain
- Update setup script to register handle mappings
- Bare domain returns 404 for handle resolution (use subdomain)
Works with custom domains that have wildcard SSL certs.
Note: workers.dev doesn't support nested subdomains (SSL limitation).
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add CBOR tag 42 decoding for CID links in cborDecode
- Use DAG-CBOR encoding for records (length-first key sorting)
- Return full proof chain in sync.getRecord (commit + MST + record)
- Skip CORS wrapping for WebSocket upgrade responses (status 101)
- Simplify setup script to use PDS hostname as handle
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add explicit CID wrapper class for reliable DAG-CBOR tag 42 encoding
instead of heuristic detection. Fix 32-bit signed integer overflow
when encoding large lengths by using Math.floor instead of bitshift.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add createCid, cidToString, base32Encode utilities
- Set up Node.js built-in test runner (zero dependencies)
- Add comprehensive tests for CBOR encoding and CID generation
- Export utility functions for testing
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>