173 lines
5.1 KiB
C#
173 lines
5.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Immutable;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace StellaOps.Scanner.Surface.FS;
|
|
|
|
/// <summary>
|
|
/// Canonical manifest describing surface artefacts produced for a scan.
|
|
/// </summary>
|
|
public sealed record SurfaceManifestDocument
|
|
{
|
|
public const string DefaultSchema = "stellaops.surface.manifest@1";
|
|
|
|
[JsonPropertyName("schema")]
|
|
public string Schema { get; init; } = DefaultSchema;
|
|
|
|
[JsonPropertyName("tenant")]
|
|
public string Tenant { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("imageDigest")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? ImageDigest { get; init; }
|
|
= null;
|
|
|
|
[JsonPropertyName("scanId")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? ScanId { get; init; }
|
|
= null;
|
|
|
|
[JsonPropertyName("generatedAt")]
|
|
public DateTimeOffset GeneratedAt { get; init; }
|
|
= DateTimeOffset.MinValue;
|
|
|
|
[JsonPropertyName("source")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public SurfaceManifestSource? Source { get; init; }
|
|
= null;
|
|
|
|
[JsonPropertyName("artifacts")]
|
|
public IReadOnlyList<SurfaceManifestArtifact> Artifacts { get; init; }
|
|
= ImmutableArray<SurfaceManifestArtifact>.Empty;
|
|
|
|
[JsonPropertyName("determinismRoot")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? DeterminismMerkleRoot { get; init; }
|
|
= null;
|
|
|
|
[JsonPropertyName("replayBundle")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public ReplayBundleReference? ReplayBundle { get; init; }
|
|
= null;
|
|
}
|
|
|
|
public sealed record ReplayBundleReference
|
|
{
|
|
[JsonPropertyName("uri")]
|
|
public string Uri { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("sha256")]
|
|
public string Sha256 { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("policyPin")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? PolicySnapshotId { get; init; }
|
|
= null;
|
|
|
|
[JsonPropertyName("feedPin")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? FeedSnapshotId { get; init; }
|
|
= null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Identifies the producer of the manifest.
|
|
/// </summary>
|
|
public sealed record SurfaceManifestSource
|
|
{
|
|
[JsonPropertyName("component")]
|
|
public string Component { get; init; } = "scanner.worker";
|
|
|
|
[JsonPropertyName("version")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? Version { get; init; }
|
|
= null;
|
|
|
|
[JsonPropertyName("workerInstance")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? WorkerInstance { get; init; }
|
|
= null;
|
|
|
|
[JsonPropertyName("attempt")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public int? Attempt { get; init; }
|
|
= null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Describes a surface artefact referenced by the manifest.
|
|
/// </summary>
|
|
public sealed record SurfaceManifestArtifact
|
|
{
|
|
[JsonPropertyName("kind")]
|
|
public string Kind { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("uri")]
|
|
public string Uri { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("digest")]
|
|
public string Digest { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("mediaType")]
|
|
public string MediaType { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("format")]
|
|
public string Format { get; init; } = string.Empty;
|
|
|
|
[JsonPropertyName("sizeBytes")]
|
|
public long SizeBytes { get; init; }
|
|
= 0;
|
|
|
|
[JsonPropertyName("view")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? View { get; init; }
|
|
= null;
|
|
|
|
[JsonPropertyName("storage")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public SurfaceManifestStorage? Storage { get; init; }
|
|
= null;
|
|
|
|
[JsonPropertyName("metadata")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public IReadOnlyDictionary<string, string>? Metadata { get; init; }
|
|
= null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Storage descriptor for an artefact.
|
|
/// </summary>
|
|
public sealed record SurfaceManifestStorage
|
|
{
|
|
[JsonPropertyName("bucket")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? Bucket { get; init; }
|
|
= null;
|
|
|
|
[JsonPropertyName("objectKey")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? ObjectKey { get; init; }
|
|
= null;
|
|
|
|
[JsonPropertyName("sizeBytes")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public long? SizeBytes { get; init; }
|
|
= null;
|
|
|
|
[JsonPropertyName("contentType")]
|
|
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
|
|
public string? ContentType { get; init; }
|
|
= null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Result from publishing a surface manifest.
|
|
/// </summary>
|
|
public sealed record SurfaceManifestPublishResult(
|
|
string ManifestDigest,
|
|
string ManifestUri,
|
|
string ArtifactId,
|
|
SurfaceManifestDocument Document,
|
|
string? DeterminismMerkleRoot = null);
|