code
Clone this repository
https://tangled.org/bretton.dev/coves
git@knot.bretton.dev:bretton.dev/coves
For self-hosted knots, clone URLs may differ based on your setup.
Document DPoP token binding implementation:
- Explain DPoP security model and why it's not a fallback
- Add flow diagrams for DPoP verification process
- Document replay protection with NonceCache
- Add code examples for DPoP verification
- List implemented security features and future enhancements
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
JWT improvements:
- Add Confirmation field for DPoP cnf.jkt claim binding
- Reorder Claims struct fields for optimal memory alignment
Test improvements:
- Replace os.Setenv/os.Unsetenv with t.Setenv for cleaner tests
- Use t.Cleanup for automatic environment restoration
- Use UUID for DPoP proof jti to ensure test uniqueness
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Enhance AtProtoAuthMiddleware with DPoP token binding support:
- Add Stop() method to prevent goroutine leaks on shutdown
- Require DPoP proof when token has cnf.jkt claim
- Treat DPoP-bound tokens without proof as unauthenticated in OptionalAuth
- Honor X-Forwarded-Proto header for URI verification behind proxies
Security model:
- DPoP is ADDITIONAL security, never a fallback for failed verification
- Token signature must be verified BEFORE checking DPoP binding
- Missing DPoP proof for bound tokens results in rejection
Tests added for:
- Middleware Stop() cleanup
- OptionalAuth with DPoP-bound tokens
- X-Forwarded-Proto handling
- DPoP replay protection integration
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add proof-of-possession verification for OAuth access tokens:
- DPoPVerifier for validating DPoP proof JWTs
- NonceCache for replay attack prevention with background cleanup
- JWK thumbprint calculation per RFC 7638
- Support for ES256 signing algorithm
- Configurable clock skew and proof age limits
Security features:
- Validates htm (HTTP method) and htu (HTTP URI) claims
- Enforces iat freshness within 5-minute window
- Tracks jti values to prevent proof reuse
- Calculates and validates JWK thumbprints for token binding
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add ES256 federation support and JWT config caching:
- DID-based key fetcher for verifying tokens from any PDS
- O(1) issuer whitelist lookups with cached config
- Environment configuration documentation
馃 Generated with [Claude Code](https://claude.com/claude-code)
Document the dual JWT verification methods (HS256 + ES256) in environment
configuration files:
- HS256: For your own PDS (fast, shared secret, no network calls)
- ES256: For federated users (DID resolution, works with any PDS)
Updates:
- .env.dev: Add HS256_ISSUERS for local development
- .env.prod.example: Add JWT Authentication section with documentation
- docker-compose.prod.yml: Pass PDS_JWT_SECRET and HS256_ISSUERS to appview
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Cache HS256_ISSUERS, PDS_JWT_SECRET, and IS_DEV_ENV at startup instead
of reading environment variables on every token verification request.
- Add jwtConfig struct with sync.Once initialization
- Use map[string]struct{} for O(1) issuer whitelist lookups
- Add InitJWTConfig() for explicit startup initialization
- Add ResetJWTConfigForTesting() for test isolation
- Update main.go to call InitJWTConfig() at startup
Before: 2-3 os.Getenv() calls + O(n) string iteration per request
After: Single pointer dereference + O(1) map lookup per request
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add support for verifying ES256 service auth tokens from federated users.
This enables users from any PDS (bsky.social, etc.) to authenticate with
Coves instances.
- DIDKeyFetcher: resolves DID documents via PLC directory to get public keys
- CombinedKeyFetcher: routes to DID or JWKS based on issuer format
- Supports did:plc: and did:web: issuers
- Converts atcrypto JWK to Go ecdsa.PublicKey for jwt-go verification
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Only did:web:coves.social can now create communities in production.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Replace local disk blobstore with S3-compatible storage configuration.
This allows blobs to be stored in OVH Object Storage while keeping
record data (CAR files, SQLite) on local NVMe.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Adds optional sources field to social.coves.embed.external lexicon
to support aggregator megathreads that combine multiple news sources.
Changes:
- Add #source definition with uri, title, domain, and optional sourcePost
- Add sources array (max 50) to #external for aggregated links
- Add maxLength constraints to domain (253) and provider (100) fields
- Update descriptions to clarify primary vs aggregated content
This enables LLM aggregators to create megathread posts that reference
multiple source articles, with optional strongRef to existing Coves
posts for future feed deprioritization.
馃 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>