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.
- 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>
Update development PostgreSQL port from 5433 to 5435 to avoid conflicts
with existing local PostgreSQL installations or other services.
Changes:
- .env.dev: Update POSTGRES_PORT to 5435
- docker-compose.dev.yml: Update health checks to use wget instead of curl
- cmd/server/main.go: Update default DATABASE_URL to use port 5435
Additional improvements:
- Replace curl with wget in Docker healthchecks (more reliable in Alpine)
- Update comments to reflect new port configuration
Ports summary:
- Dev PostgreSQL: 5435 (was 5433)
- Test PostgreSQL: 5434 (unchanged)
- PDS: 3001
- AppView: 8081
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>