05 — dot-apr-approve Minimal Design (staged only, not deployed)
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_votewith a handler arm indot-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-approvebound 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.