using StellaOps.Policy; using StellaOps.Policy.Determinization; using StellaOps.Policy.Determinization.Models; namespace StellaOps.Policy.Engine.Policies; /// /// Rule set for determinization policy evaluation. /// Rules are evaluated in priority order (lower = higher priority). /// public sealed class DeterminizationRuleSet { public IReadOnlyList Rules { get; } private DeterminizationRuleSet(IReadOnlyList rules) { Rules = rules; } /// /// Creates the default rule set per advisory specification. /// public static DeterminizationRuleSet Default(DeterminizationOptions options) => new(new List { // Rule 1: Escalate if runtime evidence shows vulnerable code loaded new DeterminizationRule { Name = "RuntimeEscalation", Priority = 10, Condition = (ctx, _) => ctx.SignalSnapshot.Runtime.HasValue && ctx.SignalSnapshot.Runtime.Value!.ObservedLoaded, Action = (ctx, _) => DeterminizationResult.Escalated( "Runtime evidence shows vulnerable code loaded in memory") }, // Rule 2: Quarantine if EPSS exceeds threshold new DeterminizationRule { Name = "EpssQuarantine", Priority = 20, Condition = (ctx, thresholds) => ctx.SignalSnapshot.Epss.HasValue && ctx.SignalSnapshot.Epss.Value!.Score >= thresholds.EpssBlockThreshold, Action = (ctx, thresholds) => DeterminizationResult.Quarantined( $"EPSS score {ctx.SignalSnapshot.Epss.Value!.Score:P1} exceeds threshold {thresholds.EpssBlockThreshold:P1}") }, // Rule 3: Quarantine if proven reachable new DeterminizationRule { Name = "ReachabilityQuarantine", Priority = 25, Condition = (ctx, _) => ctx.SignalSnapshot.Reachability.HasValue && ctx.SignalSnapshot.Reachability.Value!.IsReachable, Action = (ctx, _) => DeterminizationResult.Quarantined( $"Vulnerable code is reachable via call graph analysis") }, // Rule 4: Block high entropy in production new DeterminizationRule { Name = "ProductionEntropyBlock", Priority = 30, Condition = (ctx, thresholds) => ctx.Environment == DeploymentEnvironment.Production && ctx.UncertaintyScore.Entropy > thresholds.MaxEntropyForAllow, Action = (ctx, thresholds) => DeterminizationResult.Quarantined( $"High uncertainty (entropy={ctx.UncertaintyScore.Entropy:F2}) exceeds production threshold ({thresholds.MaxEntropyForAllow:F2})") }, // Rule 5: Defer if evidence is stale new DeterminizationRule { Name = "StaleEvidenceDefer", Priority = 40, Condition = (ctx, _) => ctx.Decay.IsStale, Action = (ctx, _) => DeterminizationResult.Deferred( $"Evidence is stale (last update: {ctx.Decay.LastSignalUpdate:u}, age: {ctx.Decay.AgeDays:F1} days)") }, // Rule 6: Guarded allow for uncertain observations in non-prod new DeterminizationRule { Name = "GuardedAllowNonProd", Priority = 50, Condition = (ctx, _) => ctx.TrustScore < 0.5 && ctx.UncertaintyScore.Entropy > 0.4 && ctx.Environment != DeploymentEnvironment.Production, Action = (ctx, _) => DeterminizationResult.GuardedPass( $"Uncertain observation (entropy={ctx.UncertaintyScore.Entropy:F2}, trust={ctx.TrustScore:F2}) allowed with guardrails in {ctx.Environment}", BuildGuardrails(ctx, GuardRailsLevel.Moderate)) }, // Rule 7: Allow if unreachable with high confidence new DeterminizationRule { Name = "UnreachableAllow", Priority = 60, Condition = (ctx, thresholds) => ctx.SignalSnapshot.Reachability.HasValue && !ctx.SignalSnapshot.Reachability.Value!.IsReachable && ctx.SignalSnapshot.Reachability.Value.Confidence >= thresholds.MinConfidenceForNotAffected, Action = (ctx, _) => DeterminizationResult.Allowed( $"Vulnerable code is unreachable (confidence={ctx.SignalSnapshot.Reachability.Value!.Confidence:P0})") }, // Rule 8: Allow if VEX not_affected with trusted issuer new DeterminizationRule { Name = "VexNotAffectedAllow", Priority = 65, Condition = (ctx, thresholds) => ctx.SignalSnapshot.Vex.HasValue && ctx.SignalSnapshot.Vex.Value!.IsNotAffected && ctx.SignalSnapshot.Vex.Value.IssuerTrust >= thresholds.MinConfidenceForNotAffected, Action = (ctx, _) => DeterminizationResult.Allowed( $"VEX statement indicates not_affected (trust={ctx.SignalSnapshot.Vex.Value!.IssuerTrust:P0})") }, // Rule 9: Allow if sufficient evidence and low entropy new DeterminizationRule { Name = "SufficientEvidenceAllow", Priority = 70, Condition = (ctx, thresholds) => ctx.UncertaintyScore.Entropy <= thresholds.MaxEntropyForAllow && ctx.TrustScore >= thresholds.MinConfidenceForNotAffected, Action = (ctx, _) => DeterminizationResult.Allowed( $"Sufficient evidence (entropy={ctx.UncertaintyScore.Entropy:F2}, trust={ctx.TrustScore:F2}) for confident determination") }, // Rule 10: Guarded allow for moderate uncertainty new DeterminizationRule { Name = "GuardedAllowModerateUncertainty", Priority = 80, Condition = (ctx, _) => ctx.UncertaintyScore.Tier <= UncertaintyTier.Moderate && ctx.TrustScore >= 0.4, Action = (ctx, _) => DeterminizationResult.GuardedPass( $"Moderate uncertainty (tier={ctx.UncertaintyScore.Tier}, trust={ctx.TrustScore:F2}) allowed with monitoring", BuildGuardrails(ctx, GuardRailsLevel.Light)) }, // Rule 11: Default - require more evidence new DeterminizationRule { Name = "DefaultDefer", Priority = 100, Condition = (_, _) => true, Action = (ctx, _) => DeterminizationResult.Deferred( $"Insufficient evidence for determination (entropy={ctx.UncertaintyScore.Entropy:F2}, tier={ctx.UncertaintyScore.Tier})") } }); private enum GuardRailsLevel { Light, Moderate, Strict } private static GuardRails BuildGuardrails(DeterminizationContext ctx, GuardRailsLevel level) => level switch { GuardRailsLevel.Light => new GuardRails { EnableMonitoring = true, RestrictToNonProd = false, RequireApproval = false, ReevalAfter = TimeSpan.FromDays(14), Notes = $"Light guardrails: entropy={ctx.UncertaintyScore.Entropy:F2}, trust={ctx.TrustScore:F2}, env={ctx.Environment}" }, GuardRailsLevel.Moderate => new GuardRails { EnableMonitoring = true, RestrictToNonProd = ctx.Environment == DeploymentEnvironment.Production, RequireApproval = false, ReevalAfter = TimeSpan.FromDays(7), Notes = $"Moderate guardrails: entropy={ctx.UncertaintyScore.Entropy:F2}, trust={ctx.TrustScore:F2}, env={ctx.Environment}" }, GuardRailsLevel.Strict => new GuardRails { EnableMonitoring = true, RestrictToNonProd = true, RequireApproval = true, ReevalAfter = TimeSpan.FromDays(3), Notes = $"Strict guardrails: entropy={ctx.UncertaintyScore.Entropy:F2}, trust={ctx.TrustScore:F2}, env={ctx.Environment}" }, _ => GuardRails.Default() }; } /// /// A single determinization rule. /// public sealed record DeterminizationRule { /// Rule name for audit/logging. public required string Name { get; init; } /// Priority (lower = evaluated first). public required int Priority { get; init; } /// Condition function. public required Func Condition { get; init; } /// Action function. public required Func Action { get; init; } }