# 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 ```sql 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 ```sql 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 確保日誌不可竄改: ```python 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