Add inherited group trigger lookup for service account suggestions
What does this MR do and why?
Group inheritance for AI Catalog is still in progress. One part of it lets a group enable a flow item once and have it apply to all projects under that group - done through an "inheritance" kind of ItemConsumer. Creating that record from the UI isn't wired up yet (separate MR), so for now you need the Rails console to set it up (see validation steps).
The problem this fixes
When you @mention someone in a comment or assign them to an issue/MR,
GitLab fetches a list of eligible users. For service accounts, if the
SA has active flow triggers it shows an AI badge next to it. If the SA
is assigned to an event it can handle it stays selectable; if not, it's
greyed out.
Before this MR, that badge logic only looked at project-level (direct) triggers. So a SA that belongs to a group-level inheritance consumer - even if it's already a member of the project - would show up with no AI badge and be treated as unselectable for AI events.
What this MR change
Adds a shared trigger lookup layer that unions a project's own triggers
with inheritance triggers from the root group, gated behind the
ai_catalog_group_inherited_consumers feature flag.
Two surfaces benefit from this:
-
@mentionautocomplete : powered by ParticipantsService via the REST endpoint. Inherited SAs now show up with the correct event bad -
Assignee / reviewer picker : powered by DuoStatusType via the GraphQL autocompleteUsers query. Inheritance triggers are loaded once per root group per request (keyed in GraphQL context to avoid N+1).
Also adds a composite index on ai_catalog_item_consumers
(group_id, kind, service_account_id) which replaces a post-filter that
was scanning all consumers for a group before narrowing by SA.
References
How to set up and validate locally
Since the UI for creating inheritance consumers is not wired up yet, you need to create the records manually from the Rails console first.
1. Setup
Expand
group = Group.find_by_full_path('your-group')
project = group.projects.first
item = Ai::Catalog::Item.where(item_type: 2).first
root = User.find_by(username: 'root')
sa_result = Namespaces::ServiceAccounts::GroupCreateService.new(
root,
{
namespace_id: group.id,
name: item.name,
username: "ai-#{item.name}-#{group.name}".parameterize,
composite_identity_enforced: true,
skip_ai_prefix_validation: true,
skip_owner_check: true,
organization_id: group.organization_id
},
uniquify_provided_username: true
).execute
sa = sa_result.payload[:user]
consumer = Ai::Catalog::ItemConsumer.new
consumer.group_id = group.id
consumer.ai_catalog_item_id = item.id
consumer.service_account_id = sa.id
consumer.kind = 1 # inheritance
consumer.save!(validate: false)
trigger = Ai::FlowTrigger.new
trigger.group_id = group.id
trigger.ai_catalog_item_consumer_id = consumer.id
trigger.event_types = [
Ai::FlowTrigger::EVENT_TYPES[:mention],
Ai::FlowTrigger::EVENT_TYPES[:assign]
]
trigger.description = "Test inheritance trigger"
trigger.active = true
trigger.save!(validate: false)
project.add_developer(sa)
Feature.enable(:ai_catalog_group_inherited_consumers, group)2. Verify in console
Expand
result = Ai::FlowTrigger.applicable_to_project(project, triggered_on: :mention)
puts result.map { |t| "ID:#{t.id} group_id:#{t.group_id.inspect}" }
# should include the new inheritance trigger with group_id set
svc = Projects::ParticipantsService.new(project, root)
participants = svc.execute(project.issues.first)
sa_entry = participants.find { |p| p[:username] == sa.username }
puts sa_entry&.dig(:flow_trigger_events).inspect
# => [:MENTION, :ASSIGN]NOTE
In my GDK I've created the Item consumer records below, with the Flow trigger mapped to assignee and mentioned event types. Service account user is @duo-release-note-flow-gitlab-duo, and it's a group-level inheritance consumer.
Expand
#<User id:1612 @duo-release-note-flow-gitlab-duo>
#<Ai::Catalog::ItemConsumer:0x000000014e8aadc8
id: 808,
ai_catalog_item_id: 5514,
group_id: 1000000,
project_id: nil,
created_at: "2026-09-24 09:46:27.938676000 +0000",
updated_at: "2026-09-24 09:46:27.938676000 +0000",
enabled: false,
locked: true,
pinned_version_prefix: nil,
service_account_id: 1612,
parent_item_consumer_id: nil,
kind: "inheritance">
#<Ai::FlowTrigger:0x0000000142264ee8
id: 183,
project_id: nil,
user_id: nil,
config_path: nil,
description: [FILTERED],
event_types: [0, 1],
created_at: "2026-09-24 09:46:43.666904000 +0000",
updated_at: "2026-09-24 09:46:43.666904000 +0000",
ai_catalog_item_consumer_id: 808,
filter: {},
active: true,
group_id: 1000000,
autonomous_service_account_id: nil>3. Verify @mention autocomplete (REST path)
- Open any issue/MR in the project
- Click the comment box and type
@followed by the SA username prefix - The SA should appear in the dropdown with an AI badge
4. Verify assignee/reviewer picker (GraphQL path)
- On the same issue open the Assignees section in the right sidebar
- Search for the SA, it should appear with an AI badge
- The badge events should reflect mention and assign
5. Verify FF off
Feature.disable(:ai_catalog_group_inherited_consumers)Repeat steps 3 and 4, the SA still appears (it's a project member) but the AI badge should not show. Re-enable after:
Feature.enable(:ai_catalog_group_inherited_consumers, group)Database Query Plan
Currently in production there are no item consumer records with kind inheritance. So to test the query, I've added 4k item_consumer records in the postgre.ai for the gitlab-org (9970) group.
Some queries will still return 0 records since the actual data isn't there, for example, when filtering by service account, none of the dummy records have a service account attached correctly, so those queries will show 0.
Click to expand
self.applicable_to_project with event_type
Query plan - https://console.postgres.ai/gitlab/projects/gitlab-production-main/sessions/58494/commands/163406
applicable_to_namespace with by_service_accounts (@duo-fix-ci-cd-pipeline-gitlab-org user_id: 32742185)
Query Plan - https://console.postgres.ai/gitlab/projects/gitlab-production-main/sessions/58494/commands/163417
applicable_to_project with triggered_on: :mention and with by_service_accounts (@duo-fix-ci-cd-pipeline-gitlab-org user_id: 32742185)
Query Plan - https://console.postgres.ai/gitlab/projects/gitlab-production-main/sessions/58494/commands/163419
active_inherited_for_group
Query plan - https://console.postgres.ai/gitlab/projects/gitlab-production-main/sessions/58494/commands/163421
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.
Related to #627518 (closed)





