doctor enhancements, setup, enhancements, ui functionality and design consolidation and , test projects fixes , product advisory attestation/rekor and delta verfications enhancements
This commit is contained in:
@@ -0,0 +1,234 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
// BundleFormatV2.cs
|
||||
// Sprint: SPRINT_20260118_018_AirGap_router_integration
|
||||
// Task: TASK-018-001 - Complete Air-Gap Bundle Format
|
||||
// Description: Air-gap bundle format v2.0.0 matching advisory specification
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Immutable;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.AirGap.Bundle.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Air-gap bundle manifest v2.0.0 per advisory specification.
|
||||
/// </summary>
|
||||
public sealed record BundleManifestV2
|
||||
{
|
||||
/// <summary>Schema version.</summary>
|
||||
[JsonPropertyName("schemaVersion")]
|
||||
public string SchemaVersion { get; init; } = "2.0.0";
|
||||
|
||||
/// <summary>Bundle information.</summary>
|
||||
[JsonPropertyName("bundle")]
|
||||
public required BundleInfoV2 Bundle { get; init; }
|
||||
|
||||
/// <summary>Verification configuration.</summary>
|
||||
[JsonPropertyName("verify")]
|
||||
public BundleVerifySection? Verify { get; init; }
|
||||
|
||||
/// <summary>Bundle metadata.</summary>
|
||||
[JsonPropertyName("metadata")]
|
||||
public BundleMetadata? Metadata { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bundle information.
|
||||
/// </summary>
|
||||
public sealed record BundleInfoV2
|
||||
{
|
||||
/// <summary>Primary image reference.</summary>
|
||||
[JsonPropertyName("image")]
|
||||
public required string Image { get; init; }
|
||||
|
||||
/// <summary>Image digest.</summary>
|
||||
[JsonPropertyName("digest")]
|
||||
public string? Digest { get; init; }
|
||||
|
||||
/// <summary>Bundle artifacts.</summary>
|
||||
[JsonPropertyName("artifacts")]
|
||||
public required ImmutableArray<BundleArtifact> Artifacts { get; init; }
|
||||
|
||||
/// <summary>OCI referrer manifest.</summary>
|
||||
[JsonPropertyName("referrers")]
|
||||
public OciReferrerIndex? Referrers { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bundle artifact entry.
|
||||
/// </summary>
|
||||
public sealed record BundleArtifact
|
||||
{
|
||||
/// <summary>Path within bundle.</summary>
|
||||
[JsonPropertyName("path")]
|
||||
public required string Path { get; init; }
|
||||
|
||||
/// <summary>Artifact type.</summary>
|
||||
[JsonPropertyName("type")]
|
||||
public BundleArtifactType Type { get; init; }
|
||||
|
||||
/// <summary>Content digest (sha256).</summary>
|
||||
[JsonPropertyName("digest")]
|
||||
public string? Digest { get; init; }
|
||||
|
||||
/// <summary>Media type.</summary>
|
||||
[JsonPropertyName("mediaType")]
|
||||
public string? MediaType { get; init; }
|
||||
|
||||
/// <summary>Size in bytes.</summary>
|
||||
[JsonPropertyName("size")]
|
||||
public long Size { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bundle artifact type.
|
||||
/// </summary>
|
||||
[JsonConverter(typeof(JsonStringEnumConverter))]
|
||||
public enum BundleArtifactType
|
||||
{
|
||||
/// <summary>SBOM document.</summary>
|
||||
[JsonPropertyName("sbom")]
|
||||
Sbom,
|
||||
|
||||
/// <summary>DSSE-signed SBOM statement.</summary>
|
||||
[JsonPropertyName("sbom.dsse")]
|
||||
SbomDsse,
|
||||
|
||||
/// <summary>VEX document.</summary>
|
||||
[JsonPropertyName("vex")]
|
||||
Vex,
|
||||
|
||||
/// <summary>DSSE-signed VEX statement.</summary>
|
||||
[JsonPropertyName("vex.dsse")]
|
||||
VexDsse,
|
||||
|
||||
/// <summary>Rekor inclusion proof.</summary>
|
||||
[JsonPropertyName("rekor.proof")]
|
||||
RekorProof,
|
||||
|
||||
/// <summary>OCI referrers index.</summary>
|
||||
[JsonPropertyName("oci.referrers")]
|
||||
OciReferrers,
|
||||
|
||||
/// <summary>Policy snapshot.</summary>
|
||||
[JsonPropertyName("policy")]
|
||||
Policy,
|
||||
|
||||
/// <summary>Feed snapshot.</summary>
|
||||
[JsonPropertyName("feed")]
|
||||
Feed,
|
||||
|
||||
/// <summary>Rekor checkpoint.</summary>
|
||||
[JsonPropertyName("rekor.checkpoint")]
|
||||
RekorCheckpoint,
|
||||
|
||||
/// <summary>Other/generic artifact.</summary>
|
||||
[JsonPropertyName("other")]
|
||||
Other
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bundle verification section.
|
||||
/// </summary>
|
||||
public sealed record BundleVerifySection
|
||||
{
|
||||
/// <summary>Trusted signing keys.</summary>
|
||||
[JsonPropertyName("keys")]
|
||||
public ImmutableArray<string> Keys { get; init; } = [];
|
||||
|
||||
/// <summary>Verification expectations.</summary>
|
||||
[JsonPropertyName("expectations")]
|
||||
public VerifyExpectations? Expectations { get; init; }
|
||||
|
||||
/// <summary>Certificate roots for verification.</summary>
|
||||
[JsonPropertyName("certificateRoots")]
|
||||
public ImmutableArray<string> CertificateRoots { get; init; } = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verification expectations.
|
||||
/// </summary>
|
||||
public sealed record VerifyExpectations
|
||||
{
|
||||
/// <summary>Expected payload types.</summary>
|
||||
[JsonPropertyName("payloadTypes")]
|
||||
public ImmutableArray<string> PayloadTypes { get; init; } = [];
|
||||
|
||||
/// <summary>Whether Rekor inclusion is required.</summary>
|
||||
[JsonPropertyName("rekorRequired")]
|
||||
public bool RekorRequired { get; init; }
|
||||
|
||||
/// <summary>Expected issuers.</summary>
|
||||
[JsonPropertyName("issuers")]
|
||||
public ImmutableArray<string> Issuers { get; init; } = [];
|
||||
|
||||
/// <summary>Minimum signature count.</summary>
|
||||
[JsonPropertyName("minSignatures")]
|
||||
public int MinSignatures { get; init; } = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OCI referrer index.
|
||||
/// </summary>
|
||||
public sealed record OciReferrerIndex
|
||||
{
|
||||
/// <summary>Referrer descriptors.</summary>
|
||||
[JsonPropertyName("manifests")]
|
||||
public ImmutableArray<OciReferrerDescriptor> Manifests { get; init; } = [];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OCI referrer descriptor.
|
||||
/// </summary>
|
||||
public sealed record OciReferrerDescriptor
|
||||
{
|
||||
/// <summary>Media type.</summary>
|
||||
[JsonPropertyName("mediaType")]
|
||||
public required string MediaType { get; init; }
|
||||
|
||||
/// <summary>Digest.</summary>
|
||||
[JsonPropertyName("digest")]
|
||||
public required string Digest { get; init; }
|
||||
|
||||
/// <summary>Artifact type.</summary>
|
||||
[JsonPropertyName("artifactType")]
|
||||
public string? ArtifactType { get; init; }
|
||||
|
||||
/// <summary>Size.</summary>
|
||||
[JsonPropertyName("size")]
|
||||
public long Size { get; init; }
|
||||
|
||||
/// <summary>Annotations.</summary>
|
||||
[JsonPropertyName("annotations")]
|
||||
public IReadOnlyDictionary<string, string>? Annotations { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bundle metadata.
|
||||
/// </summary>
|
||||
public sealed record BundleMetadata
|
||||
{
|
||||
/// <summary>When bundle was created.</summary>
|
||||
[JsonPropertyName("createdAt")]
|
||||
public DateTimeOffset CreatedAt { get; init; }
|
||||
|
||||
/// <summary>Bundle creator.</summary>
|
||||
[JsonPropertyName("createdBy")]
|
||||
public string? CreatedBy { get; init; }
|
||||
|
||||
/// <summary>Bundle description.</summary>
|
||||
[JsonPropertyName("description")]
|
||||
public string? Description { get; init; }
|
||||
|
||||
/// <summary>Source environment.</summary>
|
||||
[JsonPropertyName("sourceEnvironment")]
|
||||
public string? SourceEnvironment { get; init; }
|
||||
|
||||
/// <summary>Target environment.</summary>
|
||||
[JsonPropertyName("targetEnvironment")]
|
||||
public string? TargetEnvironment { get; init; }
|
||||
|
||||
/// <summary>Additional labels.</summary>
|
||||
[JsonPropertyName("labels")]
|
||||
public IReadOnlyDictionary<string, string>? Labels { get; init; }
|
||||
}
|
||||
@@ -5,11 +5,12 @@ namespace StellaOps.AirGap.Bundle.Models;
|
||||
/// <summary>
|
||||
/// Manifest for an offline bundle, inventorying all components with content digests.
|
||||
/// Used for integrity verification and completeness checking in air-gapped environments.
|
||||
/// Sprint: SPRINT_20260118_018 (TASK-018-001) - Updated to v2.0.0
|
||||
/// </summary>
|
||||
public sealed record BundleManifest
|
||||
{
|
||||
public required string BundleId { get; init; }
|
||||
public string SchemaVersion { get; init; } = "1.0.0";
|
||||
public string SchemaVersion { get; init; } = "2.0.0";
|
||||
public required string Name { get; init; }
|
||||
public required string Version { get; init; }
|
||||
public required DateTimeOffset CreatedAt { get; init; }
|
||||
@@ -23,6 +24,103 @@ public sealed record BundleManifest
|
||||
public ImmutableArray<RuleBundleComponent> RuleBundles { get; init; } = [];
|
||||
public long TotalSizeBytes { get; init; }
|
||||
public string? BundleDigest { get; init; }
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// v2.0.0 Additions - Sprint: SPRINT_20260118_018 (TASK-018-001)
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// Image reference this bundle is for (advisory-specified format).
|
||||
/// Example: "registry.example.com/app@sha256:..."
|
||||
/// </summary>
|
||||
public string? Image { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// List of artifacts in the bundle with path and type information.
|
||||
/// </summary>
|
||||
public ImmutableArray<BundleArtifact> Artifacts { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Verification section with keys and expectations.
|
||||
/// </summary>
|
||||
public BundleVerifySection? Verify { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Artifact entry in a bundle (v2.0.0).
|
||||
/// Sprint: SPRINT_20260118_018 (TASK-018-001)
|
||||
/// </summary>
|
||||
public sealed record BundleArtifact(
|
||||
/// <summary>Relative path within the bundle.</summary>
|
||||
string Path,
|
||||
/// <summary>Artifact type: sbom, vex, dsse, rekor-proof, oci-referrers, etc.</summary>
|
||||
string Type,
|
||||
/// <summary>Content type (MIME).</summary>
|
||||
string? ContentType,
|
||||
/// <summary>SHA-256 digest of the artifact.</summary>
|
||||
string? Digest,
|
||||
/// <summary>Size in bytes.</summary>
|
||||
long? SizeBytes);
|
||||
|
||||
/// <summary>
|
||||
/// Verification section for bundle validation (v2.0.0).
|
||||
/// Sprint: SPRINT_20260118_018 (TASK-018-001)
|
||||
/// </summary>
|
||||
public sealed record BundleVerifySection
|
||||
{
|
||||
/// <summary>
|
||||
/// Trusted signing keys for verification.
|
||||
/// Formats: kms://..., file://..., sigstore://...
|
||||
/// </summary>
|
||||
public ImmutableArray<string> Keys { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Verification expectations.
|
||||
/// </summary>
|
||||
public BundleVerifyExpectations? Expectations { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional: path to trust root certificate.
|
||||
/// </summary>
|
||||
public string? TrustRoot { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Optional: Rekor checkpoint for offline proof verification.
|
||||
/// </summary>
|
||||
public string? RekorCheckpointPath { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verification expectations (v2.0.0).
|
||||
/// Sprint: SPRINT_20260118_018 (TASK-018-001)
|
||||
/// </summary>
|
||||
public sealed record BundleVerifyExpectations
|
||||
{
|
||||
/// <summary>
|
||||
/// Expected payload types in DSSE envelopes.
|
||||
/// Example: ["application/vnd.cyclonedx+json;version=1.6", "application/vnd.openvex+json"]
|
||||
/// </summary>
|
||||
public ImmutableArray<string> PayloadTypes { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Whether Rekor proof is required for verification.
|
||||
/// </summary>
|
||||
public bool RekorRequired { get; init; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Minimum number of signatures required.
|
||||
/// </summary>
|
||||
public int MinSignatures { get; init; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Required artifact types that must be present.
|
||||
/// </summary>
|
||||
public ImmutableArray<string> RequiredArtifacts { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Whether all artifacts must pass checksum verification.
|
||||
/// </summary>
|
||||
public bool VerifyChecksums { get; init; } = true;
|
||||
}
|
||||
|
||||
public sealed record FeedComponent(
|
||||
|
||||
Reference in New Issue
Block a user