// -----------------------------------------------------------------------------
// 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; }
}