Bind workflow tokens to foundational flow ID
What does this MR do and why?
Passes the Rails-authorized foundational flow ID to DWS when minting workflow tokens across every server-started execution path, allowing DWS to reject registered flow substitution. Non-foundational flows and the direct-access token endpoint remain unbound for compatibility. Vendors gitlab-duo-workflow-service-client 0.12, which adds flow_config_id to GenerateTokenRequest.
Related #2431
References
- https://gitlab.com/gitlab-org/modelops/applied-ml/code-suggestions/ai-assist/-/work_items/2431
- gitlab-org/modelops/applied-ml/code-suggestions/ai-assist!6430 (merged)
DWS/Rails Compatibility
| Rails | DWS | Workflows | Substitution blocked |
|---|---|---|---|
| Old | Old | Work | No |
| Old | New | Work | No; tokens remain unbound |
| New | Old | Work | No; the optional protobuf field is ignored |
| New | New | Work | Yes |
Either MR can deploy first. Older self-managed GitLab versions remain compatible because DWS permits tokens without a binding. When a binding is present, DWS fails closed: it requires a non-empty string claim and permits only the matching registry flow. Debug users retain the existing binding bypass.
Screenshots or screen recordings
Not applicable. This change has no UI.
How to set up and validate locally
Run GDK with this Rails branch and DWS from gitlab-org/modelops/applied-ml/code-suggestions/ai-assist!6430 (merged). Enable Duo Agent Platform and the foundational flows used below for the test project. Configure their service accounts, then set:
export GITLAB_URL="http://gdk.test:3000"
export GITLAB_TOKEN="<personal-access-token-with-api-scope>"
export PROJECT_ID="<numeric-project-id>"Generic workflow API path
This exercises API::Helpers::DuoWorkflowHelpers#start_workflow_params:
curl --request POST \
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
--header "Content-Type: application/json" \
--data "{
\"project_id\": \"$PROJECT_ID\",
\"workflow_definition\": \"developer/v1\",
\"goal\": \"Create hello.txt containing hello\",
\"start_workflow\": true
}" \
--url "$GITLAB_URL/api/v4/ai/duo_workflows/workflows"Confirm the workflow pipeline starts and DWS receives developer as the
flow_config_id in the token request.
Catalog execution path
Enable Developer Flow from the AI Catalog for the test project. Look up its consumer ID:
curl --request POST \
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
--header "Content-Type: application/json" \
--data "{\"query\":\"query { aiCatalogConfiguredItems(projectId: \\\"gid://gitlab/Project/$PROJECT_ID\\\") { nodes { id item { name } } } }\"}" \
--url "$GITLAB_URL/api/graphql"Use the numeric suffix from
gid://gitlab/AiCatalogItemConsumer/<numeric-id>:
export AI_CATALOG_ITEM_CONSUMER_ID="<numeric-id>"
curl --request POST \
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
--header "Content-Type: application/json" \
--data "{
\"project_id\": \"$PROJECT_ID\",
\"ai_catalog_item_consumer_id\": $AI_CATALOG_ITEM_CONSUMER_ID,
\"goal\": \"Create hello.txt containing hello\",
\"start_workflow\": true
}" \
--url "$GITLAB_URL/api/v4/ai/duo_workflows/workflows"Confirm the workflow pipeline starts and DWS receives developer as the
flow_config_id in the token request. This exercises
Ai::Catalog::ExecuteWorkflowService.
Dedicated foundational-flow path
This path is used by code review, reviewer recommendations, and workplan generation. To exercise it with Code Review Flow:
- Enable Code Review Flow for a project and configure its service account.
- Create a non-draft merge request with a change to review.
- Assign
@GitLabDuoas a reviewer, use the/assign_reviewer @GitLabDuoquick action, or mention@GitLabDuoand ask for a review. - Confirm a session and workflow pipeline are created.
- Confirm DWS receives
code_reviewas theflow_config_idin the token request.
This exercises Ai::DuoWorkflows::CreateAndStartWorkflowService.
Binding enforcement
For each server-started path above, the flow ID in the DWS token request must
match the resolved flow used to start the workload. With the accompanying DWS
branch, presenting a token bound to developer while requesting
flowConfigId: secrets_fp_detection must fail with PERMISSION_DENIED before
flow resolution.
The direct-access token-only endpoint is intentionally unbound because it does not authorize or start a specific flow.
MR acceptance checklist
- Targeted service and client specs pass.
- All server-started foundational flow paths bind the resolved flow ID.
- Non-foundational and direct-access token callers remain backward-compatible.
- Vendored
gitlab-duo-workflow-service-client0.12, regenerated from the rebased DWS branch.