Repository navigation
governance: define authority and decision-context contract with execution-time revalidation #700
Description
Parent: mctlhq/.github#181
Source: mctlhq/.github#182 decision-assurance audit (G6/G7).
Problem
MCTL has canonical principals, tenant roles, approval requests, policy decisions and exact-action hashes, but the decision chain does not yet provide one explicit contract for reviewer context and authority freshness across decision and execution.
Stored authority claims are evidence, not an authorization substitute. A valid approval must not remain executable indefinitely after authority, policy or relevant context changes.
Goal
Compose existing identity/policy/approval primitives into a minimal authority + decision-context contract and define the execution-time revalidation boundary.
Required context
At minimum make reconstructable/referenceable: intent/source, actor/subject/tenant, target, exact operation/payload hash, policy id/version/decision/reasons, risk/side-effect classification where available, approver authority basis, decision time and expiry/freshness semantics.
Scope
- Define authority evidence captured at decision time.
- Define which authority/policy facts are revalidated at execution and what drift requires reapproval.
- Define expiry/freshness semantics for approvals.
- Preserve privacy by references/redaction rather than indiscriminate payload logging.
- Reuse Unified Identity/AuthZ and existing policy contracts; no parallel authorization model.
- Break-glass implementation is explicitly out of scope for this required item; it can be designed separately if needed.
Acceptance criteria
- Contract identifies the minimum decision context and authority evidence required for a governed approval.
- Execution revalidates the defined live authority/policy facts before side effects.
- Permission/policy drift and expiry produce typed refusal/reapproval outcomes.
- F3/F4/F6/F9 scenarios from fix(audit): record what actually happened, not just what was submitted #182 have executable tests or bounded proof.
- Existing canonical principal/tenant/policy identifiers are reused.
Refs mctlhq/.github#181, mctlhq/.github#182, mctlhq/.github#91.
Scenario mapping from #182 (authoritative; correction to the first investigation)
The first proposal could not read mctlhq/.github#182 and guessed the F-mapping; three of the four were wrong, and F6 had no test. Use exactly this mapping from the #182 table:
| ID | #182 scenario | Required contract | Test / proof |
|---|---|---|---|
| F3 | Approver loses permissions before execution | Authority revalidation boundary. Revoked authority -> approval_authority_revoked; disabled/merged decider -> approval_decider_disabled; unobservable authority -> 503 approval_authority_unavailable (fail closed, approval not spent). |
Revoked-authority, disabled-decider and unavailable-authority cases all belong to F3. |
| F4 | Execute hours/days later after context changes | Expiry and freshness semantics (fresh_until, expires_at). |
The injected-clock stale/expired tests belong to F4. |
| F6 | Reviewer sees only "Approve operation?" | Mandatory decision context shown to the reviewer and bound to the decision: target, exact payload (hash/reference, redacted), risk/side-effect classification, intent/source, and policy id/version/decision/reasons. | New, required: (a) the approval read/decision view returned to the reviewer contains every mandatory field; (b) an approval request missing any mandatory field cannot be approved (typed refusal, no grant); (c) the decision records the context digest it was made on, and a consume whose context no longer matches is refused. |
| F9 | Evaluate under policy v1, execute under v2 | Policy drift detection and re-evaluation/reapproval. | The v1 -> v2 drift test (approval_policy_drift, new approval under v2 succeeds) belongs to F9. |
docs/decision-context-contract.md and the test names must use this mapping. The acceptance criterion "F3/F4/F6/F9 scenarios from #182 have executable tests or bounded proof" is not met without the F6 test above.
Cross-repo note: mctl-agents matches refusal codes by substring, so approval_policy_drift reads as stale and triggers a re-grant. Keep reapproval_required set on every drift/stale/revoked refusal so callers can key on it rather than on code names.
Activity
mctl-agents commentedon Oct 19, 2026
mctl-agents issue-investigator has analyzed this issue and created a proposal:
https://github.com/mctlhq/mctl-gitops/tree/main/platform-gitops/agents-state/mctl-api/proposals/issue-700-governance-define-authority-and-decision/
Status:
proposed— pending human approval. Reviewrequirements.md,design.mdandtasks.md, then approve: signal this issue's DevLoopWorkflow (mctl-apiPOST /api/v1/agents/dev-loop/dev-loop-mctlhq-mctl-api-700/approve, orpython -m orchestrator.temporal.cli approve dev-loop-mctlhq-mctl-api-700 --approver <your-identity>) — the workflow flips.status.yamltoacceptedvia themctl-agents-approveoperation and runs the Tier 2 implementer. If no DevLoopWorkflow is running for this issue (pre-Temporal proposal), run themctl-agents-approveoperation directly withservice=mctl-api slug=issue-700-governance-define-authority-and-decision.The approver is recorded in
.status.yamland in the gitops commit, and the implementer refuses a proposal whosecontrol.requires_human_approvalcarries no named approver — so prefer the mctl-api endpoint, which takes the approver from the authenticated caller rather than from what the caller types.chore(agents): investigate mctlhq/mctl-api#700 2026-10-19
mashkovd commentedon Oct 19, 2026
@mctl reinvestigate
The issue body now carries the authoritative F3/F4/F6/F9 mapping from mctlhq/.github#182 and a required F6 test (section "Scenario mapping from #182").
mctl-agents commentedon Oct 19, 2026
@mashkovd re-investigation started: Argo workflow
mctl-agents-investigate-e3555d84(mctl-api/issue-700-governance-define-authority-and-decision).mctl-agents commentedon Oct 19, 2026
mctl-agents issue-investigator has analyzed this issue and created a proposal:
https://github.com/mctlhq/mctl-gitops/tree/main/platform-gitops/agents-state/mctl-api/proposals/issue-700-governance-define-authority-and-decision/
Status:
proposed— pending human approval. Reviewrequirements.md,design.mdandtasks.md, then approve: signal this issue's DevLoopWorkflow (mctl-apiPOST /api/v1/agents/dev-loop/dev-loop-mctlhq-mctl-api-700/approve, orpython -m orchestrator.temporal.cli approve dev-loop-mctlhq-mctl-api-700 --approver <your-identity>) — the workflow flips.status.yamltoacceptedvia themctl-agents-approveoperation and runs the Tier 2 implementer. If no DevLoopWorkflow is running for this issue (pre-Temporal proposal), run themctl-agents-approveoperation directly withservice=mctl-api slug=issue-700-governance-define-authority-and-decision.The approver is recorded in
.status.yamland in the gitops commit, and the implementer refuses a proposal whosecontrol.requires_human_approvalcarries no named approver — so prefer the mctl-api endpoint, which takes the approver from the authenticated caller rather than from what the caller types.chore(agents): investigate mctlhq/mctl-api#700 2026-10-19
mctl-agents commentedon Oct 19, 2026
Approval grant
aar_c54c8a1cd6a6440ea43271ee12541ceewas superseded because the proposal was rewritten. It was bound to digestsha256:c3de71f28d6b73e9079f777130df78d6db944bfa9cdc0530579485360839e817; the current digest issha256:9b0ce40ccf18cc2b3417958ef314f66e0a7575f6793fca10719224ca5f877c29. Please decide the fresh grantaar_9191404ab95c4c5d88b28cc87c80f45d.