Register the BLSA flow with the AI Catalog

Depends on !257091 (merged), which defines the bl_security_analyzer flag. Targets bl-split/mr1-business-logic-analyzer-type. GitLab retargets to master when !257091 (merged) merges.

What does this MR do and why?

  • Registers the Business Logic Security Analyzer (BLSA) foundational flow, bl_security/experimental, with the AI Catalog.
  • The catalog shows it as "Business Logic Security Scan". It uses the default Flow Registry version (1.0.0), with no version pin.
  • Runs it automatically on a merge request's successful head pipeline. In this MR every run scans the whole repository. Scoping to the changed files lands in !257465 (merged).
  • Everything sits behind the bl_security_analyzer flag (experiment, default off). The engine (ai-assist !7077) has not merged yet and must deploy before or with this MR.

Part of the BLSA split of !246889. Stacked on !257091 (merged). Tracker: https://gitlab.com/gitlab-org/gitlab/-/work_items/630266

Stacked below: !257465 (merged) (MR scan scope), !257196 (merged), !257199 (merged)

When the flow runs

The trigger fires only when the pipeline succeeds (default_trigger_filter). The precondition also requires source merge_request_event or push, on a non-default branch.

Pipeline case Runs? What it scans
MR pipeline succeeds Yes Whole repository. !257465 (merged) scopes it to the files the MR adds or modifies
Branch pipeline that is an open MR's head pipeline Yes Same as above: the goal is that MR's IID
Branch pipeline with no open MR No Refused, reason: :no_merge_request
Default branch No Precondition excludes it. Full default-branch scans are started from GitLab Duo Chat or the API (documented in !257199 (merged))
MR from a fork No Refused, reason: :fork_merge_request. The workload would check out the wrong code
Child pipeline (parent_pipeline) or failed pipeline No Precondition / success filter
Other head-pipeline sources (web, api, trigger, schedule) No Precondition accepts merge_request_event and push only

How to review

  1. Registration: bl_security/definition.rb, foundational_flow.rb, items.rb.
  2. When it runs: the definition.rb precondition and default_trigger_filter; the "which pipelines fire the flow" spec table in foundational_flow_spec.rb.
  3. Refusals: goal_validator_resolver, goal_templates/bl_security.rb (merge_request_for), and their specs.
  4. Trigger-filter plumbing: attributes.rb, the sync services, item_consumers/create_service.rb, inherited_project_authorization.rb.
  5. Model selection: feature_setting.rb, features_configurable.rb, feature_metadata.yml.
  • Skip doc/, public/, locale/: generated.
  • The files that matter most: definition.rb, the goal template, inherited_project_authorization.rb, foundational_flow_spec.rb.
  • Suggested reviewers: AI Catalog/DAP backend for the flow and trigger provisioning; AppSec for inherited_project_authorization.rb and the fork refusal; model-selection owners for the feature setting.
  • Known wart: the generated GraphQL docs say "Bl security feature setting" (from humanize in the features enum).

Backward compatibility / impact on existing flows

Shared code Change Risk Mitigation
SyncFoundationalFlowsService, SyncBatchFoundationalFlowsService Copy the flow's default_trigger_filter into new trigger rows Other flows could get a filter Attribute defaults to {}; only BLSA sets one
ItemConsumers::CreateService `trigger_filter = default_trigger_filter`
InheritedProjectAuthorization Accepts a filter key on trigger creation Could let a caller set an arbitrary filter Accepted only when it equals the flow's own default_trigger_filter. Without this, projects created after the flow was enabled got no trigger

Design decisions

  • Scan only successful pipelines. The pipeline hook fires on every status change, and success is the one stable status a trigger filter can match. It also avoids spending on pipelines that failed.
  • The trigger filter is copied onto each trigger. Like other trigger settings, it's stored on the trigger row when the flow is enabled. A later change to the definition doesn't update existing triggers.

Not in this MR (later in the stack)

  • Scanning only the changed files: !257465 (merged). Until it merges, each run scans the whole repository (the flow is behind an off flag).
  • One run per pipeline, and skipping stale and merge-train pipelines: !257199 (merged). Until it merges, a pipeline can start more than one run, for example when a job is retried.

Known limitations

  • Expected refusals are logged at error level. FlowTriggers::RunService logs every refused goal as Flow execution failed, including a branch pipeline with no MR. Follow-up: log expected refusals at info level.
  • An MR can be scanned twice when its head pipeline changes kind. If a branch pipeline becomes the MR's head pipeline after an MR pipeline did, both are scanned.
  • Model selection shows the flow only when the flag is on instance-wide. The flow itself checks the flag per top-level group.
File inventory (30 files)
  • Flow and goal template: ee/app/models/ai/catalog/foundational_flow/bl_security/definition.rb, ee/app/models/ai/catalog/goal_templates/bl_security.rb
  • Registry wiring: foundational_flow.rb, foundational_flow/attributes.rb (default_trigger_filter), foundational_flow/items.rb (BL_SECURITY_FLOW_REFERENCE)
  • AI feature: ee/app/models/ai/feature_setting.rb, ee/app/models/concerns/ai/model_selection/features_configurable.rb, ee/lib/gitlab/ai/feature_settings/feature_metadata.yml
  • Trigger provisioning: sync_foundational_flows_service.rb, sync_batch_foundational_flows_service.rb, item_consumers/create_service.rb, ee/lib/ai/catalog/flows/inherited_project_authorization.rb
  • Shared list: app/models/concerns/enums/security.rb (FLOW_BACKED_SCAN_TYPES), scripts/lint/keela_excluded.yml
  • Generated: doc/api/graphql/reference/_index.md, doc/api/graphql/reference/experimental/enums.md, public/-/graphql/introspection_result.json, locale/gitlab.pot
  • Specs: 11 spec files plus ee/spec/factories/ai/feature_settings.rb
Hand-merge notes
  • sync_foundational_flows_service.rb, item_consumers/create_service.rb and their specs were merged by hand.
  • They keep master's group-inheritance behavior. Only the default_trigger_filter change is layered on top.
  • New specs cover the filter paths: one-group sync, batch sync, item-consumer creation.

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.

Edited by Meir Benayoun

Merge request reports

Loading
Loading