Code Suggestions still work on GitLab.com when group Duo availability is set to "Always Off"

Summary

On GitLab.com (SaaS), a group Owner setting GitLab Duo availability to "Always Off" (never_on) does not disable Code Suggestions for that group's members. Members continue to receive Code Suggestions, and the resulting Duo Agent Platform / AI Gateway usage is counted towards the customer's credit usage, despite the group being explicitly set to "Always Off". A customer reported unexpected credit usage traced to Code Suggestions under exactly this configuration.

This behavior is a known gap discussed in #535507 (moved): "Always Off" acts as a true kill switch on self-managed instances, but on GitLab.com it only controls context access rather than gating feature (and credit) usage.

Steps to reproduce

  1. On GitLab.com, have a top-level group on a plan with a Duo add-on (Duo Pro/Enterprise) assigned to users.
  2. As a group Owner, go to Settings > GitLab Duo and set GitLab Duo availability to Always Off.
  3. As a member of that group with a Duo seat, open a project in a supported IDE and trigger Code Suggestions.
  4. Observe that Code Suggestions still return completions.
  5. Check Duo usage for the namespace.

What is the current bug behavior?

Code Suggestions remain functional and count towards credit usage even though group-level Duo availability is set to "Always Off". The "Always Off" toggle gives group Owners the reasonable expectation of a kill switch, but on SaaS it does not stop Code Suggestions or the associated credit usage.

What is the expected correct behavior?

When a group's Duo availability is set to "Always Off" on GitLab.com, Code Suggestions should be disabled for that group's members and no credit usage should be recorded, matching the kill-switch behavior on self-managed instances (or the difference should be clearly documented and surfaced).

Relevant logs and/or screenshots

N/A — customer-reported credit usage attributed to Code Suggestions.

Possible fixes

The root cause is that the access_code_suggestions policy only checks the instance-level duo_never_on?, never the namespace-level setting.

In ee/app/policies/ee/global_policy.rb, ai_features_banned reads the instance setting:

condition(:ai_features_banned) do
  ::Gitlab::CurrentSettings.duo_never_on?
end

rule do
  code_suggestions_licensed & ~ai_features_banned & code_suggestions_enabled_for_user
end.enable :access_code_suggestions

And duo_never_on? in ee/app/models/ee/application_setting.rb reads only the instance value:

def duo_never_on?
  duo_availability == :never_on
end

On SaaS there is no instance admin setting duo_availability = never_on, so this always returns false. A group Owner's "Always Off" writes never_on to NamespaceSetting.duo_availability (delegated from Group in ee/app/models/ee/group.rb: delegate :duo_availability, ... to: :namespace_settings), but access_code_suggestions is a global/user policy that never consults the namespace setting. The group- and project-scoped ai_features_banned conditions in ee/app/policies/ee/group_policy.rb and ee/app/policies/ee/project_policy.rb also delegate to the same instance-level check, so they do not close the gap either.

Fix options:

  • Make the Code Suggestions availability check honor a namespace-level never_on for the relevant group(s) on SaaS, not just the instance setting.
  • Alternatively, if the divergent behavior is intended, clearly document it and surface the blocking reason to users/admins.

Related discussion: #535507 (moved).

Edited by 🤖 GitLab Bot 🤖