Skip to content

Commit e2c8b53

Browse files
committed
Add commercial evidence filesystem observation
1 parent 03f96ac commit e2c8b53

7 files changed

Lines changed: 186 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +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 |
7879

7980
## Requirements
8081

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Phase 40 Commercial Evidence Filesystem Execution
2+
3+
Phase 40 turns the file verification contracts from Phase 39 into filesystem-backed execution helpers. It still does not manufacture commercial evidence. It reads retained files from disk, computes real SHA-256 digests, and feeds the existing verification, retention, sealing, attachment, and promotion-gate contracts.
4+
5+
Public APIs use domain names such as `SigtranCommercialEvidenceFileSystemObserver`; phase numbers are intentionally kept out of source type names.
6+
7+
## Unit 1 - Filesystem Observation
8+
9+
`SigtranCommercialEvidenceFileSystemObserver` observes a promotion handoff item against the local filesystem:
10+
11+
- Reads the retained file path or an explicit local path override.
12+
- Reports existence and file size.
13+
- Computes the actual SHA-256 digest for existing files.
14+
- Uses a deterministic missing-file digest marker for absent files.
15+
- Produces a `SigtranCommercialEvidenceRetainedFile` so the Phase 39 verification pipeline can evaluate the observation.
16+
17+
The observer is the first executable bridge from retained dossier paths to real file verification.
18+
19+
## Validation
20+
21+
Each unit in this phase is validated with:
22+
23+
```powershell
24+
dotnet build src\Sigtran.NET.sln
25+
dotnet run --project src\Sigtran.NET.Tests\Sigtran.NET.Tests.csproj
26+
dotnet pack src\Sigtran.NET\Sigtran.NET.csproj -c Release
27+
```

docs/PHASE40_SUMMARY.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Phase 40 Summary - Commercial Evidence Filesystem Execution
2+
3+
Phase 40 prepares the SDK to run commercial evidence file verification against real retained files on disk.
4+
5+
## Completed Capabilities
6+
7+
- Filesystem observer that computes SHA-256 digests from existing retained files and maps missing files into explicit non-verified retained file observations.
8+
9+
## Readiness Position
10+
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.

docs/PHASE_INDEX.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +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 |
4748

4849
## Current Commercial Gate
4950

docs/SDK_ROADMAP.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,14 @@ Status: Phase 38 is foundation-complete. Artifact intake target identity binds a
349349

350350
Status: Phase 39 is foundation-complete. Retained file evidence item verification checks existence, non-empty size, SHA-256 validity, digest match, and UTC observation time. Retained file manifest coverage verifies that every promotion-required handoff item has a unique verified retained file. File verification reporting exposes missing, empty, invalid digest, digest mismatch, non-UTC observation, duplicate path, and incomplete handoff blockers. Retention ledger modeling binds verified files to reviewer identity, immutable retention, UTC retention windows, and minimum duration checks. Integrity sealing computes and validates a deterministic aggregate SHA-256 digest over the ledger. Publication attachment planning covers sealed ledger entries, validates attachment digests, includes the commercial readiness report, and blocks trace-bearing attachments without redaction approval. Verified promotion gating requires ready attachments, ready integrity seal, ready retention ledger, verified file report, commercial readiness report presence, and explicit approval before evidence can move into release publication decisions. Command planning orders observation, digest computation, comparison, report, ledger, seal, attachment, and promotion-gate work for workflow materialization. Status reporting separates foundation readiness from real retained file evidence and commercial publication readiness. Commercial publication remains blocked until real retained file evidence is captured and approved.
351351

352+
## Phase 40 - Commercial Evidence Filesystem Execution
353+
354+
- Execute retained evidence file observation against the local filesystem.
355+
- Build verification manifests, reports, retained artifacts, ledger, seal, attachments, promotion gate, and command materialization from observed files.
356+
- 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.
357+
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.
359+
352360
## Recommended First Deliverable
353361

354362
The first useful SDK release should be an alpha package focused on M3UA over a transport abstraction:

