more audit work

This commit is contained in:
master
2026-01-08 10:21:51 +02:00
parent 43c02081ef
commit 51cf4bc16c
546 changed files with 36721 additions and 4003 deletions

View File

@@ -29,9 +29,18 @@ public sealed class DeltaComputationEngine : IDeltaComputationEngine
var headComponents = headVerdict.Components
.ToDictionary(c => c.Purl, c => c, StringComparer.Ordinal);
var addedComponents = ComputeAddedComponents(baseComponents, headComponents);
var removedComponents = ComputeRemovedComponents(baseComponents, headComponents);
var changedComponents = ComputeChangedComponents(baseComponents, headComponents);
var changedPairs = FindChangedComponentPairs(baseComponents, headComponents);
var changedComponents = BuildChangedComponents(changedPairs);
var changedBasePurls = changedPairs
.Select(pair => pair.Base.Purl)
.ToHashSet(StringComparer.Ordinal);
var changedHeadPurls = changedPairs
.Select(pair => pair.Head.Purl)
.ToHashSet(StringComparer.Ordinal);
var addedComponents = ComputeAddedComponents(baseComponents, headComponents, changedHeadPurls);
var removedComponents = ComputeRemovedComponents(baseComponents, headComponents, changedBasePurls);
var baseVulns = baseVerdict.Vulnerabilities
.ToDictionary(v => v.Id, v => v, StringComparer.Ordinal);
@@ -77,10 +86,11 @@ public sealed class DeltaComputationEngine : IDeltaComputationEngine
private static ImmutableArray<ComponentDelta> ComputeAddedComponents(
IReadOnlyDictionary<string, Component> baseComponents,
IReadOnlyDictionary<string, Component> headComponents)
IReadOnlyDictionary<string, Component> headComponents,
ISet<string> excludedPurls)
{
return headComponents
.Where(kv => !baseComponents.ContainsKey(kv.Key))
.Where(kv => !baseComponents.ContainsKey(kv.Key) && !excludedPurls.Contains(kv.Key))
.OrderBy(kv => kv.Key, StringComparer.Ordinal)
.Select(kv => new ComponentDelta(
kv.Value.Purl,
@@ -93,10 +103,11 @@ public sealed class DeltaComputationEngine : IDeltaComputationEngine
private static ImmutableArray<ComponentDelta> ComputeRemovedComponents(
IReadOnlyDictionary<string, Component> baseComponents,
IReadOnlyDictionary<string, Component> headComponents)
IReadOnlyDictionary<string, Component> headComponents,
ISet<string> excludedPurls)
{
return baseComponents
.Where(kv => !headComponents.ContainsKey(kv.Key))
.Where(kv => !headComponents.ContainsKey(kv.Key) && !excludedPurls.Contains(kv.Key))
.OrderBy(kv => kv.Key, StringComparer.Ordinal)
.Select(kv => new ComponentDelta(
kv.Value.Purl,
@@ -107,18 +118,15 @@ public sealed class DeltaComputationEngine : IDeltaComputationEngine
.ToImmutableArray();
}
private static ImmutableArray<ComponentVersionDelta> ComputeChangedComponents(
IReadOnlyDictionary<string, Component> baseComponents,
IReadOnlyDictionary<string, Component> headComponents)
private static ImmutableArray<ComponentVersionDelta> BuildChangedComponents(
IReadOnlyCollection<(Component Base, Component Head)> pairs)
{
return baseComponents
.Where(kv => headComponents.TryGetValue(kv.Key, out var head)
&& !string.Equals(kv.Value.Version, head.Version, StringComparison.Ordinal))
.OrderBy(kv => kv.Key, StringComparer.Ordinal)
.Select(kv =>
return pairs
.OrderBy(pair => pair.Base.Purl, StringComparer.Ordinal)
.Select(pair =>
{
var baseComponent = kv.Value;
var headComponent = headComponents[kv.Key];
var baseComponent = pair.Base;
var headComponent = pair.Head;
var fixedVulns = baseComponent.Vulnerabilities
.Except(headComponent.Vulnerabilities, StringComparer.Ordinal)
.OrderBy(v => v, StringComparer.Ordinal)
@@ -139,6 +147,60 @@ public sealed class DeltaComputationEngine : IDeltaComputationEngine
.ToImmutableArray();
}
private static IReadOnlyCollection<(Component Base, Component Head)> FindChangedComponentPairs(
IReadOnlyDictionary<string, Component> baseComponents,
IReadOnlyDictionary<string, Component> headComponents)
{
var pairs = new List<(Component Base, Component Head)>();
var matchedBase = new HashSet<string>(StringComparer.Ordinal);
var matchedHead = new HashSet<string>(StringComparer.Ordinal);
foreach (var baseComponent in baseComponents.Values.OrderBy(c => c.Purl, StringComparer.Ordinal))
{
if (headComponents.TryGetValue(baseComponent.Purl, out var headComponent)
&& !string.Equals(baseComponent.Version, headComponent.Version, StringComparison.Ordinal))
{
pairs.Add((baseComponent, headComponent));
matchedBase.Add(baseComponent.Purl);
matchedHead.Add(headComponent.Purl);
}
}
var baseByIdentity = baseComponents.Values
.Where(c => !matchedBase.Contains(c.Purl))
.GroupBy(GetComponentIdentity, StringComparer.Ordinal)
.Where(g => g.Count() == 1)
.ToDictionary(g => g.Key, g => g.First(), StringComparer.Ordinal);
var headByIdentity = headComponents.Values
.Where(c => !matchedHead.Contains(c.Purl))
.GroupBy(GetComponentIdentity, StringComparer.Ordinal)
.Where(g => g.Count() == 1)
.ToDictionary(g => g.Key, g => g.First(), StringComparer.Ordinal);
foreach (var (identity, baseComponent) in baseByIdentity.OrderBy(kv => kv.Key, StringComparer.Ordinal))
{
if (!headByIdentity.TryGetValue(identity, out var headComponent))
{
continue;
}
if (string.Equals(baseComponent.Version, headComponent.Version, StringComparison.Ordinal))
{
continue;
}
pairs.Add((baseComponent, headComponent));
matchedBase.Add(baseComponent.Purl);
matchedHead.Add(headComponent.Purl);
}
return pairs;
}
private static string GetComponentIdentity(Component component)
=> $"{component.Type}:{component.Name}";
private static ImmutableArray<VulnerabilityDelta> ComputeAddedVulnerabilities(
IReadOnlyDictionary<string, Vulnerability> baseVulns,
IReadOnlyDictionary<string, Vulnerability> headVulns)

View File

@@ -5,6 +5,6 @@ Source of truth: `docs/implplan/SPRINT_20251229_049_BE_csproj_audit_maint_tests.
| Task ID | Status | Notes |
| --- | --- | --- |
| AUDIT-0273-M | DONE | Revalidated 2026-01-07; open findings tracked in audit report. |
| AUDIT-0273-T | DONE | Revalidated 2026-01-07; open findings tracked in audit report. |
| AUDIT-0273-A | TODO | Revalidated 2026-01-07 (open findings). |
| AUDIT-0073-M | DONE | Revalidated 2026-01-08; open findings tracked in audit report. |
| AUDIT-0073-T | DONE | Revalidated 2026-01-08; open findings tracked in audit report. |
| AUDIT-0073-A | TODO | Revalidated 2026-01-08 (open findings). |