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.
Configuration changes:
- Add gofmt, gofumpt, and goimports linters to .golangci.yml
- Configure gofmt.simplify to simplify code where possible
- Configure gofumpt with extra-rules for stricter formatting
- Configure errcheck.check-blank=false to allow blank assignments in defer closures (idiomatic Go)
- Disable govet shadow checking to reduce noise in tests (common practice)
- Exclude local_dev_data and vendor directories from linting
Makefile enhancements:
- Add 'fmt' target: format all Go code with gofmt
- Add 'fmt-check' target: verify code is formatted (CI-friendly, fails if not formatted)
- Update 'lint' target: now runs fmt-check automatically before linting
- Update 'lint-fix' target: runs golangci-lint --fix AND gofmt
- Update linter to run on specific paths (./cmd/... ./internal/... ./tests/...) to avoid permission issues
Formatting is now enforced as part of the standard lint workflow.
Running 'make lint' will catch both code issues and formatting problems.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix errcheck issues: add error handling for unchecked returns
- Added proper error checks for JSON encoders with logging
- Wrapped deferred cleanup calls (Close, Rollback) with anonymous functions
- Added error handling for SetReadDeadline, Write, and HTTP response operations
- Fix shadow declarations: rename variables to avoid shadowing
- Renamed inner error variables to descriptive names (closeErr, rollbackErr, marshalErr, etc.)
- Fixed shadow issues in cmd/genjwks, cmd/server, and internal packages
- Fix staticcheck issues: document empty branches
- Added explanatory comments for intentionally empty branches
- Made error handling more explicit with updateErr variables
- Remove unused functions to clean up codebase
- Removed putRecordOnPDS() in communities service
- Removed extractDomain() in communities service
- Removed validateHandle() in jetstream community consumer
- Removed nullBytes() in postgres community repo
- Removed unused strings import
- Simplify nil checks for slices per gosimple suggestions
- len() for nil slices is defined as zero, removed redundant nil checks
All production code now passes golangci-lint with zero errors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This PR implements the V2 Communities Architecture with critical fixes
for production readiness.
## V2 Architecture Highlights
**Communities now own their own repositories:**
- Each community has its own DID (did:plc:xxx)
- Each community owns its own atProto repository (at://community_did/...)
- Communities are truly portable (can migrate between instances)
- Follows atProto patterns (matches feed generators, labelers)
## Critical Fixes
1. **PDS Credential Persistence**: Fixed bug where credentials were lost
on server restart, causing community updates to fail
2. **Encryption at Rest**: Community PDS credentials encrypted using
PostgreSQL pgcrypto
3. **Handle Simplification**: Single handle field (removed duplicate
atProtoHandle), using subdomain pattern (*.communities.coves.social)
4. **Default Domain Fix**: Changed from coves.local → coves.social to
avoid .local TLD validation errors
5. **V2 Enforcement**: Removed V1 compatibility, strict rkey="self"
## Testing
- ✅ Full E2E test coverage (PDS → Jetstream → AppView)
- ✅ Integration tests for credential persistence
- ✅ Unit tests for V2 validation
- ✅ Real Jetstream firehose consumption
## Documentation
- Updated PRD_COMMUNITIES.md with V2 status
- Created PRD_BACKLOG.md for technical debt tracking
- Documented handle refactor and security considerations
## Security Notes
- Added TODO for did:web domain verification (prevents impersonation)
- Documented in PRD_BACKLOG.md as P0 priority
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added infrastructure/technical TODOs:
- OAuth authentication for community actions (P1)
- Jetstream consumer race condition (P2)
- Structured logging migration (P3)
- PDS URL resolution from DID (P3)
- PLC directory registration for prod (P3)
Feature-specific TODOs (avatars, moderator checks, update/delete handlers)
are tracked in their respective PRDs (PRD_COMMUNITIES, PRD_GOVERNANCE).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem:
- Default INSTANCE_DID was did:web:coves.local
- instanceDomain extracted as "coves.local"
- Community handles generated as "{name}.communities.coves.local"
- .local TLD is disallowed per atProto spec (RFC 6762)
- Result: Community creation failed immediately with InvalidHandleError
Solution:
- Changed default to did:web:coves.social (.social is valid TLD)
- Added TODO comment documenting did:web domain verification security issue
- Created docs/PRD_BACKLOG.md to track follow-up work
Security Note:
Self-hosters can currently set INSTANCE_DID to any domain without
verification. This enables domain impersonation attacks. Added to
backlog (P0) to implement did:web verification per atProto spec.
Testing:
- All integration tests pass (TestCommunity_E2E)
- Community handles now: gaming.communities.coves.social ✓
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add logging for internal server errors in community XRPC handlers to
aid debugging during development. Internal errors are now logged before
returning generic error responses to clients.
Changes:
- Add log import to errors.go
- Log actual error details when returning InternalServerError
- Add TODO comment to migrate to proper structured logger
Rationale:
During E2E testing, internal errors were being silently swallowed making
debugging difficult. This change logs the actual error while still
returning safe generic error messages to clients.
Security note:
- Internal error details are NOT exposed to clients
- Logging is for server-side debugging only
- Generic "InternalServerError" message still returned to clients
TODO: Replace log.Printf with structured logger (e.g., zerolog/zap)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>