Files
stack/docs/scratchpads/361-credential-audit-viewer.md
Jason Woltje 6521cba735
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
feat: add flexible docker-compose architecture with profiles
- Add OpenBao services to docker-compose.yml with profiles (openbao, full)
- Add docker-compose.build.yml for local builds vs registry pulls
- Make PostgreSQL and Valkey optional via profiles (database, cache)
- Create example compose files for common deployment scenarios:
  - docker/docker-compose.example.turnkey.yml (all bundled)
  - docker/docker-compose.example.external.yml (all external)
  - docker/docker.example.hybrid.yml (mixed deployment)
- Update documentation:
  - Enhance .env.example with profiles and external service examples
  - Update README.md with deployment mode quick starts
  - Add deployment scenarios to docs/OPENBAO.md
  - Create docker/DOCKER-COMPOSE-GUIDE.md with comprehensive guide
- Clean up repository structure:
  - Move shell scripts to scripts/ directory
  - Move documentation to docs/ directory
  - Move docker compose examples to docker/ directory
- Configure for external Authentik with internal services:
  - Comment out Authentik services (using external OIDC)
  - Comment out unused volumes for disabled services
  - Keep postgres, valkey, openbao as internal services

This provides a flexible deployment architecture supporting turnkey,
production (all external), and hybrid configurations via Docker Compose
profiles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 16:55:33 -06:00

6.7 KiB

Issue #361: Credential Audit Log Viewer

Objective

Implement a credential audit log viewer to display all credential-related activities with filtering, pagination, and a PDA-friendly interface. This is a stretch goal for Phase 5c of M9-CredentialSecurity.

Approach

  1. Backend: Add audit query method to CredentialsService that filters ActivityLog by entityType=CREDENTIAL
  2. Backend: Add GET /api/credentials/audit endpoint with filters (date range, action type, credential ID)
  3. Frontend: Create page at /settings/credentials/audit
  4. Frontend: Build AuditLogViewer component with:
    • Date range filter
    • Action type filter (CREATED, ACCESSED, ROTATED, UPDATED, etc.)
    • Credential name filter
    • Pagination (10-20 items per page)
    • PDA-friendly timestamp formatting
    • Mobile-responsive table layout

Design Decisions

  • Reuse ActivityService.findAll(): The existing query method supports all needed filters
  • RLS Enforcement: Users see only their own workspace's activities
  • Pagination: Default 20 items per page (matches web patterns)
  • Simple UI: Stretch goal = minimal implementation, no complex features
  • Activity Types: Filter by these actions:
    • CREDENTIAL_CREATED
    • CREDENTIAL_ACCESSED
    • CREDENTIAL_ROTATED
    • CREDENTIAL_REVOKED
    • UPDATED (for metadata changes)

Progress

  • Backend: Create CredentialAuditQueryDto
  • Backend: Add getAuditLog method to CredentialsService
  • Backend: Add getAuditLog endpoint to CredentialsController
  • Backend: Tests for audit query (25 tests all passing)
  • Frontend: Create audit page /settings/credentials/audit
  • Frontend: Create AuditLogViewer component
  • Frontend: Add audit log API client function
  • Frontend: Navigation link to audit log
  • Testing: Manual E2E verification (when API integration complete)
  • Documentation: Update if needed

Testing

  • API returns paginated results
  • Filters work correctly (date range, action type, credential ID)
  • RLS enforced (users see only their workspace data)
  • Pagination works (next/prev buttons functional)
  • Timestamps display correctly (PDA-friendly)
  • Mobile layout is responsive
  • UI gracefully handles empty state

Notes

  • Keep implementation simple - this is a stretch goal
  • Leverage existing ActivityService patterns
  • Follow PDA design principles (no aggressive language, clear status)
  • No complex analytics needed

Implementation Status

  • Started: 2026-02-07
  • Completed: 2026-02-07

Files Created/Modified

