KB-7B43

06 — Reworked dot-c1-grant-issue contract (governed propose path) 2026-06-23

4 min read Revision 1
c1-legodot-c1-grant-issuereworkdot-apr-proposeno-bypass

06 — Reworked dot-c1-grant-issue contract

Reworked script: staged-artifacts/scripts/dot-c1-grant-issue.reworked. It replaces the defective skeleton at reports/c1-lego-…/staged-artifacts/scripts/dot-c1-grant-issue.

A. Defects of the old skeleton (confirmed against live SSOT)

  1. curl … /items/governance_build_authorization — that Directus endpoint does not exist (gba is a raw PG table, absent from directus_collections). Cannot mint anything.
  2. Posts ~13 columns that don't exist (grant_id, action, build_step, single_use, lease_ttl, manifest_bound_hash, owner, revocable, plan_ref, reject_on, scope-as-string).
  3. Bypass: a direct REST POST to the grant table would skip authorize_build_step, quorum, president vote, and the unimplemented-handler trigger ⇒ GOVERNED_C1_DRYRUN_REJECT_GRANT_BYPASS. It is inert only because (1)+(2) make it fail.

B. Reworked contract (the issuer is now a PROPOSER, not a writer)

requirement (§3.5) how met
not POST to Directus gba ✓ no curl to gba; no Directus write at all
not assume gba is a Directus collection ✓ preflight to_regclass('public.governance_build_authorization') (raw table)
not use wrong columns ✓ uses no gba columns; emits a proposed_action payload only; the handler maps live schema
call the governed authorize_build_step path dot-apr-propose --action-code authorize_build_step --proposed-action <C1 payload>
validate live schema ✓ preflight asserts gba table + authorize_build_step action row exist; warns if handler still unimplemented
support --dry-run ✓ prints the APR it WOULD propose
emit no grant in --dry-run ✓ exits before proposing; mints nothing
return exact reject codes ✓ exit 2 (missing --manifest-hash), exit 4 (gba/action absent); downstream reject codes are the handler's (file 07)

C. Flow (governed, end to end)

dot-c1-grant-issue --manifest-hash <cser-v1>            # Cấp A: propose only
      └─> dot-apr-propose (authorize_build_step APR, proposed_action=C1 payload, priority=high)
            └─> approvals: 1 human president + 2 ai_council (proposer excluded, no rejects)  [quorum_passed]
                  └─> dot-apr-execute (Cấp B)
                        └─> dispatch_handler 'dot-apr-execute:authorize_build_step'
                              └─> execute_authorize_build_step  -> 1 grant (run_pg), status=active
                                    └─> trg_apr_block_unimplemented re-proves quorum on APPLY

The issuer never holds grant-mint authority; the handler does, and only behind quorum.

D. proposed_action payload (fixed C1 scope)

See payloads/authorize_build_step_apr_proposed_action.json. Key locks: c1=true, scope={DRYRUN-NS, dot:c1:vocab, DOT_C1_VOCAB_BUILD, …}, commit_allowed=false, risk_level=high, manifest_hash (required, from a DOT_C1_VOCAB_BUILD dry-run), ttl_seconds=7200.

E. request_type

apr_request_types (14 active) has no authorize_build_step default; dot-apr-propose accepts an explicit --action-code (FK to apr_action_types, which DOES contain authorize_build_step). The script uses --request-type rule_change (an active row; operator may pick another active row) + explicit --action-code authorize_build_step.

F. Lifecycle note (honest)

The reworked issuer is still a staged script (not born/registered/cataloged as a DOT). This macro's charter is the handler + binding + issuer redesign, staged for owner review — not the DOT lifecycle registration of the issuer (that remains the separate, owner/operator-gated step named in the predecessor HOLD). The issuer rework is design-completeC1_AUTH_HANDLER_HOLD_GRANT_ISSUER_REWORK_INCOMPLETE does not fire; but "design-complete" ≠ "registered DOT".

Back to Knowledge Hub knowledge/dev/laws-new/reports/c1-authorize-build-step-handler-minimal-lego-patch/06-reworked-dot-c1-grant-issue-contract-2026-06-23.md