KB-3FDA

02 Guarded Handler Implementation

3 min read Revision 1

02 · Guarded Handler Implementation (Phase A)

Before

wf_candidate_action_vocabulary had 11 actions, all backend_handler='unimplemented'.

What was built (live, additive, reversible, birth-free)

  1. wf_candidate_action_log — dedicated audit-first table. We did NOT reuse process_axis_action_log because that table FKs action_code → process_axis_action_vocabulary (the apr/axis layer); candidate-layer codes would violate it.
  2. fn_wf_candidate_action_execute(action_code, subject_kind, subject_code, actor, actor_type, preview default true) — single fail-closed dispatcher mirroring fn_process_axis_execute_guarded_action.
  3. Registered the handler on all 11 vocabulary rows (UPDATE ... 11).
  4. v_wf_candidate_action_handler_status — handler + gate matrix for the UI.

Gate model (fail-closed by construction)

  • Gate Arequires_president AND actor_type ≠ human → BLOCKED. AI can never cast a president vote.
  • Gate Brequires_president → must find a real human president approve vote in apr_approvals joined to the subject's approval_requests. None exist → BLOCKED (even for a human actor).
  • Gate Crequires_owner → must find an active row in governance_object_ownership (object_ref=subject). Ownership=0 → BLOCKED.
  • Gate Dmutates_canon → never executed here; canon is owner+president governed.
  • Otherwise → SAFE_TRIAGE: audit-logged; preview by default; no canon/owner/birth/event effect.

The handler can NEVER: approve, birth, write canon, activate events, create axis_assignment, or create ownership.

Live proof (run via psql, results captured)

call actor result
MARK_NOT_PROCESS / WPC-OS-INFRA (preview) ai_agent PREVIEW
ASSIGN_OWNER / WPC-DOCKER-RUNTIME ai_agent BLOCKED — no active assigned owner
CREATE_BIRTH_REQUEST / job:cut ai_agent BLOCKED — president vote required; ai cannot satisfy
CREATE_BIRTH_REQUEST / job:cut human (alice) BLOCKED — no human president approve vote
RECONCILE_TO_DOT / WPC-DOT-BIN-RECONCILE ai_agent BLOCKED — no active assigned owner
SEND_TO_GOVERNANCE / job:cut human BLOCKED — no human president approve vote
NOPE (unknown) ai_agent BLOCKED — unknown action_code

Gate matrix: 2 FAIL_CLOSED_OWNER, 2 FAIL_CLOSED_PRESIDENT, 7 SAFE_TRIAGE_PREVIEW. Action log after proof: 5 BLOCKED + 1 PREVIEW.

Handler list (action → gate_class)

  • SAFE_TRIAGE: ACCEPT_OS_LEVEL, CONFIRM_PROCESS_CANDIDATE, MARK_NOT_PROCESS, MERGE_CANDIDATES, QUARANTINE_IGNORE, REQUEST_MORE_EVIDENCE, SPLIT_CANDIDATE
  • FAIL_CLOSED_OWNER: ASSIGN_OWNER, RECONCILE_TO_DOT (also mutates_canon)
  • FAIL_CLOSED_PRESIDENT: CREATE_BIRTH_REQUEST, SEND_TO_GOVERNANCE (both mutate_canon)

Blocker

None for handler implementation. The president/owner gates are designed to stay closed until real authority exists — that is the correct end state, not a blocker to fix.

Back to Knowledge Hub knowledge/dev/reports/architecture/rp-process-axis-owner-gate-handler-ui-content-dotkg-closeout-2026-06-04/02-guarded-handler-implementation.md