Audit Chain

Every security-relevant action, cryptographically chained. Tamper-evident by design.

HMAC-SHA256 row chaining, append-only database triggers, monotonic per-tenant sequence. Three independent tamper signals built into the schema, not bolted on.

WHY THIS IS NOT A FEATURE

Our audit log is cryptographically chained at the row level

An attacker with full database write access still cannot forge or delete a row without leaving evidence. Same hash-chain primitive used in blockchain ledgers, applied at the row level, with an HMAC secret instead of a consensus protocol.

7 years. 2,555 days. Every security-relevant action by every user, captured and verifiable.

HOW IT WORKS

Three fields turn each row into evidence

Every row in audit_logs carries three protective fields. The table is unremarkable; the discipline lives in what gets computed and signed for each insert.

FIELD 01

sequence

Monotonically increasing integer, per tenant. A gap in the sequence means a row was deleted, and the verifier flags the first missing number.

FIELD 02

prev_hash

Points back to the previous row's row_hash. A broken chain means a row was reordered or inserted out of band.

FIELD 03

row_hash

HMAC-SHA256 over the canonical serialization of {tenant_id, sequence, prev_hash, actor_id, action, resource_type, resource_id, payload, created_at}, signed with AUDIT_HMAC_KEY held by the application, not the database.

THREE TAMPER SIGNALS

What we detect, and how

Attack What we detect How
Row mutation The stored row_hash no longer matches the recomputed HMAC. Verifier walks the chain and recomputes each row from its canonical payload.
Row deletion A sequence gap appears, and the surviving row's prev_hash no longer matches its actual predecessor. Sequence check plus chain check; either alone is sufficient to detect.
Row insertion or reordering The inserted row cannot reference a real prev_hash, so the chain fails at the inserted row or the one after it. Chain walk catches the discontinuity at the first invalid hash.

DEFENCES IN DEPTH

Three layers, separated on purpose

LAYER 01

Append-only enforcement

A PostgreSQL trigger blocks every DELETE against audit_logs. Deletion is only possible inside a transaction that has SET LOCAL app.audit_retention_cleanup = on, a flag held by the retention sweep. SET LOCAL is transaction-scoped, so the flag auto-clears on commit or rollback and cannot leak to later statements.

LAYER 02

Key separation

The HMAC secret lives in the application configuration, not the database. A read-only database compromise cannot forge valid rows. A write-level database compromise is caught by the next verifier run, which uses the HMAC secret to recompute every row and surfaces failures as their own audit events.

LAYER 03

Verifier independence

The verifier walks each tenant's chain end to end using the application-held HMAC secret. Its outcomes are themselves audit-chain entries, so a disabled or skipped run is visible the moment it happens.

WHAT GETS LOGGED

Every event that touches the operational record

  • 01 All authentication: login, logout, MFA enrolment, password change, password reset
  • 02 All authorization: role changes, permission grants, API key creation and revocation
  • 03 All sensitive admin actions: tenant settings, retention changes, RLS context overrides
  • 04 All work-order signoffs, with the SHA-256 of the signature payload
  • 05 All subscription and billing events: webhook receipt, plan change, customer-portal session
  • 06 All ingest-source configuration changes
  • 07 All SSO configuration changes
  • 08 All exports: CSV, PDF, scheduled report deliveries
  • 09 All bulk deletes and data-subject right-of-erasure exercises

RETENTION

2,555 days. Independent of operational retention.

RetentionConfig.AUDIT_LOG_DAYS keeps the chain for seven years. Tenant.data_retention_days is designed to control operational data separately, so machine telemetry can be purged on a configurable window while the audit chain continues to span the SOC 2 CC2.2 evidence window and the financial-adjacent retention norms.

COMPLIANCE MAPPING

What the chain answers for

SOC 2 CC6.1 & CC7.2

Tamper-evident logging and the change-management evidence trail. The chain is what your SOC 2 auditor walks through during the observation period to satisfy CC6.1 (logical access) and CC7.2 (system monitoring).

ISO 27001 A.12.4

Event logging and operator log integrity. Every administrator action and exception lands on the chain with timestamp, attribution, and the canonical payload that was acted on.

FDA 21 CFR Part 11 §11.10(e)

Secure, computer-generated, time-stamped audit trails for electronic records. Each signed event is attributable, contemporaneous, original, accurate, and time-stamped, supporting customer 21 CFR Part 11 validation efforts.

GDPR Article 30

Records of processing activities. Your DPO can pull a tenant-scoped audit slice on demand. Personal data inside audit_logs is limited to user identifiers and IP addresses; richer payloads carry only the minimum context needed to reconstruct the event.

EU NIS2 Directive

Incident investigation evidence. Member-state CSIRTs and your own forensic team can reconstruct exactly who did what and when, with a chain whose integrity does not depend on database administrator trust.

THE VERIFIER

Audit-logged audit verification

Chain verification recomputes each row from its canonical payload using the tenant's HMAC secret, returning PASS with the row count or FAIL at the first broken sequence number. Verifier outcomes are themselves audit-chain entries.

Cadence

On-demand from the admin verifier endpoint today. Scheduled daily verification ships with the platform GA release.

Outcome

PASS with the row count, or FAIL with the first sequence number where the chain broke. The row itself is preserved as evidence.

Source

Verifier source code is available for your auditor to walk through. We will sit in the room while they do.

WHY THIS BEATS "WE HAVE AUDIT LOGS"

Standard audit logs do not survive a determined operator

Plain audit table

Append-friendly but mutable. Anyone with database write access can change a row, drop a row, or insert one. No mathematical signal that it happened.

WORM storage

Helps against deletion, less helpful against insertion or reordering. Storage-level integrity does not catch a row that should never have been there.

Hash-chained log (this)

Mathematically tamper-evident. Detects mutation, deletion, and insertion at the row level, with the parent hash as the integrity anchor.

FREQUENTLY ASKED

What happens to the chain if a hash mismatches?

The verifier returns FAIL with the first sequence number where the chain broke. The row itself is not deleted, we keep the evidence. The failure is recorded as its own chain entry and surfaces through the platform's incident path.

Can the database administrator tamper with the chain?

Not without (a) breaking the append-only trigger, (b) obtaining the HMAC secret that lives outside the database, and (c) rewriting every subsequent row for the affected tenant. All three actions would themselves leave forensic evidence.

Can you delete a row for GDPR right-to-erasure?

Personal data inside audit_logs is already minimised to a user_id and IP. Right-to-erasure on the user record does not remove audit history, since that processing rests on Article 6(1)(c) legal obligation and (f) legitimate interest. We can pseudonymise the user_id reference if your DPO requires it.

Does the chain slow down writes?

Each insert computes one HMAC and reads one previous row, both indexed. Negligible cost at typical workloads, and the verifier runs out of band.

STOP REACTING. START PREDICTING.

Connect Haltless to your existing PLCs, run a pilot on up to ten machines, and see the explainable health score on your own equipment. No new hardware, no proprietary sensors, no consultants.

We use cookies to improve your experience, analyze site traffic, and optimize our marketing. By clicking "Accept All", you consent to our use of cookies. Privacy Policy