src/Sigtran.NET.Tests/Program.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@
305305
Run("SIGTRAN commercial evidence verified promotion gate requires approval", SigtranCommercialEvidenceVerifiedPromotionGateRequiresApproval);
306306
Run("SIGTRAN commercial evidence file verification command plan orders execution", SigtranCommercialEvidenceFileVerificationCommandPlanOrdersExecution);
307307
Run("SIGTRAN commercial evidence file verification status summarizes readiness", SigtranCommercialEvidenceFileVerificationStatusSummarizesReadiness);
308+
Run("SIGTRAN commercial evidence filesystem observer computes retained file digest", SigtranCommercialEvidenceFileSystemObserverComputesRetainedFileDigest);
308309
Run("SIGTRAN status capabilities use domain documentation labels", SigtranStatusCapabilitiesUseDomainDocumentationLabels);
309310
Run("Native SCTP platform probe reports socket creation capability", NativeSctpPlatformProbeReportsSocketCreationCapability);
310311
Run("Native SCTP socket factory creates or reports unsupported platform", NativeSctpSocketFactoryCreatesOrReportsUnsupportedPlatform);
@@ -5157,6 +5158,51 @@ static void SigtranCommercialEvidenceFileVerificationStatusSummarizesReadiness()
51575158
Assert(!blockers.Contains("status-final-validation-pending"), "file verification status should clear final validation blocker");
51585159
}
51595160

