"""Audit service: write structured, immutable audit entries to DB.""" import json from typing import Any from sqlalchemy.ext.asyncio import AsyncSession from app.core.logging import get_logger from app.models.audit_log import AuditLog logger = get_logger(__name__) class AuditService: """Persists audit events. Every mutating API action should call this.""" def __init__(self, db: AsyncSession) -> None: self.db = db async def log( self, username: str, action: str, target: str | None = None, result: str = "success", details: dict[str, Any] | None = None, ip_address: str | None = None, ) -> AuditLog: entry = AuditLog( username=username, action=action, target=target, result=result, details=json.dumps(details) if details else None, ip_address=ip_address, ) self.db.add(entry) await self.db.flush() logger.info( "audit", username=username, action=action, target=target, result=result, ) return entry