Postgres audit_ledger append-only guard gains exactly one
execution entry: cloud/ledger_pg_guard.apply_pg_guard, runnable
as 'python3 -m cloud.ledger_pg_guard' (explicit ops command,
not a migration script). It executes PG_GUARD_SQL verbatim from
the constant -- no second copy of the SQL anywhere -- refuses
non-PgConnection targets, does not commit itself (caller/CLI
commits), and refuses with exit 2 on a non-postgres backend so
a no-PG environment can never claim hardening. ensure_schema
still skips PG triggers; POSTGRES_SCHEMA still builds only the
table. Tests lock all of this with a recording fake connection
(no PG execution is faked), a source scan asserting only
ledger.py and ledger_pg_guard.py reference the constant, and
CLI dry-run/refusal cases. Real-PG syntax and UPDATE/DELETE
blocking verification is explicitly left to B5, not claimed here.
(cherry picked from commit b1f6c9158d628186965a9e57576ff8c9500e3f73)
Track 3 decisions (audit_pushback) now really block the server merge
endpoint and really land on the track 4 hash chain, via the new
cloud/audit_wiring.py translation layer:
- POST /tasks/{id}/merge ANDs the chain pushback block
(merge_blocked/release_blocked/blocked_by=audit_pushback/round/
failed_checks, replayed per module+contract version) with the
hard gate's five checks in every gate mode; either side blocks
-> 409, status unchanged, audit_pushback_blocked appended to
merge_gate.blocks. Ledger reads that fail (other than a missing
audit_ledger table) fail closed to 409.
- Every pushback/fix/re-audit/rebuild/escalation step is written
to the ledger with track 3 fields authoritative and track 4
storage authoritative; CONDITIONAL maps to fail at the boundary
with the original preserved, history never rewritten.
- Hard-gate 409 blocks codes feed pushback packages machine-first
(branch protection survives as its own extra check).
- Re-audit QA guard: a claimed pass with un-rerun or failed QA
links never reaches the chain.
- Track 4 compat: one audit_wiring_event action for escalation /
blocked-quota / audit-sample kinds, counted in the timeline.
- Resolved tension (documented in audit_wiring.py): a meta-review
correction to fail re-blocks at once, but a correction to pass
does NOT unblock by itself -- track 3 schedules a re-audit,
it does not release the gate; track 4 failure counts still use
effective verdicts, so the two views may disagree while a
re-audit is pending.
Tests: cloud/tests/test_audit_wiring.py (18 items), incl. a real
HTTP end-to-end chain (fail -> 409 -> fix -> re-audit pass ->
200) and a separate QA-link chain test.