Skip to content

Commit 7ec8715

Browse files
committed
Add commercial evidence filesystem manifest execution
1 parent e2c8b53 commit 7ec8715

7 files changed

Lines changed: 200 additions & 8 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ The first production milestone is M3UA over a transport abstraction. SCCP, TCAP,
7575
| Commercial evidence execution orchestration | Phase 37 foundation-complete: evidence execution run identity, stage catalog, operator command plan, execution environment contract, artifact collection manifest, digest/redaction verification, blocker classification, retry/resume policy, status reporting, and final validation are available; real retained execution artifacts are still required before commercial publication |
7676
| Commercial evidence artifact intake | Phase 38 foundation-complete: artifact intake target identity, artifact source registration, SHA-256 digest coverage, redaction review, completeness evaluation, dossier reporting, promotion handoff, execution-to-dossier bridge, status reporting, and final validation are available, binding a stable intake id, reviewer identity, UTC receipt time, run-scoped dossier root, concrete source paths, unique retained dossier paths, retained digests, trace-bearing artifact approvals, explicit intake blockers, retained Markdown summary, digest-covered handoff, end-to-end intake assembly, and intake readiness status to a governed execution run; real artifact files are still required before commercial publication |
7777
| Commercial evidence file verification | Phase 39 foundation-complete: retained file evidence item verification, retained file manifest coverage, file verification blocker reporting, retention ledger modeling, integrity sealing, publication attachment planning, verified promotion gating, command planning, status reporting, final validation, and documentation alignment are available, checking file existence, non-empty size, SHA-256 validity, digest match, UTC observation time, unique retained paths, promotion-required handoff coverage, explicit verification blockers, reviewer identity, immutable retention, UTC retention windows, minimum duration, deterministic aggregate ledger digests, sealed ledger attachment coverage, trace-bearing redaction approval, commercial readiness report presence, explicit promotion approval, workflow-ready verification command order, and readiness status separation; real retained file evidence remains required before commercial publication |
78-
| Commercial evidence filesystem execution | Phase 40 in progress: filesystem observation is available, reading retained files from disk, computing real SHA-256 digests, reporting file existence and size, and mapping observations into the retained file verification model; manifest execution, report execution, artifact writing, ledger execution, seal execution, attachment execution, promotion execution, command materialization, status reporting, and final validation remain |
78+
| Commercial evidence filesystem execution | Phase 40 in progress: filesystem observation and manifest execution are available, reading retained files from disk, computing real SHA-256 digests, reporting file existence and size, supporting retained-path-to-local-path overrides, and building retained file manifests from real observations; report execution, artifact writing, ledger execution, seal execution, attachment execution, promotion execution, command materialization, status reporting, and final validation remain |
7979

8080
## Requirements
8181

