save development progress

This commit is contained in:
StellaOps Bot
2025-12-25 23:09:58 +02:00
parent d71853ad7e
commit aa70af062e
351 changed files with 37683 additions and 150156 deletions

View File

@@ -0,0 +1,195 @@
// -----------------------------------------------------------------------------
// SbomRegistration.cs
// Sprint: SPRINT_8200_0013_0003_SCAN_sbom_intersection_scoring
// Task: SBOM-8200-000
// Description: Domain model for SBOM registration
// -----------------------------------------------------------------------------
namespace StellaOps.Concelier.SbomIntegration.Models;
/// <summary>
/// Registered SBOM for advisory matching.
/// </summary>
public sealed record SbomRegistration
{
/// <summary>Registration identifier.</summary>
public Guid Id { get; init; }
/// <summary>SBOM content digest (SHA-256).</summary>
public required string Digest { get; init; }
/// <summary>SBOM format: CycloneDX or SPDX.</summary>
public required SbomFormat Format { get; init; }
/// <summary>SBOM specification version.</summary>
public required string SpecVersion { get; init; }
/// <summary>Primary component name (e.g., container image name).</summary>
public string? PrimaryName { get; init; }
/// <summary>Primary component version.</summary>
public string? PrimaryVersion { get; init; }
/// <summary>Total component count in SBOM.</summary>
public int ComponentCount { get; init; }
/// <summary>Extracted PURLs from SBOM components.</summary>
public IReadOnlyList<string> Purls { get; init; } = [];
/// <summary>When the SBOM was registered.</summary>
public DateTimeOffset RegisteredAt { get; init; }
/// <summary>When the SBOM was last matched against advisories.</summary>
public DateTimeOffset? LastMatchedAt { get; init; }
/// <summary>Number of advisories affecting this SBOM.</summary>
public int AffectedCount { get; init; }
/// <summary>Source of the SBOM (scanner, upload, etc.).</summary>
public required string Source { get; init; }
/// <summary>Optional tenant ID for multi-tenant deployments.</summary>
public string? TenantId { get; init; }
}
/// <summary>
/// SBOM format type.
/// </summary>
public enum SbomFormat
{
/// <summary>CycloneDX format.</summary>
CycloneDX,
/// <summary>SPDX format.</summary>
SPDX
}
/// <summary>
/// Result of matching an SBOM against advisories.
/// Distinct from <see cref="StellaOps.Concelier.Interest.Models.SbomMatch"/> which is simpler for score calculation.
/// </summary>
public sealed record SbomAdvisoryMatch
{
/// <summary>Match identifier.</summary>
public Guid Id { get; init; }
/// <summary>SBOM registration ID.</summary>
public required Guid SbomId { get; init; }
/// <summary>SBOM digest.</summary>
public required string SbomDigest { get; init; }
/// <summary>Canonical advisory ID.</summary>
public required Guid CanonicalId { get; init; }
/// <summary>Matched PURL from SBOM.</summary>
public required string Purl { get; init; }
/// <summary>Whether the code path is reachable.</summary>
public bool IsReachable { get; init; }
/// <summary>Whether deployed in production environment.</summary>
public bool IsDeployed { get; init; }
/// <summary>Match confidence (0-1).</summary>
public double Confidence { get; init; } = 1.0;
/// <summary>How the match was determined.</summary>
public required MatchMethod Method { get; init; }
/// <summary>When the match was recorded.</summary>
public DateTimeOffset MatchedAt { get; init; }
}
/// <summary>
/// Method used to match SBOM component to advisory.
/// </summary>
public enum MatchMethod
{
/// <summary>Exact PURL match.</summary>
ExactPurl,
/// <summary>PURL with version range match.</summary>
PurlVersionRange,
/// <summary>CPE-based match for OS packages.</summary>
Cpe,
/// <summary>Component name and version heuristic.</summary>
NameVersion
}
/// <summary>
/// Input for registering an SBOM.
/// </summary>
public sealed record SbomRegistrationInput
{
/// <summary>SBOM content digest.</summary>
public required string Digest { get; init; }
/// <summary>SBOM format.</summary>
public required SbomFormat Format { get; init; }
/// <summary>SBOM specification version.</summary>
public required string SpecVersion { get; init; }
/// <summary>Primary component name.</summary>
public string? PrimaryName { get; init; }
/// <summary>Primary component version.</summary>
public string? PrimaryVersion { get; init; }
/// <summary>List of PURLs extracted from SBOM.</summary>
public required IReadOnlyList<string> Purls { get; init; }
/// <summary>Source of registration.</summary>
public required string Source { get; init; }
/// <summary>Optional tenant ID.</summary>
public string? TenantId { get; init; }
/// <summary>Optional reachability data per PURL.</summary>
public IReadOnlyDictionary<string, bool>? ReachabilityMap { get; init; }
/// <summary>Optional deployment status per PURL.</summary>
public IReadOnlyDictionary<string, bool>? DeploymentMap { get; init; }
}
/// <summary>
/// Result of SBOM learning (registration + matching + scoring).
/// </summary>
public sealed record SbomLearnResult
{
/// <summary>SBOM registration.</summary>
public required SbomRegistration Registration { get; init; }
/// <summary>Matches found against advisories.</summary>
public required IReadOnlyList<SbomAdvisoryMatch> Matches { get; init; }
/// <summary>Number of interest scores updated.</summary>
public int ScoresUpdated { get; init; }
/// <summary>Processing time in milliseconds.</summary>
public double ProcessingTimeMs { get; init; }
}
/// <summary>
/// Delta changes to an existing SBOM.
/// </summary>
public sealed record SbomDeltaInput
{
/// <summary>PURLs to add to the SBOM.</summary>
public IReadOnlyList<string> AddedPurls { get; init; } = [];
/// <summary>PURLs to remove from the SBOM.</summary>
public IReadOnlyList<string> RemovedPurls { get; init; } = [];
/// <summary>Optional updated reachability data.</summary>
public IReadOnlyDictionary<string, bool>? ReachabilityMap { get; init; }
/// <summary>Optional updated deployment status.</summary>
public IReadOnlyDictionary<string, bool>? DeploymentMap { get; init; }
/// <summary>Whether this delta represents a complete replacement.</summary>
public bool IsFullReplacement { get; init; }
}