Files
git.stella-ops.org/src/Policy/__Tests/StellaOps.Policy.Tests/Gates/VexProofGateTests.cs

269 lines
8.7 KiB
C#

// SPDX-License-Identifier: BUSL-1.1
// Copyright (c) 2025 StellaOps
// Sprint: SPRINT_20260112_004_BE_policy_determinization_attested_rules (DET-ATT-004)
// Task: Unit tests for VexProofGate anchor-aware mode
using System.Collections.Immutable;
using StellaOps.Policy.Gates;
using StellaOps.Policy.TrustLattice;
using VexStatus = StellaOps.Policy.Confidence.Models.VexStatus;
using Xunit;
namespace StellaOps.Policy.Tests.Gates;
public class VexProofGateTests
{
private static readonly DateTimeOffset FixedTime = new(2026, 1, 14, 12, 0, 0, TimeSpan.Zero);
private static MergeResult CreateMergeResult(VexStatus status) =>
new()
{
Status = status,
Confidence = 0.9,
HasConflicts = false,
AllClaims = ImmutableArray<ScoredClaim>.Empty,
WinningClaim = new ScoredClaim
{
SourceId = "test",
Status = status,
OriginalScore = 0.9,
AdjustedScore = 0.9,
ScopeSpecificity = 1,
Accepted = true,
Reason = "Test claim"
},
Conflicts = ImmutableArray<ConflictRecord>.Empty
};
[Fact]
public async Task EvaluateAsync_WhenDisabled_ReturnsPass()
{
// Arrange
var options = new VexProofGateOptions { Enabled = false };
var gate = new VexProofGate(options);
var mergeResult = CreateMergeResult(VexStatus.NotAffected);
var context = new PolicyGateContext { Environment = "production" };
// Act
var result = await gate.EvaluateAsync(mergeResult, context);
// Assert
Assert.True(result.Passed);
Assert.Equal("disabled", result.Reason);
}
[Fact]
public async Task EvaluateAsync_WhenAnchorAwareModeEnabled_RequiresAnchoring()
{
// Arrange
var options = new VexProofGateOptions
{
Enabled = true,
RequireProofForNotAffected = true,
AnchorAwareMode = true,
RequireVexAnchoring = true
};
var gate = new VexProofGate(options);
var mergeResult = CreateMergeResult(VexStatus.NotAffected);
var context = new PolicyGateContext
{
Environment = "production",
Metadata = new Dictionary<string, string>
{
["vex_proof_id"] = "proof-123",
["vex_proof_confidence_tier"] = "high",
["vex_proof_anchored"] = "false" // Not anchored
}
};
// Act
var result = await gate.EvaluateAsync(mergeResult, context);
// Assert
Assert.False(result.Passed);
Assert.Equal("vex_not_anchored", result.Reason);
}
[Fact]
public async Task EvaluateAsync_WhenAnchorAwareModeEnabled_PassesWithAnchoring()
{
// Arrange
var options = new VexProofGateOptions
{
Enabled = true,
RequireProofForNotAffected = true,
AnchorAwareMode = true,
RequireVexAnchoring = true,
RequireRekorVerification = false
};
var gate = new VexProofGate(options);
var mergeResult = CreateMergeResult(VexStatus.NotAffected);
var context = new PolicyGateContext
{
Environment = "production",
Metadata = new Dictionary<string, string>
{
["vex_proof_id"] = "proof-123",
["vex_proof_confidence_tier"] = "high",
["vex_proof_anchored"] = "true",
["vex_proof_envelope_digest"] = "sha256:abc123"
}
};
// Act
var result = await gate.EvaluateAsync(mergeResult, context);
// Assert
Assert.True(result.Passed);
Assert.Equal("proof_valid", result.Reason);
}
[Fact]
public async Task EvaluateAsync_WhenRekorRequired_FailsWithoutRekor()
{
// Arrange
var options = new VexProofGateOptions
{
Enabled = true,
RequireProofForNotAffected = true,
AnchorAwareMode = true,
RequireVexAnchoring = true,
RequireRekorVerification = true
};
var gate = new VexProofGate(options);
var mergeResult = CreateMergeResult(VexStatus.NotAffected);
var context = new PolicyGateContext
{
Environment = "production",
Metadata = new Dictionary<string, string>
{
["vex_proof_id"] = "proof-123",
["vex_proof_confidence_tier"] = "high",
["vex_proof_anchored"] = "true",
["vex_proof_rekor_verified"] = "false"
}
};
// Act
var result = await gate.EvaluateAsync(mergeResult, context);
// Assert
Assert.False(result.Passed);
Assert.Equal("rekor_verification_missing", result.Reason);
}
[Fact]
public async Task EvaluateAsync_WhenRekorRequired_PassesWithRekor()
{
// Arrange
var options = new VexProofGateOptions
{
Enabled = true,
RequireProofForNotAffected = true,
AnchorAwareMode = true,
RequireVexAnchoring = true,
RequireRekorVerification = true
};
var gate = new VexProofGate(options);
var mergeResult = CreateMergeResult(VexStatus.NotAffected);
var context = new PolicyGateContext
{
Environment = "production",
Metadata = new Dictionary<string, string>
{
["vex_proof_id"] = "proof-123",
["vex_proof_confidence_tier"] = "high",
["vex_proof_anchored"] = "true",
["vex_proof_envelope_digest"] = "sha256:abc123",
["vex_proof_rekor_verified"] = "true",
["vex_proof_rekor_log_index"] = "12345678"
}
};
// Act
var result = await gate.EvaluateAsync(mergeResult, context);
// Assert
Assert.True(result.Passed);
Assert.Equal("proof_valid", result.Reason);
Assert.True(result.Details.ContainsKey("rekorLogIndex"));
}
[Fact]
public async Task EvaluateAsync_StrictAnchorAware_EnforcesAllRequirements()
{
// Arrange
var options = VexProofGateOptions.StrictAnchorAware;
var gate = new VexProofGate(options);
var mergeResult = CreateMergeResult(VexStatus.NotAffected);
var context = new PolicyGateContext
{
Environment = "production",
Metadata = new Dictionary<string, string>
{
["vex_proof_id"] = "proof-123",
["vex_proof_confidence_tier"] = "high",
["vex_proof_all_signed"] = "true",
["vex_proof_anchored"] = "true",
["vex_proof_envelope_digest"] = "sha256:abc123",
["vex_proof_rekor_verified"] = "true",
["vex_proof_rekor_log_index"] = "12345678"
}
};
// Act
var result = await gate.EvaluateAsync(mergeResult, context);
// Assert
Assert.True(result.Passed);
Assert.Equal("proof_valid", result.Reason);
}
[Fact]
public async Task EvaluateAsync_StrictAnchorAware_FailsWithoutSignedStatements()
{
// Arrange
var options = VexProofGateOptions.StrictAnchorAware;
var gate = new VexProofGate(options);
var mergeResult = CreateMergeResult(VexStatus.NotAffected);
var context = new PolicyGateContext
{
Environment = "production",
Metadata = new Dictionary<string, string>
{
["vex_proof_id"] = "proof-123",
["vex_proof_confidence_tier"] = "high",
["vex_proof_all_signed"] = "false", // Not signed
["vex_proof_anchored"] = "true",
["vex_proof_rekor_verified"] = "true"
}
};
// Act
var result = await gate.EvaluateAsync(mergeResult, context);
// Assert
Assert.False(result.Passed);
Assert.Equal("unsigned_statements", result.Reason);
}
[Fact]
public void StrictAnchorAware_HasExpectedDefaults()
{
// Act
var options = VexProofGateOptions.StrictAnchorAware;
// Assert
Assert.True(options.Enabled);
Assert.Equal("high", options.MinimumConfidenceTier);
Assert.True(options.RequireProofForNotAffected);
Assert.True(options.RequireProofForFixed);
Assert.True(options.RequireSignedStatements);
Assert.True(options.AnchorAwareMode);
Assert.True(options.RequireVexAnchoring);
Assert.True(options.RequireRekorVerification);
Assert.Equal(0, options.MaxAllowedConflicts);
Assert.Equal(72, options.MaxProofAgeHours);
}
}