// ----------------------------------------------------------------------------- // IHumanApprovalAttestationService.cs // Sprint: SPRINT_3801_0001_0004_human_approval_attestation (APPROVE-001) // Description: Interface for creating human approval attestations. // ----------------------------------------------------------------------------- using System.Threading; using System.Threading.Tasks; using StellaOps.Scanner.WebService.Contracts; using StellaOps.Scanner.WebService.Domain; namespace StellaOps.Scanner.WebService.Services; /// /// Creates DSSE attestations for human approval decisions. /// /// /// /// Human approvals record decisions made by authorized personnel to /// accept, defer, reject, suppress, or escalate security findings. /// /// /// These attestations have a 30-day default TTL to force periodic /// re-review of risk acceptance decisions. /// /// public interface IHumanApprovalAttestationService { /// /// Creates a human approval attestation. /// /// The approval input parameters. /// Cancellation token. /// /// A containing the /// attestation statement and content-addressed attestation ID. /// Task CreateAttestationAsync( HumanApprovalAttestationInput input, CancellationToken cancellationToken = default); /// /// Gets an existing approval attestation. /// /// The scan ID. /// The finding ID. /// Cancellation token. /// The attestation result if found, null otherwise. Task GetAttestationAsync( ScanId scanId, string findingId, CancellationToken cancellationToken = default); /// /// Gets all active approval attestations for a scan. /// /// The scan ID. /// Cancellation token. /// List of active approval attestations. Task> GetApprovalsByScanAsync( ScanId scanId, CancellationToken cancellationToken = default); /// /// Revokes an existing approval attestation. /// /// The scan ID. /// The finding ID. /// Who revoked the approval. /// Reason for revocation. /// Cancellation token. /// True if revoked, false if not found. Task RevokeApprovalAsync( ScanId scanId, string findingId, string revokedBy, string reason, CancellationToken cancellationToken = default); } /// /// Input for creating a human approval attestation. /// public sealed record HumanApprovalAttestationInput { /// /// The scan ID. /// public required ScanId ScanId { get; init; } /// /// The finding ID (e.g., CVE identifier). /// public required string FindingId { get; init; } /// /// The approval decision. /// public required ApprovalDecision Decision { get; init; } /// /// The approver's user ID. /// public required string ApproverUserId { get; init; } /// /// The approver's display name. /// public string? ApproverDisplayName { get; init; } /// /// The approver's role. /// public string? ApproverRole { get; init; } /// /// Justification for the decision. /// public required string Justification { get; init; } /// /// Optional custom TTL for the approval. /// public TimeSpan? ApprovalTtl { get; init; } /// /// Reference to the policy decision attestation. /// public string? PolicyDecisionRef { get; init; } /// /// Optional restrictions on the approval scope. /// public ApprovalRestrictions? Restrictions { get; init; } /// /// Optional prior approval being superseded. /// public string? Supersedes { get; init; } /// /// Optional metadata. /// public IDictionary? Metadata { get; init; } } /// /// Result of creating a human approval attestation. /// public sealed record HumanApprovalAttestationResult { /// /// Whether the attestation was created successfully. /// public required bool Success { get; init; } /// /// The human approval statement. /// public HumanApprovalStatement? Statement { get; init; } /// /// The content-addressed attestation ID. /// public string? AttestationId { get; init; } /// /// The DSSE envelope (if signing is enabled). /// public string? DsseEnvelope { get; init; } /// /// Error message if creation failed. /// public string? Error { get; init; } /// /// Whether the approval has been revoked. /// public bool IsRevoked { get; init; } /// /// Creates a successful result. /// public static HumanApprovalAttestationResult Succeeded( HumanApprovalStatement statement, string attestationId, string? dsseEnvelope = null) => new() { Success = true, Statement = statement, AttestationId = attestationId, DsseEnvelope = dsseEnvelope }; /// /// Creates a failed result. /// public static HumanApprovalAttestationResult Failed(string error) => new() { Success = false, Error = error }; }