// // Copyright (c) StellaOps. Licensed under the BUSL-1.1. // using System.Collections.Immutable; namespace StellaOps.Scanner.Emit.Pedigree; /// /// Provider interface for retrieving component pedigree data from Feedser. /// Sprint: SPRINT_20260107_005_002 Task PD-001 /// public interface IPedigreeDataProvider { /// /// Retrieves pedigree data for a component identified by its PURL. /// /// Package URL identifying the component. /// Cancellation token. /// Pedigree data if available, null otherwise. Task GetPedigreeAsync( string purl, CancellationToken cancellationToken = default); /// /// Retrieves pedigree data for multiple components. /// /// Package URLs identifying the components. /// Cancellation token. /// Dictionary of PURL to pedigree data (missing components not included). Task> GetPedigreesBatchAsync( IEnumerable purls, CancellationToken cancellationToken = default); } /// /// Aggregate of pedigree information for a component. /// public sealed record PedigreeData { /// /// Gets the ancestor components (upstream sources). /// public ImmutableArray Ancestors { get; init; } = ImmutableArray.Empty; /// /// Gets the variant components (distro-specific packages derived from same source). /// public ImmutableArray Variants { get; init; } = ImmutableArray.Empty; /// /// Gets the relevant commits (security fixes, backports). /// public ImmutableArray Commits { get; init; } = ImmutableArray.Empty; /// /// Gets the patches applied to the component. /// public ImmutableArray Patches { get; init; } = ImmutableArray.Empty; /// /// Gets optional notes about the pedigree (e.g., backport explanation). /// public string? Notes { get; init; } /// /// Gets whether any pedigree data is present. /// public bool HasData => !Ancestors.IsDefaultOrEmpty || !Variants.IsDefaultOrEmpty || !Commits.IsDefaultOrEmpty || !Patches.IsDefaultOrEmpty || Notes is not null; } /// /// Represents an upstream ancestor component. /// public sealed record AncestorComponent { /// /// Gets the component type (e.g., "library", "application"). /// public string Type { get; init; } = "library"; /// /// Gets the component name. /// public required string Name { get; init; } /// /// Gets the upstream version. /// public required string Version { get; init; } /// /// Gets the Package URL for the ancestor. /// public string? Purl { get; init; } /// /// Gets the URL to the upstream project. /// public string? ProjectUrl { get; init; } /// /// Gets the relationship level (1 = direct parent, 2 = grandparent, etc.). /// public int Level { get; init; } = 1; } /// /// Represents a variant component (distro-specific package). /// public sealed record VariantComponent { /// /// Gets the component type. /// public string Type { get; init; } = "library"; /// /// Gets the package name in the distribution. /// public required string Name { get; init; } /// /// Gets the distribution-specific version. /// public required string Version { get; init; } /// /// Gets the Package URL for the variant. /// public required string Purl { get; init; } /// /// Gets the distribution name (e.g., "debian", "rhel", "alpine"). /// public string? Distribution { get; init; } /// /// Gets the distribution release (e.g., "bookworm", "9.3"). /// public string? Release { get; init; } } /// /// Represents commit information for a security fix or backport. /// public sealed record CommitInfo { /// /// Gets the commit SHA (full or abbreviated). /// public required string Uid { get; init; } /// /// Gets the URL to view the commit. /// public string? Url { get; init; } /// /// Gets the commit message (may be truncated). /// public string? Message { get; init; } /// /// Gets the author information. /// public CommitActor? Author { get; init; } /// /// Gets the committer information. /// public CommitActor? Committer { get; init; } /// /// Gets the CVE IDs resolved by this commit, if known. /// public ImmutableArray ResolvesCves { get; init; } = ImmutableArray.Empty; } /// /// Represents an actor (author or committer) in a commit. /// public sealed record CommitActor { /// /// Gets the actor's name. /// public string? Name { get; init; } /// /// Gets the actor's email. /// public string? Email { get; init; } /// /// Gets the timestamp of the action. /// public DateTimeOffset? Timestamp { get; init; } } /// /// Represents a patch applied to the component. /// public sealed record PatchInfo { /// /// Gets the patch type. /// public PatchType Type { get; init; } = PatchType.Backport; /// /// Gets the URL to the patch file. /// public string? DiffUrl { get; init; } /// /// Gets the patch diff content (optional, may be truncated). /// public string? DiffText { get; init; } /// /// Gets the CVE IDs resolved by this patch. /// public ImmutableArray Resolves { get; init; } = ImmutableArray.Empty; /// /// Gets the functions affected by this patch. /// public ImmutableArray AffectedFunctions { get; init; } = ImmutableArray.Empty; /// /// Gets the source of the patch (e.g., "debian-security"). /// public string? Source { get; init; } } /// /// Patch type enumeration per CycloneDX 1.7 specification. /// public enum PatchType { /// Informal patch not associated with upstream. Unofficial, /// A patch that is a bugfix or security fix that does not change feature. Monkey, /// A patch that is a backport of a fix from a later version. Backport, /// A cherry-picked commit from upstream. CherryPick } /// /// Represents a vulnerability resolved by a patch. /// public sealed record PatchResolution { /// /// Gets the vulnerability ID (e.g., "CVE-2024-1234"). /// public required string Id { get; init; } /// /// Gets the source of the vulnerability reference. /// public string? SourceName { get; init; } /// /// Gets the URL to the vulnerability reference. /// public string? SourceUrl { get; init; } }