up
This commit is contained in:
@@ -231,6 +231,168 @@ public sealed class PolicyRuntimeEvaluationServiceTests
|
||||
Assert.Equal("warn", response.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EvaluateAsync_GatesUnreachableWithoutEvidenceRef_ToUnderInvestigation()
|
||||
{
|
||||
const string policy = """
|
||||
policy "Reachability gate policy" syntax "stella-dsl@1" {
|
||||
rule unreachable_to_not_affected priority 10 {
|
||||
when reachability.state == "unreachable"
|
||||
then status := "not_affected"
|
||||
because "unreachable + evidence"
|
||||
}
|
||||
|
||||
rule gated_to_under_investigation priority 20 {
|
||||
when reachability.state == "under_investigation"
|
||||
then status := "under_investigation"
|
||||
because "unreachable but missing evidence"
|
||||
}
|
||||
|
||||
rule default priority 100 {
|
||||
when true
|
||||
then status := "affected"
|
||||
because "default"
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
var harness = CreateHarness();
|
||||
await harness.StoreTestPolicyAsync("pack-3", 1, policy);
|
||||
|
||||
var fact = new ReachabilityFact
|
||||
{
|
||||
Id = "fact-1",
|
||||
TenantId = "tenant-1",
|
||||
ComponentPurl = "pkg:npm/lodash@4.17.21",
|
||||
AdvisoryId = "CVE-2024-0001",
|
||||
State = ReachabilityState.Unreachable,
|
||||
Confidence = 0.92m,
|
||||
Score = 0m,
|
||||
HasRuntimeEvidence = false,
|
||||
Source = "graph-analyzer",
|
||||
Method = AnalysisMethod.Static,
|
||||
EvidenceRef = null,
|
||||
EvidenceHash = "sha256:deadbeef",
|
||||
ComputedAt = new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero),
|
||||
Metadata = new Dictionary<string, object?>()
|
||||
};
|
||||
|
||||
await harness.ReachabilityStore.SaveAsync(fact, CancellationToken.None);
|
||||
|
||||
var request = CreateRequest("pack-3", 1, severity: "Low");
|
||||
var response = await harness.Service.EvaluateAsync(request, CancellationToken.None);
|
||||
|
||||
Assert.Equal("under_investigation", response.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EvaluateAsync_GatesUnreachableWithLowConfidence_ToUnderInvestigation()
|
||||
{
|
||||
const string policy = """
|
||||
policy "Reachability gate policy" syntax "stella-dsl@1" {
|
||||
rule unreachable_to_not_affected priority 10 {
|
||||
when reachability.state == "unreachable"
|
||||
then status := "not_affected"
|
||||
because "unreachable + evidence"
|
||||
}
|
||||
|
||||
rule gated_to_under_investigation priority 20 {
|
||||
when reachability.state == "under_investigation"
|
||||
then status := "under_investigation"
|
||||
because "unreachable but low confidence"
|
||||
}
|
||||
|
||||
rule default priority 100 {
|
||||
when true
|
||||
then status := "affected"
|
||||
because "default"
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
var harness = CreateHarness();
|
||||
await harness.StoreTestPolicyAsync("pack-4", 1, policy);
|
||||
|
||||
var fact = new ReachabilityFact
|
||||
{
|
||||
Id = "fact-1",
|
||||
TenantId = "tenant-1",
|
||||
ComponentPurl = "pkg:npm/lodash@4.17.21",
|
||||
AdvisoryId = "CVE-2024-0001",
|
||||
State = ReachabilityState.Unreachable,
|
||||
Confidence = 0.7m,
|
||||
Score = 0m,
|
||||
HasRuntimeEvidence = false,
|
||||
Source = "graph-analyzer",
|
||||
Method = AnalysisMethod.Static,
|
||||
EvidenceRef = "cas://reachability/facts/fact-1",
|
||||
EvidenceHash = "sha256:deadbeef",
|
||||
ComputedAt = new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero),
|
||||
Metadata = new Dictionary<string, object?>()
|
||||
};
|
||||
|
||||
await harness.ReachabilityStore.SaveAsync(fact, CancellationToken.None);
|
||||
|
||||
var request = CreateRequest("pack-4", 1, severity: "Low");
|
||||
var response = await harness.Service.EvaluateAsync(request, CancellationToken.None);
|
||||
|
||||
Assert.Equal("under_investigation", response.Status);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EvaluateAsync_AllowsUnreachableWithEvidenceRefAndHighConfidence()
|
||||
{
|
||||
const string policy = """
|
||||
policy "Reachability gate policy" syntax "stella-dsl@1" {
|
||||
rule unreachable_to_not_affected priority 10 {
|
||||
when reachability.state == "unreachable"
|
||||
then status := "not_affected"
|
||||
because "unreachable + evidence"
|
||||
}
|
||||
|
||||
rule gated_to_under_investigation priority 20 {
|
||||
when reachability.state == "under_investigation"
|
||||
then status := "under_investigation"
|
||||
because "gated"
|
||||
}
|
||||
|
||||
rule default priority 100 {
|
||||
when true
|
||||
then status := "affected"
|
||||
because "default"
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
var harness = CreateHarness();
|
||||
await harness.StoreTestPolicyAsync("pack-5", 1, policy);
|
||||
|
||||
var fact = new ReachabilityFact
|
||||
{
|
||||
Id = "fact-1",
|
||||
TenantId = "tenant-1",
|
||||
ComponentPurl = "pkg:npm/lodash@4.17.21",
|
||||
AdvisoryId = "CVE-2024-0001",
|
||||
State = ReachabilityState.Unreachable,
|
||||
Confidence = 0.92m,
|
||||
Score = 0m,
|
||||
HasRuntimeEvidence = false,
|
||||
Source = "graph-analyzer",
|
||||
Method = AnalysisMethod.Static,
|
||||
EvidenceRef = "cas://reachability/facts/fact-1",
|
||||
EvidenceHash = "sha256:deadbeef",
|
||||
ComputedAt = new DateTimeOffset(2025, 1, 1, 0, 0, 0, TimeSpan.Zero),
|
||||
Metadata = new Dictionary<string, object?>()
|
||||
};
|
||||
|
||||
await harness.ReachabilityStore.SaveAsync(fact, CancellationToken.None);
|
||||
|
||||
var request = CreateRequest("pack-5", 1, severity: "Low");
|
||||
var response = await harness.Service.EvaluateAsync(request, CancellationToken.None);
|
||||
|
||||
Assert.Equal("not_affected", response.Status);
|
||||
}
|
||||
|
||||
private static RuntimeEvaluationRequest CreateRequest(
|
||||
string packId,
|
||||
int version,
|
||||
|
||||
Reference in New Issue
Block a user