audit PK: id 7 required 1 unique

Description

Tamper-evident, append-only record of all significant system events and user actions across the Meander platform. Supports compliance, security investigations, and regulatory reporting requirements.

17
Attributes
6
Indexes
6
Validation Rules
7
CRUD Operations

Data Structure

Name Type Description Constraints
id uuid Primary key, generated server-side at write time
PKrequiredunique
user_id uuid FK to users — the authenticated user who triggered the event. Nullable for system-generated events (cron jobs, background tasks).
-
organization_id uuid FK to organizations — the tenant context in which the event occurred. Nullable for global-admin or cross-org system events.
-
action string Verb describing the operation performed. Uses dot-notation namespacing: entity_type.verb (e.g., user.created, expense.approved, session.terminated, auth.login_failed).
required
entity_type string The domain entity type affected by the action (e.g., user, activity, expense, assignment, session, organization, feature_flag). Used for filtering and cross-referencing.
required
entity_id string Identifier of the affected entity instance. Stored as string to accommodate UUID, numeric, and slug-based IDs across entity types.
-
actor_role enum The role the user held at time of action, denormalized for query performance without join to user_roles.
-
severity enum Severity classification of the event for alerting and dashboard prioritization.
required
outcome enum Whether the action succeeded or failed. Failures are always logged, even for security-sensitive operations like authentication.
required
ip_address string IPv4 or IPv6 address of the request origin. Captured from X-Forwarded-For header (Vercel / CDN aware).
-
user_agent string HTTP User-Agent string. Enables device/client type analysis (Flutter app vs browser admin portal).
-
session_id string FK-by-value to sessions table. Stored as string rather than hard FK to preserve audit records after session deletion.
-
before_state json Snapshot of the entity's field values before the operation. Null for create events. Enables diff views in the audit log UI.
-
after_state json Snapshot of the entity's field values after the operation. Null for delete events. Sensitive fields (passwords, tokens) are redacted before storage.
-
metadata json Arbitrary event-specific context not captured in structured fields (e.g., bulk operation count, export file format, assigned role name, rejection reason).
-
checksum string SHA-256 HMAC of all other fields in the record using a server-side secret key. Used by the tamper-detection scan to verify log integrity.
required
created_at datetime UTC timestamp of when the event was recorded. Set server-side; never accepted from client.
required

Database Indexes

idx_audit_logs_org_created
btree

Columns: organization_id, created_at

idx_audit_logs_user_created
btree

Columns: user_id, created_at

idx_audit_logs_entity
btree

Columns: entity_type, entity_id

idx_audit_logs_action
btree

Columns: action

idx_audit_logs_severity_created
btree

Columns: severity, created_at

idx_audit_logs_created_at
btree

Columns: created_at

Validation Rules

action_format_validation error

Validation failed

created_at_server_only error

Validation failed

entity_id_required_for_entity_actions error

Validation failed

ip_address_format warning

Validation failed

before_after_state_size_limit warning

Validation failed

checksum_integrity_on_read error

Validation failed

Business Rules

append_only_immutability
on_update

Audit log records are strictly append-only. No UPDATE operations are permitted after creation. Any attempt to modify an existing record must be rejected at the application and database layer (achieved via row-level security policy in PostgreSQL denying UPDATE on audit_logs).

deletion_by_retention_policy_only
on_delete

Records may only be deleted by the scheduled audit-retention-job enforcing the organization's configured retention window (minimum 12 months for GDPR-compliant archival). Manual deletion via the UI or API is not permitted.

checksum_on_create
on_create

A SHA-256 HMAC checksum is computed over all field values at write time using a server-managed secret. The checksum is stored in the record and used by periodic integrity scans to detect tampering.

Enforced by: Audit Service
sensitive_field_redaction
on_create

Before/after state snapshots must have sensitive fields redacted (passwords, tokens, API keys, personal health data in assignments) before storage. The redaction list is defined in a server-side config, not client-controlled.

Enforced by: Audit Service
org_tenant_isolation
always

Audit log reads are scoped to organization_id matching the requesting user's active org context. Global Admins may query across organizations for system-level events only. Coordinators and Org Admins see only their own organization's logs.

system_events_logged_without_user
on_create

Background jobs (cron schedulers, retention jobs, bulk sync tasks) may create audit records with user_id = NULL and actor_role = 'system'. These are valid records and must not be filtered out by queries.

critical_events_trigger_security_alert
on_create

Any audit log record created with severity = 'critical' must synchronously notify the security-monitoring-service so it can surface the event on the Security Dashboard and evaluate anomaly thresholds.

auth_failures_always_logged
on_create

Failed authentication attempts (wrong password, BankID error, token rejection) must always be logged regardless of whether the user_id can be resolved. IP address and user_agent are required for these records to support brute-force detection.

Storage Configuration

Storage Type
primary_table
Location
main_db
Partitioning
by_date
Retention
archive_after_1year