generated from coulomb/repo-seed
54 lines
1.6 KiB
Python
54 lines
1.6 KiB
Python
"""Small audit interface shared by backends and integrations."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime, timezone
|
|
from typing import Any, Protocol
|
|
from uuid import uuid4
|
|
|
|
|
|
def utc_now() -> str:
|
|
return datetime.now(timezone.utc).replace(microsecond=0).isoformat()
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class AuditEvent:
|
|
"""Minimal event envelope for the first Audit Core implementation."""
|
|
|
|
source: str
|
|
action: str
|
|
resource: str
|
|
outcome: str
|
|
tenant: str = "platform"
|
|
scope: str = "platform-control-plane"
|
|
actor: str | None = None
|
|
reason: str | None = None
|
|
details: dict[str, Any] = field(default_factory=dict)
|
|
event_id: str = field(default_factory=lambda: str(uuid4()))
|
|
observed_at: str = field(default_factory=utc_now)
|
|
schema_version: str = "audit-core.event.v1alpha1"
|
|
|
|
def as_record(self) -> dict[str, Any]:
|
|
return {
|
|
"schema_version": self.schema_version,
|
|
"event_id": self.event_id,
|
|
"observed_at": self.observed_at,
|
|
"tenant": self.tenant,
|
|
"scope": self.scope,
|
|
"source": self.source,
|
|
"actor": self.actor,
|
|
"action": self.action,
|
|
"resource": self.resource,
|
|
"outcome": self.outcome,
|
|
"reason": self.reason,
|
|
"details": self.details,
|
|
}
|
|
|
|
|
|
class AuditBackend(Protocol):
|
|
"""Protocol implemented by audit sinks."""
|
|
|
|
def emit(self, event: AuditEvent) -> str:
|
|
"""Persist an event and return a backend-specific reference."""
|