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>
This commit is contained in:
@@ -20,6 +20,10 @@ from app.schemas.notification import (
|
||||
from app.schemas.blocker import (
|
||||
BlockerCreate, BlockerResolve, BlockerResponse, BlockerListResponse
|
||||
)
|
||||
from app.schemas.audit import (
|
||||
AuditLogResponse, AuditLogListResponse, AuditAlertResponse, AuditAlertListResponse,
|
||||
IntegrityCheckRequest, IntegrityCheckResponse
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"LoginRequest",
|
||||
@@ -64,4 +68,10 @@ __all__ = [
|
||||
"BlockerResolve",
|
||||
"BlockerResponse",
|
||||
"BlockerListResponse",
|
||||
"AuditLogResponse",
|
||||
"AuditLogListResponse",
|
||||
"AuditAlertResponse",
|
||||
"AuditAlertListResponse",
|
||||
"IntegrityCheckRequest",
|
||||
"IntegrityCheckResponse",
|
||||
]
|
||||
|
||||
61
backend/app/schemas/audit.py
Normal file
61
backend/app/schemas/audit.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional, List, Any
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class AuditLogResponse(BaseModel):
|
||||
id: str
|
||||
event_type: str
|
||||
resource_type: str
|
||||
resource_id: Optional[str]
|
||||
user_id: Optional[str]
|
||||
action: str
|
||||
changes: Optional[List[dict]]
|
||||
request_metadata: Optional[dict]
|
||||
sensitivity_level: str
|
||||
checksum: str
|
||||
created_at: datetime
|
||||
user_name: Optional[str] = None
|
||||
user_email: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class AuditLogListResponse(BaseModel):
|
||||
logs: List[AuditLogResponse]
|
||||
total: int
|
||||
offset: int
|
||||
limit: int
|
||||
|
||||
|
||||
class AuditAlertResponse(BaseModel):
|
||||
id: str
|
||||
audit_log_id: str
|
||||
alert_type: str
|
||||
recipients: List[str]
|
||||
message: Optional[str]
|
||||
is_acknowledged: bool
|
||||
acknowledged_by: Optional[str]
|
||||
acknowledged_at: Optional[datetime]
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class AuditAlertListResponse(BaseModel):
|
||||
alerts: List[AuditAlertResponse]
|
||||
total: int
|
||||
|
||||
|
||||
class IntegrityCheckRequest(BaseModel):
|
||||
start_date: datetime
|
||||
end_date: datetime
|
||||
|
||||
|
||||
class IntegrityCheckResponse(BaseModel):
|
||||
total_checked: int
|
||||
valid_count: int
|
||||
invalid_count: int
|
||||
invalid_records: List[str]
|
||||
Reference in New Issue
Block a user