Block workflow start when an admin denies a full tool group
What does this MR do and why?
Duo Workflow only enforces tool governance mid-run. A background flow can start even when an admin has denied every tool in a group it declares. It then runs a full session without those tools and does worse work.
This adds a start-time check to CreateWorkflowService. It applies only to the background governance surface, which today is Duo Developer, and only when the duo_workflow_background_tool_governance flag is on. The flag defaults off, so this is a no-op until enabled.
The service reads the flow's declared agent_privileges and resolves them against the admin's tool rules with the existing Ai::ToolRules::ResolutionService. If every tool in a declared group is denied, the flow refuses to start with a :forbidden error naming the group. A partial deny inside a group still lets the flow start, since mid-run JWT enforcement already covers that case. run_command is the only tool in the run_commands group, so denying it blocks Duo Developer at start. That falls out of the group logic; it is not special-cased.
If governance resolution itself fails, the flow refuses to start with reason :governance_resolution_failed.
One caveat worth calling out: this check trusts the tool groups a flow declares in Rails, and those have drifted from the DWS toolset for Duo Developer. Rails declares READ_WRITE_FILES, READ_ONLY_GITLAB, READ_WRITE_GITLAB, RUN_COMMANDS, and USE_GIT, but the DWS 3.0.0 toolset for Developer only uses file tools plus run_command. Fully denying READ_ONLY_GITLAB, READ_WRITE_GITLAB, or USE_GIT would block Developer even though it never calls those tools. Rails has no visibility into the DWS toolset, so keeping the declared groups in sync with it is a requirement of this approach going forward.
The issue description names the flag duo_workflow_runner_tool_governance. The real flag is duo_workflow_background_tool_governance.
How to reproduce the issue
You need a GDK where Duo Developer runs, and a project in a top-level group. Run these in gdk rails c on master. I wrote these steps from the specs and haven't run them in a GDK.
-
Turn on background governance. Turn off the runner precondition so the console call does not need a runner.
Feature.enable(:duo_workflow_background_tool_governance) Feature.disable(:duo_workflow_precondition_check) -
Deny
run_commandfor background flows in the top-level group.project = Project.find_by_full_path('<group>/<project>') user = User.find_by_username('<username>') Ai::ToolRule.create!(namespace: project.root_ancestor, tool_name: 'run_command', background_access: :deny) -
Create a Duo Developer session with the same params
Ai::Catalog::ExecuteWorkflowServicepasses.params = { environment: 'web', workflow_definition: 'developer/v1', goal: 'test', agent_privileges: Ai::Catalog::FoundationalFlow.developer_v1.agent_privileges } Ai::DuoWorkflows::CreateWorkflowService.new(container: project, current_user: user, params: params).execute
The call succeeds and creates a workflow. That session would run without run_command, which is the only way Duo Developer pushes code or opens an MR.
How to test the fix
-
Check out this branch and repeat steps 1 to 3. The call now returns an error and creates no workflow:
message: "An administrator denied all tools in run_commands. This flow needs at least one of them to run." payload: { reason: :privilege_groups_denied } -
Check that these cases still create a workflow:
- Replace the rule with a deny on
create_merge_requestonly. A partial deny inside a group does not block the start. - Keep the rule and run
Feature.disable(:duo_workflow_background_tool_governance). - Replace the rule with
web_access: :denyand nobackground_access. - Delete the rule.
- Replace the rule with a deny on
-
Clean up with
Feature.enable(:duo_workflow_precondition_check). -
Run the specs:
bin/rspec ee/spec/services/ai/duo_workflows/create_workflow_service_spec.rb
References
- Issue: https://gitlab.com/gitlab-org/gitlab/-/work_items/607134
- DWS companion MR: gitlab-org/modelops/applied-ml/code-suggestions/ai-assist!7142 (merged)
Screenshots or screen recordings
N/A. This is a backend service change with no UI.
How to set up and validate locally
Covered by "How to reproduce the issue" and "How to test the fix" above.
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.