using System.Text.Json.Serialization; namespace StellaOps.BinaryIndex.Builders; /// /// A claim asserting a CVE verdict for a specific fingerprint. /// Created when reproducible builds show a function was modified to fix a CVE. /// public sealed record FingerprintClaim { /// /// Unique identifier for this claim. /// public Guid Id { get; init; } /// /// ID of the fingerprint this claim is about. /// public required Guid FingerprintId { get; init; } /// /// CVE identifier (e.g., "CVE-2023-12345"). /// public required string CveId { get; init; } /// /// Verdict: whether this fingerprint is fixed, vulnerable, or unknown. /// public required ClaimVerdict Verdict { get; init; } /// /// Evidence supporting this claim. /// public required FingerprintClaimEvidence Evidence { get; init; } /// /// Hash of the DSSE attestation if signed. /// public string? AttestationDsseHash { get; init; } /// /// When this claim was created. /// public DateTimeOffset CreatedAt { get; init; } = DateTimeOffset.UtcNow; /// /// When this claim was last updated. /// public DateTimeOffset? UpdatedAt { get; init; } /// /// Source that generated this claim (e.g., "repro-builder-alpine"). /// public string? Source { get; init; } /// /// Confidence in this claim (0.0-1.0). /// public decimal Confidence { get; init; } = 1.0m; } /// /// Verdict for a fingerprint claim. /// [JsonConverter(typeof(JsonStringEnumConverter))] public enum ClaimVerdict { /// /// The fingerprint is from a binary that contains the CVE fix. /// Fixed, /// /// The fingerprint is from a binary that is vulnerable to the CVE. /// Vulnerable, /// /// Unable to determine fix status. /// Unknown } /// /// Evidence supporting a fingerprint claim. /// public sealed record FingerprintClaimEvidence { /// /// Git commit or patch reference that introduced the fix. /// public required string PatchCommit { get; init; } /// /// List of function names that changed between vulnerable and fixed versions. /// public required IReadOnlyList ChangedFunctions { get; init; } /// /// Similarity scores for modified functions (function name -> score). /// public IReadOnlyDictionary? FunctionSimilarities { get; init; } /// /// Reference to the vulnerable build artifacts. /// public string? VulnerableBuildRef { get; init; } /// /// Reference to the patched build artifacts. /// public string? PatchedBuildRef { get; init; } /// /// Source package name. /// public string? SourcePackage { get; init; } /// /// Vulnerable version string. /// public string? VulnerableVersion { get; init; } /// /// Patched version string. /// public string? PatchedVersion { get; init; } /// /// Distro and release this build was done for. /// public string? DistroRelease { get; init; } /// /// Builder image used for reproducible builds. /// public string? BuilderImage { get; init; } /// /// Timestamp of the vulnerable build. /// public DateTimeOffset? VulnerableBuildTimestamp { get; init; } /// /// Timestamp of the patched build. /// public DateTimeOffset? PatchedBuildTimestamp { get; init; } /// /// Diff statistics summary. /// public DiffStatistics? DiffStatistics { get; init; } } /// /// Repository for managing fingerprint claims. /// public interface IFingerprintClaimRepository { /// /// Creates a new fingerprint claim. /// /// The claim to create. /// Cancellation token. /// The created claim ID. Task CreateClaimAsync(FingerprintClaim claim, CancellationToken ct = default); /// /// Creates multiple claims in a batch. /// /// Claims to create. /// Cancellation token. Task CreateClaimsBatchAsync(IEnumerable claims, CancellationToken ct = default); /// /// Gets a claim by ID. /// /// Claim ID. /// Cancellation token. /// The claim if found. Task GetClaimByIdAsync(Guid id, CancellationToken ct = default); /// /// Gets all claims for a specific fingerprint. /// /// Fingerprint ID. /// Cancellation token. /// List of claims for the fingerprint. Task> GetClaimsByFingerprintAsync( Guid fingerprintId, CancellationToken ct = default); /// /// Gets all claims for a specific fingerprint hash. /// /// Fingerprint hash (hex-encoded). /// Cancellation token. /// List of claims for the fingerprint. Task> GetClaimsByFingerprintHashAsync( string fingerprintHash, CancellationToken ct = default); /// /// Gets all claims for a specific CVE. /// /// CVE identifier. /// Cancellation token. /// List of claims for the CVE. Task> GetClaimsByCveAsync( string cveId, CancellationToken ct = default); /// /// Gets claims with a specific verdict. /// /// Verdict to filter by. /// Maximum results to return. /// Cancellation token. /// List of claims with the verdict. Task> GetClaimsByVerdictAsync( ClaimVerdict verdict, int limit = 100, CancellationToken ct = default); /// /// Updates an existing claim. /// /// The updated claim. /// Cancellation token. Task UpdateClaimAsync(FingerprintClaim claim, CancellationToken ct = default); /// /// Deletes a claim by ID. /// /// Claim ID. /// Cancellation token. /// True if deleted, false if not found. Task DeleteClaimAsync(Guid id, CancellationToken ct = default); /// /// Checks if a claim already exists for a fingerprint+CVE combination. /// /// Fingerprint ID. /// CVE identifier. /// Cancellation token. /// True if a claim exists. Task ClaimExistsAsync(Guid fingerprintId, string cveId, CancellationToken ct = default); } /// /// Repository for managing function fingerprints (per-binary breakdown). /// public interface IFunctionFingerprintRepository { /// /// Stores function fingerprints for a binary. /// /// Parent binary fingerprint ID. /// Function fingerprints to store. /// Cancellation token. Task StoreFunctionsAsync( Guid binaryFingerprintId, IEnumerable functions, CancellationToken ct = default); /// /// Gets all function fingerprints for a binary. /// /// Parent binary fingerprint ID. /// Cancellation token. /// List of function fingerprints. Task> GetFunctionsByBinaryAsync( Guid binaryFingerprintId, CancellationToken ct = default); /// /// Searches for functions by name pattern. /// /// Function name pattern (SQL LIKE). /// Maximum results. /// Cancellation token. /// Matching functions with their binary IDs. Task> SearchFunctionsByNameAsync( string namePattern, int limit = 100, CancellationToken ct = default); /// /// Finds functions matching a specific basic block hash. /// /// Hash to search for. /// Cancellation token. /// Matching functions with their binary IDs. Task> FindByBasicBlockHashAsync( byte[] basicBlockHash, CancellationToken ct = default); /// /// Deletes all function fingerprints for a binary. /// /// Parent binary fingerprint ID. /// Cancellation token. Task DeleteFunctionsByBinaryAsync(Guid binaryFingerprintId, CancellationToken ct = default); }