Documentation Index
Fetch the complete documentation index at: https://docs.knoxcall.com/llms.txt
Use this file to discover all available pages before exploring further.
SHA-256 Hash Chain — Critical Audit Chain
For sensitive operations — BYOK KMS lifecycle, secret store migrations, and tenant impersonation — each write goes into a separate, append-only table (audit_log_critical) that is distinct from the standard audit_logs table.
The critical chain is protected by:
- Application-layer SHA-256 hash chain — each row commits to the prior row via
prev_hash(32 bytes) androw_hash = SHA-256(canonical_bytes_of_this_row). Tampering with any row changes itsrow_hash, which breaks every subsequentprev_hashlink. A verifier can detect the exact row that was altered. - Append-only enforcement — database triggers prevent UPDATE and DELETE at the Postgres level. There is no retention pruning on this table; records exist indefinitely.
- Serialized writes — an advisory lock (
pg_advisory_xact_lock) on every write ensures monotonic, gap-freesequence_numbervalues. A gap in sequence numbers indicates a deletion attempt.
Critical chain row schema
| Field | Type | Description |
|---|---|---|
sequence_number | BIGINT | Monotonically increasing; gaps indicate tampering |
prev_hash | BYTEA (32) | SHA-256 of the previous row’s canonical bytes; all-zero for the genesis row |
row_hash | BYTEA (32) | SHA-256 of this row’s canonical bytes |
at | TIMESTAMPTZ | Wall-clock timestamp of the action |
tenant_id | UUID | Tenant subject of the action (nullable for operator-level events) |
actor_id | UUID | User who performed the action (nullable for system-triggered events) |
action | TEXT | One of the 15 action values listed above |
resource_type | TEXT | One of the 7 resource types listed above |
resource_id | TEXT | UUID or other identifier of the affected resource |
details | JSONB | Action-specific context. Never contains plaintext secret values. |
Canonical serialization
Therow_hash is computed over a deterministic length-prefixed byte sequence:
details_canonical_json is JSON with keys recursively sorted so the hash is deterministic regardless of insertion order. The sentinel byte distinguishes null (\x00) from empty string (\x01).
The authoritative implementation is computeRowHash() in src/audit/critical.ts. An external verifier can re-derive any row’s hash from raw DB values and this spec.