feat: invite minting (rook DPoP mint, org Access admin, /roost)
Add commons-only rook invite minting via POST /api/invites: DPoP auth resolves the rook, proof-of-life returns MintLocked before quota checks, lifetime quota returns QuotaExceeded, and an atomic conditional INSERT returns {token,url,remaining}.
Gate /admin/* with in-worker Cloudflare Access JWT verification using RS256 against the team JWKS with an in-memory cache, fail closed to 404 when Access bindings are missing, and expose org minting, quota config, and paginated invite listing routes.
Reconcile invites and invite_quotas to the COUNT-based schema with default quota seed 3, add GET /roost 302, keep the feature commons-only with reference-variant 404 coverage, and add tests for Access deny/fail-closed, quotas, pagination, and token generation.
Include incidental pre-existing tsc fixes in auth.ts and sequencer-do.ts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add project scaffold and SQLite storage layer
Bootstrap TypeScript/Hono/better-sqlite3/vitest project with multi-tenant
SqliteRepoStorage implementing @atproto/repo's RepoStorage interface.
- tsconfig.json, vitest.config.ts, .gitignore, README.md
- src/config.ts: env var parsing with validation
- src/db.ts: schema init for accounts, blocks, collections, blobs, firehose_events
- src/storage.ts: SqliteRepoStorage with account-scoped queries, transactional applyCommit, prev_data_cid tracking
- src/cbor-compat.ts: CBOR compat layer ported from cirrus
- src/index.ts: Hono health-check server
- test/storage.test.ts: 8 tests covering Repo.create, applyWrites, multi-tenant isolation, transaction atomicity
feat: invite minting (rook DPoP mint, org Access admin, /roost)
Add commons-only rook invite minting via POST /api/invites: DPoP auth resolves the rook, proof-of-life returns MintLocked before quota checks, lifetime quota returns QuotaExceeded, and an atomic conditional INSERT returns {token,url,remaining}.
Gate /admin/* with in-worker Cloudflare Access JWT verification using RS256 against the team JWKS with an in-memory cache, fail closed to 404 when Access bindings are missing, and expose org minting, quota config, and paginated invite listing routes.
Reconcile invites and invite_quotas to the COUNT-based schema with default quota seed 3, add GET /roost 302, keep the feature commons-only with reference-variant 404 coverage, and add tests for Access deny/fail-closed, quotas, pagination, and token generation.
Include incidental pre-existing tsc fixes in auth.ts and sequencer-do.ts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat: handle acceptance policy at signup (reservation, blocklist, HandleTaken 409)
Evaluate submitted handles at POST /api/signup in a fixed order against the
lowercased single name label: single-label/syntax (InvalidHandle) -> reservation
of 1-2 char labels (HandleReserved) -> blocklist membership (HandleReserved) ->
availability (HandleTaken 409). Reservation and blocklist share one code path and
message so refusals reveal nothing about which rule matched.
The availability check is now a D1 SELECT (directory.handleExists, existence-only,
any row active-or-not) that runs before PLC DID creation and Account DO
provisioning, closing the orphaned-identity leak where a duplicate handle was only
caught at the final INSERT after an identity had already been minted. The
UNIQUE-constraint catch is kept as the concurrent-race backstop and its code is
renamed HandleAlreadyTaken -> HandleTaken.
The name label is lowercased at the boundary so PLC alsoKnownAs, the Account DO,
the D1 row, and the response all carry the lowercase handle. The blocklist lives
in src/handle-policy.ts (three reviewable sections, 249/53/63 = 365 entries) with
a test asserting complete per-section membership against an independent literal
fixture. The duplicate-handle integration test now asserts HandleTaken and proves
no PLC DID fetch or Account DO id is created on a rejected duplicate.
Note: `npx tsc --noEmit` still reports 22 pre-existing errors in out-of-scope
files (account-do.ts, auth.ts, sequencer-do.ts, and unrelated worker.ts paths);
this change introduces none and resolves one.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat: invite minting (rook DPoP mint, org Access admin, /roost)
Add commons-only rook invite minting via POST /api/invites: DPoP auth resolves the rook, proof-of-life returns MintLocked before quota checks, lifetime quota returns QuotaExceeded, and an atomic conditional INSERT returns {token,url,remaining}.
Gate /admin/* with in-worker Cloudflare Access JWT verification using RS256 against the team JWKS with an in-memory cache, fail closed to 404 when Access bindings are missing, and expose org minting, quota config, and paginated invite listing routes.
Reconcile invites and invite_quotas to the COUNT-based schema with default quota seed 3, add GET /roost 302, keep the feature commons-only with reference-variant 404 coverage, and add tests for Access deny/fail-closed, quotas, pagination, and token generation.
Include incidental pre-existing tsc fixes in auth.ts and sequencer-do.ts.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>