Implement comprehensive CRUD API for managing user credentials with encryption, RLS, and audit logging following TDD methodology. Features: - POST /api/credentials - Create encrypted credential - GET /api/credentials - List credentials (masked values only) - GET /api/credentials/:id - Get single credential (masked) - GET /api/credentials/:id/value - Decrypt plaintext (rate limited 10/min) - PATCH /api/credentials/:id - Update metadata - POST /api/credentials/:id/rotate - Rotate credential value - DELETE /api/credentials/:id - Soft delete Security: - All values encrypted via VaultService (TransitKey.CREDENTIALS) - List/Get endpoints NEVER return plaintext (only maskedValue) - getValue endpoint rate limited to 10 requests/minute per user - All operations audit-logged with CREDENTIAL_* ActivityAction - RLS enforces per-user isolation via getRlsClient() pattern - Input validation via class-validator DTOs Testing: - 26/26 unit tests passing - 95.71% code coverage (exceeds 85% requirement) - Service: 95.16% - Controller: 100% - TypeScript checks pass Files created: - apps/api/src/credentials/credentials.service.ts - apps/api/src/credentials/credentials.service.spec.ts - apps/api/src/credentials/credentials.controller.ts - apps/api/src/credentials/credentials.controller.spec.ts - apps/api/src/credentials/credentials.module.ts - apps/api/src/credentials/dto/*.dto.ts (5 DTOs) Files modified: - apps/api/src/app.module.ts - imported CredentialsModule Note: Admin credentials endpoints deferred to future issue. Current implementation covers all user credential endpoints. Refs #346 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.4 KiB
3.4 KiB
Issue #356: Build credential CRUD API endpoints
Objective
Implement CRUD API endpoints for managing user credentials with encryption, RLS, and audit logging.
Approach
Following TDD approach:
- Create DTOs with validation
- Write service tests first (RED)
- Implement service with VaultService integration (GREEN)
- Write controller tests (RED)
- Implement controller with guards (GREEN)
- Create module and wire dependencies
- Verify all tests pass with 85%+ coverage
Key Patterns Followed
- RLS: Use
getRlsClient() ?? this.prismapattern - Encryption: Use VaultService with TransitKey.CREDENTIALS
- Activity logging: Fire-and-forget pattern like existing activity helpers
- DTOs: class-validator decorators for input validation
- Guards: AuthGuard + WorkspaceGuard + PermissionGuard
- Rate limiting: @Throttle decorator on getValue endpoint (10/minute)
Files Created
- apps/api/src/credentials/dto/create-credential.dto.ts
- apps/api/src/credentials/dto/update-credential.dto.ts
- apps/api/src/credentials/dto/query-credential.dto.ts
- apps/api/src/credentials/dto/credential-response.dto.ts
- apps/api/src/credentials/dto/rotate-credential.dto.ts
- apps/api/src/credentials/dto/index.ts
- apps/api/src/credentials/credentials.service.spec.ts (18 tests - all passing)
- apps/api/src/credentials/credentials.service.ts
- apps/api/src/credentials/credentials.controller.spec.ts (8 tests - all passing)
- apps/api/src/credentials/credentials.controller.ts
- apps/api/src/credentials/credentials.module.ts
- apps/api/src/credentials/index.ts
Files Modified
- apps/api/src/app.module.ts - imported CredentialsModule
Admin Credentials Controller
Decision: Not implemented in this phase
- Issue #356 listed admin endpoints as optional ("Admin Secret Endpoints")
- The UserCredential model supports SYSTEM scope for admin secrets
- Admin endpoints can be added in a future issue when needed
- Current implementation covers all user credential endpoints
Testing Results
- Service tests: 18/18 passing
- Controller tests: 8/8 passing
- Total: 26/26 tests passing
- Coverage: 95.71% (exceeds 85% requirement)
- Service: 95.16%
- Controller: 100%
- TypeScript: All checks pass
Endpoints Implemented
- POST /api/credentials - Create credential
- GET /api/credentials - List credentials (masked values only)
- GET /api/credentials/:id - Get single credential (masked value only)
- GET /api/credentials/:id/value - Decrypt and return plaintext (rate limited 10/min)
- PATCH /api/credentials/:id - Update metadata
- POST /api/credentials/:id/rotate - Rotate credential value
- DELETE /api/credentials/:id - Soft delete
Security Features
- All credential values encrypted with VaultService (TransitKey.CREDENTIALS)
- List/Get endpoints NEVER return plaintext (only maskedValue)
- getValue endpoint rate limited to 10 requests/minute per user
- All operations audit-logged with CREDENTIAL_* ActivityAction enums
- RLS enforces per-user isolation
- Input validation via class-validator DTOs
Notes
- CREDENTIAL_* ActivityAction enums already existed in schema (from issue #355)
- Used existing activity logging pattern (fire-and-forget)
- Followed existing controller patterns for guards and decorators
- maskedValue shows last 4 characters with **** prefix
- TypeScript exactOptionalPropertyTypes required careful handling in update method