Some checks failed
Deploy to Staging / Build Images (pull_request) Successful in 4m42s
Deploy to Staging / Deploy to Staging (pull_request) Successful in 37s
Deploy to Staging / Verify Staging (pull_request) Failing after 6s
Deploy to Staging / Notify Staging Ready (pull_request) Has been skipped
Deploy to Staging / Notify Staging Failure (pull_request) Successful in 6s
- Add audit_logs table with categories, severities, and indexes - Create AuditLogService and AuditLogRepository - Add REST API endpoints for viewing and exporting logs - Wire audit logging into auth, vehicles, admin, and backup features - Add desktop AdminLogsPage with filters and CSV export - Add mobile AdminLogsMobileScreen with card layout - Implement 90-day retention cleanup job - Remove old AuditLogPanel from AdminCatalogPage Security fixes: - Escape LIKE special characters to prevent pattern injection - Limit CSV export to 5000 records to prevent memory exhaustion - Add truncation warning headers for large exports 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
4.5 KiB
4.5 KiB
Audit Log Feature
Centralized audit logging system for tracking all user and system actions across MotoVaultPro.
Architecture
Frontend
+--------------+ +-------------------+
| AdminLogsPage| | AdminLogsMobile |
| (desktop) | | Screen (mobile) |
+------+-------+ +--------+----------+
| |
+-------------------+
|
| useAuditLogs hook
v
adminApi.unifiedAuditLogs
|
| HTTP
v
GET /api/admin/audit-logs?search=X&category=Y&...
GET /api/admin/audit-logs/export
|
+--------v--------+
| AuditLogController |
+--------+--------+
|
+--------v--------+
| AuditLogService |<----- Other services call
| log(category,...)| auditLogService.info()
+--------+--------+
|
+--------v--------+
| AuditLogRepository |
+--------+--------+
v
+-------------+
| audit_logs | (PostgreSQL)
+-------------+
Data Flow
Feature Service (vehicles, auth, etc.)
|
| auditLogService.info(category, userId, action, resourceType?, resourceId?, details?)
v
AuditLogService
|
| INSERT INTO audit_logs
v
PostgreSQL audit_logs table
|
| GET /api/admin/audit-logs (with filters)
v
AdminLogsPage/Mobile displays filtered, paginated results
Database Schema
CREATE TABLE audit_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
category VARCHAR(20) NOT NULL CHECK (category IN ('auth', 'vehicle', 'user', 'system', 'admin')),
severity VARCHAR(10) NOT NULL CHECK (severity IN ('info', 'warning', 'error')),
user_id VARCHAR(255), -- NULL for system-initiated actions
action VARCHAR(500) NOT NULL,
resource_type VARCHAR(100),
resource_id VARCHAR(255),
details JSONB,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
Indexes
idx_audit_logs_category_created- B-tree for category filteringidx_audit_logs_severity_created- B-tree for severity filteringidx_audit_logs_user_created- B-tree for user filteringidx_audit_logs_created- B-tree for date orderingidx_audit_logs_action_gin- GIN trigram for text search
API Endpoints
GET /api/admin/audit-logs
Returns paginated audit logs with optional filters.
Query Parameters:
search- Text search on action field (ILIKE)category- Filter by category (auth, vehicle, user, system, admin)severity- Filter by severity (info, warning, error)startDate- ISO date string for date range startendDate- ISO date string for date range endlimit- Page size (default 25, max 100)offset- Pagination offset
Response:
{
"logs": [
{
"id": "uuid",
"category": "vehicle",
"severity": "info",
"userId": "auth0|...",
"action": "Vehicle created: 2024 Toyota Camry",
"resourceType": "vehicle",
"resourceId": "vehicle-uuid",
"details": { "vin": "...", "make": "Toyota" },
"createdAt": "2024-01-15T10:30:00Z"
}
],
"total": 150,
"limit": 25,
"offset": 0
}
GET /api/admin/audit-logs/export
Returns CSV file with filtered audit logs.
Query Parameters: Same as list endpoint (except pagination)
Response: CSV file download
Usage in Features
import { auditLogService } from '../../audit-log';
// In vehicles.service.ts
await auditLogService.info(
'vehicle',
userId,
`Vehicle created: ${vehicleDesc}`,
'vehicle',
vehicleId,
{ vin, make, model, year }
).catch(err => logger.error('Failed to log audit event', { error: err }));
Retention Policy
- Logs older than 90 days are automatically deleted
- Cleanup job runs daily at 3 AM
- Implemented in
jobs/cleanup.job.ts
Categories
| Category | Description | Examples |
|---|---|---|
auth |
Authentication events | Signup, password reset |
vehicle |
Vehicle CRUD | Create, update, delete |
user |
User management | Profile updates |
system |
System operations | Backup, restore |
admin |
Admin actions | Grant/revoke admin |
Severity Levels
| Level | Color (UI) | Description |
|---|---|---|
info |
Blue | Normal operations |
warning |
Yellow | Potential issues |
error |
Red | Failed operations |