Add [session:123] reference filter for Duo Agent sessions

What does this MR do and why?

Extends GitLab Flavored Markdown so Duo Agent Platform sessions can be referenced from issue comments, MR descriptions, wiki pages, and other Markdown fields using the [session:123] syntax, with cross-project support ([session:group/project/123]) mirroring the existing extensible reference filters such as [vulnerability:123].

Rendered links are scoped by the :read_duo_workflow ability, so sessions the user cannot see fall back to raw text via the standard reference redaction path. Autocomplete support is intentionally out of scope and will be handled as a follow-up (per the parent issue).

Resolves #606314

Screenshots or screen recordings

TODO once verified in GDK.

How to set up and validate locally

  1. In a GDK project, create a Duo Agent Platform session (or use an existing one).
  2. In an issue comment, MR description, or wiki page, type: [session:] [session://]
  3. Confirm that the reference renders as a link to /<group>/<project>/-/automate/agent-sessions/<id> for users with :read_duo_workflow on the session, and as raw text otherwise.
  4. Confirm that pasting the same URL into the same fields also renders as the extensible reference form.

Database review

This MR adds one new ActiveRecord scope on Ai::DuoWorkflows::Workflow:

scope :with_project, -> { preload(:project) }

The scope is used from Banzai::ReferenceParser::SessionParser#records_for_nodes to hydrate a batch of workflow records with their parent projects for Markdown reference rendering. preload triggers two separate PK-index queries (no joins).

Query 1: batch fetch of sessions

SELECT "duo_workflows_workflows".*
FROM "duo_workflows_workflows"
WHERE "duo_workflows_workflows"."id" IN ($1, $2, ...);

EXPLAIN (from local GDK postgres):

Index Scan using duo_workflows_workflows_pkey on duo_workflows_workflows
   (cost=0.14..4.20 rows=3 width=414)
   Index Cond: (id = ANY ('{1,2,3}'::bigint[]))

Query 2: preload of projects

SELECT "projects".*
FROM "projects"
WHERE "projects"."id" IN ($1, $2, ...);

EXPLAIN:

Index Scan using projects_pkey on projects
   (cost=0.14..3.09 rows=3 width=1479)
   Index Cond: (id = ANY ('{1,2,3}'::bigint[]))

Bounds

Both IN (…) lists are bounded by the number of [session:…] references in a single Markdown blob. Reference filters use Banzai::Filter::FILTER_ITEM_LIMIT (currently 300) as a hard upper bound on matches per document, so the IN cardinality is at most ~300.

No new indexes are required — both queries use existing primary-key indexes. No pagination or update_all/delete_all involved.

MR acceptance checklist

  • Follows the guidelines from Extensible reference filters
  • Test coverage mirrored from the vulnerability filter/parser specs
  • Changelog: added / EE: true in commit trailer
  • Manually verified in GDK
Edited by Titiksha Bansal

Merge request reports

Loading