Authority P1 Hardening — 03 Apply-Time Quorum Re-Proof
03 — Apply-Time Quorum Re-Proof
Goal
A request must not become applied merely because status='approved'. At the approved→applied transition the system must independently re-prove that live votes currently satisfy quorum.
Mechanism (reuse, not rewrite)
The system already had a live-ready quorum primitive: quorum_passed(p_code text) RETURNS boolean (STABLE). It looks up the request by code, reads proposed_action_code and its risk_level from apr_action_types, counts approve/president/council/reject votes from apr_approvals with proposer self-exclusion, and returns true only if: no reject vote, and quorum met for the risk tier (high: ≥1 president AND ≥2 ai_council; medium: ≥1 president; low: ≥1 approve). It returns false when the action code or risk is null — i.e. fail-closed for legacy/scanner null-action rows.
Per the laws doc (live_ready_means_use_not_rewrite), this primitive was reused rather than reimplemented.
Implementation (no new trigger)
Rather than add a parallel trigger (which trips the DDL trigger-guard and would push trigger_guard_alerts 129→130), the existing apply-guard function fn_apr_block_unimplemented_handler was extended via CREATE OR REPLACE. The new quorum re-proof runs FIRST — before the original IF NEW.proposed_action_code IS NULL THEN RETURN NEW early-return that was the loophole — so null-action rows can no longer slip past. If quorum_passed(NEW.code) is false the trigger raises and blocks the apply. The existing trigger trg_apr_block_unimplemented (BEFORE UPDATE WHEN new.status=applied AND old.status<>applied) carries it; no trigger DDL occurred, so trigger_guard_alerts stayed 129.
What the guard verifies at apply time
- Quorum proof present (risk-appropriate president/council counts).
- Required approvals still valid right now (re-counted live, not trusted from status).
- Any reject vote blocks (via quorum_passed).
- handler_ref not unimplemented (original check, retained).
- Not terminal/rejected (enforced by
fn_enforce_apr_lifecycle, unchanged).
Status + guards
v_apply_time_quorum_reproof_status: reproof_state = IMPLEMENTED, reproof_before_null_earlyreturn = true, apply_trigger_enabled = true.v_apply_time_quorum_no_go_guard: 4/4 PASS (reproof_present, reproof_precedes_null_shortcut, reproof_failclosed, reproof_reject_blocks).v_apply_time_quorum_regression_guard: 2/2 PASS.- Prior-session
v_authority_lifecycle_failclosed_guard.apply_quorum_reproof_presentrefreshed to live-derived: now PASS + blocking.
Safety of the change
The only behavioral change is that approved-without-genuine-quorum rows can no longer apply. Live audit shows zero such legitimate applies in flight: the sole DB applier (auto_apply_approval) returns 0; dot-apr-execute is failing on curl; all 19 pending and 2 approved rows have 0 votes (none apply-ready). Properly quorumed applies are unaffected (proven by positive controls T5 and LIVE-POS). Fully reversible via 99_rollback.sql.