Add tests for SBOM generation determinism across multiple formats

- Created `StellaOps.TestKit.Tests` project for unit tests related to determinism.
- Implemented `DeterminismManifestTests` to validate deterministic output for canonical bytes and strings, file read/write operations, and error handling for invalid schema versions.
- Added `SbomDeterminismTests` to ensure identical inputs produce consistent SBOMs across SPDX 3.0.1 and CycloneDX 1.6/1.7 formats, including parallel execution tests.
- Updated project references in `StellaOps.Integration.Determinism` to include the new determinism testing library.
This commit is contained in:
master
2025-12-23 18:56:12 +02:00
committed by StellaOps Bot
parent 7ac70ece71
commit 491e883653
409 changed files with 23797 additions and 17779 deletions

View File

@@ -50,6 +50,14 @@ public static class VerdictEndpoints
.Produces<VerifyVerdictResponse>(StatusCodes.Status200OK)
.Produces(StatusCodes.Status404NotFound)
.Produces(StatusCodes.Status500InternalServerError);
// GET /api/v1/verdicts/{verdictId}/envelope - SPRINT_4000_0100_0001
group.MapGet("/{verdictId}/envelope", DownloadEnvelopeAsync)
.WithName("DownloadEnvelope")
.WithSummary("Download DSSE envelope for verdict")
.Produces(StatusCodes.Status200OK, contentType: "application/json")
.Produces(StatusCodes.Status404NotFound)
.Produces(StatusCodes.Status500InternalServerError);
}
private static async Task<IResult> StoreVerdictAsync(
@@ -294,4 +302,34 @@ public static class VerdictEndpoints
);
}
}
private static async Task<IResult> DownloadEnvelopeAsync(
string verdictId,
[FromServices] IVerdictRepository repository,
[FromServices] ILogger<Program> logger,
CancellationToken cancellationToken)
{
try
{
logger.LogInformation("Downloading envelope for verdict {VerdictId}", verdictId);
var record = await repository.GetVerdictAsync(verdictId, cancellationToken);
if (record is null)
{
return Results.NotFound(new { error = "Verdict not found", verdict_id = verdictId });
}
var envelopeBytes = System.Text.Encoding.UTF8.GetBytes(record.Envelope);
var fileName = $"verdict-{verdictId.Replace(':', '-')}-envelope.json";
return Results.File(envelopeBytes, contentType: "application/json", fileDownloadName: fileName);
}
catch (Exception ex)
{
logger.LogError(ex, "Error downloading envelope for verdict {VerdictId}", verdictId);
return Results.Problem(
title: "Internal server error",
detail: "Failed to download verdict envelope",
statusCode: StatusCodes.Status500InternalServerError
);
}
}
}