158 lines
4.5 KiB
C#
158 lines
4.5 KiB
C#
using System.Collections.Immutable;
|
|
using System.Linq;
|
|
|
|
namespace StellaOps.Policy.Exceptions.Models;
|
|
|
|
/// <summary>
|
|
/// Policy defining conditions that trigger exception re-evaluation.
|
|
/// When any condition is met, the exception may be invalidated or flagged.
|
|
/// </summary>
|
|
public sealed record RecheckPolicy
|
|
{
|
|
/// <summary>
|
|
/// Unique identifier for this policy configuration.
|
|
/// </summary>
|
|
public required string PolicyId { get; init; }
|
|
|
|
/// <summary>
|
|
/// Human-readable name for this policy.
|
|
/// </summary>
|
|
public required string Name { get; init; }
|
|
|
|
/// <summary>
|
|
/// Conditions that trigger recheck.
|
|
/// </summary>
|
|
public required ImmutableArray<RecheckCondition> Conditions { get; init; }
|
|
|
|
/// <summary>
|
|
/// Default action when any condition is triggered.
|
|
/// </summary>
|
|
public required RecheckAction DefaultAction { get; init; }
|
|
|
|
/// <summary>
|
|
/// Whether this policy is active.
|
|
/// </summary>
|
|
public bool IsActive { get; init; } = true;
|
|
|
|
/// <summary>
|
|
/// When this policy was created.
|
|
/// </summary>
|
|
public required DateTimeOffset CreatedAt { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// A single condition that triggers exception re-evaluation.
|
|
/// </summary>
|
|
public sealed record RecheckCondition
|
|
{
|
|
/// <summary>
|
|
/// Type of condition to check.
|
|
/// </summary>
|
|
public required RecheckConditionType Type { get; init; }
|
|
|
|
/// <summary>
|
|
/// Threshold value (interpretation depends on Type).
|
|
/// </summary>
|
|
public decimal? Threshold { get; init; }
|
|
|
|
/// <summary>
|
|
/// Environment scopes where this condition applies.
|
|
/// </summary>
|
|
public ImmutableArray<string> EnvironmentScope { get; init; } = [];
|
|
|
|
/// <summary>
|
|
/// Action to take when this specific condition is triggered.
|
|
/// If null, uses policy's DefaultAction.
|
|
/// </summary>
|
|
public RecheckAction? Action { get; init; }
|
|
|
|
/// <summary>
|
|
/// Human-readable description of this condition.
|
|
/// </summary>
|
|
public string? Description { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Types of recheck conditions.
|
|
/// </summary>
|
|
public enum RecheckConditionType
|
|
{
|
|
/// <summary>Reachability graph changes (new paths discovered).</summary>
|
|
ReachGraphChange,
|
|
|
|
/// <summary>EPSS score exceeds threshold.</summary>
|
|
EPSSAbove,
|
|
|
|
/// <summary>CVSS score exceeds threshold.</summary>
|
|
CVSSAbove,
|
|
|
|
/// <summary>Unknown budget exceeds threshold.</summary>
|
|
UnknownsAbove,
|
|
|
|
/// <summary>New CVE added to same package.</summary>
|
|
NewCVEInPackage,
|
|
|
|
/// <summary>KEV (Known Exploited Vulnerability) flag set.</summary>
|
|
KEVFlagged,
|
|
|
|
/// <summary>Exception nearing expiry (days before).</summary>
|
|
ExpiryWithin,
|
|
|
|
/// <summary>VEX status changes (e.g., from NotAffected to Affected).</summary>
|
|
VEXStatusChange,
|
|
|
|
/// <summary>Package version changes.</summary>
|
|
PackageVersionChange
|
|
}
|
|
|
|
/// <summary>
|
|
/// Action to take when a recheck condition is triggered.
|
|
/// </summary>
|
|
public enum RecheckAction
|
|
{
|
|
/// <summary>Log warning but allow exception to remain active.</summary>
|
|
Warn,
|
|
|
|
/// <summary>Require manual re-approval of exception.</summary>
|
|
RequireReapproval,
|
|
|
|
/// <summary>Automatically revoke the exception.</summary>
|
|
Revoke,
|
|
|
|
/// <summary>Block build/deployment pipeline.</summary>
|
|
Block
|
|
}
|
|
|
|
/// <summary>
|
|
/// Result of evaluating recheck conditions against an exception.
|
|
/// </summary>
|
|
public sealed record RecheckEvaluationResult
|
|
{
|
|
/// <summary>Whether any conditions were triggered.</summary>
|
|
public required bool IsTriggered { get; init; }
|
|
|
|
/// <summary>List of triggered conditions with details.</summary>
|
|
public required ImmutableArray<TriggeredCondition> TriggeredConditions { get; init; }
|
|
|
|
/// <summary>Recommended action based on triggered conditions.</summary>
|
|
public required RecheckAction? RecommendedAction { get; init; }
|
|
|
|
/// <summary>When this evaluation was performed.</summary>
|
|
public required DateTimeOffset EvaluatedAt { get; init; }
|
|
|
|
/// <summary>Human-readable summary.</summary>
|
|
public string Summary => IsTriggered
|
|
? $"{TriggeredConditions.Length} condition(s) triggered: {string.Join(", ", TriggeredConditions.Select(t => t.Type))}"
|
|
: "No conditions triggered";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Details of a triggered recheck condition.
|
|
/// </summary>
|
|
public sealed record TriggeredCondition(
|
|
RecheckConditionType Type,
|
|
string Description,
|
|
decimal? CurrentValue,
|
|
decimal? ThresholdValue,
|
|
RecheckAction Action);
|