Skip to main content

04 — Data Model

Canonical event & BigQuery schema

One envelope normalizes every source. Common fields are strongly typed columns for fast filtering; source-specific payloads live in a single JSON column.

Fields​

FieldDescriptionTypeReq
event_idUnique event identifier (UUID)STRING●
occurred_atWhen the event occurred at the sourceTIMESTAMP●
received_atWhen the API received the log · partition key · API-enrichedTIMESTAMP●
source_systemSource system name (jenkins, vault…)STRING●
source_instanceSpecific instance / environment of the sourceSTRING○
actionAction / event name performedSTRING●
outcomeResult of the action (SUCCESS, FAILURE, DENIED)STRING○
severitySeverity level (INFO, WARN, ERROR)STRING○
actor_idSubject / account that initiated the actionSTRING○
target_idTarget resource affected by the actionSTRING○
correlation_idTrace ID linking operations across servicesSTRING○
ingest_client_idZitadel client authenticated by the API · from JWT subjectSTRING○
metadataSource-specific fields in extensible JSONJSON○

BigQuery DDL​

CREATE TABLE audit.audit_logs (
event_id STRING NOT NULL,
occurred_at TIMESTAMP NOT NULL,
received_at TIMESTAMP NOT NULL,
source_system STRING NOT NULL,
source_instance STRING,
action STRING NOT NULL,
outcome STRING,
severity STRING,
actor_id STRING,
target_id STRING,
correlation_id STRING,
ingest_client_id STRING,
metadata JSON
)
PARTITION BY DATE(received_at)
CLUSTER BY source_system, action;
PARTITIONDaily on received_at — prunes scans & enables retention expiry.
CLUSTERBy source & action — most filters hit these, cutting bytes read.