using StellaOps.Policy.Registry.Contracts; namespace StellaOps.Policy.Registry.Services; /// /// Service for managing policy pack review workflows with audit trails. /// Implements REGISTRY-API-27-006: Review workflow with audit trails. /// public interface IReviewWorkflowService { /// /// Submits a policy pack for review. /// Task SubmitForReviewAsync( Guid tenantId, Guid packId, SubmitReviewRequest request, CancellationToken cancellationToken = default); /// /// Approves a review request. /// Task ApproveAsync( Guid tenantId, string reviewId, ApproveReviewRequest request, CancellationToken cancellationToken = default); /// /// Rejects a review request. /// Task RejectAsync( Guid tenantId, string reviewId, RejectReviewRequest request, CancellationToken cancellationToken = default); /// /// Requests changes to a policy pack under review. /// Task RequestChangesAsync( Guid tenantId, string reviewId, RequestChangesRequest request, CancellationToken cancellationToken = default); /// /// Gets a review request by ID. /// Task GetReviewAsync( Guid tenantId, string reviewId, CancellationToken cancellationToken = default); /// /// Lists review requests for a tenant. /// Task ListReviewsAsync( Guid tenantId, ReviewStatus? status = null, Guid? packId = null, int pageSize = 20, string? pageToken = null, CancellationToken cancellationToken = default); /// /// Gets the audit trail for a review. /// Task> GetAuditTrailAsync( Guid tenantId, string reviewId, CancellationToken cancellationToken = default); /// /// Gets the audit trail for a policy pack across all reviews. /// Task> GetPackAuditTrailAsync( Guid tenantId, Guid packId, int limit = 100, CancellationToken cancellationToken = default); } /// /// Request to submit a policy pack for review. /// public sealed record SubmitReviewRequest { public string? Description { get; init; } public IReadOnlyList? Reviewers { get; init; } public ReviewUrgency Urgency { get; init; } = ReviewUrgency.Normal; public IReadOnlyDictionary? Metadata { get; init; } } /// /// Request to approve a review. /// public sealed record ApproveReviewRequest { public string? Comment { get; init; } public string? ApprovedBy { get; init; } } /// /// Request to reject a review. /// public sealed record RejectReviewRequest { public required string Reason { get; init; } public string? RejectedBy { get; init; } } /// /// Request to request changes. /// public sealed record RequestChangesRequest { public required IReadOnlyList Comments { get; init; } public string? RequestedBy { get; init; } } /// /// Review comment. /// public sealed record ReviewComment { public string? RuleId { get; init; } public required string Comment { get; init; } public ReviewCommentSeverity Severity { get; init; } = ReviewCommentSeverity.Suggestion; } /// /// Review comment severity. /// public enum ReviewCommentSeverity { Suggestion, Warning, Blocking } /// /// Review urgency level. /// public enum ReviewUrgency { Low, Normal, High, Critical } /// /// Review request status. /// public enum ReviewStatus { Pending, InReview, ChangesRequested, Approved, Rejected, Cancelled } /// /// Review request. /// public sealed record ReviewRequest { public required string ReviewId { get; init; } public required Guid TenantId { get; init; } public required Guid PackId { get; init; } public required string PackVersion { get; init; } public required ReviewStatus Status { get; init; } public string? Description { get; init; } public IReadOnlyList? Reviewers { get; init; } public ReviewUrgency Urgency { get; init; } public string? SubmittedBy { get; init; } public required DateTimeOffset SubmittedAt { get; init; } public DateTimeOffset? ResolvedAt { get; init; } public string? ResolvedBy { get; init; } public IReadOnlyList? PendingComments { get; init; } public IReadOnlyDictionary? Metadata { get; init; } } /// /// Review decision result. /// public sealed record ReviewDecision { public required string ReviewId { get; init; } public required ReviewStatus NewStatus { get; init; } public required DateTimeOffset DecidedAt { get; init; } public string? DecidedBy { get; init; } public string? Comment { get; init; } public IReadOnlyList? Comments { get; init; } } /// /// List of review requests. /// public sealed record ReviewRequestList { public required IReadOnlyList Items { get; init; } public string? NextPageToken { get; init; } public int TotalCount { get; init; } } /// /// Audit entry for review actions. /// public sealed record ReviewAuditEntry { public required string AuditId { get; init; } public required string ReviewId { get; init; } public required Guid PackId { get; init; } public required ReviewAuditAction Action { get; init; } public required DateTimeOffset Timestamp { get; init; } public string? PerformedBy { get; init; } public ReviewStatus? PreviousStatus { get; init; } public ReviewStatus? NewStatus { get; init; } public string? Comment { get; init; } public IReadOnlyDictionary? Details { get; init; } } /// /// Review audit action types. /// public enum ReviewAuditAction { Submitted, AssignedReviewer, RemovedReviewer, CommentAdded, ChangesRequested, Approved, Rejected, Cancelled, Reopened, StatusChanged }