Fix build and code structure improvements. New but essential UI functionality. CI improvements. Documentation improvements. AI module improvements.
This commit is contained in:
@@ -0,0 +1,255 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// 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;
|
||||
|
||||
/// <summary>
|
||||
/// Service for verifying replay hashes and detecting drift in security evaluations.
|
||||
/// </summary>
|
||||
public interface IReplayVerificationService
|
||||
{
|
||||
/// <summary>
|
||||
/// Verifies a replay hash by re-computing it with provided or current inputs.
|
||||
/// </summary>
|
||||
/// <param name="request">Verification request.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>Verification result with match status and drift details.</returns>
|
||||
Task<ReplayVerificationResult> VerifyAsync(
|
||||
ReplayVerificationRequest request,
|
||||
CancellationToken ct = default);
|
||||
|
||||
/// <summary>
|
||||
/// Compares two replay hashes and identifies drift between them.
|
||||
/// </summary>
|
||||
/// <param name="hashA">First replay hash.</param>
|
||||
/// <param name="hashB">Second replay hash.</param>
|
||||
/// <param name="tenantId">Tenant identifier.</param>
|
||||
/// <param name="ct">Cancellation token.</param>
|
||||
/// <returns>Drift analysis between the two evaluations.</returns>
|
||||
Task<ReplayDriftAnalysis> CompareDriftAsync(
|
||||
string hashA,
|
||||
string hashB,
|
||||
string tenantId,
|
||||
CancellationToken ct = default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request for replay verification.
|
||||
/// </summary>
|
||||
public sealed record ReplayVerificationRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// The replay hash to verify.
|
||||
/// </summary>
|
||||
public required string ReplayHash { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Tenant identifier.
|
||||
/// </summary>
|
||||
public required string TenantId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional: SBOM digest to use for verification.
|
||||
/// If not provided, will try to lookup from stored hash metadata.
|
||||
/// </summary>
|
||||
public string? SbomDigest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional: Feeds snapshot digest to use.
|
||||
/// If not provided, uses current feeds.
|
||||
/// </summary>
|
||||
public string? FeedsSnapshotDigest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional: Policy version to use.
|
||||
/// If not provided, uses current policy.
|
||||
/// </summary>
|
||||
public string? PolicyVersion { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional: VEX verdicts digest to use.
|
||||
/// If not provided, uses current VEX state.
|
||||
/// </summary>
|
||||
public string? VexVerdictsDigest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional: Timestamp to use for verification.
|
||||
/// If not provided, uses current time.
|
||||
/// </summary>
|
||||
public DateTimeOffset? Timestamp { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to freeze time to the original evaluation timestamp.
|
||||
/// </summary>
|
||||
public bool FreezeTime { get; init; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Whether to re-evaluate policy with frozen feeds.
|
||||
/// </summary>
|
||||
public bool ReEvaluatePolicy { get; init; } = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Result of replay verification.
|
||||
/// </summary>
|
||||
public sealed record ReplayVerificationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether the replay hash matches.
|
||||
/// </summary>
|
||||
public required bool IsMatch { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The expected replay hash.
|
||||
/// </summary>
|
||||
public required string ExpectedHash { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The computed replay hash.
|
||||
/// </summary>
|
||||
public required string ComputedHash { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Overall verification status.
|
||||
/// </summary>
|
||||
public required ReplayVerificationStatus Status { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The inputs used for the expected hash (from storage).
|
||||
/// </summary>
|
||||
public ReplayHashInputs? ExpectedInputs { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The inputs used to compute the verification hash.
|
||||
/// </summary>
|
||||
public ReplayHashInputs? ComputedInputs { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Field-level differences between expected and computed.
|
||||
/// </summary>
|
||||
public ImmutableArray<ReplayFieldDrift> Drifts { get; init; } = ImmutableArray<ReplayFieldDrift>.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// When the verification was performed.
|
||||
/// </summary>
|
||||
public DateTimeOffset VerifiedAt { get; init; } = DateTimeOffset.UtcNow;
|
||||
|
||||
/// <summary>
|
||||
/// Optional message with additional context.
|
||||
/// </summary>
|
||||
public string? Message { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Error message if verification failed.
|
||||
/// </summary>
|
||||
public string? Error { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verification status enumeration.
|
||||
/// </summary>
|
||||
public enum ReplayVerificationStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// Hash matches exactly - evaluation is reproducible.
|
||||
/// </summary>
|
||||
Match,
|
||||
|
||||
/// <summary>
|
||||
/// Hash doesn't match - drift detected.
|
||||
/// </summary>
|
||||
Drift,
|
||||
|
||||
/// <summary>
|
||||
/// Unable to lookup original inputs.
|
||||
/// </summary>
|
||||
InputsNotFound,
|
||||
|
||||
/// <summary>
|
||||
/// Verification failed due to error.
|
||||
/// </summary>
|
||||
Error
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Field-level drift in replay verification.
|
||||
/// </summary>
|
||||
public sealed record ReplayFieldDrift
|
||||
{
|
||||
/// <summary>
|
||||
/// Name of the field that drifted.
|
||||
/// </summary>
|
||||
public required string FieldName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Expected value (from original evaluation).
|
||||
/// </summary>
|
||||
public required string ExpectedValue { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Actual/computed value.
|
||||
/// </summary>
|
||||
public required string ActualValue { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Severity of the drift: "info", "warning", "critical".
|
||||
/// </summary>
|
||||
public required string Severity { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Human-readable description of the drift impact.
|
||||
/// </summary>
|
||||
public string? Description { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Analysis of drift between two replay evaluations.
|
||||
/// </summary>
|
||||
public sealed record ReplayDriftAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// First replay hash.
|
||||
/// </summary>
|
||||
public required string HashA { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Second replay hash.
|
||||
/// </summary>
|
||||
public required string HashB { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the hashes are identical.
|
||||
/// </summary>
|
||||
public required bool IsIdentical { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Inputs for first hash.
|
||||
/// </summary>
|
||||
public ReplayHashInputs? InputsA { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Inputs for second hash.
|
||||
/// </summary>
|
||||
public ReplayHashInputs? InputsB { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Field-level drifts between A and B.
|
||||
/// </summary>
|
||||
public ImmutableArray<ReplayFieldDrift> Drifts { get; init; } = ImmutableArray<ReplayFieldDrift>.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Summary of drift severity.
|
||||
/// </summary>
|
||||
public required string DriftSummary { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// When the analysis was performed.
|
||||
/// </summary>
|
||||
public DateTimeOffset AnalyzedAt { get; init; } = DateTimeOffset.UtcNow;
|
||||
}
|
||||
Reference in New Issue
Block a user