audit PK: id 10 required 1 unique

Description

Tamper-evident, append-only record of significant actions performed across the Meander platform, scoped per organization. Captures actor identity, action type, affected resource, outcome, and contextual metadata to support compliance auditing, security investigations, and Global Admin support-access accountability.

18
Attributes
7
Indexes
6
Validation Rules
11
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Immutable primary key generated at write time
PKrequiredunique
organization_id uuid FK to organizations. Every audit entry is scoped to exactly one tenant; cross-tenant reads are prohibited
required
actor_user_id uuid FK to users. The human who triggered the action. NULL for automated system actions (e.g. expiry-check-service auto-pause, background-sync-scheduler)
-
actor_role enum Role the actor held at the moment of the action. Stored denormalized so role changes do not rewrite history
-
actor_session_id uuid FK to sessions. Links the audit entry to the specific authenticated session, enabling session-level investigation
-
actor_ip_address string IP address of the request origin. IPv4 or IPv6. NULL for background system jobs
-
source_product enum Which product surface generated this entry
required
action string Dot-notation action identifier, e.g. user.created, expense.approved, session.revoked, role.assigned, data_export.bufdir, support_access.granted
required
action_category enum High-level grouping for filtering and dashboard aggregation
required
resource_type string The entity type affected by the action, e.g. user, expense, session, module_configuration, bufdir_export
required
resource_id uuid Primary key of the affected resource record. NULL when action targets a collection or no specific record (e.g. bulk export)
-
resource_display_name string Human-readable label for the resource at the time of the action (e.g. user email, expense amount+date). Denormalized so renames or deletions do not break audit readability
-
outcome enum Whether the action succeeded, was rejected by authorization, or failed due to an error
required
severity enum Operational severity for alerting and dashboard triage
required
metadata json Structured context specific to the action type: before/after values for config changes, export row counts, failed field names for validation errors, support-access grant expiry date, etc.
-
user_agent string HTTP User-Agent header from the request. Distinguishes mobile vs web portal vs API client
-
checksum string HMAC-SHA256 of the record's canonical fields (id, organization_id, actor_user_id, action, resource_id, outcome, created_at) signed with a server-side key. Enables tamper detection during audit exports
required
created_at datetime UTC timestamp set by the database at insert time. Immutable — no application-layer override permitted
required

Database Indexes

idx_audit_logs_org_created
btree

Columns: organization_id, created_at

idx_audit_logs_actor_user
btree

Columns: actor_user_id, created_at

idx_audit_logs_action_category
btree

Columns: organization_id, action_category, created_at

idx_audit_logs_resource
btree

Columns: resource_type, resource_id

idx_audit_logs_session
btree

Columns: actor_session_id

idx_audit_logs_severity
btree

Columns: organization_id, severity, created_at

idx_audit_logs_outcome
btree

Columns: organization_id, outcome, created_at

Validation Rules

action_dot_notation_format error

Validation failed

actor_presence_required_for_human_actions error

Validation failed

organization_id_not_null error

Validation failed

valid_enum_values error

Validation failed

metadata_size_limit error

Validation failed

export_checksum_verification critical

Validation failed

Business Rules

append_only_immutability
always

Audit log records are permanently immutable. No UPDATE or DELETE is permitted at the application layer. The database role used by the API has INSERT and SELECT grants only on this table — no UPDATE or DELETE grants exist

Enforced by: Audit Log Service
organization_scoped_reads
always

Every query against audit_logs MUST include organization_id as a filter predicate. The audit-log-service enforces this before executing any SELECT. Global Admins with active support access may read an org's logs only within the granted time window

support_access_always_logged
on_create

Every action taken by a Global Admin under a time-bounded support-access grant must produce an audit entry with action_category=support_access and severity=warning, regardless of outcome. This is non-negotiable per the platform spec

mandatory_for_sensitive_operations
on_create

The following operations must produce an audit entry or be rejected: expense approval/rejection, role assignment/revocation, user deactivation, module configuration change, Bufdir export, session revocation, support-access grant/revoke. Services performing these operations call audit-log-service synchronously inside the same transaction

checksum_generation_required
on_create

The audit-log-service computes the HMAC-SHA256 checksum before INSERT. Records without a valid checksum are rejected. The signing key is server-side only and rotated quarterly

Enforced by: Audit Log Service
severity_escalation_for_denied_outcomes
on_create

Any entry with outcome=denied is automatically escalated to severity=warning minimum. If action_category is authentication or support_access the severity is escalated to critical

created_at_server_only
on_create

The created_at timestamp is set exclusively by the database DEFAULT NOW(). No application code may supply a created_at value. This prevents backdating of audit entries

Enforced by: Audit Log Service

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
by_date
Retention
archive_after_1year