feat: Implement EvidenceBundleAttestationBuilder with unit tests for claims generation and tenant validation
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled

This commit is contained in:
master
2025-11-20 09:17:58 +02:00
parent 10212d67c0
commit f0e74d2ee8
4 changed files with 219 additions and 1 deletions

View File

@@ -0,0 +1,67 @@
using StellaOps.Concelier.Core.Attestation;
namespace StellaOps.Concelier.Core.Tests.Attestation;
public sealed class EvidenceBundleAttestationBuilderTests
{
private static readonly string RepoRoot =
Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "..", "..", "..", "..", "..", "..", ".."));
[Fact]
public async Task BuildAsync_ProducesClaimsFromSampleBundle()
{
var sampleDir = Path.Combine(RepoRoot, "docs", "samples", "evidence-bundle");
var tarPath = Path.Combine(sampleDir, "evidence-bundle-m0.tar.gz");
var manifestPath = Path.Combine(sampleDir, "manifest.json");
var transparencyPath = Path.Combine(sampleDir, "transparency.json");
var builder = new EvidenceBundleAttestationBuilder();
var claims = await builder.BuildAsync(
new EvidenceBundleAttestationRequest(
tarPath,
manifestPath,
transparencyPath,
pipelineVersion: "git:test-sha"),
CancellationToken.None);
Assert.Equal("evidence-bundle-m0", claims.SubjectName);
Assert.StartsWith("sha256:", claims.SubjectDigest);
Assert.Equal("evidence-bundle-m0", claims.BundleId);
Assert.Equal("1.0.0", claims.BundleVersion);
Assert.Equal("demo", claims.Tenant);
Assert.Equal("vex", claims.Scope);
Assert.True(claims.AocGuardrails);
Assert.Contains("schema:frozen:1.0", claims.AocDetails);
Assert.Equal(tarPath, claims.EvidenceBundlePath);
Assert.Equal("offline", claims.Transparency.SkipReason);
}
[Fact]
public async Task BuildAsync_EnforcesLowercaseTenant()
{
var tempManifest = Path.Combine(Path.GetTempPath(), $"manifest-{Guid.NewGuid():N}.json");
var manifest = """
{
"bundle_id": "test-bundle",
"version": "1.0.0",
"created": "2025-11-19T00:00:00Z",
"tenant": "Demo",
"scope": "vex",
"inputs": ["sha256:abc"],
"aoc": {"guardrails": true, "details": ["schema:frozen:1.0"]}
}
""";
await File.WriteAllTextAsync(tempManifest, manifest);
var tempTar = Path.Combine(Path.GetTempPath(), $"bundle-{Guid.NewGuid():N}.tar.gz");
await File.WriteAllTextAsync(tempTar, "dummy");
var builder = new EvidenceBundleAttestationBuilder();
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() =>
builder.BuildAsync(new EvidenceBundleAttestationRequest(tempTar, tempManifest, null, "git:test"), CancellationToken.None));
Assert.Contains("Tenant must be lowercase", ex.Message);
}
}