5161+
static void SigtranCommercialEvidenceFileSystemObserverComputesRetainedFileDigest()
5162+
{
5163+
string tempRoot = Path.Combine(Path.GetTempPath(), "sigtran-commercial-evidence-" + Guid.NewGuid().ToString("N"));
5164+
Directory.CreateDirectory(tempRoot);
5165+
5166+
try
5167+
{
5168+
string retainedPath = Path.Combine(tempRoot, "sbom.spdx.json");
5169+
byte[] content = "sigtran commercial evidence"u8.ToArray();
5170+
File.WriteAllBytes(retainedPath, content);
5171+
string expectedSha256 = Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(content)).ToLowerInvariant();
5172+
SigtranCommercialEvidencePromotionHandoffItem item = new(
5173+
SigtranCommercialEvidenceChecklistKind.Sbom,
5174+
retainedPath,
5175+
expectedSha256,
5176+
requiredForPromotion: true);
5177+
5178+
SigtranCommercialEvidenceFileSystemObservation observation = SigtranCommercialEvidenceFileSystemObserver.Observe(
5179+
item,
5180+
observedAtUtc: DateTimeOffset.UtcNow);
5181+
SigtranCommercialEvidenceFileSystemObservation missing = SigtranCommercialEvidenceFileSystemObserver.Observe(
5182+
new SigtranCommercialEvidencePromotionHandoffItem(
5183+
SigtranCommercialEvidenceChecklistKind.Sbom,
5184+
Path.Combine(tempRoot, "missing.spdx.json"),
5185+
expectedSha256,
5186+
requiredForPromotion: true),
5187+
observedAtUtc: DateTimeOffset.UtcNow);
5188+
5189+
Assert(observation.IsVerified, observation.Describe());
5190+
Assert(observation.FileSystemPathMatchesRetainedPath, "filesystem observation should preserve retained path identity");
5191+
AssertEqual(expectedSha256, observation.RetainedFile.ActualSha256, "filesystem observation digest");
5192+
AssertEqual(content.Length, (int)observation.RetainedFile.SizeBytes, "filesystem observation size");
5193+
Assert(!missing.IsVerified, "missing filesystem evidence should not verify");
5194+
Assert(!missing.Exists, "missing filesystem evidence should report missing file");
5195+
AssertEqual(SigtranCommercialEvidenceFileSystemObserver.MissingFileSha256, missing.RetainedFile.ActualSha256, "missing file digest marker");
5196+
}
5197+
finally
5198+
{
5199+
if (tempRoot.StartsWith(Path.GetTempPath(), StringComparison.OrdinalIgnoreCase) && Directory.Exists(tempRoot))
5200+
{
5201+
Directory.Delete(tempRoot, recursive: true);
5202+
}
5203+
}
5204+
}
5205+
51605206
static SigtranCommercialEvidenceFileVerificationCommandPlan CreateDefaultCommercialEvidenceFileVerificationCommandPlan()
51615207
{
51625208
return SigtranCommercialEvidenceFileVerificationCommands.CreateDefault("artifacts/commercial-evidence");
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System.Security.Cryptography;
2+
3+
namespace Sigtran.NET.Core.Utilities;
4+
5+
/// <summary>
6+
/// Describes one retained commercial evidence file observation from the local filesystem.
7+
/// </summary>
8+
public sealed class SigtranCommercialEvidenceFileSystemObservation
9+
{
10+
/// <summary>Creates a retained commercial evidence filesystem observation.</summary>
11+
/// <param name="fileSystemPath">The local filesystem path that was observed.</param>
12+
/// <param name="retainedFile">The retained file verification model created from the observation.</param>
13+
public SigtranCommercialEvidenceFileSystemObservation(
14+
string fileSystemPath,
15+
SigtranCommercialEvidenceRetainedFile retainedFile)
16+
{
17+
FileSystemPath = string.IsNullOrWhiteSpace(fileSystemPath) ? throw new ArgumentException("Filesystem path is required.", nameof(fileSystemPath)) : fileSystemPath;
18+
RetainedFile = retainedFile ?? throw new ArgumentNullException(nameof(retainedFile));
19+
}
20+
21+
/// <summary>The local filesystem path that was observed.</summary>
22+
public string FileSystemPath { get; }
23+
24+
/// <summary>The retained file verification model created from the observation.</summary>
25+
public SigtranCommercialEvidenceRetainedFile RetainedFile { get; }
26+
27+
/// <summary>Whether the observed filesystem path matches the retained evidence path.</summary>
28+
public bool FileSystemPathMatchesRetainedPath => string.Equals(FileSystemPath, RetainedFile.RetainedPath, StringComparison.OrdinalIgnoreCase);
29+
30+
/// <summary>Whether the observed filesystem file exists.</summary>
31+
public bool Exists => RetainedFile.Exists;
32+
33+
/// <summary>Whether the observed digest matches the promotion handoff digest.</summary>
34+
public bool DigestMatchesHandoff => RetainedFile.DigestMatches;
35+
36+
/// <summary>Whether the filesystem observation verifies the retained evidence file.</summary>
37+
public bool IsVerified => RetainedFile.IsVerified;
38+
39+
/// <summary>Formats a compact filesystem observation summary.</summary>
40+
/// <returns>The filesystem observation summary.</returns>
41+
public string Describe()
42+
{
43+
return $"commercialEvidenceFileSystemObservation={FileSystemPath} verified={IsVerified} exists={Exists}";
44+
}
45+
}
46+
47+
/// <summary>
48+
/// Observes retained commercial evidence files from the local filesystem.
49+
/// </summary>
50+
public static class SigtranCommercialEvidenceFileSystemObserver
51+
{
52+
/// <summary>The deterministic digest marker used when a file is missing.</summary>
53+
public const string MissingFileSha256 = "0000000000000000000000000000000000000000000000000000000000000000";
54+
55+
/// <summary>Observes a retained evidence file and computes its digest when it exists.</summary>
56+
/// <param name="item">The promotion handoff item that declares the expected retained file.</param>
57+
/// <param name="fileSystemPath">An optional local filesystem path override.</param>
58+
/// <param name="observedAtUtc">An optional UTC observation time.</param>
59+
/// <returns>The filesystem observation.</returns>
60+
public static SigtranCommercialEvidenceFileSystemObservation Observe(
61+
SigtranCommercialEvidencePromotionHandoffItem item,
62+
string? fileSystemPath = null,
63+
DateTimeOffset? observedAtUtc = null)
64+
{
65+
ArgumentNullException.ThrowIfNull(item);
66+
67+
string path = string.IsNullOrWhiteSpace(fileSystemPath) ? item.RetainedPath : fileSystemPath;
68+
DateTimeOffset observedAt = observedAtUtc ?? DateTimeOffset.UtcNow;
69+
observedAt = observedAt.Offset == TimeSpan.Zero ? observedAt : observedAt.ToUniversalTime();
70+
71+
bool exists = File.Exists(path);
72+
long sizeBytes = exists ? new FileInfo(path).Length : 0;
73+
string actualSha256 = exists ? ComputeSha256(path) : MissingFileSha256;
74+
75+
SigtranCommercialEvidenceRetainedFile retainedFile = new(
76+
item.Kind,
77+
item.RetainedPath,
78+
item.Sha256,
79+
actualSha256,
80+
sizeBytes,
81+
observedAt,
82+
exists);
83+
84+
return new(path, retainedFile);
85+
}
86+
87+
private static string ComputeSha256(string path)
88+
{
89+
using FileStream stream = File.OpenRead(path);
90+
return Convert.ToHexString(SHA256.HashData(stream)).ToLowerInvariant();
91+
}
92+
}

0 commit comments

Comments
 (0)