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.