Implement InMemory Transport Layer for StellaOps Router
- Added InMemoryTransportOptions class for configuration settings including timeouts and latency. - Developed InMemoryTransportServer class to handle connections, frame processing, and event management. - Created ServiceCollectionExtensions for easy registration of InMemory transport services. - Established project structure and dependencies for InMemory transport library. - Implemented comprehensive unit tests for endpoint discovery, connection management, request/response flow, and streaming capabilities. - Ensured proper handling of cancellation, heartbeat, and hello frames within the transport layer.
This commit is contained in:
249
src/Cli/StellaOps.Cli/Services/Models/MirrorBundleModels.cs
Normal file
249
src/Cli/StellaOps.Cli/Services/Models/MirrorBundleModels.cs
Normal file
@@ -0,0 +1,249 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace StellaOps.Cli.Services.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Air-gap mirror bundle format for offline operation with DSSE signature support.
|
||||
/// Maps to docs/schemas/mirror-bundle.schema.json
|
||||
/// </summary>
|
||||
internal sealed record MirrorBundle
|
||||
{
|
||||
[JsonPropertyName("schemaVersion")]
|
||||
public int SchemaVersion { get; init; } = 1;
|
||||
|
||||
[JsonPropertyName("generatedAt")]
|
||||
public DateTimeOffset GeneratedAt { get; init; }
|
||||
|
||||
[JsonPropertyName("targetRepository")]
|
||||
public string? TargetRepository { get; init; }
|
||||
|
||||
[JsonPropertyName("domainId")]
|
||||
public required string DomainId { get; init; }
|
||||
|
||||
[JsonPropertyName("displayName")]
|
||||
public string? DisplayName { get; init; }
|
||||
|
||||
[JsonPropertyName("exports")]
|
||||
public required IReadOnlyList<MirrorBundleExport> Exports { get; init; }
|
||||
}
|
||||
|
||||
internal sealed record MirrorBundleExport
|
||||
{
|
||||
[JsonPropertyName("key")]
|
||||
public required string Key { get; init; }
|
||||
|
||||
[JsonPropertyName("format")]
|
||||
public required string Format { get; init; }
|
||||
|
||||
[JsonPropertyName("exportId")]
|
||||
public required string ExportId { get; init; }
|
||||
|
||||
[JsonPropertyName("querySignature")]
|
||||
public string? QuerySignature { get; init; }
|
||||
|
||||
[JsonPropertyName("createdAt")]
|
||||
public required DateTimeOffset CreatedAt { get; init; }
|
||||
|
||||
[JsonPropertyName("artifactSizeBytes")]
|
||||
public long? ArtifactSizeBytes { get; init; }
|
||||
|
||||
[JsonPropertyName("artifactDigest")]
|
||||
public required string ArtifactDigest { get; init; }
|
||||
|
||||
[JsonPropertyName("consensusRevision")]
|
||||
public string? ConsensusRevision { get; init; }
|
||||
|
||||
[JsonPropertyName("policyRevisionId")]
|
||||
public string? PolicyRevisionId { get; init; }
|
||||
|
||||
[JsonPropertyName("policyDigest")]
|
||||
public string? PolicyDigest { get; init; }
|
||||
|
||||
[JsonPropertyName("consensusDigest")]
|
||||
public string? ConsensusDigest { get; init; }
|
||||
|
||||
[JsonPropertyName("scoreDigest")]
|
||||
public string? ScoreDigest { get; init; }
|
||||
|
||||
[JsonPropertyName("sourceProviders")]
|
||||
public IReadOnlyList<string>? SourceProviders { get; init; }
|
||||
|
||||
[JsonPropertyName("attestation")]
|
||||
public MirrorAttestationDescriptor? Attestation { get; init; }
|
||||
}
|
||||
|
||||
internal sealed record MirrorAttestationDescriptor
|
||||
{
|
||||
[JsonPropertyName("predicateType")]
|
||||
public required string PredicateType { get; init; }
|
||||
|
||||
[JsonPropertyName("rekorLocation")]
|
||||
public string? RekorLocation { get; init; }
|
||||
|
||||
[JsonPropertyName("envelopeDigest")]
|
||||
public string? EnvelopeDigest { get; init; }
|
||||
|
||||
[JsonPropertyName("signedAt")]
|
||||
public DateTimeOffset? SignedAt { get; init; }
|
||||
}
|
||||
|
||||
internal sealed record MirrorBundleSignature
|
||||
{
|
||||
[JsonPropertyName("path")]
|
||||
public string? Path { get; init; }
|
||||
|
||||
[JsonPropertyName("algorithm")]
|
||||
public required string Algorithm { get; init; }
|
||||
|
||||
[JsonPropertyName("keyId")]
|
||||
public required string KeyId { get; init; }
|
||||
|
||||
[JsonPropertyName("provider")]
|
||||
public string? Provider { get; init; }
|
||||
|
||||
[JsonPropertyName("signedAt")]
|
||||
public required DateTimeOffset SignedAt { get; init; }
|
||||
}
|
||||
|
||||
internal sealed record MirrorBundleManifest
|
||||
{
|
||||
[JsonPropertyName("schemaVersion")]
|
||||
public int SchemaVersion { get; init; } = 1;
|
||||
|
||||
[JsonPropertyName("generatedAt")]
|
||||
public DateTimeOffset GeneratedAt { get; init; }
|
||||
|
||||
[JsonPropertyName("domainId")]
|
||||
public required string DomainId { get; init; }
|
||||
|
||||
[JsonPropertyName("displayName")]
|
||||
public string? DisplayName { get; init; }
|
||||
|
||||
[JsonPropertyName("targetRepository")]
|
||||
public string? TargetRepository { get; init; }
|
||||
|
||||
[JsonPropertyName("bundle")]
|
||||
public required MirrorFileDescriptor Bundle { get; init; }
|
||||
|
||||
[JsonPropertyName("exports")]
|
||||
public IReadOnlyList<MirrorBundleExport>? Exports { get; init; }
|
||||
}
|
||||
|
||||
internal sealed record MirrorFileDescriptor
|
||||
{
|
||||
[JsonPropertyName("path")]
|
||||
public required string Path { get; init; }
|
||||
|
||||
[JsonPropertyName("sizeBytes")]
|
||||
public required long SizeBytes { get; init; }
|
||||
|
||||
[JsonPropertyName("digest")]
|
||||
public required string Digest { get; init; }
|
||||
|
||||
[JsonPropertyName("signature")]
|
||||
public MirrorBundleSignature? Signature { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request model for creating a mirror bundle.
|
||||
/// </summary>
|
||||
internal sealed record MirrorCreateRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Domain identifier (e.g., "vex-advisories", "vulnerability-feeds", "policy-packs").
|
||||
/// </summary>
|
||||
public required string DomainId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Human-readable display name for the bundle.
|
||||
/// </summary>
|
||||
public string? DisplayName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Target OCI repository for this bundle.
|
||||
/// </summary>
|
||||
public string? TargetRepository { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Export format filter (e.g., "openvex", "csaf", "cyclonedx").
|
||||
/// </summary>
|
||||
public string? Format { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Provider filter for VEX exports.
|
||||
/// </summary>
|
||||
public IReadOnlyList<string>? Providers { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Output directory for the bundle files.
|
||||
/// </summary>
|
||||
public required string OutputDirectory { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to include DSSE signatures.
|
||||
/// </summary>
|
||||
public bool IncludeSignatures { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether to include attestation metadata.
|
||||
/// </summary>
|
||||
public bool IncludeAttestations { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Tenant scope for the exports.
|
||||
/// </summary>
|
||||
public string? Tenant { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Result model for mirror bundle creation.
|
||||
/// </summary>
|
||||
internal sealed record MirrorCreateResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Path to the created bundle manifest.
|
||||
/// </summary>
|
||||
public required string ManifestPath { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Path to the bundle archive (if created).
|
||||
/// </summary>
|
||||
public string? BundlePath { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Path to the bundle signature (if created).
|
||||
/// </summary>
|
||||
public string? SignaturePath { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Number of exports included in the bundle.
|
||||
/// </summary>
|
||||
public int ExportCount { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Total size in bytes of all exported artifacts.
|
||||
/// </summary>
|
||||
public long TotalSizeBytes { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Bundle digest for verification.
|
||||
/// </summary>
|
||||
public string? BundleDigest { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Timestamp when the bundle was generated.
|
||||
/// </summary>
|
||||
public DateTimeOffset GeneratedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Domain ID of the bundle.
|
||||
/// </summary>
|
||||
public required string DomainId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Export details for verbose output.
|
||||
/// </summary>
|
||||
public IReadOnlyList<MirrorBundleExport>? Exports { get; init; }
|
||||
}
|
||||
Reference in New Issue
Block a user