Add duo_developer feature setting

What does this MR do and why?

For https://gitlab.com/gitlab-org/gitlab/-/work_items/613151

Introduces a dedicated duo_developer feature setting (ID 26) for the DAP developer flow so it has an independent model selection entry in the admin UI, separate from the shared duo_agent_platform feature setting.

Follows the same pattern used for the duo_agent_platform → duo_agent_platform_agentic_chat split (!213517 (merged)) and the review_merge_request → review_merge_request_dap split (!236876 (merged)).

Gated behind the duo_developer_model_config feature flag: Ai::DuoWorkflows::WorkflowContextGenerationService#ai_feature returns :duo_developer for the developer/v1 foundational flow only when the flag is enabled for the current user; otherwise it falls back to :duo_agent_platform (previous behavior).

Post-deployment migrations copy existing duo_agent_platform rows into duo_developer across the three feature-setting tables (ai_feature_settings, instance_model_selection_feature_settings, ai_namespace_feature_settings), including the model_allowlist_enabled / model_allowlist_gitlab_model_refs columns added to the latter two since the reference MRs, so self-managed/self-hosted and GitLab.com instances start with equivalent model config.

Companion AI Gateway MR (deploy first): gitlab-org/modelops/applied-ml/code-suggestions/ai-assist!6636 (merged)

Closes gitlab-org#23227 (closed)

Screenshots

Screenshot_2026-08-26_at_12.56.39_PM

How to set up and validate locally

  1. Run the migrations:

    bin/rails db:migrate
  2. Verify the three tables have a row for duo_developer (feature = 26) copied from duo_agent_platform (feature = 16):

    # Rails console
    Ai::FeatureSetting.find_by(feature: :duo_developer)
    Ai::ModelSelection::NamespaceFeatureSetting.where(feature: :duo_developer).count
    Ai::InstanceFeatureSetting.where(feature: :duo_developer).count
  3. Navigate to Admin area → AI-powered features and confirm a "Duo Developer" entry appears grouped alongside "Agents & flows" and "Agentic Chat" (not under the classic features), with independent model selection.

  4. Enable the feature flag and verify WorkflowContextGenerationService#ai_feature returns the new symbol for the developer flow:

    # Rails console
    Feature.enable(:duo_developer_model_config)
    
    user = User.find_by(username: 'your-username')
    service = Ai::DuoWorkflows::WorkflowContextGenerationService.new(
      current_user: user,
      workflow_definition: Ai::Catalog::FoundationalFlow['developer/v1'].foundational_flow_reference
    )
    service.send(:ai_feature) # => :duo_developer
  5. Disable the flag and confirm the method falls back to :duo_agent_platform:

    Feature.disable(:duo_developer_model_config)
    service.send(:ai_feature) # => :duo_agent_platform
  6. Confirm duo_developer is treated as a DAP feature for self-hosted entitlement, not routed through the classic self-hosted-models check (Ai::UserAuthorizable#check_dap_self_hosted_feature):

    # Rails console
    self_hosted_model = Ai::SelfHostedModel.first
    feature_setting = Ai::FeatureSetting.find_or_initialize_by_feature(:duo_developer)
    feature_setting.update!(provider: :self_hosted, self_hosted_model: self_hosted_model)
    
    user.send(:check_dap_self_hosted_feature, feature_setting) # => a Response, not nil
  7. In the GraphQL API (or Admin UI), confirm setting duo_developer's self-hosted model is authorized the same way as duo_agent_platform (via the update_dap_self_hosted_model ability), not manage_self_hosted_models_settings.

References

Edited by Manoj M J

Merge request reports

Loading
Loading