From 6af84c521688acec8d070f8266e847e3630e65ca Mon Sep 17 00:00:00 2001 From: Sharang Parnerkar <30073382+mighty840@users.noreply.github.com> Date: Wed, 22 Jul 2026 14:18:04 +0200 Subject: [PATCH] fix(orchestrator): refresh control_refs on existing findings during re-scan The dedup loop only inserted first-seen findings; re-scans skipped existing fingerprints entirely, so control_refs (re)computed by the mapping passes were discarded. A finding first seen before control mapping was enabled/tuned would therefore never gain its control mappings without being deleted + re-added. Now: existing findings whose re-scan produced non-empty control_refs get updated in place ($set control_refs). Guarded on non-empty so a run where mapping didn't run (breakpilot unreachable) can't wipe existing refs. New findings unchanged. Co-Authored-By: Claude Opus 4.8 --- compliance-agent/src/pipeline/orchestrator.rs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/compliance-agent/src/pipeline/orchestrator.rs b/compliance-agent/src/pipeline/orchestrator.rs index da92ade..8f038ea 100644 --- a/compliance-agent/src/pipeline/orchestrator.rs +++ b/compliance-agent/src/pipeline/orchestrator.rs @@ -277,8 +277,10 @@ impl PipelineOrchestrator { } } - // Dedup against existing findings and insert new ones + // Dedup against existing findings: insert first-seen ones, and refresh the + // control mappings on ones we've seen before. let mut new_count = 0u32; + let mut refreshed_count = 0u32; let mut new_findings: Vec = Vec::new(); for mut finding in all_findings { finding.scan_run_id = Some(scan_run_id.to_string()); @@ -293,8 +295,25 @@ impl PipelineOrchestrator { finding.id = result.inserted_id.as_object_id(); new_findings.push(finding); new_count += 1; + } else if !finding.control_refs.is_empty() { + // Re-scan refresh: a mapping pass (newly enabled or tuned) computed + // control_refs for a finding first seen before mapping ran. Persist + // them onto the existing row — the insert path alone never would. + self.db + .findings() + .update_one( + doc! { "fingerprint": &finding.fingerprint }, + doc! { "$set": { "control_refs": finding.control_refs.clone() } }, + ) + .await?; + refreshed_count += 1; } } + if refreshed_count > 0 { + tracing::info!( + "[{repo_id}] Refreshed control_refs on {refreshed_count} existing findings" + ); + } // Remove stale SBOM entries for this repo before reinserting if !sbom_entries.is_empty() { -- 2.54.0