commits
createAccount(handle, { records }) registers a new account on the fly
and optionally seeds records (e.g. publicKey/self). Replaces the need
to rely on pre-generated pool accounts for specific test scenarios.
HTTP endpoint: POST /_test/create-account { handle, records? }
New exports: generateAccounts(n, domain) creates test accounts with
human-readable Dutch names, AccountPool provides atomic file-lock
allocation for parallel test isolation across worker processes.
New endpoint: POST /_test/cleanup?did= clears records, blobs, and
tokens for a single DID without affecting other accounts. Also adds
cleanupDid() JS method on FakePds and OAuthState.
PAR now captures redirect_uri and state, storing a pending
authorization keyed by request_uri. The new GET /oauth/authorize
endpoint consumes the pending auth and 302-redirects back to the
client with code, state, and iss — enabling Playwright tests to
exercise the full browser OAuth flow.
Also adds POST /_test/reset for HTTP-based state reset and bumps
version to 0.3.0.
Serves minimal DID documents at GET /did:plc:* from the accounts table.
Returns id, alsoKnownAs (handle), and service (PDS endpoint). Enables
identity resolution in tests when OPAKE_PLC_DIRECTORY points at the
fake PDS. Also returns 404 for .well-known/atproto-did (localhost can't
use Host-based handle resolution). 49 tests passing.
Round 2 adversary review (19 findings, 5 critical). Fixed:
- PAR returns 201 (RFC 9126) with code in response for testable e2e flow
- PAR/token accept form-encoded bodies (RFC 6749)
- Bearer scheme rejected in OAuth mode (DPoP only per AT Protocol)
- Missing grant_type returns InvalidRequest not UnsupportedGrantType
- PAR rejects unknown login_hint instead of using it as DID
- Nonce rotation consolidated (no double rotation)
- Map iteration during deletion made safe
- Authorization server metadata: added require_pushed_authorization_requests,
client_id_metadata_document_supported, authorization_response_iss_supported
- 47 tests (19 OAuth, 28 core) all passing
README covers all endpoints, auth modes, and API surface.
License matches opake (AGPL-3.0-or-later). package.json
updated with author, repository, engines, and license field.
Well-known metadata, PAR, token exchange, refresh with token
invalidation. issueOAuthTokens() helper skips browser flow for test
setup. DPoP nonce rotates on each token response. Auth mode "oauth"
validates DPoP/Bearer tokens and returns nonce on 401. 14 new tests.
Implements all 6 repo endpoints (getRecord, listRecords, createRecord,
putRecord, deleteRecord, uploadBlob), blob retrieval, legacy auth
(createSession, refreshSession), and resolveHandle.
Records sort by rkey (not insertion order), cursor pagination uses range
queries, createRecord rejects existing rkeys, session state is per-
instance, TID generation handles clock skew. 28 tests passing.
Hardened via adversarial review (VDD): 4 critical and 7 medium findings
fixed in first pass.
New exports: generateAccounts(n, domain) creates test accounts with
human-readable Dutch names, AccountPool provides atomic file-lock
allocation for parallel test isolation across worker processes.
New endpoint: POST /_test/cleanup?did= clears records, blobs, and
tokens for a single DID without affecting other accounts. Also adds
cleanupDid() JS method on FakePds and OAuthState.
PAR now captures redirect_uri and state, storing a pending
authorization keyed by request_uri. The new GET /oauth/authorize
endpoint consumes the pending auth and 302-redirects back to the
client with code, state, and iss — enabling Playwright tests to
exercise the full browser OAuth flow.
Also adds POST /_test/reset for HTTP-based state reset and bumps
version to 0.3.0.
Serves minimal DID documents at GET /did:plc:* from the accounts table.
Returns id, alsoKnownAs (handle), and service (PDS endpoint). Enables
identity resolution in tests when OPAKE_PLC_DIRECTORY points at the
fake PDS. Also returns 404 for .well-known/atproto-did (localhost can't
use Host-based handle resolution). 49 tests passing.
Round 2 adversary review (19 findings, 5 critical). Fixed:
- PAR returns 201 (RFC 9126) with code in response for testable e2e flow
- PAR/token accept form-encoded bodies (RFC 6749)
- Bearer scheme rejected in OAuth mode (DPoP only per AT Protocol)
- Missing grant_type returns InvalidRequest not UnsupportedGrantType
- PAR rejects unknown login_hint instead of using it as DID
- Nonce rotation consolidated (no double rotation)
- Map iteration during deletion made safe
- Authorization server metadata: added require_pushed_authorization_requests,
client_id_metadata_document_supported, authorization_response_iss_supported
- 47 tests (19 OAuth, 28 core) all passing
Implements all 6 repo endpoints (getRecord, listRecords, createRecord,
putRecord, deleteRecord, uploadBlob), blob retrieval, legacy auth
(createSession, refreshSession), and resolveHandle.
Records sort by rkey (not insertion order), cursor pagination uses range
queries, createRecord rejects existing rkeys, session state is per-
instance, TID generation handles clock skew. 28 tests passing.
Hardened via adversarial review (VDD): 4 critical and 7 medium findings
fixed in first pass.