Introduce Vexer platform scaffolding and enrich Concelier merge
This commit is contained in:
166
src/StellaOps.Vexer.Storage.Mongo/VexMongoModels.cs
Normal file
166
src/StellaOps.Vexer.Storage.Mongo/VexMongoModels.cs
Normal file
@@ -0,0 +1,166 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using StellaOps.Vexer.Core;
|
||||
|
||||
namespace StellaOps.Vexer.Storage.Mongo;
|
||||
|
||||
internal sealed class VexRawDocumentRecord
|
||||
{
|
||||
[BsonId]
|
||||
public string Id { get; set; } = default!;
|
||||
|
||||
public string ProviderId { get; set; } = default!;
|
||||
|
||||
public string Format { get; set; } = default!;
|
||||
|
||||
public string SourceUri { get; set; } = default!;
|
||||
|
||||
public DateTime RetrievedAt { get; set; }
|
||||
= DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc);
|
||||
|
||||
public string Digest { get; set; } = default!;
|
||||
|
||||
public byte[] Content { get; set; } = Array.Empty<byte>();
|
||||
|
||||
public Dictionary<string, string> Metadata { get; set; } = new(StringComparer.Ordinal);
|
||||
|
||||
public static VexRawDocumentRecord FromDomain(VexRawDocument document)
|
||||
=> new()
|
||||
{
|
||||
Id = document.Digest,
|
||||
ProviderId = document.ProviderId,
|
||||
Format = document.Format.ToString().ToLowerInvariant(),
|
||||
SourceUri = document.SourceUri.ToString(),
|
||||
RetrievedAt = document.RetrievedAt.UtcDateTime,
|
||||
Digest = document.Digest,
|
||||
Content = document.Content.ToArray(),
|
||||
Metadata = document.Metadata.ToDictionary(kvp => kvp.Key, kvp => kvp.Value, StringComparer.Ordinal),
|
||||
};
|
||||
|
||||
public VexRawDocument ToDomain()
|
||||
=> new(
|
||||
ProviderId,
|
||||
Enum.Parse<VexDocumentFormat>(Format, ignoreCase: true),
|
||||
new Uri(SourceUri),
|
||||
RetrievedAt,
|
||||
Digest,
|
||||
new ReadOnlyMemory<byte>(Content ?? Array.Empty<byte>()),
|
||||
(Metadata ?? new Dictionary<string, string>(StringComparer.Ordinal))
|
||||
.ToImmutableDictionary(StringComparer.Ordinal));
|
||||
}
|
||||
|
||||
internal sealed class VexExportManifestRecord
|
||||
{
|
||||
[BsonId]
|
||||
public string Id { get; set; } = default!;
|
||||
|
||||
public string QuerySignature { get; set; } = default!;
|
||||
|
||||
public string Format { get; set; } = default!;
|
||||
|
||||
public DateTime CreatedAt { get; set; }
|
||||
= DateTime.SpecifyKind(DateTime.UtcNow, DateTimeKind.Utc);
|
||||
|
||||
public string ArtifactAlgorithm { get; set; } = default!;
|
||||
|
||||
public string ArtifactDigest { get; set; } = default!;
|
||||
|
||||
public int ClaimCount { get; set; }
|
||||
= 0;
|
||||
|
||||
public bool FromCache { get; set; }
|
||||
= false;
|
||||
|
||||
public List<string> SourceProviders { get; set; } = new();
|
||||
|
||||
public string? ConsensusRevision { get; set; }
|
||||
= null;
|
||||
|
||||
public string? PredicateType { get; set; }
|
||||
= null;
|
||||
|
||||
public string? RekorApiVersion { get; set; }
|
||||
= null;
|
||||
|
||||
public string? RekorLocation { get; set; }
|
||||
= null;
|
||||
|
||||
public string? RekorLogIndex { get; set; }
|
||||
= null;
|
||||
|
||||
public string? RekorInclusionProofUri { get; set; }
|
||||
= null;
|
||||
|
||||
public string? EnvelopeDigest { get; set; }
|
||||
= null;
|
||||
|
||||
public DateTime? SignedAt { get; set; }
|
||||
= null;
|
||||
|
||||
public long SizeBytes { get; set; }
|
||||
= 0;
|
||||
|
||||
public static VexExportManifestRecord FromDomain(VexExportManifest manifest)
|
||||
=> new()
|
||||
{
|
||||
Id = CreateId(manifest.QuerySignature, manifest.Format),
|
||||
QuerySignature = manifest.QuerySignature.Value,
|
||||
Format = manifest.Format.ToString().ToLowerInvariant(),
|
||||
CreatedAt = manifest.CreatedAt.UtcDateTime,
|
||||
ArtifactAlgorithm = manifest.Artifact.Algorithm,
|
||||
ArtifactDigest = manifest.Artifact.Digest,
|
||||
ClaimCount = manifest.ClaimCount,
|
||||
FromCache = manifest.FromCache,
|
||||
SourceProviders = manifest.SourceProviders.ToList(),
|
||||
ConsensusRevision = manifest.ConsensusRevision,
|
||||
PredicateType = manifest.Attestation?.PredicateType,
|
||||
RekorApiVersion = manifest.Attestation?.Rekor?.ApiVersion,
|
||||
RekorLocation = manifest.Attestation?.Rekor?.Location,
|
||||
RekorLogIndex = manifest.Attestation?.Rekor?.LogIndex,
|
||||
RekorInclusionProofUri = manifest.Attestation?.Rekor?.InclusionProofUri?.ToString(),
|
||||
EnvelopeDigest = manifest.Attestation?.EnvelopeDigest,
|
||||
SignedAt = manifest.Attestation?.SignedAt?.UtcDateTime,
|
||||
SizeBytes = manifest.SizeBytes,
|
||||
};
|
||||
|
||||
public VexExportManifest ToDomain()
|
||||
{
|
||||
var signedAt = SignedAt.HasValue
|
||||
? new DateTimeOffset(DateTime.SpecifyKind(SignedAt.Value, DateTimeKind.Utc))
|
||||
: (DateTimeOffset?)null;
|
||||
|
||||
var attestation = PredicateType is null
|
||||
? null
|
||||
: new VexAttestationMetadata(
|
||||
PredicateType,
|
||||
RekorApiVersion is null || RekorLocation is null
|
||||
? null
|
||||
: new VexRekorReference(
|
||||
RekorApiVersion,
|
||||
RekorLocation,
|
||||
RekorLogIndex,
|
||||
RekorInclusionProofUri is null ? null : new Uri(RekorInclusionProofUri)),
|
||||
EnvelopeDigest,
|
||||
signedAt);
|
||||
|
||||
return new VexExportManifest(
|
||||
Id,
|
||||
new VexQuerySignature(QuerySignature),
|
||||
Enum.Parse<VexExportFormat>(Format, ignoreCase: true),
|
||||
CreatedAt,
|
||||
new VexContentAddress(ArtifactAlgorithm, ArtifactDigest),
|
||||
ClaimCount,
|
||||
SourceProviders,
|
||||
FromCache,
|
||||
ConsensusRevision,
|
||||
attestation,
|
||||
SizeBytes);
|
||||
}
|
||||
|
||||
public static string CreateId(VexQuerySignature signature, VexExportFormat format)
|
||||
=> string.Create(CultureInfo.InvariantCulture, $"{signature.Value}|{format.ToString().ToLowerInvariant()}");
|
||||
}
|
||||
Reference in New Issue
Block a user