up
This commit is contained in:
@@ -17,7 +17,32 @@ internal sealed record PolicyEvaluationContext(
|
||||
PolicyEvaluationAdvisory Advisory,
|
||||
PolicyEvaluationVexEvidence Vex,
|
||||
PolicyEvaluationSbom Sbom,
|
||||
PolicyEvaluationExceptions Exceptions);
|
||||
PolicyEvaluationExceptions Exceptions,
|
||||
PolicyEvaluationReachability Reachability,
|
||||
DateTimeOffset? EvaluationTimestamp = null)
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the evaluation timestamp for deterministic time-based operations.
|
||||
/// This value is injected at evaluation time rather than using DateTime.UtcNow
|
||||
/// to ensure deterministic, reproducible results.
|
||||
/// </summary>
|
||||
public DateTimeOffset Now => EvaluationTimestamp ?? DateTimeOffset.MinValue;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a context without reachability data (for backwards compatibility).
|
||||
/// </summary>
|
||||
public PolicyEvaluationContext(
|
||||
PolicyEvaluationSeverity severity,
|
||||
PolicyEvaluationEnvironment environment,
|
||||
PolicyEvaluationAdvisory advisory,
|
||||
PolicyEvaluationVexEvidence vex,
|
||||
PolicyEvaluationSbom sbom,
|
||||
PolicyEvaluationExceptions exceptions,
|
||||
DateTimeOffset? evaluationTimestamp = null)
|
||||
: this(severity, environment, advisory, vex, sbom, exceptions, PolicyEvaluationReachability.Unknown, evaluationTimestamp)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed record PolicyEvaluationSeverity(string Normalized, decimal? Score = null);
|
||||
|
||||
@@ -158,3 +183,96 @@ internal sealed record PolicyExceptionApplication(
|
||||
string AppliedStatus,
|
||||
string? AppliedSeverity,
|
||||
ImmutableDictionary<string, string> Metadata);
|
||||
|
||||
/// <summary>
|
||||
/// Reachability evidence for policy evaluation.
|
||||
/// </summary>
|
||||
internal sealed record PolicyEvaluationReachability(
|
||||
string State,
|
||||
decimal Confidence,
|
||||
decimal Score,
|
||||
bool HasRuntimeEvidence,
|
||||
string? Source,
|
||||
string? Method,
|
||||
string? EvidenceRef)
|
||||
{
|
||||
/// <summary>
|
||||
/// Default unknown reachability state.
|
||||
/// </summary>
|
||||
public static readonly PolicyEvaluationReachability Unknown = new(
|
||||
State: "unknown",
|
||||
Confidence: 0m,
|
||||
Score: 0m,
|
||||
HasRuntimeEvidence: false,
|
||||
Source: null,
|
||||
Method: null,
|
||||
EvidenceRef: null);
|
||||
|
||||
/// <summary>
|
||||
/// Reachable state.
|
||||
/// </summary>
|
||||
public static PolicyEvaluationReachability Reachable(
|
||||
decimal confidence = 1m,
|
||||
decimal score = 1m,
|
||||
bool hasRuntimeEvidence = false,
|
||||
string? source = null,
|
||||
string? method = null) => new(
|
||||
State: "reachable",
|
||||
Confidence: confidence,
|
||||
Score: score,
|
||||
HasRuntimeEvidence: hasRuntimeEvidence,
|
||||
Source: source,
|
||||
Method: method,
|
||||
EvidenceRef: null);
|
||||
|
||||
/// <summary>
|
||||
/// Unreachable state.
|
||||
/// </summary>
|
||||
public static PolicyEvaluationReachability Unreachable(
|
||||
decimal confidence = 1m,
|
||||
bool hasRuntimeEvidence = false,
|
||||
string? source = null,
|
||||
string? method = null) => new(
|
||||
State: "unreachable",
|
||||
Confidence: confidence,
|
||||
Score: 0m,
|
||||
HasRuntimeEvidence: hasRuntimeEvidence,
|
||||
Source: source,
|
||||
Method: method,
|
||||
EvidenceRef: null);
|
||||
|
||||
/// <summary>
|
||||
/// Whether the reachability state is definitively reachable.
|
||||
/// </summary>
|
||||
public bool IsReachable => State.Equals("reachable", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Whether the reachability state is definitively unreachable.
|
||||
/// </summary>
|
||||
public bool IsUnreachable => State.Equals("unreachable", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Whether the reachability state is unknown.
|
||||
/// </summary>
|
||||
public bool IsUnknown => State.Equals("unknown", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Whether the reachability state is under investigation.
|
||||
/// </summary>
|
||||
public bool IsUnderInvestigation => State.Equals("under_investigation", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
/// <summary>
|
||||
/// Whether this reachability data has high confidence (>= 0.8).
|
||||
/// </summary>
|
||||
public bool IsHighConfidence => Confidence >= 0.8m;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this reachability data has medium confidence (>= 0.5 and < 0.8).
|
||||
/// </summary>
|
||||
public bool IsMediumConfidence => Confidence >= 0.5m && Confidence < 0.8m;
|
||||
|
||||
/// <summary>
|
||||
/// Whether this reachability data has low confidence (< 0.5).
|
||||
/// </summary>
|
||||
public bool IsLowConfidence => Confidence < 0.5m;
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@ internal sealed class PolicyExpressionEvaluator
|
||||
"vex" => new EvaluationValue(new VexScope(this, context.Vex)),
|
||||
"advisory" => new EvaluationValue(new AdvisoryScope(context.Advisory)),
|
||||
"sbom" => new EvaluationValue(new SbomScope(context.Sbom)),
|
||||
"reachability" => new EvaluationValue(new ReachabilityScope(context.Reachability)),
|
||||
"now" => new EvaluationValue(context.Now),
|
||||
"true" => EvaluationValue.True,
|
||||
"false" => EvaluationValue.False,
|
||||
_ => EvaluationValue.Null,
|
||||
@@ -98,6 +100,11 @@ internal sealed class PolicyExpressionEvaluator
|
||||
return sbom.Get(member.Member);
|
||||
}
|
||||
|
||||
if (raw is ReachabilityScope reachability)
|
||||
{
|
||||
return reachability.Get(member.Member);
|
||||
}
|
||||
|
||||
if (raw is ComponentScope componentScope)
|
||||
{
|
||||
return componentScope.Get(member.Member);
|
||||
@@ -811,4 +818,51 @@ internal sealed class PolicyExpressionEvaluator
|
||||
return vex.Statements[^1];
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SPL scope for reachability predicates.
|
||||
/// Provides access to reachability state, confidence, score, and evidence.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// SPL predicates supported:
|
||||
/// - reachability.state == "reachable"
|
||||
/// - reachability.state == "unreachable"
|
||||
/// - reachability.state == "unknown"
|
||||
/// - reachability.confidence >= 0.8
|
||||
/// - reachability.score > 0.5
|
||||
/// - reachability.has_runtime_evidence == true
|
||||
/// - reachability.is_reachable == true
|
||||
/// - reachability.is_unreachable == true
|
||||
/// - reachability.is_high_confidence == true
|
||||
/// - reachability.source == "grype"
|
||||
/// - reachability.method == "static"
|
||||
/// </example>
|
||||
private sealed class ReachabilityScope
|
||||
{
|
||||
private readonly PolicyEvaluationReachability reachability;
|
||||
|
||||
public ReachabilityScope(PolicyEvaluationReachability reachability)
|
||||
{
|
||||
this.reachability = reachability;
|
||||
}
|
||||
|
||||
public EvaluationValue Get(string member) => member.ToLowerInvariant() switch
|
||||
{
|
||||
"state" => new EvaluationValue(reachability.State),
|
||||
"confidence" => new EvaluationValue(reachability.Confidence),
|
||||
"score" => new EvaluationValue(reachability.Score),
|
||||
"has_runtime_evidence" or "hasruntimeevidence" => new EvaluationValue(reachability.HasRuntimeEvidence),
|
||||
"source" => new EvaluationValue(reachability.Source),
|
||||
"method" => new EvaluationValue(reachability.Method),
|
||||
"evidence_ref" or "evidenceref" => new EvaluationValue(reachability.EvidenceRef),
|
||||
"is_reachable" or "isreachable" => new EvaluationValue(reachability.IsReachable),
|
||||
"is_unreachable" or "isunreachable" => new EvaluationValue(reachability.IsUnreachable),
|
||||
"is_unknown" or "isunknown" => new EvaluationValue(reachability.IsUnknown),
|
||||
"is_under_investigation" or "isunderinvestigation" => new EvaluationValue(reachability.IsUnderInvestigation),
|
||||
"is_high_confidence" or "ishighconfidence" => new EvaluationValue(reachability.IsHighConfidence),
|
||||
"is_medium_confidence" or "ismediumconfidence" => new EvaluationValue(reachability.IsMediumConfidence),
|
||||
"is_low_confidence" or "islowconfidence" => new EvaluationValue(reachability.IsLowConfidence),
|
||||
_ => EvaluationValue.Null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user