using System.Collections.Immutable; using Microsoft.Extensions.Logging.Abstractions; using StellaOps.Excititor.Attestation.Dsse; using StellaOps.Excititor.Attestation.Models; using StellaOps.Excititor.Attestation.Signing; using StellaOps.Excititor.Core; namespace StellaOps.Excititor.Attestation.Tests; public sealed class VexDsseBuilderTests { [Fact] public async Task CreateEnvelopeAsync_ProducesDeterministicPayload() { var signer = new FakeSigner("signature-value", "key-1"); var builder = new VexDsseBuilder(signer, NullLogger.Instance); var request = new VexAttestationRequest( ExportId: "exports/123", QuerySignature: new VexQuerySignature("filters"), Artifact: new VexContentAddress("sha256", "deadbeef"), Format: VexExportFormat.Json, CreatedAt: DateTimeOffset.UtcNow, SourceProviders: ImmutableArray.Create("vendor"), Metadata: ImmutableDictionary.Empty); var envelope = await builder.CreateEnvelopeAsync(request, request.Metadata, CancellationToken.None); Assert.Equal("application/vnd.in-toto+json", envelope.PayloadType); Assert.Single(envelope.Signatures); Assert.Equal("signature-value", envelope.Signatures[0].Signature); Assert.Equal("key-1", envelope.Signatures[0].KeyId); var digest = VexDsseBuilder.ComputeEnvelopeDigest(envelope); Assert.StartsWith("sha256:", digest); } private sealed class FakeSigner : IVexSigner { private readonly string _signature; private readonly string _keyId; public FakeSigner(string signature, string keyId) { _signature = signature; _keyId = keyId; } public ValueTask SignAsync(ReadOnlyMemory payload, CancellationToken cancellationToken) => ValueTask.FromResult(new VexSignedPayload(_signature, _keyId)); } }