Send ask tools in the tool access policies claim

What does this MR do and why?

Ai::ToolRules::ResolutionService already computes an ask_tools list, but Rails never included it in the tool_access_policies JWT claim sent to the Duo Workflow Service, so ask had to be inferred from a tool being absent from both allow and deny.

Send it explicitly, matching the field the Duo Workflow Service already parses and already uses to decide whether governance is active for a workflow.

Also excludes asked tools from the MCP-derived allow additions in the /ws claim builder: MCP server tool names get gitlab_-prefixed, and a few catalog tools already carry that prefix natively (for example gitlab_api_get), so an asked tool could otherwise end up listed in both allow and ask on the wire. The Duo Workflow Service's own ask-wins precedence already made this a no-op in practice, but the claim should not carry a contradictory pair of lists, so it's fixed at the source too.

Measured claim size impact: the default (no rules configured) case grows by 9 bytes; a fully-configured namespace (every governed tool asked) adds about 1.8 KB of JSON, well within request header limits.

This change is safe to ship on its own — the Duo Workflow Service already treats a non-empty ask list as active governance, independent of the companion MR below.

References

Resolves https://gitlab.com/gitlab-org/gitlab/-/issues/600612

Companion Duo Workflow Service MR, which acts on the ask list's contents (not required for this MR to be safe or complete on its own): gitlab-org/modelops/applied-ml/code-suggestions/ai-assist!6594 (merged)

Screenshots or screen recordings

Not applicable. No UI in this repo changes.

How to set up and validate locally

  1. In a Rails console, pick (or create) a governed group and set an explicit "Ask" rule on a tool, for example:
    group = Group.find_by_full_path('<group>')
    Ai::ToolRule.find_or_initialize_for_namespace(namespace_id: group.id, tool_name: 'list_issues')
      .tap { |r| r.web_access = :ask }.save!
  2. Confirm the resolver actually reports it:
    payload = Ai::ToolRules::ResolutionService.new(namespace: group, surface: :web).execute.payload
    payload[:ask_tools] # => ["list_issues"]
    payload[:pre_approved_tools] # => does not include "list_issues"
  3. Mint a real token and decode it to see the actual claim. On a local GDK (not SaaS-licensed), self-signed token minting needs an env override:
    # CLOUD_CONNECTOR_SELF_SIGN_TOKENS=true bin/rails console
    user = User.find_by(username: 'root')
    client = Ai::DuoWorkflow::DuoWorkflowService::Client.new(
      duo_workflow_service_url: 'localhost:50052', current_user: user, secure: false,
      pre_approved_tools: payload[:pre_approved_tools], denied_tools: payload[:denied_tools],
      ask_tools: payload[:ask_tools]
    )
    token = client.send(:cloud_connector_token)
    JSON.parse(JWT.decode(token, nil, false)[0]['tool_access_policies'])
    # => {"allow"=>[...], "ask"=>["list_issues"], "deny"=>[]}
  4. Regression check for the bug this fixes: set every tool in read_only_gitlab (the only default-Allow group) to :ask, and re-run step 3. Before this change, allow and deny both come back empty and ask is silently dropped from the claim — indistinguishable, on the wire, from a namespace with no governance configured at all. After this change, ask carries all of them, so the Duo Workflow Service's existing governance_active check (already on main) correctly stays active instead of going false.
  5. Regression check for the MCP collision: enable an MCP server whose tools include one that's also asked (or reuse a catalog tool with a native gitlab_ prefix, like gitlab_api_get, and set it to Ask), and confirm the claim's allow list does not also contain that tool name.
  6. Run the updated specs:
    bundle exec rspec ee/spec/services/ai/tool_rules/resolution_service_spec.rb \
      ee/spec/lib/ai/duo_workflow/duo_workflow_service/client_spec.rb \
      ee/spec/services/ai/duo_workflows/workflow_context_generation_service_spec.rb \
      ee/spec/requests/api/ai/duo_workflows/workflows_spec.rb

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.

Edited by Rahul Barnwal

Merge request reports

Loading
Loading