using StellaOps.Policy.TrustLattice; using System.Collections.Immutable; using VexStatus = StellaOps.Policy.Confidence.Models.VexStatus; namespace StellaOps.Policy.Gates; public sealed record MinimumConfidenceGateOptions { public bool Enabled { get; init; } = true; public IReadOnlyDictionary Thresholds { get; init; } = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["production"] = 0.75, ["staging"] = 0.60, ["development"] = 0.40, }; public IReadOnlyCollection ApplyToStatuses { get; init; } = new[] { VexStatus.NotAffected, VexStatus.Fixed, }; } public sealed class MinimumConfidenceGate : IPolicyGate { private readonly MinimumConfidenceGateOptions _options; public MinimumConfidenceGate(MinimumConfidenceGateOptions? options = null) { _options = options ?? new MinimumConfidenceGateOptions(); } public Task EvaluateAsync(MergeResult mergeResult, PolicyGateContext context, CancellationToken ct = default) { if (!_options.Enabled) { return Task.FromResult(Pass("disabled")); } if (mergeResult.Status == VexStatus.Affected) { return Task.FromResult(Pass("affected_bypass")); } if (!_options.ApplyToStatuses.Contains(mergeResult.Status)) { return Task.FromResult(Pass("status_not_applicable")); } var threshold = GetThreshold(context.Environment); var passed = mergeResult.Confidence >= threshold; var details = ImmutableDictionary.Empty .Add("threshold", threshold) .Add("confidence", mergeResult.Confidence) .Add("environment", context.Environment); return Task.FromResult(new GateResult { GateName = nameof(MinimumConfidenceGate), Passed = passed, Reason = passed ? null : "confidence_below_threshold", Details = details, }); } private double GetThreshold(string environment) { if (_options.Thresholds.TryGetValue(environment, out var threshold)) { return threshold; } if (_options.Thresholds.TryGetValue("production", out var prod)) { return prod; } return 0.0; } private static GateResult Pass(string reason) => new() { GateName = nameof(MinimumConfidenceGate), Passed = true, Reason = reason, Details = ImmutableDictionary.Empty, }; }