using System; namespace StellaOps.Provenance; public static partial class ProvenanceExtensions { /// /// Attach DSSE provenance + trust info to an event document in-place. /// Designed for generic DocumentObject-based event envelopes. /// public static DocumentObject AttachDsseProvenance( this DocumentObject eventDoc, DsseProvenance dsse, TrustInfo trust) { if (eventDoc is null) throw new ArgumentNullException(nameof(eventDoc)); if (dsse is null) throw new ArgumentNullException(nameof(dsse)); if (trust is null) throw new ArgumentNullException(nameof(trust)); var dsseDoc = new DocumentObject { { "envelopeDigest", dsse.EnvelopeDigest }, { "payloadType", dsse.PayloadType }, { "key", new DocumentObject { { "keyId", dsse.Key.KeyId }, { "issuer", StringOrNull(dsse.Key.Issuer) }, { "algo", StringOrNull(dsse.Key.Algo) } } } }; if (dsse.Rekor is not null) { var rekorDoc = new DocumentObject { { "logIndex", dsse.Rekor.LogIndex }, { "uuid", dsse.Rekor.Uuid } }; if (dsse.Rekor.IntegratedTime is not null) rekorDoc.Add("integratedTime", dsse.Rekor.IntegratedTime); if (dsse.Rekor.MirrorSeq is not null) rekorDoc.Add("mirrorSeq", dsse.Rekor.MirrorSeq); dsseDoc.Add("rekor", rekorDoc); } if (dsse.Chain is not null && dsse.Chain.Count > 0) { var chainArray = new DocumentArray(); foreach (var link in dsse.Chain) { chainArray.Add(new DocumentObject { { "type", link.Type }, { "id", link.Id }, { "digest", link.Digest } }); } dsseDoc.Add(ChainFieldName, chainArray); } var trustDoc = new DocumentObject { { "verified", trust.Verified }, { "verifier", StringOrNull(trust.Verifier) } }; if (trust.Witnesses is not null) trustDoc.Add("witnesses", trust.Witnesses); if (trust.PolicyScore is not null) trustDoc.Add("policyScore", trust.PolicyScore); var provenanceDoc = new DocumentObject { { DsseFieldName, dsseDoc } }; eventDoc[ProvenanceFieldName] = provenanceDoc; eventDoc[TrustFieldName] = trustDoc; return eventDoc; } }