[FF] duo_workflow_local_tool_governance -- enforce Duo tool governance on local surfaces
Summary
Roll out the duo_workflow_local_tool_governance feature flag, which enforces human-in-the-loop AI tool governance rules for GitLab Duo agentic flows on local surfaces (IDE, CLI, Chat). When enabled, local-surface sessions resolve tool permissions against the local_access rule column and client-supplied agent privileges are clamped to that governance resolution. Default off; when off, behavior is byte-identical to today (web_access resolution). See Governance tool rules (Ai::ToolRule) are not ap... (#606343 - closed) for context. Introduced in Enforce tool governance on local surfaces for D... (!249463 - merged). The confidential security tracker gitlab#606692 can be closed once this flag is enabled.
- DRI: @dbernardi
- Team Slack channel:
#g_developer_clients
What could go wrong?
The flip affects all execution modes on local surfaces, not only auto mode. Manual-mode users will silently gain pre-approvals wherever a local allow rule differs from the web rules, and a local deny will block a tool regardless of execution mode. There is also a known fail-open: if governance resolution errors at the JWT-claim mint sites, denied tools resolve to empty (admin denies are dropped) rather than failing closed. This is pre-existing master behavior tracked for the re-key follow-up.
Watch Duo workflow error rates and tool-approval metrics on https://dashboards.gitlab.net during each rollout step.
Blockers before enabling
- Re-key surface selection and the privilege clamp off the server-derived FlowExecutionAuthorizer execution classification (from Govern Duo flow runs by how they are executed (!248339 - merged)) instead of the client-supplied environment, so the column choice cannot be spoofed. This must land before this flag or
duo_client_executed_flow_governanceorduo_workflow_background_tool_governancegoes GA. - Settle the
externalsurface split-brain: on master the degraded_surface passthrough reads thelocal_accesscolumn on the creation-resolution path while the clamp and JWT mints fall back to web, so the two can resolve against different columns for the same workflow. Decide the intended external-surface behavior and make it consistent before enabling. - Row-derived pre-approval intersects the JWT ceiling (ai-assist!6491 / #608968). With local
askrules live, a tool can still be auto-approved through the workflow row, which sits outside the ceiling - so the admin'saskwouldn't actually hold. This is the "one gap" I flagged on the epic. - Empty or errored governance claim fails closed (#611843). An empty
tool_access_policiesclaim is read as "no ceiling" today, and the mint-side case you already noted above (resolution error -> emptydenied_tools) drops admin denies instead of failing closed. Both need to fail closed before we lean on the token to carry local denies. - Token bound to its workflow (#605431). This flag puts local
denyinto the token; while tokens are unbound a permissive one can be replayed onto a governed workflow and that deny is bypassed - so binding needs to be in effect, with client adoption, before the flip.
Rollout
Run all production /chatops in #production and cross-post results to #g_developer_clients.
Non-production
/chatops gitlab run feature set duo_workflow_local_tool_governance 50 --actors --dev --pre --staging --staging-ref
/chatops gitlab run feature set duo_workflow_local_tool_governance true --dev --pre --staging --staging-ref
Production — percentage rollout (wait at least 15 min between steps, watch dashboards):
/chatops gitlab run feature set duo_workflow_local_tool_governance <percentage> --actors
Or target specific actors instead:
/chatops gitlab run feature set --group=gitlab-org,gitlab-com duo_workflow_local_tool_governance true
/chatops gitlab run feature set --user=dbernardi duo_workflow_local_tool_governance true
Before global rollout
Confirm the relevant gotchas before going to 100%, see enabling a feature for GitLab.com:
- Both blockers above resolved
- Docs + version history updated
- Change management issue opened, if required
- External API consumers handled with a fail-open mechanism, if applicable
Cleanup
Remove the flag once deemed stable. Remove the flag and its YAML definition from the codebase, then:
/chatops gitlab run release check <merge-request-url> <milestone>
/chatops gitlab run feature delete duo_workflow_local_tool_governance --dev --pre --staging --staging-ref --production
Rollback
/chatops gitlab run feature set duo_workflow_local_tool_governance false # production
/chatops gitlab run feature set duo_workflow_local_tool_governance false --dev --pre --staging --staging-ref # non-production
/chatops gitlab run feature delete duo_workflow_local_tool_governance --dev --pre --staging --staging-ref --production # remove entirely