Complete batch 012 (golden set diff) and 013 (advisory chat), fix build errors

Sprints completed:
- SPRINT_20260110_012_* (golden set diff layer - 10 sprints)
- SPRINT_20260110_013_* (advisory chat - 4 sprints)

Build fixes applied:
- Fix namespace conflicts with Microsoft.Extensions.Options.Options.Create
- Fix VexDecisionReachabilityIntegrationTests API drift (major rewrite)
- Fix VexSchemaValidationTests FluentAssertions method name
- Fix FixChainGateIntegrationTests ambiguous type references
- Fix AdvisoryAI test files required properties and namespace aliases
- Add stub types for CveMappingController (ICveSymbolMappingService)
- Fix VerdictBuilderService static context issue

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
master
2026-01-11 10:09:07 +02:00
parent a3b2f30a11
commit 7f7eb8b228
232 changed files with 58979 additions and 91 deletions

View File

@@ -2,6 +2,7 @@
// Sprint: SPRINT_20260109_009_003_BE_cve_symbol_mapping
// Task: Implement API endpoints
using System.Collections.Immutable;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;
using StellaOps.Reachability.Core.CveMapping;

View File

@@ -0,0 +1,151 @@
// Licensed to StellaOps under the AGPL-3.0-or-later license.
// Stub types for CVE-Symbol mapping service
using System.Collections.Immutable;
namespace StellaOps.Reachability.Core.CveMapping;
/// <summary>
/// Service for CVE-symbol mapping operations.
/// </summary>
public interface ICveSymbolMappingService
{
Task<IReadOnlyList<CveSymbolMapping>> GetMappingsForCveAsync(string cveId, CancellationToken cancellationToken);
Task<IReadOnlyList<CveSymbolMapping>> GetMappingsForPackageAsync(string purl, CancellationToken cancellationToken);
Task<IReadOnlyList<CveSymbolMapping>> SearchBySymbolAsync(string symbol, string? language, CancellationToken cancellationToken);
Task<CveSymbolMapping> AddOrUpdateMappingAsync(CveSymbolMapping mapping, CancellationToken cancellationToken);
Task<PatchAnalysisResult> AnalyzePatchAsync(string? commitUrl, string? diffContent, CancellationToken cancellationToken);
Task<IReadOnlyList<CveSymbolMapping>> EnrichFromOsvAsync(string cveId, CancellationToken cancellationToken);
Task<MappingStats> GetStatsAsync(CancellationToken cancellationToken);
}
/// <summary>
/// A mapping between a CVE and a vulnerable symbol.
/// </summary>
public record CveSymbolMapping
{
public required string CveId { get; init; }
public required string Purl { get; init; }
public required VulnerableSymbol Symbol { get; init; }
public MappingSource Source { get; init; }
public double Confidence { get; init; }
public VulnerabilityType VulnerabilityType { get; init; }
public ImmutableArray<string> AffectedVersions { get; init; } = [];
public ImmutableArray<string> FixedVersions { get; init; } = [];
public string? EvidenceUri { get; init; }
}
/// <summary>
/// Represents a vulnerable symbol (function/method).
/// </summary>
public record VulnerableSymbol
{
public required string Symbol { get; init; }
public string? CanonicalId { get; init; }
public string? FilePath { get; init; }
public int? StartLine { get; init; }
public int? EndLine { get; init; }
}
/// <summary>
/// Source of the mapping.
/// </summary>
public enum MappingSource
{
Unknown = 0,
Osv = 1,
Nvd = 2,
Manual = 3,
PatchAnalysis = 4,
Vendor = 5
}
/// <summary>
/// Type of vulnerability.
/// </summary>
public enum VulnerabilityType
{
Unknown = 0,
BufferOverflow = 1,
SqlInjection = 2,
XSS = 3,
CommandInjection = 4,
PathTraversal = 5,
Deserialization = 6,
Cryptographic = 7,
Other = 99
}
/// <summary>
/// Result of patch analysis.
/// </summary>
public record PatchAnalysisResult
{
public required IReadOnlyList<ExtractedSymbol> ExtractedSymbols { get; init; }
public DateTimeOffset AnalyzedAt { get; init; }
}
/// <summary>
/// Symbol extracted from a patch.
/// </summary>
public record ExtractedSymbol
{
public required string Symbol { get; init; }
public string? FilePath { get; init; }
public int? StartLine { get; init; }
public int? EndLine { get; init; }
public ChangeType ChangeType { get; init; }
public string? Language { get; init; }
}
/// <summary>
/// Type of change in a patch.
/// </summary>
public enum ChangeType
{
Unknown = 0,
Added = 1,
Modified = 2,
Deleted = 3
}
/// <summary>
/// Statistics about the mapping corpus.
/// </summary>
public record MappingStats
{
public int TotalMappings { get; init; }
public int UniqueCves { get; init; }
public int UniquePackages { get; init; }
public Dictionary<string, int>? BySource { get; init; }
public Dictionary<string, int>? ByVulnerabilityType { get; init; }
public double AverageConfidence { get; init; }
public DateTimeOffset LastUpdated { get; init; }
}
/// <summary>
/// Null implementation of the CVE symbol mapping service.
/// </summary>
public sealed class NullCveSymbolMappingService : ICveSymbolMappingService
{
public Task<IReadOnlyList<CveSymbolMapping>> GetMappingsForCveAsync(string cveId, CancellationToken cancellationToken)
=> Task.FromResult<IReadOnlyList<CveSymbolMapping>>([]);
public Task<IReadOnlyList<CveSymbolMapping>> GetMappingsForPackageAsync(string purl, CancellationToken cancellationToken)
=> Task.FromResult<IReadOnlyList<CveSymbolMapping>>([]);
public Task<IReadOnlyList<CveSymbolMapping>> SearchBySymbolAsync(string symbol, string? language, CancellationToken cancellationToken)
=> Task.FromResult<IReadOnlyList<CveSymbolMapping>>([]);
public Task<CveSymbolMapping> AddOrUpdateMappingAsync(CveSymbolMapping mapping, CancellationToken cancellationToken)
=> Task.FromResult(mapping);
public Task<PatchAnalysisResult> AnalyzePatchAsync(string? commitUrl, string? diffContent, CancellationToken cancellationToken)
=> Task.FromResult(new PatchAnalysisResult { ExtractedSymbols = [], AnalyzedAt = DateTimeOffset.UtcNow });
public Task<IReadOnlyList<CveSymbolMapping>> EnrichFromOsvAsync(string cveId, CancellationToken cancellationToken)
=> Task.FromResult<IReadOnlyList<CveSymbolMapping>>([]);
public Task<MappingStats> GetStatsAsync(CancellationToken cancellationToken)
=> Task.FromResult(new MappingStats { LastUpdated = DateTimeOffset.UtcNow });
}