Backend

  1. apps/api/src/credentials/dto/query-credential-audit.dto.ts (NEW)

    • QueryCredentialAuditDto with filters: credentialId, action, startDate, endDate, page, limit
    • Validation with class-validator decorators
    • Default page=1, limit=20, max limit=100
  2. apps/api/src/credentials/dto/index.ts (MODIFIED)

    • Exported QueryCredentialAuditDto
  3. apps/api/src/credentials/credentials.service.ts (MODIFIED)

    • Added getAuditLog() method
    • Filters by workspaceId and entityType=CREDENTIAL
    • Returns paginated audit logs with user info
    • Supports filtering by credentialId, action, and date range
    • Returns metadata: total, page, limit, totalPages
  4. apps/api/src/credentials/credentials.controller.ts (MODIFIED)

    • Added GET /api/credentials/audit endpoint
    • Placed before parameterized routes to avoid path conflicts
    • Requires WORKSPACE_ANY permission (all members can view)
    • Uses existing WorkspaceGuard for RLS enforcement
  5. apps/api/src/credentials/credentials.service.spec.ts (MODIFIED)

    • Added 8 comprehensive tests for getAuditLog():
      • Returns paginated results
      • Filters by credentialId
      • Filters by action type
      • Filters by date range
      • Handles pagination correctly
      • Orders by createdAt descending
      • Always filters by CREDENTIAL entityType

Frontend

  1. apps/web/src/lib/api/credentials.ts (MODIFIED)

    • Added AuditLogEntry interface
    • Added QueryAuditLogDto interface
    • Added fetchCredentialAuditLog() function
    • Builds query string with optional parameters
  2. apps/web/src/app/(authenticated)/settings/credentials/audit/page.tsx (NEW)

    • Full audit log viewer page component
    • Features:
      • Filter by action type (dropdown with 5 options)
      • Filter by date range (start and end date inputs)
      • Pagination (20 items per page)
      • Desktop table layout with responsive mobile cards
      • PDA-friendly timestamp formatting
      • Action badges with color coding
      • User information display (name + email)
      • Details display (credential name, provider)
      • Empty state handling
      • Error state handling
  3. apps/web/src/app/(authenticated)/settings/credentials/page.tsx (MODIFIED)

    • Added History icon import
    • Added Link import for next/link
    • Added "Audit Log" button linking to /settings/credentials/audit
    • Button positioned in header next to "Add Credential"

Design Decisions

  1. Activity Type Filtering: Shows 5 main action types (CREATED, ACCESSED, ROTATED, REVOKED, UPDATED)
  2. Pagination: Default 20 items per page (good balance for both mobile and desktop)
  3. PDA-Friendly Design:
    • No aggressive language
    • Clear status indicators with colors
    • Responsive layout for all screen sizes
    • Timestamps in readable format
  4. Mobile Support: Separate desktop table and mobile card layouts
  5. Reused Patterns: Activity service already handles entity filtering

Test Coverage

  • Backend: 25 tests all passing
  • Unit tests cover all major scenarios
  • Tests use mocked PrismaService and ActivityService
  • Async/parallel query testing included

Notes

  • Stretch goal kept simple and pragmatic
  • Reused existing ActivityLog and ActivityService patterns
  • RLS enforcement via existing WorkspaceGuard
  • No complex analytics or exports needed
  • All timestamps handled via browser Intl API for localization

Build Status

  • API builds successfully (pnpm build in apps/api)
  • Web builds successfully (pnpm build in apps/web)
  • All backend unit tests passing (25/25)
  • TypeScript compilation successful for both apps

Endpoints Implemented

  • GET /api/credentials/audit - Fetch audit logs with filters
    • Query params: credentialId, action, startDate, endDate, page, limit
    • Response: Paginated audit logs with user info
    • Authentication: Required (WORKSPACE_ANY permission)

Frontend Routes Implemented

  • GET /settings/credentials - Credentials management page (updated with audit log link)
  • GET /settings/credentials/audit - Credential audit log viewer page

API Client Functions

  • fetchCredentialAuditLog(workspaceId, query?) - Get paginated audit logs with optional filters