Workstream H: Implement VS-03 Approval Workflow (Maker-Checker governance)
- 3 API endpoints: POST /approvals, GET /approvals, POST /approvals/{id}/approve
- State machine: DRAFT → PROPOSED → APPROVED → ACTIVE
- RBAC enforcement: Maker ≠ Checker separation of duties
- Evidence linkage: PBO/DSR/OOS artifact URLs stored
- Schema: Append-only events with correlation_id
- Tests: 5+ unit/integration scenarios
- Documentation: Full API contracts + compliance procedures
- AGENTS.md v16.0 13/13 compliance ✅
Closes workstream H (Phase 2 implementation).
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
namespace KArtSell.Modules.ModelOperations.ApprovalWorkflow;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class ApprovalProposal
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid ModelId { get; set; }
|
||||
public ApprovalStatus Status { get; set; }
|
||||
public string CreatedBy { get; set; } = null!;
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
public string Justification { get; set; } = null!;
|
||||
public DateOnly EffectiveAt { get; set; }
|
||||
|
||||
public DateTimeOffset? ProposedAt { get; set; }
|
||||
public string? ApprovedBy { get; set; }
|
||||
public DateTimeOffset? ApprovedAt { get; set; }
|
||||
public string? ApprovalNotes { get; set; }
|
||||
|
||||
public string? ActivatedBy { get; set; }
|
||||
public DateTimeOffset? ActivatedAt { get; set; }
|
||||
|
||||
public DateTimeOffset PublishedAt { get; set; }
|
||||
public int Revision { get; set; }
|
||||
public Guid CorrelationId { get; set; }
|
||||
|
||||
public List<ApprovalEvidence> Evidence { get; set; } = [];
|
||||
public List<ApprovalEvent> Events { get; set; } = [];
|
||||
|
||||
public bool CanBeProposed => Status == ApprovalStatus.Draft && CreatedBy is not null;
|
||||
public bool CanBeApproved => Status == ApprovalStatus.Proposed;
|
||||
public bool CanBeActivated => Status == ApprovalStatus.Approved;
|
||||
}
|
||||
|
||||
public enum ApprovalStatus
|
||||
{
|
||||
Draft,
|
||||
Proposed,
|
||||
Approved,
|
||||
Active,
|
||||
Rejected
|
||||
}
|
||||
|
||||
public class ApprovalEvidence
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid ApprovalProposalId { get; set; }
|
||||
public string EvidenceType { get; set; } = null!;
|
||||
public string EvidenceUrl { get; set; } = null!;
|
||||
public string? ReviewerComment { get; set; }
|
||||
public DateTimeOffset PublishedAt { get; set; }
|
||||
public Guid CorrelationId { get; set; }
|
||||
}
|
||||
|
||||
public class ApprovalEvent
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid ApprovalProposalId { get; set; }
|
||||
public string EventType { get; set; } = null!;
|
||||
public string ActorEmail { get; set; } = null!;
|
||||
public DateTimeOffset EventAt { get; set; }
|
||||
public Dictionary<string, object>? Details { get; set; }
|
||||
public DateTimeOffset PublishedAt { get; set; }
|
||||
public Guid CorrelationId { get; set; }
|
||||
}
|
||||
|
||||
public class CreateApprovalProposalRequest
|
||||
{
|
||||
public Guid ModelId { get; set; }
|
||||
public DateOnly EffectiveAt { get; set; }
|
||||
public string Justification { get; set; } = null!;
|
||||
}
|
||||
|
||||
public class ApproveApprovalRequest
|
||||
{
|
||||
public string ApprovalNotes { get; set; } = null!;
|
||||
public List<EvidenceItem> Evidence { get; set; } = [];
|
||||
}
|
||||
|
||||
public class EvidenceItem
|
||||
{
|
||||
public string Type { get; set; } = null!;
|
||||
public string Url { get; set; } = null!;
|
||||
public string? Comment { get; set; }
|
||||
}
|
||||
|
||||
public class ApprovalProposalResponse
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid ModelId { get; set; }
|
||||
public string Status { get; set; } = null!;
|
||||
public string CreatedBy { get; set; } = null!;
|
||||
public DateTimeOffset CreatedAt { get; set; }
|
||||
public string Justification { get; set; } = null!;
|
||||
public DateOnly EffectiveAt { get; set; }
|
||||
public string? ApprovedBy { get; set; }
|
||||
public DateTimeOffset? ApprovedAt { get; set; }
|
||||
public string? ApprovalNotes { get; set; }
|
||||
public List<ApprovalEvidenceResponse> Evidence { get; set; } = [];
|
||||
}
|
||||
|
||||
public class ApprovalEvidenceResponse
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string EvidenceType { get; set; } = null!;
|
||||
public string EvidenceUrl { get; set; } = null!;
|
||||
public string? ReviewerComment { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user