# Caliber C49 — Audit Chain Integrity (contract excerpt)

_Source: `system/caliber/lib/c49-audit-chain-integrity.mjs` (header). The scanner is the mechanical
enforcement that keeps the operating standard installed. No redaction required — scanner logic, no
secrets or customer data._

For every `.sql` file under `apps/*/supabase/migrations/` and `apps/*/scripts/`, C49 detects patterns
that erode tamper-evidence in hash-chained `audit_events` tables:

- **Rule 1 — Forbidden payload-column UPDATE (FAIL).** `UPDATE audit_events SET <payload-column> = …`
  is never permitted post-write. Payload columns: `before, after, changed_fields, request_id,
  entity_id, parent_event_id, action, entity_type, actor_kind, actor_id, account_id, chain_seq, id,
  created_at, source`.
- **Rule 2 — Non-payload UPDATE without annotation (FAIL → WARN with annotation).** Any
  `UPDATE audit_events SET …` that touches no payload column but lacks the inline
  `-- caliber-allow: audit-redaction <rationale>` annotation → FAIL. With the annotation → WARN.
- **Rule 3 — `DELETE FROM audit_events` (FAIL).** Deletion is never a permitted redaction path.
- **Rule 4 — `ALTER TABLE audit_events ADD COLUMN` (WARN).** Advisory: a payload-bound column
  requires a declared `chain_seq` cutoff.

**Grandfather allowlist** (pre-standard migrations, named explicitly; findings downgraded to INFO):
`20260502c_audit_chain_seq.sql`, `20260507c_*.sql`, `20260529a_audit_sensitive_columns.sql`.

**Severity:** Major 2pt, Engineering family. No bootstrap grace (forward-looking). Kill switch
`CALIBER_C49=0`.

The payload-column list above is annotated in source as "mirrored from `audit_capture_direct`'s
`v_payload`" — the same 15 fields shown in `payload-boundary.sql`. The two label columns from the
incident are absent from it, which is the mechanical basis for Rule 1 vs Rule 2 discriminating a
payload mutation from a non-payload one.
