KB-1325

RS4A-08 — Durable Failure-Audit Sink Contract v0.2 — 2026-06-21

6 min read Revision 1
rs4aaudit-sinkevent_outboxappend-onlyimmutabilityv0.2fail-closeddesign-only2026-06-21

RS4A-08 — Durable Failure-Audit Sink Contract v0.2 — 2026-06-21

Macro: RS4A · Mục tiêu H Deliverable: 08 of 14 · design-only (does NOT patch event_outbox, does NOT create a ledger) Builds on: RS3B-06 sink selection (event_outbox lead, SINK_CANDIDATE_SELECTED_FAIL_CLOSED). Gate: REGISTRATION_HOLD · REGISTRATION_CAN_PROCEED = NO Status: SINK_CANDIDATE_SELECTED_FAIL_CLOSEDevent_outbox remains the lead reuse candidate; live reads confirm no enforced immutability/retention, so the sink stays fail-closed. No new ledger.


1. Requirement (from the phase model)

RS4A-04 Phase 5 requires that a registration failure — especially a rolled-back Phase-3 transaction — leaves a durable audit record written outside the rolled-back transaction (RS2-PATCH1 Codex R3). The registrar source writes no audit at all (D20). The sink must be reused from an existing surface (no new ledger until reuse is exhausted).


2. Live candidate evidence (my own read-only reads, 2026-06-21)

Candidate Live fact Immutability Verdict
event_outbox 215,647 rows; only one user trigger: trg_event_outbox_type_validate BEFORE INSERTfn_event_type_validate(); has safe_payload jsonb + payload_classification (payload-safety); normal heap (writable after a Phase-3 rollback) none (no UPDATE/DELETE-blocking trigger/constraint) lead candidate, fail-closed
registry_changelog mutable by design (resolve columns resolved/resolved_by/resolved_at); birth/label AFTER INSERT triggers none (explicitly mutable) rejected as immutable sink
governance_audit_log 1 row; no triggers none rejected (no immutability, weak payload safety)
iu_route_attempt retry ledger UNIQUE(idempotency_key,attempt_no) n/a rejected (wrong domain)

event_outbox scores highest on schema fit + payload safety + post-rollback writability + already-exists (no new ledger). But it fails immutability and retention/idempotency-dedup — the same as every candidate.


3. Required sink properties (criteria the selected sink must satisfy)

Property Requirement Live status on event_outbox
Append-only / immutability UPDATE/DELETE blocked by trigger or revoked grants absent — only BEFORE INSERT validate
Restricted writer enumerable, restricted grant for the registrar role not enumerable from read-only
Retention covers the replay horizon; no silent purge unproven
Idempotency / dedup a dedup key for failure records (one per (logical_request_key, phase, run_id)) absent (only PK on id)
Payload safety classified payload, no secrets, forbidden-key guard present (safe_payload + payload_classification)
Post-rollback writability writable outside a rolled-back txn present (heap table)
No-activation lane the audit write must NOT use an event_type/delivery_lane that triggers downstream execution must be proven per chosen lane

4. Failure-audit envelope shape (design)

failure_audit_envelope {
  event_domain: "dot_registration",
  event_type:   "registration_failure",          # MUST be a non-executing audit type (no downstream automation)
  delivery_lane:"audit",                          # MUST NOT be an execution lane
  severity:     "warn" | "error",
  subject_table:"dot_tools",
  subject_ref:  <dot_code | null>,
  actor_ref:    <registrar run identity>,         # event_outbox.actor_ref is NOT NULL
  correlation_id:<run_id>,
  safe_payload: { phase, reject_codes[], logical_request_key, attempt_id,
                  artifact_hash_attested?: <trusted_attested only>, owner_envelope_ref?, apr_ref? },
  payload_classification: "governance_audit",
  dedup_key:    H(logical_request_key, phase, run_id)   # required for idempotent failure records
}

Rules: never write request_proposed.* secrets; artifact_hash in payload is the attested value or omitted; the envelope is advisory forensics, not an authority record.


5. Decision — harden by contract, or stay candidate?

Decision: event_outbox is SELECTED as the lead reuse candidate but STAYS FAIL-CLOSED until an append-only/immutability + retention + dedup hardening is separately designed and Owner-approved. It can be hardened by contract (an UPDATE/DELETE-blocking trigger + restricted writer grant + dedup unique on dedup_key + retention policy) without a new ledger — but that hardening is its own separately-born, separately-tested, separately-rollback-able block (no mega-coupling), and RS4A does not author it (no patch, no DDL). Until then, AUDIT_SINK_UNAVAILABLE fires whenever durable append-only audit cannot be guaranteed, and registration must not report success with audit unwritten.

6. Status

  • Sink contract v0.2: SINK_CANDIDATE_SELECTED_FAIL_CLOSEDevent_outbox lead; immutability/retention/dedup must be proven before use.
  • G6 remains OPEN. No event_outbox patch, no new ledger, no DDL. Gate REGISTRATION_HOLD · CAN_PROCEED = NO.
Back to Knowledge Hub knowledge/dev/laws-new/reports/rs4a/08-durable-failure-audit-sink-contract-v0-2-2026-06-21.md