KB-1B43

05 — dot-apr-approve Minimal Design (staged only, not deployed)

6 min read Revision 1

05 — dot-apr-approve minimal design (DESIGN-ONLY · NOT DEPLOYED)

Labels: LOCAL_STAGING_NOT_SSOT · NOT_GOVERNED_RUNTIME · NOT_DEPLOYED · NOT_REGISTRY_PROOF. This is a specification only. No script was written to runtime; no DOT was born/registered; no APR approved. This DOT, if ever built, must be deployed only through a DOT-approved path (see Bootstrap below).

Purpose

Let one real, authenticated approver record one approve/reject decision for one APR into apr_approvals, with identity binding, proposer-exclusion, rationale, audit, and quorum readback. It must not auto-approve, must not let the agent impersonate an approver, must not mint votes by root/operator convenience, must not bypass quorum. It only records a decision by the authenticated approver.

Proposed CLI surface

dot-apr-approve --apr APR-0415 \
                --decision approve|reject \
                --approver <real_identity> \
                --approver-type human|ai_council \
                --rationale "<scoped text>"

Architecture decision (important — avoids the prior dot-c1-grant-issue defect)

apr_approvals is not a usable Directus collection (0 directus_fields). Therefore the tool must NOT POST to a Directus /items/apr_approvals endpoint (that endpoint is effectively absent — the exact defect that made the old dot-c1-grant-issue a would-be bypass). The vote must be written via the governed PG write path (the same run_pg mechanism dot-apr-execute uses for execute_patch_ops_code), behind an authority gate. Two viable shapes:

  • (A) New governed APR action record_apr_vote with a handler arm in dot-apr-execute — fits the existing apr_action_types/handler model, but ironically would route a vote through the execute tool. Discouraged.
  • (B) Standalone governed CLI dot-apr-approve bound to the PG write path under the approver's own authenticated credential. Preferred.

The crux: approver authentication (HARD PREREQUISITE)

Today approver is a free-text string with no credential binding. A tool that trusts a --approver flag is just a prettier fakeable insert. So dot-apr-approve is only meaningful if the owner first provides an authenticated-approver substrate: each president/council seat holds its own credential/token, and the tool verifies authenticated_caller == claimed approver before writing. Without this substrate the DOT cannot be trusted and must not be built. This is an owner/operator prerequisite, not an agent deliverable.

Required guards (fail-closed)

G1  APR exists (by code) ............................. else reject
G2  APR status = pending ............................. else reject
G3  caller authenticated AND caller == --approver .... else reject  (no impersonation)
G4  approver-type ∈ {human, ai_council} .............. else reject
G5  proposer-exclusion: approver != proposer ......... read BOTH source_context.proposer/created_by
       AND the `source` field; if proposer unknowable, refuse (fail-closed), not allow
G6  duplicate vote: UNIQUE(apr_id, approver) ......... ON CONFLICT → reject/no-op, never double-count
G7  --rationale required and non-empty ............... scoped to the one APR
G8  scope = exactly one APR .......................... no batch, no wildcard
G9  decision ∈ {approve, reject} ..................... reject blocks quorum downstream (already enforced)
G10 write ONE audit-bearing row via governed PG path . record channel/actor/auth provenance
G11 NEVER write as root/SYNC_SECRET/owner convenience  no auto-approve, no agent-as-approver
post readback: print quorum_passed(apr) + counts; tool itself does NOT flip APR status

Note: status flip pending→approved stays a separate governed step so fn_apr_quorum_check re-proves quorum at transition. dot-apr-approve only adds votes; it never approves the APR itself.

Required lifecycle plan (per DOT-100% rule; all DOT-or-DOT-approved)

reuse-first      none reusable (file 02) — genuinely net-new approve primitive
birth/khai sinh  DOT birth via governed birth path
governance       DOT admission/governance path
registration     dot-dot-register (C1-style targeted/idempotent; avoid registrar duplicate defect)
catalog          dot_tools / CAT-006 row (code, name, script_path, file_path)
ledger           DOT-manage ledger entry + KB readback
rollback/retire  retire path + remove catalog row; additive revert of the bin script
readback         catalog row + ledger entry + orphan check all read back
orphan check     no dangling contract/registry/grant after retire

Bootstrap problem (why this can't self-deploy) — see file 07

Deploying a new bin/dot/dot-apr-approve script is a patch_ops_code change = risk high ⇒ it needs an APR with quorum = 1 president + 2 ai_council — i.e. the very channel this DOT would create. Chicken-and-egg. The only legitimate resolutions are owner/operator decisions (file 07), not agent actions.

Explicit non-goals

No generic authorization framework · no arbitrary action_code · no hardcoded approver values · no PASS/seal on invalid input · no write outside apr_approvals · no status flip · no W1→W9 · no grant mint.

Back to Knowledge Hub knowledge/dev/laws-new/reports/apr-approval-channel-discovery-and-bootstrap/05-dot-apr-approve-minimal-design-if-needed.md