""" Append-only audit log for sensitive operations (identity resolution, reverse image search, gallery mutations). Format: one JSON object per line (JSONL). """ from __future__ import annotations import json from datetime import datetime, timezone from pathlib import Path from typing import Any from config import settings from loguru import logger def audit_log( action: str, actor: str = "anonymous", target: str | None = None, outcome: str = "success", details: dict[str, Any] | None = None, ) -> None: """Append a structured audit entry.""" entry = { "timestamp": datetime.now(timezone.utc).isoformat(), "action": action, "actor": actor, "target": target, "outcome": outcome, "details": details or {}, } path = Path(settings.audit_log_path) path.parent.mkdir(parents=True, exist_ok=True) try: with open(path, "a", encoding="utf-8") as f: f.write(json.dumps(entry, ensure_ascii=False) + "\n") except OSError as e: logger.warning(f"Audit log write failed: {e}")