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>
92 lines
3.4 KiB
Markdown
92 lines
3.4 KiB
Markdown
# 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:
|
|
|
|
1. Create DTOs with validation
|
|
2. Write service tests first (RED)
|
|
3. Implement service with VaultService integration (GREEN)
|
|
4. Write controller tests (RED)
|
|
5. Implement controller with guards (GREEN)
|
|
6. Create module and wire dependencies
|
|
7. Verify all tests pass with 85%+ coverage
|
|
|
|
## Key Patterns Followed
|
|
|
|
- RLS: Use `getRlsClient() ?? this.prisma` pattern
|
|
- 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
|
|
|
|
- [x] apps/api/src/credentials/dto/create-credential.dto.ts
|
|
- [x] apps/api/src/credentials/dto/update-credential.dto.ts
|
|
- [x] apps/api/src/credentials/dto/query-credential.dto.ts
|
|
- [x] apps/api/src/credentials/dto/credential-response.dto.ts
|
|
- [x] apps/api/src/credentials/dto/rotate-credential.dto.ts
|
|
- [x] apps/api/src/credentials/dto/index.ts
|
|
- [x] apps/api/src/credentials/credentials.service.spec.ts (18 tests - all passing)
|
|
- [x] apps/api/src/credentials/credentials.service.ts
|
|
- [x] apps/api/src/credentials/credentials.controller.spec.ts (8 tests - all passing)
|
|
- [x] apps/api/src/credentials/credentials.controller.ts
|
|
- [x] apps/api/src/credentials/credentials.module.ts
|
|
- [x] apps/api/src/credentials/index.ts
|
|
|
|
## Files Modified
|
|
|
|
- [x] 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
|