Introduce duo_code_review_flow_priority feature flag and update Modes::Dap#active? to route Duo Enterprise users through DAP when consent is given
Summary
Introduce the duo_code_review_flow_priority feature flag and update Ai::DuoCodeReview::Modes::Dap#active? so that Duo Enterprise users are routed through DAP when the new feature flag is enabled and their group has explicitly consented (via the group_consents table introduced in #602688 (closed)). The existing duo_code_review_dap_internal_users override is preserved as a fast-path that bypasses the consent requirement.
This is part of epic &22247.
Depends on: #602688 (closed) (group_consents table and Groups::Consent model must exist first).
Why
Today, Modes::Dap#active? short-circuits for any user with a Duo Enterprise add-on:
# Current behaviour
return ::Feature.enabled?(:duo_code_review_dap_internal_users, user) if user_has_duo_enterprise_add_on?This means Code Review Flow being enabled for the namespace is completely ignored for Duo Enterprise users — they always fall through to Modes::Classic. The fix inverts the priority: if the new feature flag is on and the group has consented, DAP wins regardless of Duo Enterprise seat assignment.
The duo_code_review_dap_internal_users flag is kept as an explicit override for GitLab-internal users, allowing us to test the full flow before rolling out to customers.
What
1. Feature flag
Add ee/config/feature_flags/ops/duo_code_review_flow_priority.yml:
---
name: duo_code_review_flow_priority
description: >
When enabled, the Code Review Flow toggle and group consent become the
authoritative routing signal for Duo Code Review, taking priority over
Duo Enterprise seat assignment. Requires explicit group consent recorded
in group_consents (feature_name: code_review_flow_dap_routing).
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/<this_issue>
introduced_by_url: # filled in by MR
rollout_issue_url: # to be created
milestone: '19.2'
group: group::ai coding
type: ops
default_enabled: false2. Updated Modes::Dap#active? logic
The current Duo Enterprise branch is a single early return:
# Before
return ::Feature.enabled?(:duo_code_review_dap_internal_users, user) if user_has_duo_enterprise_add_on?It becomes a structured block with three explicit paths:
# After
if user_has_duo_enterprise_add_on?
# Fast-path override: internal GitLab users bypass the consent requirement.
# Preserves existing behaviour — no change for users covered by this flag.
return true if ::Feature.enabled?(:duo_code_review_dap_internal_users, user)
# New path: route through DAP if the feature flag is on AND the group has
# explicitly consented to DAP routing (recorded in group_consents).
if ::Feature.enabled?(:duo_code_review_flow_priority)
return container.root_ancestor.consented_to?(:code_review_flow_dap_routing) &&
container.duo_code_review_dap_available? &&
duo_agent_platform_configured?
end
# Default: Duo Enterprise without the new flag → not active, falls through to Classic.
return false
endThe non-Duo-Enterprise branch (Duo Pro/Core) is unchanged.
Decision table for Duo Enterprise users after this change:
duo_code_review_dap_internal_users |
duo_code_review_flow_priority |
Group consented? | Result |
|---|---|---|---|
| enabled (for user) | any | any | |
| disabled | enabled | yes | |
| disabled | enabled | no | |
| disabled | disabled | any |
How
- Add
ee/config/feature_flags/ops/duo_code_review_flow_priority.yml. - Update
active?inee/app/models/ai/duo_code_review/modes/dap.rbas described above. - Update
ee/spec/models/ai/duo_code_review/modes/dap_spec.rbto cover all new branches inside thewhen user has duo_enterprise add-oncontext:duo_code_review_dap_internal_usersenabled → active (existing spec, verify it still passes).duo_code_review_dap_internal_usersdisabled +duo_code_review_flow_priorityenabled + group consented → active.duo_code_review_dap_internal_usersdisabled +duo_code_review_flow_priorityenabled + group not consented → not active.duo_code_review_dap_internal_usersdisabled +duo_code_review_flow_prioritydisabled → not active (existing behaviour).
- Verify all existing non-Duo-Enterprise specs still pass without modification.
Acceptance criteria
-
duo_code_review_flow_priorityfeature flag exists,default_enabled: false, typeops. - When
duo_code_review_dap_internal_usersis enabled for a Duo Enterprise user,active?returnstrueregardless of consent or the new flag (existing override preserved). - When
duo_code_review_flow_priorityis enabled and the group has aGroups::Consentrecord for:code_review_flow_dap_routing,active?returnstruefor Duo Enterprise users (subject toduo_code_review_dap_available?andduo_agent_platform_configured?). - When
duo_code_review_flow_priorityis enabled but the group has not consented,active?returnsfalsefor Duo Enterprise users (falls through to Classic). - When
duo_code_review_flow_priorityis disabled, Duo Enterprise behaviour is identical to today (no regression). - Non-Duo-Enterprise (Duo Pro/Core) routing is completely unchanged.
- All new branches are covered by unit tests in
dap_spec.rb.
Out of scope
- Writing the consent record from the UI (Issues 4 & 5).
- Any frontend changes.
- Changes to
Modes::ClassicorModeResolver.