Add ai_workflows scope to group GraphQL fields

What does this MR do and why?

Add ai_workflows scope to group GraphQL fields

Custom Flow composite identity tokens carry only the ai_workflows OAuth scope. GraphQL fields default to the api and read_api scopes, so Query.group and Query.groups silently returned null for these tokens regardless of the service account's role, while Query.project and Query.namespace already declared the scope.

Declaring the scope on the root fields alone is not enough:

  • Namespace.projects lacked the scope, blocking group { projects }.
  • Types::Namespaces::GroupInterface redefines id, name and fullPath, and GroupType redefines webUrl, so the scopes declared on NamespaceType do not apply to Group and those fields still resolved to null.

Align the affected fields with the ai_workflows allowlist already exposed by NamespaceType. Deeper authorization layers (read_group ability, Duo policy gates, composite identity) are unaffected.

References

#606488 (closed)

Screenshots or screen recordings

Before After
FireShot_Capture_033_-Sessions___Automate___DUO-TEST___Apple___GitLab-_gdk.test FireShot_Capture_034_-Sessions___Automate___DUO-TEST___Apple___GitLab-_gdk.test

How to set up and validate locally

Prerequisites

  • GDK with EE license and Duo features enabled
  • A group with at least one project (e.g. duo-test/apple)

Steps

  1. Create a custom flow in AI Catalog using the YAML below
  2. Trigger the flow from an issue in the group's project
  3. Verify all probe queries return data (not null):
    • groups(first: 5) — returns groups
    • group(fullPath:) — returns group data
    • namespace(fullPath:) — returns namespace data
    • group.projects — returns projects
Flow YAML
version: v1
environment: ambient

components:
  - name: graphql_auth_probe
    type: AgentComponent
    prompt_id: graphql_auth_probe_prompt
    inputs:
      - from: "context:goal"
        as: "goal"
      - from: "context:project_id"
        as: "project_id"
    toolset:
      - "gitlab_graphql"
    ui_log_events:
      - "on_agent_final_answer"
      - "on_tool_execution_success"
      - "on_tool_execution_failed"

prompts:
  - prompt_id: graphql_auth_probe_prompt
    name: GraphQL auth probe
    unit_primitives: []

    prompt_template:
      system: |
        You are a GitLab GraphQL authorization diagnostic agent.

        Your task is to verify whether the authentication context of the
        Custom Flow can read GitLab GraphQL data.

        You must dynamically discover accessible groups and projects.
        Do not hardcode any group or project paths.

        Requirements:

        - You may only use the gitlab_graphql tool.
        - Do not use the REST API.
        - Do not guess or fabricate any results.
        - Execute each query one by one.
        - Report the raw JSON returned by every executed query.
        - Replace TARGET_GROUP_PATH and TARGET_PROJECT_PATH with the paths
          discovered from previous query results.

        ## Execution plan

        Step 1:
        Run Query 0 to inspect the current authenticated user.

        Step 2:
        Run Query 1 to discover accessible groups.

        If no groups are returned:
        - Report that group-level probes cannot continue.
        - Skip Queries 2 through 5.
        - Go directly to the final summary.

        Step 3:
        Take the fullPath of the first group returned by Query 1 and use it
        as TARGET_GROUP_PATH for Queries 2, 3, and 4.

        Step 4:
        Run Query 2 using TARGET_GROUP_PATH.

        Step 5:
        Run Query 3 using TARGET_GROUP_PATH.

        Step 6:
        Run Query 4 using TARGET_GROUP_PATH.

        If projects are returned:
        - Take the fullPath of the first project.
        - Use it as TARGET_PROJECT_PATH for Query 5.

        If no projects are returned:
        - Report that project-level probes cannot continue.
        - Skip Query 5.

        Step 7:
        Run Query 5 using TARGET_PROJECT_PATH.

        After all executable queries have completed, provide a concise
        authorization diagnostic summary covering:

        - Whether currentUser returned data.
        - Whether groups(first: 5) returned any groups.
        - Whether group(fullPath:) returned null or data.
        - Whether namespace(fullPath:) returned null or data.
        - Whether group.projects returned visible projects.
        - Whether project(fullPath:) returned basic project data.
        - Which authorization layer is most likely responsible for any failure.

      user: |
        Run the following GitLab GraphQL authorization probe queries in the
        current Custom Flow session.

        Context:

        - Trigger goal: {{goal}}
        - Trigger project_id: {{project_id}}

        ## Query 0: Current authenticated user

        query CurrentUserProbe {
          currentUser {
            id
            username
            name
            webUrl
          }
        }

        ## Query 1: Discover accessible groups

        query DiscoverGroups {
          groups(first: 5) {
            nodes {
              id
              name
              fullPath
            }
          }
        }

        Use the fullPath of the first group returned by Query 1 as
        TARGET_GROUP_PATH.

        If Query 1 returns no groups, skip Queries 2 through 5 and go
        directly to the authorization diagnostic summary.

        ## Query 2: Group by fullPath

        query GroupProbe {
          group(fullPath: "TARGET_GROUP_PATH") {
            id
            name
            fullPath
          }
        }

        ## Query 3: Namespace by fullPath

        query NamespaceProbe {
          namespace(fullPath: "TARGET_GROUP_PATH") {
            id
            name
            fullPath
          }
        }

        ## Query 4: Group projects

        query GroupProjectsProbe {
          group(fullPath: "TARGET_GROUP_PATH") {
            id
            name
            fullPath
            projects(first: 5, includeSubgroups: true) {
              nodes {
                id
                name
                fullPath
              }
            }
          }
        }

        Use the fullPath of the first project returned by Query 4 as
        TARGET_PROJECT_PATH.

        If Query 4 returns no projects, skip Query 5.

        ## Query 5: Project by fullPath

        query ProjectProbe {
          project(fullPath: "TARGET_PROJECT_PATH") {
            id
            name
            fullPath
          }
        }

        Return the raw JSON result of each executed query, followed by the
        authorization diagnostic findings.

    params:
      timeout: 300

routers:
  - from: graphql_auth_probe
    to: end

flow:
  entry_point: graphql_auth_probe

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 Xingli Wu

Merge request reports

Loading
Loading