commits
The endpoint was defined but never exposed publicly.
Delete records via API instead.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Delete each record through the normal flow before wiping,
so relays and indexers can clean up their indexes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Standardize JSDoc type annotation spacing and improve multiline
formatting for better readability.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add JSDoc type annotations for TypeScript checking
- Reorganize pds.js into 13 logical sections with box-style headers:
Types & Constants, Utilities, CBOR Encoding, Content Identifiers,
Cryptography, Authentication, Merkle Search Tree, CAR Files,
Blob Handling, Relay Notification, Routing, Personal Data Server,
Workers Entry Point
- Add ASCII art file header with feature list
- Add tsconfig.json for type checking
- Add typecheck npm script
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements full AT Protocol blob support:
- uploadBlob: Upload blobs with MIME type sniffing (JPEG, PNG, GIF,
WebP, MP4, AVIF, HEIC) and CID generation using raw codec
- getBlob: Retrieve blobs with proper Content-Type, security headers,
and CID format validation
- listBlobs: Paginated blob listing with composite cursor
Storage and lifecycle:
- R2 bucket for blob data with DID-prefixed keys
- SQLite tables for blob metadata and record associations
- Automatic orphan cleanup via DO alarm (24hr) and on record deletion
- Race-safe concurrent upload handling
Includes comprehensive test coverage:
- Unit tests for MIME sniffing, CID generation, blob ref detection
- E2E tests for all blob endpoints and lifecycle scenarios
🤖 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>
Implement com.atproto.server.refreshSession for token refresh:
- Add verifyRefreshJwt with audience validation
- Extract shared verifyJwt helper to reduce duplication
- Change refresh token expiration from 90 days to 24 hours
- Fix error name AuthenticationRequired → AuthRequired
Tests:
- Unit tests for verifyRefreshJwt (valid, expired, wrong type, malformed)
- E2E tests for happy path and error cases
- Remove test numbers from e2e.sh for easier maintenance
🤖 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>
- Format test/e2e.sh with shfmt
- Add shfmt to npm run format script
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add @biomejs/biome with 2-space indent, single quotes
- Add npm scripts: format, lint, check
- Auto-fix all lint issues
🤖 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>
🤖 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>
- Add JSDoc type annotations for TypeScript checking
- Reorganize pds.js into 13 logical sections with box-style headers:
Types & Constants, Utilities, CBOR Encoding, Content Identifiers,
Cryptography, Authentication, Merkle Search Tree, CAR Files,
Blob Handling, Relay Notification, Routing, Personal Data Server,
Workers Entry Point
- Add ASCII art file header with feature list
- Add tsconfig.json for type checking
- Add typecheck npm script
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements full AT Protocol blob support:
- uploadBlob: Upload blobs with MIME type sniffing (JPEG, PNG, GIF,
WebP, MP4, AVIF, HEIC) and CID generation using raw codec
- getBlob: Retrieve blobs with proper Content-Type, security headers,
and CID format validation
- listBlobs: Paginated blob listing with composite cursor
Storage and lifecycle:
- R2 bucket for blob data with DID-prefixed keys
- SQLite tables for blob metadata and record associations
- Automatic orphan cleanup via DO alarm (24hr) and on record deletion
- Race-safe concurrent upload handling
Includes comprehensive test coverage:
- Unit tests for MIME sniffing, CID generation, blob ref detection
- E2E tests for all blob endpoints and lifecycle scenarios
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement com.atproto.server.refreshSession for token refresh:
- Add verifyRefreshJwt with audience validation
- Extract shared verifyJwt helper to reduce duplication
- Change refresh token expiration from 90 days to 24 hours
- Fix error name AuthenticationRequired → AuthRequired
Tests:
- Unit tests for verifyRefreshJwt (valid, expired, wrong type, malformed)
- E2E tests for happy path and error cases
- Remove test numbers from e2e.sh for easier maintenance
🤖 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>