Build credential CRUD API endpoints #356

Closed
opened 2026-02-07 17:11:44 +00:00 by jason.woltje · 0 comments
Owner

Phase 3b - User Credential API

Problem

Users and admins need CRUD API endpoints to manage credentials (API keys, git tokens, etc.) stored in the UserCredential table. Credential values must be encrypted via VaultService and access must be audit-logged.

Requirements

User Credential Endpoints

  • POST /api/credentials - Create credential (encrypt value, store ciphertext)
  • GET /api/credentials - List credentials (masked values only, NEVER plaintext)
  • GET /api/credentials/:id - Get single credential (masked)
  • GET /api/credentials/:id/value - Decrypt and return value (audit logged)
  • PATCH /api/credentials/:id - Update metadata only (not the value)
  • POST /api/credentials/:id/rotate - Replace with new encrypted value
  • DELETE /api/credentials/:id - Soft-delete (set isActive=false)

Admin Secret Endpoints

  • POST /api/admin/secrets - Create system-level secret (AdminGuard)
  • GET /api/admin/secrets - List system secrets (AdminGuard)
  • PATCH /api/admin/secrets/:id - Update system secret
  • DELETE /api/admin/secrets/:id - Revoke system secret

Security Design

  • User endpoints: AuthGuard + WorkspaceGuard + PermissionGuard
  • Admin endpoints: AuthGuard + AdminGuard
  • GET /:id/value is intentionally separate from GET /:id - listing should NEVER return plaintext
  • Every decryption (GET /value) creates an audit log entry (ActivityAction.CREDENTIAL_ACCESSED)
  • Create, rotate, and delete also create audit entries
  • Credential value never appears in response DTOs (only maskedValue)

Implementation Notes

  • CredentialsModule with controller, service, DTOs
  • Inject VaultService for encrypt/decrypt
  • Inject ActivityService for audit logging
  • Create DTOs: CreateCredentialDto, UpdateCredentialDto, QueryCredentialDto, CredentialResponseDto
  • CredentialResponseDto MUST NOT include encryptedValue field
  • On create: encrypt value, generate maskedValue (last 4 chars), store
  • On rotate: encrypt new value, update maskedValue and rotatedAt
  • On getValue: decrypt, update lastUsedAt, log access

Files

  • apps/api/src/credentials/credentials.module.ts (new)
  • apps/api/src/credentials/credentials.controller.ts (new)
  • apps/api/src/credentials/credentials.controller.spec.ts (new)
  • apps/api/src/credentials/credentials.service.ts (new)
  • apps/api/src/credentials/credentials.service.spec.ts (new)
  • apps/api/src/credentials/dto/create-credential.dto.ts (new)
  • apps/api/src/credentials/dto/update-credential.dto.ts (new)
  • apps/api/src/credentials/dto/query-credential.dto.ts (new)
  • apps/api/src/credentials/dto/credential-response.dto.ts (new)
  • apps/api/src/credentials/admin-credentials.controller.ts (new)
  • apps/api/src/credentials/admin-credentials.controller.spec.ts (new)
  • apps/api/src/app.module.ts (modify - import CredentialsModule)

Acceptance Criteria

  • All user credential CRUD endpoints working
  • All admin secret endpoints working
  • Values encrypted via VaultService before storage
  • Plaintext never appears in list/get responses (only maskedValue)
  • GET /value decrypts and returns plaintext
  • All credential operations audit-logged
  • RLS enforces per-user isolation
  • Input validation via class-validator DTOs
  • Unit tests for service logic
  • Integration tests for API endpoints

Dependencies

  • Depends on: UserCredential model
  • Depends on: VaultService (Phase 2b)
  • Blocks: Frontend credential management (Phase 4)

Refs #346

## Phase 3b - User Credential API ### Problem Users and admins need CRUD API endpoints to manage credentials (API keys, git tokens, etc.) stored in the UserCredential table. Credential values must be encrypted via VaultService and access must be audit-logged. ### Requirements #### User Credential Endpoints - POST /api/credentials - Create credential (encrypt value, store ciphertext) - GET /api/credentials - List credentials (masked values only, NEVER plaintext) - GET /api/credentials/:id - Get single credential (masked) - GET /api/credentials/:id/value - Decrypt and return value (audit logged) - PATCH /api/credentials/:id - Update metadata only (not the value) - POST /api/credentials/:id/rotate - Replace with new encrypted value - DELETE /api/credentials/:id - Soft-delete (set isActive=false) #### Admin Secret Endpoints - POST /api/admin/secrets - Create system-level secret (AdminGuard) - GET /api/admin/secrets - List system secrets (AdminGuard) - PATCH /api/admin/secrets/:id - Update system secret - DELETE /api/admin/secrets/:id - Revoke system secret ### Security Design - User endpoints: AuthGuard + WorkspaceGuard + PermissionGuard - Admin endpoints: AuthGuard + AdminGuard - GET /:id/value is intentionally separate from GET /:id - listing should NEVER return plaintext - Every decryption (GET /value) creates an audit log entry (ActivityAction.CREDENTIAL_ACCESSED) - Create, rotate, and delete also create audit entries - Credential value never appears in response DTOs (only maskedValue) ### Implementation Notes - CredentialsModule with controller, service, DTOs - Inject VaultService for encrypt/decrypt - Inject ActivityService for audit logging - Create DTOs: CreateCredentialDto, UpdateCredentialDto, QueryCredentialDto, CredentialResponseDto - CredentialResponseDto MUST NOT include encryptedValue field - On create: encrypt value, generate maskedValue (last 4 chars), store - On rotate: encrypt new value, update maskedValue and rotatedAt - On getValue: decrypt, update lastUsedAt, log access ### Files - apps/api/src/credentials/credentials.module.ts (new) - apps/api/src/credentials/credentials.controller.ts (new) - apps/api/src/credentials/credentials.controller.spec.ts (new) - apps/api/src/credentials/credentials.service.ts (new) - apps/api/src/credentials/credentials.service.spec.ts (new) - apps/api/src/credentials/dto/create-credential.dto.ts (new) - apps/api/src/credentials/dto/update-credential.dto.ts (new) - apps/api/src/credentials/dto/query-credential.dto.ts (new) - apps/api/src/credentials/dto/credential-response.dto.ts (new) - apps/api/src/credentials/admin-credentials.controller.ts (new) - apps/api/src/credentials/admin-credentials.controller.spec.ts (new) - apps/api/src/app.module.ts (modify - import CredentialsModule) ### Acceptance Criteria - [ ] All user credential CRUD endpoints working - [ ] All admin secret endpoints working - [ ] Values encrypted via VaultService before storage - [ ] Plaintext never appears in list/get responses (only maskedValue) - [ ] GET /value decrypts and returns plaintext - [ ] All credential operations audit-logged - [ ] RLS enforces per-user isolation - [ ] Input validation via class-validator DTOs - [ ] Unit tests for service logic - [ ] Integration tests for API endpoints ### Dependencies - Depends on: UserCredential model - Depends on: VaultService (Phase 2b) - Blocks: Frontend credential management (Phase 4) Refs #346
jason.woltje added this to the M9-CredentialSecurity (0.0.9) milestone 2026-02-07 17:11:44 +00:00
jason.woltje added the securityapiapip1 labels 2026-02-07 17:11:44 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaic/stack#356