feat: DFOS credentials, delegation, revocation, and full cross-language parity#43
Merged
feat: DFOS credentials, delegation, revocation, and full cross-language parity#43
Conversation
…-based auth Replace VC-JWT credential system with DFOS credentials — UCAN-style delegation chains with CID-addressable payloads, monotonic attenuation, and two resource types (chain: exact, manifest: transitive). Delete credential.ts entirely, no backward compat (pre-v1). Steps implemented: - Step 1: DFOS Credentials (create, verify, delegation chains, attenuation, resource matching with manifestLookup callback, public aud:"*" semantics) - Step 2: Content chain authorization updated to use DFOS credentials with resolveIdentity for delegation chain verification - Step 3: Beacon update — manifestContentId replaces merkleRoot, drop version field. Beacon is now a manifest pointer, not a merkle root announcement. - Step 4: Revocation artifacts — new signed revocation type, gossiped like beacons, permanent (no un-revoke) Relay updates: - Content-plane auth uses verifyDFOSCredential + verifyDelegationChain - Ingestion pipeline passes resolveIdentity for credential verification - Beacon response shape updated for new VerifiedBeacon type 235 protocol tests + 91 relay tests = 326 total, all passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…(Step 5) Extend RelayStore interface with revocation set and public credential storage. MemoryRelayStore implements both with Map-backed data structures. Ingestion pipeline classifies and processes two new artifact types: - did:dfos:revocation → verify, add to revocation set, remove any stored public credential that was revoked - did:dfos:credential (aud: "*") → verify signature, check not revoked, store as standing authorization. Private credentials (aud: specific DID) are silently ignored. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add verifyContentAccess to auth module — checks creator access, stored
public credentials, and per-request credentials in order. Replaces the
old verifyReadCredential that did inline VC-JWT verification.
Well-known endpoint now returns structured capabilities object:
{ proof, content, documents, log } instead of flat boolean fields.
Version bumped to 0.8.0.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Paginated plaintext content reading endpoint. Returns resolved documents for each operation in the content chain, ordered by chain sequence. - StoredDocument type with operationCID, documentCID, document, signerDID, createdAt - getDocuments on RelayStore — walks chain log, resolves blobs, paginates - Auth-gated via verifyContentAccess (creator, public credential, or per-request credential) - Cursor-based pagination using operation CID Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add reference-content-stream/v1 — a toy discriminated-union event schema for developing and testing content stream patterns. Five actions: create-item, update-item, delete-item, react, unreact. Includes worked example with 6-operation chain demonstrating full CRUD lifecycle, reactions, and deletion cascades, plus expected projected state after folding. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New spec documents: - CREDENTIALS.md — DFOS credential format, delegation chains, attenuation rules, resource types, public credentials, revocation - SIWD.md — Sign In With DFOS protocol, managed + sovereign signing, challenge schema, 3P verification Updated specs: - PROTOCOL.md — remove VC-JWT references, add credential/revocation pointers, update beacon payload (manifestContentId) - WEB-RELAY.md — documents endpoint, credential-based auth, public credential ingestion, capabilities object, version 0.8.0 - CONTENT-MODEL.md — reference content stream schema, projection rules, createdByDID convention, targetOperationCID pattern Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…t, POSTER.html removal Security: scope revocation storage to (issuerDID, credentialCID) so only the credential issuer can revoke it. Previously any DID could submit a revocation for any credential CID. Schema consistency: add version: 1 to DFOSCredentialPayload and RevocationPayload, matching the convention of all other payload schemas. Add .min(1) to credential iss field. Fix audience check to reject when requesterDID is absent on non-public credentials. Spec alignment: remove all dangling VC-JWT references across PROTOCOL.md, WEB-RELAY.md, SIWD.md, CREDENTIALS.md, CLAUDE-SKILL.md, README.md. Fix well-known capabilities to match implementation. Fix credential type references (DFOSContentRead/Write → generic DFOS credentials with action attenuations). Update reference implementation map. OpenAPI: update well-known response to capabilities object, fix beacon schema (manifestContentId, flat response), add documents endpoint, fix credential header descriptions. Cleanup: remove POSTER.html (stale, superseded by protocol site). Regenerate example fixtures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update dfos-protocol-go to match the new DFOS credential format (replacing VC-JWTs) and new beacon format (manifestContentId replacing merkleRoot). Update relay-conformance tests for the same changes. Run prettier across TS files. Go changes: - SignBeacon: manifestContentId replaces merkleRoot, drop version - CreateCredential: DFOS credential format with CID derivation - VerifyCredential: parse flat DFOS credential payload instead of nested vc+jwt structure - VerifyBeacon: manifestContentId (22-char content ID) replaces merkleRoot (64-char hex), drop version check - All Go tests updated and passing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- dfos-web-relay-go: well-known response uses capabilities object, beacon GET returns flat fields (manifestContentId, createdAt), BeaconPayload uses manifestContentId - relay-conformance: TestWellKnown checks capabilities.proof, TestBeaconReplacement uses manifestContentId - Run prettier across all TS/MD files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ce tests - dfos-cli: beacon announce takes manifestContentId instead of building merkle root from content IDs. Show command reads flat beacon response format. - site-protocol: remove poster.astro page (POSTER.html was deleted) - relay-conformance: remaining beacon tests use manifestContentId instead of BuildMerkleRoot - dfos-web-relay-go: beacon GET returns flat fields, well-known uses capabilities object - Run prettier across all files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…t scopes, terminology cleanup - TS: delegation chain revocation checking at every prf level - TS: manifest scope resolution with manifestLookup callback in verifyContentAccess - TS: getPublicCredentials returns manifest-scoped credentials for chain requests - Go protocol: CID integrity check, version validation, VerifiedCredential struct cleanup (Aud/Action/CID fields) - Go relay: revocation + credential ingestion, store, and classification - Go relay: documents endpoint (GET /content/:contentId/documents) - Go relay: well-known documents capability, version 0.8.0 - Go relay: updated verifyReadCredential error messages - OpenAPI: enum updates (IngestionResult.kind, StoredOperation.chainType), field fixes (nextCursor, headCID, limit defaults), added log endpoints, uploadBlob path fix - Prose: PROTOCOL.md, CREDENTIALS.md, WEB-RELAY.md terminology (VC-JWT → DFOS credential, sub → aud) - CLI: help text terminology cleanup - Example fixtures: sub → aud, subjectPublicKey → audiencePublicKey - Go test comments: VC → credential terminology Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
- Rewrite Go relay auth with full verifyContentAccess matching TS relay: creator check → public credentials → per-request credential, with delegation chain verification, revocation at every level, manifest transitive lookup, and monotonic attenuation enforcement - Fix Go GetPublicCredentials manifest matching bug (dead code) - Fix Go ingestRevocation: unconditional CID check, version/type validation - Restore beacon version: 1 field across TS/Go schemas for consistency - Add TS relay integration tests: revocation ingestion, public credential ingestion, standing authorization, revocation cascade, documents endpoint - Fix stale test names (DFOSContentRead → read credential) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…elegation chain parity, SQLite store - F1: TS relay credential verification now uses historical key resolution (credentials survive key rotation, revocation is the invalidation mechanism) - F2: chain:* wildcard resource support in matchesResource and isAttenuated across TS protocol, TS relay, Go relay, and Go protocol library - F3: Go verifyCredentialCore att pairing fix (action+resource from same entry) - F4: Go protocol-level delegation chain walk (VerifyDelegationChain) — content chain authorization now walks prf recursively instead of flat iss != creatorDID check - F5: Go VerifyRevocation extracted to protocol library, relay uses it - F6: SQLite store implementations for all 7 new methods (revocations, public credentials, documents) with schema DDL - F7: Go conformance tests for revocation, public credentials, standing authorization, and documents endpoint - F8: TS tests for chain:* wildcard attenuation, cascading revocation, and wildcard standing authorization Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ization - Make verifyDelegationChain unexported (only called internally) - Add chain:* wildcard handling in verifyContentAuthorization so wildcard-scoped write credentials work for delegated content creation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Document chain:* wildcard resource pattern in CREDENTIALS.md with full attenuation hierarchy table (chain:* > manifest:M > chain:X) - Export AttEntry, ParseAtt, ParsePrf, ParseResource, ParseActions, IsAttenuated from Go protocol library — relay imports shared types instead of maintaining ~200 lines of duplicated logic - Fix conformance test timestamp format (RFC3339 → protocol millisecond format) so revocation tests pass against both TS and Go relays - Add conformance-server.ts for running Go conformance tests against the TS relay locally Conformance: 102 tests pass against both TS relay and Go relay. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PROTOCOL.md links to /credentials and SIWD.md exists but neither had site pages. Adds both spec pages following the existing pattern and updates footer navigation + specs grid on all pages. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ecurity Add 22 unit tests for delegation.go exports (ParseResource, ParseActions, ParseAtt, ParsePrf, IsAttenuated) covering chain:* wildcard, manifest interactions, narrowing/widening, and edge cases. Add 9 conformance tests exercising credential security boundaries: - chain:* wildcard standing auth and per-request credentials - audience mismatch rejection - cascading revocation (parent revoked blocks child) - delegation expiry bounds enforcement - attenuation violation rejection (scope widening) - delegation gap rejection (child issuer not in parent audience) - multi-hop delegation chain (3 levels: creator → A → B → reader) - delegation root mismatch rejection All tests verified against both TS relay and Go relay. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Credentials are long-lived artifacts — their validity persists across key rotations. Revocation (not key rotation) is the invalidation mechanism. Previously, ingest.ts used current-state-only key resolution for public credential ingestion, causing valid credentials signed before a key rotation to be rejected. Now uses historical key resolution (walking the full identity chain log) consistent with access-time verification. Go relay already used historical resolution — no code change needed. Updates CREDENTIALS.md spec prose to document the key resolution distinction between auth tokens (current-state) and credentials (historical). Adds key rotation row to the comparison table. Adds tests: - TS relay: credential ingestion after key rotation, per-request credential access after key rotation (2 new tests, 107 total) - Go conformance: public credential ingestion after key rotation, per-request credential after key rotation (2 new tests, verified against both TS and Go relays) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…y gaps - Extract createHistoricalIdentityResolver as shared helper (was duplicated in auth.ts and ingest.ts) - Fix content chain authorization to use historical key resolution (parity with Go relay) - Add idempotency guards to ingestRevocation and ingestPublicCredential - Update Go VerifiedCredential to carry full Att []AttEntry array - Replace legacy CreateCredential(credType, contentID) API with CreateCredential(resource, action) — new att-based vocabulary - Update all conformance tests, protocol tests, and CLI to new API - Add revocation scope prose to CREDENTIALS.md (forward-looking only) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Rename VerifyCredential expectedType parameter to expectedAction, accepting "read"/"write" directly instead of mapping through legacy type strings. Update all call sites across protocol library, CLI, and tests. No legacy credential type vocabulary remains in active code. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The well-known endpoint now reads the version from package.json at runtime via createRequire, eliminating a manual sync point during releases. QUICKSTART.md updated to reference :latest tag with a note about pinned versions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This was referenced Apr 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Complete credential and authorization layer for the DFOS protocol, with full parity across TypeScript and Go implementations:
prfarrays, and monotonic attenuation enforcement (max 16 hops)aud: "*") stored by relays, granting any authenticated identity access without per-request credential headerschain:*wildcard resource — Broadest scope credential covering all content chains, with full attenuation hierarchy:chain:*>manifest:M>chain:Xprfwalk with signature verification, audience linkage, expiry bounds, revocation at every hop, and identity deletion checkscreateHistoricalIdentityResolverhelper eliminates duplicationCreateCredentialuses att-based vocabulary (resource,action) directly. No legacycredTypeshim.VerifiedCredentialcarries fullAtt []AttEntryarrayGET /content/:contentId/documentsreturns document history with operation CIDs, document CIDs, signer DIDs, and timestampsmanifest:<id>credentials transitively cover all content chains indexed by that manifest's entriesAttEntry,ParseAtt,ParsePrf,ParseResource,ParseActions,IsAttenuated,VerifyRevocationextracted to protocol library/credentialsand/siwdspec pages, updated navigation across all pagesTest coverage
chain:*wildcard access, attenuation violation rejection, cascading revocation, audience mismatch, delegation expiry bounds, delegation gap, root mismatch, credential ingestion/access after key rotationSpecs
CREDENTIALS.md— Full credential spec includingchain:*wildcard, attenuation rules, delegation chain verification, revocation scope semantics, key resolution (historical vs current-state)SIWD.md— Sign In With DFOS specification for third-party identity verificationPROTOCOL.md— Updated with credential references and terminology alignmentWEB-RELAY.md— Updated with credential endpoints and revocation semanticsCONTENT-MODEL.md— Updated content model terminologyTest plan
pnpm typecheck— 0 errorspnpm test— all TS tests pass (107 relay, 242 protocol)Generated with Claude Code