Files
git.stella-ops.org/src/Scanner/__Libraries/StellaOps.Scanner.Surface.FS/SurfaceManifestModels.cs
StellaOps Bot 885ce86af4
Some checks failed
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Mirror Thin Bundle Sign & Verify / mirror-sign (push) Has been cancelled
feat: Add VEX Lens CI and Load Testing Plan
- Introduced a comprehensive CI job structure for VEX Lens, including build, test, linting, and load testing.
- Defined load test parameters and SLOs for VEX Lens API and Issuer Directory.
- Created Grafana dashboards and alerting mechanisms for monitoring API performance and error rates.
- Established offline posture guidelines for CI jobs and load testing.

feat: Implement deterministic projection verification script

- Added `verify_projection.sh` script for verifying the integrity of projection exports against expected hashes.
- Ensured robust error handling for missing files and hash mismatches.

feat: Develop Vuln Explorer CI and Ops Plan

- Created CI jobs for Vuln Explorer, including build, test, and replay verification.
- Implemented backup and disaster recovery strategies for MongoDB and Redis.
- Established Merkle anchoring verification and automation for ledger projector.

feat: Introduce EventEnvelopeHasher for hashing event envelopes

- Implemented `EventEnvelopeHasher` to compute SHA256 hashes for event envelopes.

feat: Add Risk Store and Dashboard components

- Developed `RiskStore` for managing risk data and state.
- Created `RiskDashboardComponent` for displaying risk profiles with filtering capabilities.
- Implemented unit tests for `RiskStore` and `RiskDashboardComponent`.

feat: Enhance Vulnerability Detail Component

- Developed `VulnerabilityDetailComponent` for displaying detailed information about vulnerabilities.
- Implemented error handling for missing vulnerability IDs and loading failures.
2025-12-02 07:18:28 +02:00

193 lines
5.7 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;
[JsonPropertyName("attestations")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public IReadOnlyList<SurfaceManifestAttestation>? Attestations { get; init; }
= null;
}
public sealed record SurfaceManifestAttestation
{
[JsonPropertyName("kind")]
public string Kind { get; init; } = string.Empty;
[JsonPropertyName("mediaType")]
public string MediaType { get; init; } = string.Empty;
[JsonPropertyName("digest")]
public string Digest { get; init; } = string.Empty;
[JsonPropertyName("uri")]
public string Uri { get; init; } = string.Empty;
}
/// <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);