up
Some checks failed
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Some checks failed
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Manifest Integrity / Validate Schema Integrity (push) Has been cancelled
Manifest Integrity / Validate Contract Documents (push) Has been cancelled
Manifest Integrity / Validate Pack Fixtures (push) Has been cancelled
Manifest Integrity / Audit SHA256SUMS Files (push) Has been cancelled
Manifest Integrity / Verify Merkle Roots (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace StellaOps.Replay.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Builds deterministic replay manifests with CAS-registered graph/trace references.
|
||||
/// </summary>
|
||||
public static class ReachabilityReplayWriter
|
||||
{
|
||||
public static ReplayManifest BuildManifestV2(
|
||||
ReplayScanMetadata scan,
|
||||
IEnumerable<ReplayReachabilityGraphReference> graphs,
|
||||
IEnumerable<ReplayReachabilityTraceReference> traces,
|
||||
string? analysisId = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(scan);
|
||||
ArgumentNullException.ThrowIfNull(graphs);
|
||||
ArgumentNullException.ThrowIfNull(traces);
|
||||
|
||||
var graphList = graphs
|
||||
.Select(g => NormalizeGraph(g))
|
||||
.OrderBy(g => g.CasUri, StringComparer.Ordinal)
|
||||
.ThenBy(g => g.Sha256, StringComparer.Ordinal)
|
||||
.ToList();
|
||||
|
||||
if (graphList.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("At least one reachability graph reference is required.");
|
||||
}
|
||||
|
||||
var traceList = traces
|
||||
.Select(t => NormalizeTrace(t))
|
||||
.OrderBy(t => t.CasUri, StringComparer.Ordinal)
|
||||
.ThenBy(t => t.Sha256, StringComparer.Ordinal)
|
||||
.ToList();
|
||||
|
||||
var manifest = new ReplayManifest
|
||||
{
|
||||
SchemaVersion = ReplayManifestVersions.V2,
|
||||
Scan = scan,
|
||||
Reachability = new ReplayReachabilitySection
|
||||
{
|
||||
AnalysisId = analysisId,
|
||||
Graphs = graphList,
|
||||
RuntimeTraces = traceList
|
||||
}
|
||||
};
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
||||
private static ReplayReachabilityGraphReference NormalizeGraph(ReplayReachabilityGraphReference graph)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(graph.CasUri))
|
||||
{
|
||||
throw new InvalidOperationException("Graph casUri is required.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(graph.Sha256))
|
||||
{
|
||||
throw new InvalidOperationException("Graph sha256 is required.");
|
||||
}
|
||||
|
||||
graph.HashAlgorithm = string.IsNullOrWhiteSpace(graph.HashAlgorithm) ? "blake3-256" : graph.HashAlgorithm;
|
||||
graph.Kind = string.IsNullOrWhiteSpace(graph.Kind) ? "static" : graph.Kind;
|
||||
graph.Namespace = string.IsNullOrWhiteSpace(graph.Namespace) ? "reachability_graphs" : graph.Namespace;
|
||||
return graph;
|
||||
}
|
||||
|
||||
private static ReplayReachabilityTraceReference NormalizeTrace(ReplayReachabilityTraceReference trace)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(trace.CasUri))
|
||||
{
|
||||
throw new InvalidOperationException("Trace casUri is required.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(trace.Sha256))
|
||||
{
|
||||
throw new InvalidOperationException("Trace sha256 is required.");
|
||||
}
|
||||
|
||||
trace.HashAlgorithm = string.IsNullOrWhiteSpace(trace.HashAlgorithm) ? "sha256" : trace.HashAlgorithm;
|
||||
trace.Namespace = string.IsNullOrWhiteSpace(trace.Namespace) ? "runtime_traces" : trace.Namespace;
|
||||
trace.Source = string.IsNullOrWhiteSpace(trace.Source) ? "runtime" : trace.Source;
|
||||
return trace;
|
||||
}
|
||||
}
|
||||
@@ -60,6 +60,9 @@ public sealed class ReplayReachabilityGraphReference
|
||||
[JsonPropertyName("sha256")]
|
||||
public string Sha256 { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("hashAlg")]
|
||||
public string HashAlgorithm { get; set; } = "sha256";
|
||||
|
||||
[JsonPropertyName("namespace")]
|
||||
public string Namespace { get; set; } = "reachability_graphs";
|
||||
|
||||
@@ -84,6 +87,9 @@ public sealed class ReplayReachabilityTraceReference
|
||||
[JsonPropertyName("sha256")]
|
||||
public string Sha256 { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("hashAlg")]
|
||||
public string HashAlgorithm { get; set; } = "sha256";
|
||||
|
||||
[JsonPropertyName("namespace")]
|
||||
public string Namespace { get; set; } = "runtime_traces";
|
||||
|
||||
@@ -94,4 +100,5 @@ public sealed class ReplayReachabilityTraceReference
|
||||
public static class ReplayManifestVersions
|
||||
{
|
||||
public const string V1 = "1.0";
|
||||
public const string V2 = "2.0";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user