up
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled

This commit is contained in:
StellaOps Bot
2025-11-27 23:44:42 +02:00
parent ef6e4b2067
commit 3b96b2e3ea
298 changed files with 47516 additions and 1168 deletions

View File

@@ -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 &lt; 0.8).
/// </summary>
public bool IsMediumConfidence => Confidence >= 0.5m && Confidence < 0.8m;
/// <summary>
/// Whether this reachability data has low confidence (&lt; 0.5).
/// </summary>
public bool IsLowConfidence => Confidence < 0.5m;
}

View File

@@ -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,
};
}
}