Files
PROJECT-CONTORL/openspec/changes/archive/2025-12-29-add-audit-trail/design.md
beabigegg 0ef78e13ff feat: implement audit trail module
- Backend (FastAPI):
  - AuditLog and AuditAlert models with Alembic migration
  - AuditService with SHA-256 checksum for log integrity
  - AuditMiddleware for request metadata extraction (IP, user_agent)
  - Integrated audit logging into Task, Project, Blocker APIs
  - Query API with filtering, pagination, CSV export
  - Integrity verification endpoint
  - Sensitive operation alerts with acknowledgement

- Frontend (React + Vite):
  - Admin AuditPage with filters and export
  - ResourceHistory component for change tracking
  - Audit service for API calls

- Testing:
  - 15 tests covering service and API endpoints

- OpenSpec:
  - add-audit-trail change archived

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-29 21:21:18 +08:00

3.8 KiB

Design: add-audit-trail

Architecture Decision

Approach: Application-layer Middleware

選擇應用層中間件而非資料庫觸發器:

方案 優點 缺點
Middleware (選擇) 可取得完整 context (user, IP)、跨資料庫相容 需要在每個 API 加入
DB Trigger 自動捕捉所有變更 無法取得 user context、MySQL 觸發器效能差

Implementation Strategy

Request → FastAPI Middleware → Extract metadata (user, IP, user_agent)
                ↓
          API Handler → Execute operation
                ↓
          AuditService.log() → Async write to pjctrl_audit_logs
                ↓
          (if sensitive) → NotificationService → Alert admins

Data Model

pjctrl_audit_logs

CREATE TABLE pjctrl_audit_logs (
    id VARCHAR(36) PRIMARY KEY,
    event_type VARCHAR(50) NOT NULL,
    resource_type VARCHAR(50) NOT NULL,
    resource_id VARCHAR(36),
    user_id VARCHAR(36),
    action ENUM('create', 'update', 'delete', 'restore', 'login', 'logout') NOT NULL,
    changes JSON,
    metadata JSON,
    sensitivity_level ENUM('low', 'medium', 'high', 'critical') DEFAULT 'low',
    checksum VARCHAR(64) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    INDEX idx_audit_user (user_id, created_at),
    INDEX idx_audit_resource (resource_type, resource_id, created_at),
    INDEX idx_audit_time (created_at),

    FOREIGN KEY (user_id) REFERENCES pjctrl_users(id) ON DELETE SET NULL
);

pjctrl_audit_alerts

CREATE TABLE pjctrl_audit_alerts (
    id VARCHAR(36) PRIMARY KEY,
    audit_log_id VARCHAR(36) NOT NULL,
    alert_type VARCHAR(50) NOT NULL,
    recipients JSON NOT NULL,
    message TEXT,
    is_acknowledged BOOLEAN DEFAULT FALSE,
    acknowledged_by VARCHAR(36),
    acknowledged_at TIMESTAMP,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,

    FOREIGN KEY (audit_log_id) REFERENCES pjctrl_audit_logs(id),
    FOREIGN KEY (acknowledged_by) REFERENCES pjctrl_users(id)
);

Checksum Calculation

確保日誌不可竄改:

import hashlib
import json

def calculate_checksum(log: AuditLog) -> str:
    content = f"{log.event_type}|{log.resource_id}|{log.user_id}|{json.dumps(log.changes, sort_keys=True)}|{log.created_at.isoformat()}"
    return hashlib.sha256(content.encode()).hexdigest()

Sensitivity Levels & Event Types

Event Type Sensitivity Alert
task.create, task.update, task.assign low No
task.delete, task.blocker medium No
project.create, project.update medium No
project.delete high Yes
user.permission_change critical Yes
user.login (異常) high Yes

API Design

Query Audit Logs

GET /api/audit-logs
Query params:
  - start_date: datetime
  - end_date: datetime
  - user_id: UUID (optional)
  - resource_type: string (optional)
  - resource_id: UUID (optional)
  - sensitivity_level: string (optional)
  - limit: int (default 50, max 100)
  - offset: int

Resource History

GET /api/audit-logs/resource/{resource_type}/{resource_id}
Returns: Change history for specific resource

Export

GET /api/audit-logs/export
Query params: same as query + format=csv
Returns: CSV file download

Integrity Check

POST /api/audit-logs/verify-integrity
Body: { start_date, end_date }
Returns: { total_checked, valid_count, invalid_records: [] }

Integration Points

  1. Task API: Log create/update/delete/assign
  2. Project API: Log create/update/delete
  3. User API: Log permission changes
  4. Auth Middleware: Log login/logout
  5. Blocker API: Log blocker events

Alert Thresholds

  • Bulk delete: > 5 deletes within 5 minutes
  • Off-hours login: Outside 06:00-22:00 local time
  • Permission escalation: Any admin role assignment