// ----------------------------------------------------------------------------- // IReplayVerificationService.cs // Sprint: SPRINT_20251228_007_BE_sbom_lineage_graph_ii (LIN-BE-033) // Task: Replay verification endpoint // Description: Interface for verifying replay hashes and detecting drift. // ----------------------------------------------------------------------------- using System.Collections.Immutable; namespace StellaOps.SbomService.Services; /// /// Service for verifying replay hashes and detecting drift in security evaluations. /// public interface IReplayVerificationService { /// /// Verifies a replay hash by re-computing it with provided or current inputs. /// /// Verification request. /// Cancellation token. /// Verification result with match status and drift details. Task VerifyAsync( ReplayVerificationRequest request, CancellationToken ct = default); /// /// Compares two replay hashes and identifies drift between them. /// /// First replay hash. /// Second replay hash. /// Tenant identifier. /// Cancellation token. /// Drift analysis between the two evaluations. Task CompareDriftAsync( string hashA, string hashB, string tenantId, CancellationToken ct = default); } /// /// Request for replay verification. /// public sealed record ReplayVerificationRequest { /// /// The replay hash to verify. /// public required string ReplayHash { get; init; } /// /// Tenant identifier. /// public required string TenantId { get; init; } /// /// Optional: SBOM digest to use for verification. /// If not provided, will try to lookup from stored hash metadata. /// public string? SbomDigest { get; init; } /// /// Optional: Feeds snapshot digest to use. /// If not provided, uses current feeds. /// public string? FeedsSnapshotDigest { get; init; } /// /// Optional: Policy version to use. /// If not provided, uses current policy. /// public string? PolicyVersion { get; init; } /// /// Optional: VEX verdicts digest to use. /// If not provided, uses current VEX state. /// public string? VexVerdictsDigest { get; init; } /// /// Optional: Timestamp to use for verification. /// If not provided, uses current time. /// public DateTimeOffset? Timestamp { get; init; } /// /// Whether to freeze time to the original evaluation timestamp. /// public bool FreezeTime { get; init; } = true; /// /// Whether to re-evaluate policy with frozen feeds. /// public bool ReEvaluatePolicy { get; init; } = false; } /// /// Result of replay verification. /// public sealed record ReplayVerificationResult { /// /// Whether the replay hash matches. /// public required bool IsMatch { get; init; } /// /// The expected replay hash. /// public required string ExpectedHash { get; init; } /// /// The computed replay hash. /// public required string ComputedHash { get; init; } /// /// Overall verification status. /// public required ReplayVerificationStatus Status { get; init; } /// /// The inputs used for the expected hash (from storage). /// public ReplayHashInputs? ExpectedInputs { get; init; } /// /// The inputs used to compute the verification hash. /// public ReplayHashInputs? ComputedInputs { get; init; } /// /// Field-level differences between expected and computed. /// public ImmutableArray Drifts { get; init; } = ImmutableArray.Empty; /// /// When the verification was performed. /// public DateTimeOffset VerifiedAt { get; init; } = DateTimeOffset.UtcNow; /// /// Optional message with additional context. /// public string? Message { get; init; } /// /// Error message if verification failed. /// public string? Error { get; init; } } /// /// Verification status enumeration. /// public enum ReplayVerificationStatus { /// /// Hash matches exactly - evaluation is reproducible. /// Match, /// /// Hash doesn't match - drift detected. /// Drift, /// /// Unable to lookup original inputs. /// InputsNotFound, /// /// Verification failed due to error. /// Error } /// /// Field-level drift in replay verification. /// public sealed record ReplayFieldDrift { /// /// Name of the field that drifted. /// public required string FieldName { get; init; } /// /// Expected value (from original evaluation). /// public required string ExpectedValue { get; init; } /// /// Actual/computed value. /// public required string ActualValue { get; init; } /// /// Severity of the drift: "info", "warning", "critical". /// public required string Severity { get; init; } /// /// Human-readable description of the drift impact. /// public string? Description { get; init; } } /// /// Analysis of drift between two replay evaluations. /// public sealed record ReplayDriftAnalysis { /// /// First replay hash. /// public required string HashA { get; init; } /// /// Second replay hash. /// public required string HashB { get; init; } /// /// Whether the hashes are identical. /// public required bool IsIdentical { get; init; } /// /// Inputs for first hash. /// public ReplayHashInputs? InputsA { get; init; } /// /// Inputs for second hash. /// public ReplayHashInputs? InputsB { get; init; } /// /// Field-level drifts between A and B. /// public ImmutableArray Drifts { get; init; } = ImmutableArray.Empty; /// /// Summary of drift severity. /// public required string DriftSummary { get; init; } /// /// When the analysis was performed. /// public DateTimeOffset AnalyzedAt { get; init; } = DateTimeOffset.UtcNow; }