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.
Add comprehensive integration tests for V2.0 community provisioning
with encrypted passwords and PDS-managed key generation.
New Test Files:
- community_provisioning_test.go: Password encryption/decryption validation
- community_service_integration_test.go: E2E PDS account creation tests
Test Coverage:
- Password encryption and decryption correctness
- Plaintext password recovery after storage
- PDS account creation with real PDS instance
- DID and handle generation by PDS
- Credential persistence and recovery
These tests verify the critical V2.0 fix: passwords are encrypted
(not hashed) to enable session recovery when access tokens expire.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Update CommunityService and server initialization to remove Coves-side
DID generation. V2.0 architecture delegates all DID and key management
to the PDS for simplicity and faster shipping.
Service Layer Changes:
- Remove didGenerator parameter from NewCommunityService
- PDS provisioner handles account creation and receives DID from PDS
- Simplified service constructor signature
Server Initialization Changes:
- Remove DID generator initialization
- Simplify PDS provisioner creation (no userService needed)
- Add comprehensive logging for dev vs production modes
- Unify PLC directory URL configuration for identity resolver
- Ensure dev mode uses local PLC directory for E2E testing
Configuration:
- IS_DEV_ENV=true: Use local PLC directory for both creation and resolution
- IS_DEV_ENV=false: Use production PLC or IDENTITY_PLC_URL override
This change prepares for V2.0 where communities are fully PDS-native entities.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
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>