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