docs/PHASE40_COMMERCIAL_EVIDENCE_FILESYSTEM_EXECUTION.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ Public APIs use domain names such as `SigtranCommercialEvidenceFileSystemObserve
1616

1717
The observer is the first executable bridge from retained dossier paths to real file verification.
1818

19+
## Unit 2 - Filesystem Manifest Execution
20+
21+
`SigtranCommercialEvidenceFileSystemManifestBuilder` observes every promotion handoff item and creates a retained file manifest from real filesystem observations:
22+
23+
- Observes every handoff item.
24+
- Supports local filesystem path overrides keyed by retained dossier path.
25+
- Preserves retained path identity while reading from mounted or copied local files.
26+
- Builds `SigtranCommercialEvidenceRetainedFileManifest` from observed files.
27+
- Reports whether all handoff items were covered, all files existed, and all digests matched.
28+
29+
This unit lets the verification pipeline evaluate a complete retained handoff using real files rather than synthetic in-memory retained file entries.
30+
1931
## Validation
2032

2133
Each unit in this phase is validated with:

docs/PHASE40_SUMMARY.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ Phase 40 prepares the SDK to run commercial evidence file verification against r
55
## Completed Capabilities
66

77
- Filesystem observer that computes SHA-256 digests from existing retained files and maps missing files into explicit non-verified retained file observations.
8+
- Filesystem manifest builder that observes every promotion handoff item, supports retained-path-to-local-path overrides, and builds a retained file manifest from real observations.
89

910
## Readiness Position
1011

11-
The phase is in progress. Filesystem observation is available. Manifest execution, report execution, artifact writing, ledger execution, seal execution, attachment execution, promotion execution, command materialization, status reporting, and final validation remain.
12+
The phase is in progress. Filesystem observation and manifest execution are available. Report execution, artifact writing, ledger execution, seal execution, attachment execution, promotion execution, command materialization, status reporting, and final validation remain.

docs/PHASE_INDEX.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ This index is the complete phase map for Sigtran.NET. It links each phase to the
4444
| 37 | Commercial evidence execution orchestration | [Phase 37 Commercial Evidence Execution Orchestration](PHASE37_COMMERCIAL_EVIDENCE_EXECUTION_ORCHESTRATION.md), [Phase 37 Summary](PHASE37_SUMMARY.md) | Foundation complete; real execution artifacts still required |
4545
| 38 | Commercial evidence artifact intake | [Phase 38 Commercial Evidence Artifact Intake](PHASE38_COMMERCIAL_EVIDENCE_ARTIFACT_INTAKE.md), [Phase 38 Summary](PHASE38_SUMMARY.md) | Foundation complete; real artifact files still required |
4646
| 39 | Commercial evidence file verification | [Phase 39 Commercial Evidence File Verification](PHASE39_COMMERCIAL_EVIDENCE_FILE_VERIFICATION.md), [Phase 39 Summary](PHASE39_SUMMARY.md) | Foundation complete; real retained file evidence required |
47-
| 40 | Commercial evidence filesystem execution | [Phase 40 Commercial Evidence Filesystem Execution](PHASE40_COMMERCIAL_EVIDENCE_FILESYSTEM_EXECUTION.md), [Phase 40 Summary](PHASE40_SUMMARY.md) | In progress; filesystem observation complete |
47+
| 40 | Commercial evidence filesystem execution | [Phase 40 Commercial Evidence Filesystem Execution](PHASE40_COMMERCIAL_EVIDENCE_FILESYSTEM_EXECUTION.md), [Phase 40 Summary](PHASE40_SUMMARY.md) | In progress; filesystem manifest execution complete |
4848

4949
## Current Commercial Gate
5050

docs/SDK_ROADMAP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ Status: Phase 39 is foundation-complete. Retained file evidence item verificatio
355355
- Build verification manifests, reports, retained artifacts, ledger, seal, attachments, promotion gate, and command materialization from observed files.
356356
- Keep filesystem execution separate from commercial publication: helpers can verify real files, but publication remains blocked until retained evidence comes from an approved commercial run.
357357

358-
Status: Phase 40 is in progress. Filesystem observation now reads retained files from disk, computes real SHA-256 digests, records file existence and size, and maps observations into the retained file verification model. Manifest execution, report execution, retained artifact writing, ledger execution, seal execution, attachment execution, promotion execution, command materialization, status reporting, and final validation remain in progress.
358+
Status: Phase 40 is in progress. Filesystem observation now reads retained files from disk, computes real SHA-256 digests, records file existence and size, and maps observations into the retained file verification model. Filesystem manifest execution now observes every promotion handoff item, supports retained-path-to-local-path overrides, and builds retained file manifests from real observations. Report execution, retained artifact writing, ledger execution, seal execution, attachment execution, promotion execution, command materialization, status reporting, and final validation remain in progress.
359359

360360
## Recommended First Deliverable
361361

src/Sigtran.NET.Tests/Program.cs

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,7 @@
306306
Run("SIGTRAN commercial evidence file verification command plan orders execution", SigtranCommercialEvidenceFileVerificationCommandPlanOrdersExecution);
307307
Run("SIGTRAN commercial evidence file verification status summarizes readiness", SigtranCommercialEvidenceFileVerificationStatusSummarizesReadiness);
308308
Run("SIGTRAN commercial evidence filesystem observer computes retained file digest", SigtranCommercialEvidenceFileSystemObserverComputesRetainedFileDigest);
309+
Run("SIGTRAN commercial evidence filesystem manifest builder observes handoff files", SigtranCommercialEvidenceFileSystemManifestBuilderObservesHandoffFiles);
309310
Run("SIGTRAN status capabilities use domain documentation labels", SigtranStatusCapabilitiesUseDomainDocumentationLabels);
310311
Run("Native SCTP platform probe reports socket creation capability", NativeSctpPlatformProbeReportsSocketCreationCapability);
311312
Run("Native SCTP socket factory creates or reports unsupported platform", NativeSctpSocketFactoryCreatesOrReportsUnsupportedPlatform);
@@ -5196,10 +5197,92 @@ static void SigtranCommercialEvidenceFileSystemObserverComputesRetainedFileDiges
51965197
}
51975198
finally
51985199
{
5199-
if (tempRoot.StartsWith(Path.GetTempPath(), StringComparison.OrdinalIgnoreCase) && Directory.Exists(tempRoot))
5200-
{
5201-
Directory.Delete(tempRoot, recursive: true);
5202-
}
5200+
DeleteTempEvidenceRoot(tempRoot);
5201+
}
5202+
}
5203+
5204+
static void SigtranCommercialEvidenceFileSystemManifestBuilderObservesHandoffFiles()
5205+
{
5206+
string tempRoot = Path.Combine(Path.GetTempPath(), "sigtran-commercial-evidence-" + Guid.NewGuid().ToString("N"));
5207+
Directory.CreateDirectory(tempRoot);
5208+
5209+
try
5210+
{
5211+
byte[] artifactContent = "verified commercial artifact"u8.ToArray();
5212+
byte[] reportContent = "verified commercial readiness report"u8.ToArray();
5213+
SigtranCommercialEvidencePromotionHandoff handoff = CreateCommercialEvidencePromotionHandoffWithDigests(
5214+
ComputeSha256Hex(artifactContent),
5215+
ComputeSha256Hex(reportContent));
5216+
IReadOnlyDictionary<string, string> pathOverrides = MaterializeHandoffFiles(tempRoot, handoff, artifactContent, reportContent);
5217+
5218+
SigtranCommercialEvidenceFileSystemManifestExecution execution = SigtranCommercialEvidenceFileSystemManifestBuilder.Build(
5219+
handoff,
5220+
pathOverrides,
5221+
DateTimeOffset.UtcNow);
5222+
5223+
Assert(execution.IsReady, execution.Describe());
5224+
AssertEqual(handoff.Items.Count, execution.Observations.Count, "filesystem manifest observation count");
5225+
Assert(execution.CoversHandoffItems, "filesystem manifest should cover handoff items");
5226+
Assert(execution.AllObservedFilesExist, "filesystem manifest should observe existing files");
5227+
Assert(execution.AllObservedDigestsMatch, "filesystem manifest should match handoff digests");
5228+
Assert(execution.Manifest.IsReady, "filesystem retained manifest should be ready");
5229+
}
5230+
finally
5231+
{
5232+
DeleteTempEvidenceRoot(tempRoot);
5233+
}
5234+
}
5235+
5236+
static IReadOnlyDictionary<string, string> MaterializeHandoffFiles(
5237+
string tempRoot,
5238+
SigtranCommercialEvidencePromotionHandoff handoff,
5239+
byte[] artifactContent,
5240+
byte[] reportContent)
5241+
{
5242+
Dictionary<string, string> paths = new(StringComparer.OrdinalIgnoreCase);
5243+
5244+
for (int i = 0; i < handoff.Items.Count; i++)
5245+
{
5246+
SigtranCommercialEvidencePromotionHandoffItem item = handoff.Items[i];
5247+
string path = Path.Combine(tempRoot, $"retained-{i:D2}.bin");
5248+
File.WriteAllBytes(path, item.RetainedPath == handoff.Report.ReportPath ? reportContent : artifactContent);
5249+
paths[item.RetainedPath] = path;
5250+
}
5251+
5252+
return paths;
5253+
}
5254+
5255+
static SigtranCommercialEvidencePromotionHandoff CreateCommercialEvidencePromotionHandoffWithDigests(
5256+
string artifactSha256,
5257+
string reportSha256)
5258+
{
5259+
SigtranCommercialEvidenceArtifactDigestManifest digests = SigtranCommercialEvidenceArtifactDigests.CreateCovered(
5260+
CreateDefaultCommercialEvidenceArtifactSourceManifest(),
5261+
artifactSha256);
5262+
SigtranCommercialEvidenceRedactionReviewManifest reviews = SigtranCommercialEvidenceRedactionReviews.CreateApproved(
5263+
digests,
5264+
"release-review",
5265+
DateTimeOffset.UtcNow);
5266+
SigtranCommercialEvidenceArtifactCompletenessResult completeness = SigtranCommercialEvidenceArtifactCompleteness.Evaluate(reviews);
5267+
SigtranCommercialEvidenceDossierIntakeReport report = SigtranCommercialEvidenceDossierIntakeReports.CreateDefault(completeness);
5268+
5269+
return SigtranCommercialEvidencePromotionHandoffs.CreateDefault(
5270+
report,
5271+
reportSha256,
5272+
"release-review",
5273+
DateTimeOffset.UtcNow);
5274+
}
5275+
5276+
static string ComputeSha256Hex(byte[] content)
5277+
{
5278+
return Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(content)).ToLowerInvariant();
5279+
}
5280+
5281+
static void DeleteTempEvidenceRoot(string tempRoot)
5282+
{
5283+
if (tempRoot.StartsWith(Path.GetTempPath(), StringComparison.OrdinalIgnoreCase) && Directory.Exists(tempRoot))
5284+
{
5285+
Directory.Delete(tempRoot, recursive: true);
52035286
}
52045287
}
52055288

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
namespace Sigtran.NET.Core.Utilities;
2+
3+
/// <summary>
4+
/// Describes filesystem-backed retained file manifest execution.
5+
/// </summary>
6+
public sealed class SigtranCommercialEvidenceFileSystemManifestExecution
7+
{
8+
/// <summary>Creates filesystem-backed retained file manifest execution.</summary>
9+
/// <param name="handoff">The promotion handoff that declares retained evidence files.</param>
10+
/// <param name="observations">The filesystem observations.</param>
11+
/// <param name="manifest">The retained file manifest created from the observations.</param>
12+
public SigtranCommercialEvidenceFileSystemManifestExecution(
13+
SigtranCommercialEvidencePromotionHandoff handoff,
14+
IReadOnlyList<SigtranCommercialEvidenceFileSystemObservation> observations,
15+
SigtranCommercialEvidenceRetainedFileManifest manifest)
16+
{
17+
Handoff = handoff ?? throw new ArgumentNullException(nameof(handoff));
18+
ArgumentNullException.ThrowIfNull(observations);
19+
Observations = observations.Count == 0 ? throw new ArgumentException("At least one filesystem observation is required.", nameof(observations)) : observations.ToArray();
20+
Manifest = manifest ?? throw new ArgumentNullException(nameof(manifest));
21+
}
22+
23+
/// <summary>The promotion handoff that declares retained evidence files.</summary>
24+
public SigtranCommercialEvidencePromotionHandoff Handoff { get; }
25+
26+
/// <summary>The filesystem observations.</summary>
27+
public IReadOnlyList<SigtranCommercialEvidenceFileSystemObservation> Observations { get; }
28+
29+
/// <summary>The retained file manifest created from the observations.</summary>
30+
public SigtranCommercialEvidenceRetainedFileManifest Manifest { get; }
31+
32+
/// <summary>Whether every handoff item was observed from the filesystem.</summary>
33+
public bool CoversHandoffItems => Handoff.Items.All(item => Observations.Any(observation =>
34+
observation.RetainedFile.Kind == item.Kind
35+
&& observation.RetainedFile.RetainedPath == item.RetainedPath
36+
&& string.Equals(observation.RetainedFile.ExpectedSha256, item.Sha256, StringComparison.OrdinalIgnoreCase)));
37+
38+
/// <summary>Whether all observed files exist on the filesystem.</summary>
39+
public bool AllObservedFilesExist => Observations.All(static observation => observation.Exists);
40+
41+
/// <summary>Whether all observed files match the handoff digests.</summary>
42+
public bool AllObservedDigestsMatch => Observations.All(static observation => observation.DigestMatchesHandoff);
43+
44+
/// <summary>Whether the filesystem-backed manifest execution is ready for verification reporting.</summary>
45+
public bool IsReady => CoversHandoffItems
46+
&& AllObservedFilesExist
47+
&& AllObservedDigestsMatch
48+
&& Manifest.IsReady;
49+
50+
/// <summary>Formats a compact filesystem manifest execution summary.</summary>
51+
/// <returns>The filesystem manifest execution summary.</returns>
52+
public string Describe()
53+
{
54+
return $"commercialEvidenceFileSystemManifestReady={IsReady} observations={Observations.Count} intake={Handoff.Report.Target.IntakeId}";
55+
}
56+
}
57+
58+
/// <summary>
59+
/// Builds retained commercial evidence file manifests from filesystem observations.
60+
/// </summary>
61+
public static class SigtranCommercialEvidenceFileSystemManifestBuilder
62+
{
63+
/// <summary>Builds a retained file manifest by observing every promotion handoff item.</summary>
64+
/// <param name="handoff">The promotion handoff that declares retained evidence files.</param>
65+
/// <param name="pathOverrides">Optional local filesystem path overrides keyed by retained path.</param>
66+
/// <param name="observedAtUtc">An optional UTC observation time.</param>
67+
/// <returns>The filesystem-backed retained file manifest execution.</returns>
68+
public static SigtranCommercialEvidenceFileSystemManifestExecution Build(
69+
SigtranCommercialEvidencePromotionHandoff handoff,
70+
IReadOnlyDictionary<string, string>? pathOverrides = null,
71+
DateTimeOffset? observedAtUtc = null)
72+
{
73+
ArgumentNullException.ThrowIfNull(handoff);
74+
75+
SigtranCommercialEvidenceFileSystemObservation[] observations = handoff.Items
76+
.Select(item => SigtranCommercialEvidenceFileSystemObserver.Observe(
77+
item,
78+
ResolvePath(item, pathOverrides),
79+
observedAtUtc))
80+
.ToArray();
81+
SigtranCommercialEvidenceRetainedFileManifest manifest = new(
82+
handoff,
83+
observations.Select(static observation => observation.RetainedFile).ToArray());
84+
85+
return new(handoff, observations, manifest);
86+
}
87+
88+
private static string? ResolvePath(
89+
SigtranCommercialEvidencePromotionHandoffItem item,
90+
IReadOnlyDictionary<string, string>? pathOverrides)
91+
{
92+
return pathOverrides is not null && pathOverrides.TryGetValue(item.RetainedPath, out string? path)
93+
? path
94+
: null;
95+
}
96+
}

0 commit comments

Comments
 (0)