Skip to main content

Data Model: Configurable Audit Log Storage Backend

AuditBackend (Python)

File: ai_platform_engineering/utils/audit_backend.py

AuditBackend (Protocol)
write(event: Dict[str, Any]) -> None
Fire-and-forget. Must never raise; catches and logs all errors internally.

get_audit_backend() -> AuditBackend
Returns the process-wide singleton. Reads AUDIT_LOG_BACKEND on first call.

AuditBackend (TypeScript)

File: ui/src/lib/audit/backend.ts

AuditBackend (interface)
write(event: Record<string, unknown>): void
Fire-and-forget. Must never throw; catches and logs all errors internally.

getAuditBackend(): AuditBackend
Returns the module-level singleton. Reads AUDIT_LOG_BACKEND on first call.

Event shape (unchanged)

All backends receive the same unified audit event dict. No new fields are added by this feature.

FieldTypeRequiredDescription
tsISO-8601 string / DateYesEvent timestamp (UTC)
typestringYesauth, tool_action, agent_delegation, openfga_rebac, cas_decision, cas_grant
tenant_idstringYesTenant identifier
subject_hashstringYessha256:<hex> hashed subject
actionstringYesHuman-readable action identifier
outcomestringYesallow, deny, success, error
correlation_idstringYesRequest/trace correlation id
sourcestringYesOriginating service layer
user_emailstringNoPlaintext email (admin display)
agent_namestringNoAgent name (tool events)
tool_namestringNoTool name (tool events)
duration_msfloatNoExecution duration in ms
reason_codestringNoMachine-readable outcome reason
context_idstringNoConversation/session id
componentstringNoComponent identifier
resource_refstringNoResource reference
pdpstringNoPolicy decision point
trace_idstringNoOpenTelemetry trace id
span_idstringNoOpenTelemetry span id

Storage representations

Local disk

<AUDIT_LOG_LOCAL_PATH>/
└── YYYY/
└── MM/
└── DD/
└── <event_type>-<YYYYMMDD>-<uuid>.ndjson

Each .ndjson file contains one JSON object per line. File is opened in append mode; multiple events from the same process/day/type share a file. File name components:

  • <event_type>auth, tool_action, agent_delegation, etc.
  • <YYYYMMDD> — event date in UTC
  • <uuid> — process-unique identifier generated at backend init (keeps files per-process)

S3

<AUDIT_LOG_S3_PREFIX>/
└── YYYY/
└── MM/
└── DD/
└── <event_type>-<YYYYMMDDTHHMMSSZ>-<uuid>.ndjson.gz

Each S3 object is a single gzip-compressed NDJSON file containing one event. Object key components:

  • <event_type> — same as local
  • <YYYYMMDDTHHMMSSZ> — event timestamp (UTC, compact ISO-8601)
  • <uuid> — random UUID4 to avoid key collisions under concurrent writers

MongoDB (unchanged)

No structural changes. Existing audit_events and authorization_decision_records collections are read-only artifacts once a non-MongoDB backend is active.


Backend state transitions

Process start


Read AUDIT_LOG_BACKEND

├── "mongodb" (or unset) ──► MongoBackend (existing behaviour)
├── "local" ──► LocalBackend (new)
├── "s3" ──► S3Backend (new)
└── <other> ──► ValueError / Error (fail-fast at startup)