Skip to content

governance: define authority and decision-context contract with execution-time revalidation #700

Closed

Description

@mashkovd

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

  1. mctl-agents commented on Oct 19, 2026

    @mctl-agents
    Contributor

    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. Review requirements.md, design.md and tasks.md, then approve: signal this issue's DevLoopWorkflow (mctl-api POST /api/v1/agents/dev-loop/dev-loop-mctlhq-mctl-api-700/approve, or python -m orchestrator.temporal.cli approve dev-loop-mctlhq-mctl-api-700 --approver <your-identity>) — the workflow flips .status.yaml to accepted via the mctl-agents-approve operation and runs the Tier 2 implementer. If no DevLoopWorkflow is running for this issue (pre-Temporal proposal), run the mctl-agents-approve operation directly with service=mctl-api slug=issue-700-governance-define-authority-and-decision.

    The approver is recorded in .status.yaml and in the gitops commit, and the implementer refuses a proposal whose control.requires_human_approval carries no named approver — so prefer the mctl-api endpoint, which takes the approver from the authenticated caller rather than from what the caller types.

  2. added a commit that references this issue on Oct 19, 2026
  3. mashkovd commented on Oct 19, 2026

    @mashkovd
    MemberAuthor

    @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").

  4. mctl-agents commented on Oct 19, 2026

    @mctl-agents
    Contributor

    @mashkovd re-investigation started: Argo workflow mctl-agents-investigate-e3555d84 (mctl-api/issue-700-governance-define-authority-and-decision).

  5. mctl-agents commented on Oct 19, 2026

    @mctl-agents
    Contributor

    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. Review requirements.md, design.md and tasks.md, then approve: signal this issue's DevLoopWorkflow (mctl-api POST /api/v1/agents/dev-loop/dev-loop-mctlhq-mctl-api-700/approve, or python -m orchestrator.temporal.cli approve dev-loop-mctlhq-mctl-api-700 --approver <your-identity>) — the workflow flips .status.yaml to accepted via the mctl-agents-approve operation and runs the Tier 2 implementer. If no DevLoopWorkflow is running for this issue (pre-Temporal proposal), run the mctl-agents-approve operation directly with service=mctl-api slug=issue-700-governance-define-authority-and-decision.

    The approver is recorded in .status.yaml and in the gitops commit, and the implementer refuses a proposal whose control.requires_human_approval carries no named approver — so prefer the mctl-api endpoint, which takes the approver from the authenticated caller rather than from what the caller types.

  6. added a commit that references this issue on Oct 19, 2026
  7. mctl-agents commented on Oct 19, 2026

    @mctl-agents
    Contributor

    Approval grant aar_c54c8a1cd6a6440ea43271ee12541cee was superseded because the proposal was rewritten. It was bound to digest sha256:c3de71f28d6b73e9079f777130df78d6db944bfa9cdc0530579485360839e817; the current digest is sha256:9b0ce40ccf18cc2b3417958ef314f66e0a7575f6793fca10719224ca5f877c29. Please decide the fresh grant aar_9191404ab95c4c5d88b28cc87c80f45d.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions