using StellaOps.Evidence.Models; namespace StellaOps.Evidence.Services; /// /// Query helpers for evidence chains. /// public sealed class EvidenceQueryService : IEvidenceQueryService { public IEnumerable GetAttestationsForSbom( EvidenceIndex index, string sbomDigest) { var sbomExists = index.Sboms.Any(s => string.Equals(s.Digest, sbomDigest, StringComparison.Ordinal)); if (!sbomExists) { return Array.Empty(); } return index.Attestations .Where(a => string.Equals(a.Type, "sbom", StringComparison.Ordinal) && string.Equals(a.Digest, sbomDigest, StringComparison.Ordinal)); } public IEnumerable GetReachabilityForVulnerability( EvidenceIndex index, string vulnerabilityId) { return index.ReachabilityProofs .Where(r => r.VulnerabilityId == vulnerabilityId); } public IEnumerable GetVexForVulnerability( EvidenceIndex index, string vulnerabilityId) { return index.VexDocuments .Where(v => v.AffectedVulnerabilities.Contains(vulnerabilityId)); } public EvidenceChainReport BuildChainReport(EvidenceIndex index) { return new EvidenceChainReport { VerdictDigest = index.Verdict.Digest, SbomCount = index.Sboms.Length, AttestationCount = index.Attestations.Length, VexCount = index.VexDocuments.Length, ReachabilityProofCount = index.ReachabilityProofs.Length, UnknownCount = index.Unknowns.Length, AllSignaturesValid = index.Attestations.All(a => a.SignatureValid), HasRekorEntries = index.Attestations.Any(a => a.RekorLogIndex is not null), ToolChainComplete = index.ToolChain is not null }; } } public interface IEvidenceQueryService { IEnumerable GetAttestationsForSbom(EvidenceIndex index, string sbomDigest); IEnumerable GetReachabilityForVulnerability(EvidenceIndex index, string vulnerabilityId); IEnumerable GetVexForVulnerability(EvidenceIndex index, string vulnerabilityId); EvidenceChainReport BuildChainReport(EvidenceIndex index); } public sealed record EvidenceChainReport { public required string VerdictDigest { get; init; } public int SbomCount { get; init; } public int AttestationCount { get; init; } public int VexCount { get; init; } public int ReachabilityProofCount { get; init; } public int UnknownCount { get; init; } public bool AllSignaturesValid { get; init; } public bool HasRekorEntries { get; init; } public bool ToolChainComplete { get; init; } }