Draft: VAC: find-only default context in ingestion (durable fix for #612930)

What does this MR do and why?

This is the durable fix for #612930, where the first pipeline on a project's default branch drops the entire SAST slice on ingestion. It makes the ingest phase resolve the tracked default context find-only, mirroring the store phase, so both phases agree on which UUID scheme to use. Tracked under #613547.

Draft while I self-review, then over to Ryan (@ryaanwells) for review. No reviewers assigned yet.

Root cause

There's a store/ingest asymmetry.

The store phase resolves the tracked context find-only. EE::Gitlab::Ci::Reports::Security::Report#tracked_context does ProjectTrackedContext.for_pipeline(pipeline).tracked.first, which is nil when a project has no tracked default context. Findings are stored with context-unaware (v1) UUIDs.

The async ingest phase then lazily find-or-creates a v2 default context mid-pipeline (via TrackedContextFinder#find_or_create_from_pipeline) and re-parses, producing context-aware (v2) UUIDs.

The stored-v1 versus reparsed-v2 UUID mismatch makes the ingestion join miss, so the whole SAST slice is dropped.

The fix

Permissive legacy fallback. Make the ingest phase find-only too, so it matches the store phase. A project without a tracked default context resolves to nil in both phases, both produce v1 UUIDs, the join hits, and nothing is dropped.

The default branch stays legacy v1/NULL-context until it is legitimately tracked, either via CreateOrUpdateDefaultTrackedContextWorker or explicit tracking.

Implementation changes:

  • Added find_from_pipeline / find_from_project to TrackedContextFinder (find-only, nil when absent). The existing find_or_create_* methods stay for the advisory scanner caller.
  • FindingMapCollection#tracked_context and IngestReportsService#tracked_context switch to find-only under the FF.
  • log_ingestion is nil-guarded (tracked_context&.is_default?).
  • MarkAsResolvedService routes a nil tracked_context to the context-less path, same as when VAC is disabled.

Feature flag

vac_find_only_default_context_ingestion (development, default_enabled: false). Off preserves the existing find-or-create behavior. On switches the ingest phase to find-only.

Test coverage

Added and extended specs in ee/spec/services/security/ingestion/:

  • tracked_context_finder_spec
  • finding_map_collection_spec
  • ingest_reports_service_spec
  • mark_as_resolved_service_spec

They cover: a first default-branch pipeline with no pre-existing context ingests as v1 when the FF is on; a legacy no-context project doesn't raise ArgumentError and passes nil context through; FF-off preserves current behavior.

Note: mark_as_resolved_service_spec is :elastic-tagged and requires a running Elasticsearch, which wasn't available in the local dev environment; the other three spec files were run locally and pass. CI will exercise the full set.

Merge request reports

Loading
Loading