Add a group descendants filter to the legacy Duo engines

What does this MR do and why?

This MR was split out of !255052 (merged) at a reviewer's request: !255052 (comment 3848489546). That lets the framework part merge on its own, and gives the engine additions their own justification here.

  • ee/app/models/analytics/aggregation_engines/code_suggestions.rb and agent_platform_sessions.rb: add a descendants :group_id filter with with_organization: false, since both tables store namespace_path without the organization prefix. max_size: 100 bounds the PostgreSQL lookup validation runs, and a TODO links #629169 to drop the override once every traversal path column carries the organization prefix.
  • ee/spec/models/analytics/aggregation_engines/code_suggestions_spec.rb and agent_platform_sessions_spec.rb: a group_id describe block for each engine, covering a group plus its descendants, and multiple group Global IDs.
  • doc/api/graphql/reference/_index.md and public/-/graphql/introspection_result.json: regenerated, because the filter is exposed as a groupId GraphQL argument on the duoCodeSuggestions and agentPlatformSessions fields.

Why

The immediate need for this filter is the AiUsageEvents engine in !254120 (merged), for the Group Comparison table on the Duo adoption dashboard. Adding the filter to these two engines came out of the review of !255052 (merged), not a confirmed product need for groupId on duoCodeSuggestions or agentPlatformSessions. This MR exists so that decision can be made on its own: merge it if a consumer is identified, or close it otherwise.

Dependencies and merge order

This MR is stacked on !255052 (merged) and targets its branch, 605518-traversal-path-filter. It will retarget to master once that MR merges.

References

Screenshots or screen recordings

Backend only, so there are no screenshots.

How to set up and validate locally

Run the specs for both engines:

bin/rspec ee/spec/models/analytics/aggregation_engines/code_suggestions_spec.rb
bin/rspec ee/spec/models/analytics/aggregation_engines/agent_platform_sessions_spec.rb

For an end-to-end check, query the filter through GraphQL against a group. Replace the Global ID with a group from your instance:

query {
  group(fullPath: "gitlab-org") {
    analytics {
      duoCodeSuggestions(groupId: ["gid://gitlab/Group/<id>"]) {
        aggregated {
          nodes {
            totalCount
          }
        }
      }
    }
  }
}

Passing a Global ID that is not an existing group, or a Project Global ID, returns a validation error instead of an empty result.

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.

🤖 Generated with Claude Code

Merge request reports

Loading
Loading