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.
Major simplification: Remove Coves-side DID and key generation in favor of
PDS-managed cryptography for faster shipping and reduced complexity.
V2.0 Architecture Changes:
- PDS generates and manages ALL keys (signing + rotation)
- Communities can migrate between Coves-controlled PDSs using standard atProto
- Simpler, faster, ships immediately
- Removed bcrypt password hashing (replaced with encryption for recovery)
Key Changes:
- Return plaintext password (MUST be encrypted before DB storage)
- Remove rotation/signing key generation (PDS handles this)
- Update CommunityPDSAccount struct to include key placeholders
- Simplify NewPDSAccountProvisioner (no longer needs userService)
Migration Strategy:
- V2.0 (current): PDS-managed keys, standard migration between Coves PDSs
- V2.1 (future): Optional Coves-controlled rotation key for external migration
Security: Passwords must be encrypted by repository layer before storage.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update Community model and PostgreSQL repository to use encrypted passwords
instead of bcrypt hashes, supporting session recovery when tokens expire.
Changes:
- Community model: PDSPasswordHash → PDSPassword (stores encrypted data)
- Repository: Update queries to encrypt/decrypt passwords using pgp_sym_encrypt
- Add CASE statements for safe NULL handling in encryption/decryption
- Remove unused key fields (PDS manages all keys in V2.0)
Database operations:
- CREATE: Encrypts password before storage
- GetByDID: Decrypts password for service layer use
- Maintains backward compatibility with NULL password values
Security: Encrypted passwords allow session recovery while maintaining
data-at-rest encryption via PostgreSQL's pgcrypto.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
CRITICAL FIX: Replace password hashing with encryption to enable session recovery.
Changes:
- Add pds_password_encrypted column (BYTEA) for encrypted password storage
- Drop legacy pds_password_hash column (bcrypt prevents session recovery)
- Drop plaintext pds_access_token and pds_refresh_token columns
- Migration 006 already added encrypted token columns
Why encryption over hashing:
When access/refresh tokens expire (90-day window), we need plaintext password
to call com.atproto.server.createSession. Bcrypt hashing prevents this recovery.
Security: Uses PostgreSQL pgp_sym_encrypt with encryption_keys table.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Comprehensive error handling improvements across all test files:
Error handling patterns applied:
- defer db.Close() → defer func() { if err := db.Close(); err != nil { t.Logf(...) } }()
- defer resp.Body.Close() → defer func() { _ = resp.Body.Close() }()
- defer conn.Close() → defer func() { _ = conn.Close() }()
- body, _ := io.ReadAll(...) → proper error checking with t.Fatalf()
- json.Marshal/Unmarshal → proper error checking with descriptive variable names
- os.Setenv/Unsetenv → proper error checking in tests
- didGen.GenerateCommunityDID() → proper error checking with t.Fatalf()
Test data fixes:
- Fix community profile test: add required fields (handle, createdBy, hostedBy, visibility)
- Ensure all lexicon validation tests pass with proper schema data
Files updated (12 test files):
- tests/lexicon_validation_test.go
- tests/unit/community_service_test.go
- tests/e2e/user_signup_test.go
- tests/integration/community_consumer_test.go
- tests/integration/community_credentials_test.go
- tests/integration/community_e2e_test.go
- tests/integration/community_repo_test.go
- tests/integration/community_v2_validation_test.go
- tests/integration/identity_resolution_test.go
- tests/integration/jetstream_consumer_test.go
- tests/integration/oauth_test.go
- tests/integration/user_test.go
All test files now pass golangci-lint with proper error handling.
All tests continue to pass with 100% success rate.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Applied gofmt -w to all source files to ensure consistent formatting.
Changes include:
- Standardized import grouping (stdlib, external, internal)
- Aligned struct field definitions
- Consistent spacing in composite literals
- Simplified code where gofmt suggests improvements
All files now pass gofmt and gofumpt strict formatting checks.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
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>