# 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 - [x] Backend: Create CredentialAuditQueryDto - [x] Backend: Add getAuditLog method to CredentialsService - [x] Backend: Add getAuditLog endpoint to CredentialsController - [x] Backend: Tests for audit query (25 tests all passing) - [x] Frontend: Create audit page /settings/credentials/audit - [x] Frontend: Create AuditLogViewer component - [x] Frontend: Add audit log API client function - [x] 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