Audit immutability is enforced at the database layer — not the API, not the application, not “best effort”. A Postgres trigger refuses to update or delete any row in audit_log. Even the database administrator cannot alter it without disabling the trigger — and that attempt is itself logged.
“I need the evidence to exist before the auditor asks for it. Not the week they arrive.”
§ Compliance Director, regulated mid-market-- Prevents UPDATE or DELETE on audit_log.
-- Enforced by Postgres. Not by the application.
CREATE OR REPLACE FUNCTION audit_immutable()
RETURNS TRIGGER AS $$
BEGIN
RAISE EXCEPTION 'audit_log rows are immutable';
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER audit_no_update
BEFORE UPDATE OR DELETE ON audit_log
FOR EACH ROW EXECUTE FUNCTION audit_immutable();
Every state-changing operation logs to an append-only table. Actor, timestamp, IP, user agent, before/after, outcome. Reconstructed history is impossible — the history is the workflow.
Postgres trigger raises an exception on UPDATE or DELETE. Application code cannot accidentally bypass — and intentional bypass requires disabling the trigger, which is itself logged.
Every transition across all nine domains. Approvals, votes, edits, reads of sensitive records, exports. Actor, IP, method, endpoint, outcome.
Core records soft-delete only with a deletion marker. Permanent removal at retention time is itself audit-logged.
Filter by actor, timestamp range, entity type, action, outcome. Built-in queries for common audit asks.
Generate evidence packs for SOC 2 CC6/CC7, ISO 27001 A.8/A.12, UK GDPR Article 30. Filtered exports for specific control tests.
Per-organisation retention policy, with GDPR Article 17 anonymisation for departed users — their entries remain, identifiers are pseudonymised.
Most audit trails are application-layer audit trails. The application writes a log when it processes a change. Which means the application can be bypassed — by a direct database connection, by a migration script, by an administrator with elevated access. The log records what the application chose to record. It does not guarantee that nothing else happened.
SOC 2 Type II and ISO 27001 require audit trails that demonstrate completeness and integrity. An auditor who asks “can this log be modified?” should hear “no” with a technical explanation, not “we have a policy that says it shouldn’t be.” Policy is not a control. A Postgres trigger that refuses UPDATE and DELETE at the database level — even for users with DBA privileges — is a control.
HelixGate enforces immutability at the database layer. The audit_log table is write-once. No application code path, no administrative database operation, and no migration can alter or delete an existing audit record. The trigger is the enforcement mechanism, not the application.
For regulated organisations, this is the difference between audit evidence and audit assertion. When an FCA supervisor or ISO 27001 certification body asks to inspect the record of a specific decision, the response is a query result — timestamped, attributed, unalterable — not a manually assembled document. The trail exists because the architecture guarantees it, not because someone remembered to log it.
We’ll show the trigger live in a demo tenant, then run an evidence export against a SOC 2 control. 30 minutes.