namespace StellaOps.Policy.Deltas; /// /// Verdict for a security state delta. /// Determines whether a change should be allowed to proceed. /// public sealed record DeltaVerdict { /// /// Unique identifier for this verdict. /// public required string VerdictId { get; init; } /// /// Reference to the delta being evaluated. /// public required string DeltaId { get; init; } /// /// When this verdict was rendered. /// public required DateTimeOffset EvaluatedAt { get; init; } /// /// The verdict outcome. /// public required DeltaVerdictStatus Status { get; init; } /// /// Recommended gate level based on delta risk. /// public DeltaGateLevel RecommendedGate { get; init; } /// /// Risk points consumed by this change. /// public int RiskPoints { get; init; } /// /// Drivers that contributed to the verdict. /// public IReadOnlyList BlockingDrivers { get; init; } = []; /// /// Drivers that raised warnings but didn't block. /// public IReadOnlyList WarningDrivers { get; init; } = []; /// /// Applied exceptions that allowed blocking drivers. /// public IReadOnlyList AppliedExceptions { get; init; } = []; /// /// Human-readable explanation. /// public string? Explanation { get; init; } /// /// Recommendations for addressing issues. /// public IReadOnlyList Recommendations { get; init; } = []; } /// /// Possible verdict outcomes for a delta. /// public enum DeltaVerdictStatus { /// /// Delta is safe to proceed. /// Pass, /// /// Delta has warnings but can proceed. /// Warn, /// /// Delta should not proceed without remediation. /// Fail, /// /// Delta is blocked but covered by exceptions. /// PassWithExceptions } /// /// Gate levels aligned with diff-aware release gates. /// public enum DeltaGateLevel { /// /// G0: No-risk (docs, comments only). /// G0, /// /// G1: Low risk (unit tests, 1 review). /// G1, /// /// G2: Moderate risk (integration tests, code owner, canary). /// G2, /// /// G3: High risk (security scan, migration plan, release captain). /// G3, /// /// G4: Very high risk (formal review, extended canary, comms plan). /// G4 } /// /// Builder for delta verdicts. /// public sealed class DeltaVerdictBuilder { private static readonly IVerdictIdGenerator DefaultIdGenerator = new VerdictIdGenerator(); private readonly IVerdictIdGenerator _idGenerator; private DeltaVerdictStatus _status = DeltaVerdictStatus.Pass; private DeltaGateLevel _gate = DeltaGateLevel.G1; private int _riskPoints; private readonly List _blockingDrivers = []; private readonly List _warningDrivers = []; private readonly List _exceptions = []; private readonly List _recommendations = []; private string? _explanation; /// /// Creates a new with the default ID generator. /// public DeltaVerdictBuilder() : this(DefaultIdGenerator) { } /// /// Creates a new with a custom ID generator. /// /// Custom verdict ID generator for testing or specialized scenarios. public DeltaVerdictBuilder(IVerdictIdGenerator idGenerator) { _idGenerator = idGenerator ?? throw new ArgumentNullException(nameof(idGenerator)); } public DeltaVerdictBuilder WithStatus(DeltaVerdictStatus status) { _status = status; return this; } public DeltaVerdictBuilder WithGate(DeltaGateLevel gate) { _gate = gate; return this; } public DeltaVerdictBuilder WithRiskPoints(int points) { _riskPoints = points; return this; } public DeltaVerdictBuilder AddBlockingDriver(DeltaDriver driver) { _blockingDrivers.Add(driver); _status = DeltaVerdictStatus.Fail; // Escalate gate based on severity if (driver.Severity == DeltaDriverSeverity.Critical && _gate < DeltaGateLevel.G4) _gate = DeltaGateLevel.G4; else if (driver.Severity == DeltaDriverSeverity.High && _gate < DeltaGateLevel.G3) _gate = DeltaGateLevel.G3; return this; } public DeltaVerdictBuilder AddWarningDriver(DeltaDriver driver) { _warningDrivers.Add(driver); if (_status == DeltaVerdictStatus.Pass) _status = DeltaVerdictStatus.Warn; // Escalate gate for medium severity warnings if (driver.Severity >= DeltaDriverSeverity.Medium && _gate < DeltaGateLevel.G2) _gate = DeltaGateLevel.G2; return this; } public DeltaVerdictBuilder AddException(string exceptionId) { _exceptions.Add(exceptionId); return this; } public DeltaVerdictBuilder AddRecommendation(string recommendation) { _recommendations.Add(recommendation); return this; } public DeltaVerdictBuilder WithExplanation(string explanation) { _explanation = explanation; return this; } public DeltaVerdict Build(string deltaId) { // If all blocking drivers are excepted, change to PassWithExceptions if (_status == DeltaVerdictStatus.Fail && _blockingDrivers.Count > 0 && _exceptions.Count >= _blockingDrivers.Count) { _status = DeltaVerdictStatus.PassWithExceptions; } var blockingDrivers = _blockingDrivers.ToList(); var warningDrivers = _warningDrivers.ToList(); var appliedExceptions = _exceptions.ToList(); // Compute content-addressed VerdictId from inputs var verdictId = _idGenerator.ComputeVerdictId( deltaId, blockingDrivers, warningDrivers, appliedExceptions, _gate); return new DeltaVerdict { VerdictId = verdictId, DeltaId = deltaId, EvaluatedAt = DateTimeOffset.UtcNow, Status = _status, RecommendedGate = _gate, RiskPoints = _riskPoints, BlockingDrivers = blockingDrivers, WarningDrivers = warningDrivers, AppliedExceptions = appliedExceptions, Explanation = _explanation ?? GenerateExplanation(), Recommendations = _recommendations.ToList() }; } private string GenerateExplanation() { return _status switch { DeltaVerdictStatus.Pass => "No blocking changes detected", DeltaVerdictStatus.Warn => $"{_warningDrivers.Count} warning(s) detected", DeltaVerdictStatus.Fail => $"{_blockingDrivers.Count} blocking issue(s) detected", DeltaVerdictStatus.PassWithExceptions => $"Blocked by {_blockingDrivers.Count} issue(s), covered by exceptions", _ => "Unknown status" }; } }