You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The decision-assurance audit found policy-approval checkpoint code/contracts but no evidence that MCTL_POLICY_APPROVALS=mctl-api is enabled in current GitOps deployment declarations. Some transports/entry points (including Bash/mentor paths identified by the audit) are also outside the canonical checkpoint.
A governance capability cannot be considered complete while the canonical policy checkpoint is optional/disabled or bypassable by normal supported entry points.
Goal
Make the canonical policy approval checkpoint an explicit production contract for governed actions, or explicitly classify paths as non-governed with enforceable boundaries.
Scope
Verify current deployment configuration and supported entry points.
Enable the canonical mctl-api-backed checkpoint where the action is classified governed.
Close normal transport gaps or explicitly exclude them with tests/documented contract.
Fail closed when a governed action requires policy/approval evidence and the checkpoint is unavailable.
Reuse existing policy/approval contracts; no second policy engine.
Acceptance criteria
Production GitOps declarations explicitly configure the canonical checkpoint for governed paths.
Supported governed transports cannot bypass the checkpoint by selecting another normal entry point.
Unavailable/misconfigured checkpoint fails closed for governed actions with typed evidence.
Deployment/test evidence demonstrates the configured path end-to-end.
Any intentionally non-governed transport is explicitly classified and cannot be mistaken for governed execution.
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-gitops-1980/approve, or python -m orchestrator.temporal.cli approve dev-loop-mctlhq-mctl-gitops-1980 --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-gitops slug=issue-1980-governance-productionize-policy-approval.
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.
Approval grant aar_9313b2e634e74a579fc8f087b157dc24 was superseded because the proposal was rewritten. It was bound to digest sha256:aa6556ba2da974cc88b1c81071da73287ee155a34737ad63c74bc07653c3b987; the current digest is sha256:e275b68c5ccbea413d82e88d39f398f660c88ce0d0fd4b5c11e8923e79ee3647. Please decide the fresh grant aar_fff21ba34dab4a589b94c6ca7dad41ad.
Receipt gate enforce is live (#2101, merge c25f0c2, 2026-10-23 ~17:35Z). Both running mctl-api replicas print MCTL_AGENT_RECEIPT_GATE=enforce; rollout completed cleanly.
Evidence at the flip:
Observe (2026-10-20 20:57Z to the flip) recorded 0 agent-receipt-gate rows: service:mctl-agent made no governed MCP calls, only reads, so enforce refuses no legitimate path seen.
Investigate, the only surface with MCTL_POLICY_APPROVALS=mctl-api, now calls MCP on scoped run tokens (mctl-agents#737, feat(agents): enforce run tokens for investigate again #2099). Two enforced runs on 2026-10-23 (bc6d5846, a765878a) succeeded, each with a token exchange and an agent_scope.denied row for the out-of-scope probe.
Still open against this issue's acceptance criteria: the Bash / MCTL_TOKEN REST path stays bypass-open in the coverage manifest (mctl-agents#717), and implement/run/shepherd/reconcile remain rollout: staged. Follow-ups: mctlhq/mctl-api#772 (spend after success), mctlhq/mctl-api#773 (receipt age bound).
The MCTL_POLICY_APPROVALS env is present in the mctl-agents-implement, mctl-agents-run and mctl-agents-shepherd CWFTs and on admins-mctl-agents-worker-base-service. The worker restarted healthy.
Six shepherd runs created after the flip all ended Succeeded.
All surfaces run mctl-agents 1.95.0, which is at or above min_approvals_version 1.86.1.
worker-exec, worker-implement and usage-collector stay no-model-session.
tests/test_policy_checkpoint_coverage.py enforces both the env literal and the boundary set.
Receipt gate (mctl-api 4.118.1): a receipt is now spent only after the handler succeeds. It moves consumed → in_flight before the handler, then to executed or back to consumed afterwards. A cancelled call spends it. A receipt whose consumed_at is older than MCTL_AGENT_RECEIPT_MAX_AGE (default 5m, max 1h), or whose fresh_until has passed, is refused with agent_receipt_stale. This closes mctl-api#772 and fix: academy datasource panels fail with "no default database" despite green test #773, via mctl-api#777 and chore: remove gitops-bump self-test scratch file #778.
Acceptance criteria
Production declarations configure the checkpoint for every surface classified governed.
No bypass through another normal entry point. Not yet.investigate-bash, implement-bash, shepherd-bash and run-bash stay bypass-open (policy: keep the mctl-api token out of agent tool subprocesses mctl-agents#717): the static MCTL_TOKEN is still in those containers. The owner chose option (c): move the runs' REST calls onto their scoped run token, then drop MCTL_TOKEN from the CWFT. The first slice is merged and live: mctl-api#779 (4.119.0) lets an investigate run token seal its own execution's snapshot. Still to do:
mctl-agents: switch WorkItemClient to the run token.
The self-attaching runs, whose token is not bound to a work item.
Action approvals for run tokens.
Dropping MCTL_TOKEN from the investigate CWFT. The other surfaces follow the same path.
Fails closed when unavailable or misconfigured:
An unknown MCTL_POLICY_APPROVALS value turns every REQUIRE_APPROVAL into a lookup error.
A store that cannot be reached returns DENY.
The receipt gate is in enforce mode.
End-to-end evidence on the newly flipped surfaces. Partial.POLICY_DECISION shows which backend answered only on a REQUIRE_APPROVAL decision (approval_pending with an aar_ ref, compared with approval_required under NO_APPROVALS). No run since the flip has made a governed call. The runs observed so far were all ALLOW by rule, and none failed.
Non-governed paths are classified explicitly, and the coverage test makes that machine-checked.
Keeping this open until #717 removes the bypass-open entries.
Before the template change, organic DevLoop run mctl-agents-investigate-2c02f23a (mctl_list_previews reports count 0 when the ArgoCD query fails mctl-api#698, image 1.98.0, we_ execution). The pod log shows run token: enforce, scope=investigate and the out-of-scope probe refused. The work_context read succeeded and WORK_CONTEXT_SNAPSHOT ... snapshot-sealed followed. mctl-api audit records work_item.snapshot succeeded with user agent:issue-investigator.
agent_scope.denied (10:22:25), the enforced out-of-scope probe;
work_item.snapshot succeeded by agent:issue-investigator (10:22:28);
agent_run_token.revoke succeeded (10:24:43).
The proposal was committed and the run Succeeded.
Still bypass-open: implement-bash, run-bash, shepherd-bash. Each needs a scope profile and an exchange-template entry, and its REST clients (ClaimClient, approvals, dev-loop GET) must move onto the run token. The approvals and self-attach design questions are open on mctlhq/mctl-agents#717. This issue stays open.
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-gitops/proposals/issue-1980-governance-productionize-policy-approval/
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-gitops-1980/approve, orpython -m orchestrator.temporal.cli approve dev-loop-mctlhq-mctl-gitops-1980 --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-gitops slug=issue-1980-governance-productionize-policy-approval.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 #1980 2026-10-19
Merge pull request #2010 from mctlhq/docs/review-notes-1979-1980
mctl-agents commentedon Oct 19, 2026
Approval grant
aar_9313b2e634e74a579fc8f087b157dc24was superseded because the proposal was rewritten. It was bound to digestsha256:aa6556ba2da974cc88b1c81071da73287ee155a34737ad63c74bc07653c3b987; the current digest issha256:e275b68c5ccbea413d82e88d39f398f660c88ce0d0fd4b5c11e8923e79ee3647. Please decide the fresh grantaar_fff21ba34dab4a589b94c6ca7dad41ad.mashkovd commentedon Oct 23, 2026
Receipt gate enforce is live (#2101, merge c25f0c2, 2026-10-23 ~17:35Z). Both running mctl-api replicas print
MCTL_AGENT_RECEIPT_GATE=enforce; rollout completed cleanly.Evidence at the flip:
agent-receipt-gaterows: service:mctl-agent made no governed MCP calls, only reads, so enforce refuses no legitimate path seen.MCTL_POLICY_APPROVALS=mctl-api, now calls MCP on scoped run tokens (mctl-agents#737, feat(agents): enforce run tokens for investigate again #2099). Two enforced runs on 2026-10-23 (bc6d5846, a765878a) succeeded, each with a token exchange and anagent_scope.deniedrow for the out-of-scope probe.Still open against this issue's acceptance criteria: the Bash /
MCTL_TOKENREST path staysbypass-openin the coverage manifest (mctl-agents#717), and implement/run/shepherd/reconcile remainrollout: staged. Follow-ups: mctlhq/mctl-api#772 (spend after success), mctlhq/mctl-api#773 (receipt age bound).mashkovd commentedon Oct 23, 2026
Status after the staged-surface flips (owner OK 2026-10-24, one OK per surface).
Done
MCTL_POLICY_APPROVALS: mctl-apias a literal, with norollout: stagedmarker left inpolicy-checkpoint-coverage.yaml: investigate (feat(mctl-api): enforce the agent receipt gate #2101 era), implement (feat(agents): govern implement with the mctl-api approvals backend #2105), run (feat(agents): govern run with the mctl-api approvals backend #2106), shepherd (feat(agents): govern shepherd with the mctl-api approvals backend #2107) and worker-control (feat(agents): govern the control worker with mctl-api approvals #2108). All five were merged on 2026-10-23 between 22:31 and 22:32Z.MCTL_POLICY_APPROVALSenv is present in themctl-agents-implement,mctl-agents-runandmctl-agents-shepherdCWFTs and onadmins-mctl-agents-worker-base-service. The worker restarted healthy.Succeeded.min_approvals_version1.86.1.governed: false, boundary: no-mctl-token(chore(agents): classify reconcile as not governed (no MCTL_TOKEN) #2109): it has no model session and noMCTL_TOKEN.no-model-session.tests/test_policy_checkpoint_coverage.pyenforces both the env literal and the boundary set.consumed_atis older thanMCTL_AGENT_RECEIPT_MAX_AGE(default 5m, max 1h), or whosefresh_untilhas passed, is refused withagent_receipt_stale. This closes mctl-api#772 and fix: academy datasource panels fail with "no default database" despite green test #773, via mctl-api#777 and chore: remove gitops-bump self-test scratch file #778.Acceptance criteria
investigate-bash,implement-bash,shepherd-bashandrun-bashstaybypass-open(policy: keep the mctl-api token out of agent tool subprocesses mctl-agents#717): the staticMCTL_TOKENis still in those containers. The owner chose option (c): move the runs' REST calls onto their scoped run token, then dropMCTL_TOKENfrom the CWFT. The first slice is merged and live: mctl-api#779 (4.119.0) lets an investigate run token seal its own execution's snapshot. Still to do:WorkItemClientto the run token.MCTL_TOKENfrom the investigate CWFT. The other surfaces follow the same path.MCTL_POLICY_APPROVALSvalue turns every REQUIRE_APPROVAL into a lookup error.POLICY_DECISIONshows which backend answered only on a REQUIRE_APPROVAL decision (approval_pendingwith anaar_ref, compared withapproval_requiredunder NO_APPROVALS). No run since the flip has made a governed call. The runs observed so far were all ALLOW by rule, and none failed.Keeping this open until #717 removes the
bypass-openentries.feat(investigate): drop MCTL_TOKEN from run-investigator
mashkovd commentedon Oct 24, 2026
investigate-bashis no longerbypass-open(#2118, merged as 79e191f, mctl-agents 1.98.0 from mctlhq/mctl-agents#788).Evidence:
Before the template change, organic DevLoop run
mctl-agents-investigate-2c02f23a(mctl_list_previews reports count 0 when the ArgoCD query fails mctl-api#698, image 1.98.0,we_execution). The pod log showsrun token: enforce, scope=investigateand the out-of-scope probe refused. The work_context read succeeded andWORK_CONTEXT_SNAPSHOT ... snapshot-sealedfollowed. mctl-api audit recordswork_item.snapshot succeededwith useragent:issue-investigator.After the template change, organic DevLoop run
mctl-agents-investigate-d65f1786(fix(implementer): use Refs, not Closes, in PRs for spike issues mctl-agents#763, submitted 10:22Z after Argo CD synced). The storedrun-investigatortemplate maps noMCTL_TOKEN. mctl-api audit shows, in order:agent_scope.denied(10:22:25), the enforced out-of-scope probe;work_item.snapshot succeededbyagent:issue-investigator(10:22:28);agent_run_token.revoke succeeded(10:24:43).The proposal was committed and the run Succeeded.
Still
bypass-open:implement-bash,run-bash,shepherd-bash. Each needs a scope profile and an exchange-template entry, and its REST clients (ClaimClient, approvals, dev-loop GET) must move onto the run token. The approvals and self-attach design questions are open on mctlhq/mctl-agents#717. This issue stays open.