Skip to content

Commit 790bb93

Browse files
committed
Add commercial evidence retained file verification
1 parent 7a0102d commit 790bb93

7 files changed

Lines changed: 197 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ The first production milestone is M3UA over a transport abstraction. SCCP, TCAP,
7474
| Commercial evidence readiness lockdown | Phase 36 foundation-complete: release target locking, protected secret readiness, evidence retention mapping, commercial evidence checklist, release preflight, protected release environments, dossier handoff, go/no-go gating, status reporting, and final validation are available; RC and stable publication remain blocked until retained commercial release evidence is complete |
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 |
77+
| Commercial evidence file verification | Phase 39 in progress: retained file evidence item verification is available, checking file existence, non-empty size, SHA-256 validity, digest match, and UTC observation time; file manifest coverage, verification reporting, retention ledger, integrity seal, publication attachments, promotion gate, command plan, status reporting, and final validation remain |
7778

7879
## Requirements
7980

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Phase 39 Commercial Evidence File Verification
2+
3+
Phase 39 turns digest-covered intake handoff records into retained file verification contracts. It does not create real commercial evidence by itself. It defines how retained artifact files are observed, matched to expected digests, checked for retention, sealed, and prepared for release evidence gates.
4+
5+
Public APIs use domain names such as `SigtranCommercialEvidenceRetainedFiles`; phase numbers are intentionally kept out of source type names.
6+
7+
## Unit 1 - Retained File Evidence Item
8+
9+
`SigtranCommercialEvidenceRetainedFiles` records an observed retained file:
10+
11+
- Checklist artifact kind.
12+
- Retained artifact path.
13+
- Expected SHA-256 digest from the promotion handoff.
14+
- Actual SHA-256 digest observed from the retained file.
15+
- Observed file size.
16+
- UTC observation time.
17+
- File existence state.
18+
19+
A retained file is verified only when the file exists, is non-empty, carries valid SHA-256 values, has matching expected and actual digests, and uses a UTC observation time.
20+
21+
## Validation
22+
23+
Each unit in this phase is validated with:
24+
25+
```powershell
26+
dotnet build src\Sigtran.NET.sln
27+
dotnet run --project src\Sigtran.NET.Tests\Sigtran.NET.Tests.csproj
28+
dotnet pack src\Sigtran.NET\Sigtran.NET.csproj -c Release
29+
```

docs/PHASE39_SUMMARY.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Phase 39 Summary - Commercial Evidence File Verification
2+
3+
Phase 39 prepares the SDK to verify retained commercial evidence files after artifact intake is complete.
4+
5+
## Completed Capabilities
6+
7+
- Retained file evidence item that verifies existence, size, SHA-256 validity, digest match, and UTC observation time.
8+
9+
## Readiness Position
10+
11+
The phase is in progress. Retained file evidence item verification is available. File manifest coverage, verification reporting, retention ledger, integrity seal, publication attachments, promotion gate, command plan, status reporting, and final validation remain.

docs/PHASE_INDEX.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ This index is the complete phase map for Sigtran.NET. It links each phase to the
4343
| 36 | Commercial evidence readiness lockdown | [Phase 36 Commercial Evidence Readiness Lockdown](PHASE36_COMMERCIAL_EVIDENCE_READINESS_LOCKDOWN.md), [Phase 36 Summary](PHASE36_SUMMARY.md) | Foundation complete; real commercial evidence still required |
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 |
46+
| 39 | Commercial evidence file verification | [Phase 39 Commercial Evidence File Verification](PHASE39_COMMERCIAL_EVIDENCE_FILE_VERIFICATION.md), [Phase 39 Summary](PHASE39_SUMMARY.md) | In progress; retained file item complete |
4647

4748
## Current Commercial Gate
4849

49-
The SDK can now define governed commercial evidence-producing execution and model intake of retained artifacts when protected secrets are available. RC publication remains blocked until retained execution-run, release-run, and commercial evidence artifacts are complete. Stable publication remains blocked until external peer evidence, trusted timestamped signing, production performance evidence, retained release-run artifacts, real artifact file evidence, and the commercial evidence dossier are complete.
50+
The SDK can now define governed commercial evidence-producing execution, model intake of retained artifacts, and start retained file verification when protected secrets are available. RC publication remains blocked until retained execution-run, release-run, and commercial evidence artifacts are complete. Stable publication remains blocked until external peer evidence, trusted timestamped signing, production performance evidence, retained release-run artifacts, real artifact file evidence, and the commercial evidence dossier are complete.

docs/SDK_ROADMAP.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,14 @@ Status: Phase 37 is foundation-complete. Evidence execution run identity binds a
341341

342342
Status: Phase 38 is foundation-complete. Artifact intake target identity binds a stable intake id, reviewer identity, UTC receipt time, and run-scoped dossier root to a governed commercial evidence execution run. Artifact source registration maps every required expected execution artifact to a concrete source path and unique retained dossier path while rejecting floating `artifacts/latest` aliases. Digest coverage records SHA-256 values for every retained source and blocks invalid digest values. Redaction review requires approved reviewer records for trace-bearing retained artifacts. Completeness evaluation reports explicit source, digest, and redaction blockers. Dossier reporting renders a retained Markdown summary with run, intake, reviewer, counts, completion state, and blockers. Promotion handoff includes all digest-covered retained artifacts and the dossier intake report. Execution-to-dossier bridge assembles the intake pipeline from a governed execution run. Status reporting exposes completed capabilities, foundation readiness, real artifact evidence readiness, publication readiness, and current blockers. Final validation is complete. Commercial publication remains blocked until real artifact files are retained, digest-calculated, redaction-reviewed, and approved.
343343

344+
## Phase 39 - Commercial Evidence File Verification
345+
346+
- Verify retained commercial evidence files against promotion handoff digests.
347+
- Track file existence, size, observation time, digest match, retention, integrity sealing, publication attachment, promotion gate, and operator command contracts.
348+
- Keep file verification separate from real lab execution: verification contracts can evaluate retained files, but publication remains blocked until real files are present and approved.
349+
350+
Status: Phase 39 is in progress. Retained file evidence item verification now checks existence, non-empty size, SHA-256 validity, digest match, and UTC observation time. File manifest coverage, verification reporting, retention ledger, integrity seal, publication attachments, promotion gate, command plan, status reporting, and final validation remain in progress.
351+
344352
## Recommended First Deliverable
345353

346354
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: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@
296296
Run("SIGTRAN commercial evidence promotion handoff includes digests and report", SigtranCommercialEvidencePromotionHandoffIncludesDigestsAndReport);
297297
Run("SIGTRAN commercial evidence dossier intake bridge builds handoff from execution run", SigtranCommercialEvidenceDossierIntakeBridgeBuildsHandoffFromExecutionRun);
298298
Run("SIGTRAN commercial evidence artifact intake status summarizes foundation readiness", SigtranCommercialEvidenceArtifactIntakeStatusSummarizesFoundationReadiness);
299+
Run("SIGTRAN commercial evidence retained file verifies observed digest", SigtranCommercialEvidenceRetainedFileVerifiesObservedDigest);
299300
Run("SIGTRAN status capabilities use domain documentation labels", SigtranStatusCapabilitiesUseDomainDocumentationLabels);
300301
Run("Native SCTP platform probe reports socket creation capability", NativeSctpPlatformProbeReportsSocketCreationCapability);
301302
Run("Native SCTP socket factory creates or reports unsupported platform", NativeSctpSocketFactoryCreatesOrReportsUnsupportedPlatform);
@@ -4975,6 +4976,36 @@ static void SigtranCommercialEvidenceArtifactIntakeStatusSummarizesFoundationRea
49754976
Assert(!blockers.Contains("status-final-validation-pending"), "final validation should no longer be a blocker");
49764977
}
49774978

4979+
static void SigtranCommercialEvidenceRetainedFileVerifiesObservedDigest()
4980+
{
4981+
SigtranCommercialEvidencePromotionHandoff handoff = CreateDefaultCommercialEvidencePromotionHandoff();
4982+
SigtranCommercialEvidencePromotionHandoffItem item = handoff.Items[0];
4983+
SigtranCommercialEvidenceRetainedFile file = SigtranCommercialEvidenceRetainedFiles.CreateVerified(item, sizeBytes: 4096, DateTimeOffset.UtcNow);
4984+
SigtranCommercialEvidenceRetainedFile mismatch = new(
4985+
item.Kind,
4986+
item.RetainedPath,
4987+
item.Sha256,
4988+
new string('c', 64),
4989+
sizeBytes: 4096,
4990+
DateTimeOffset.UtcNow,
4991+
exists: true);
4992+
4993+
Assert(file.IsVerified, file.Describe());
4994+
Assert(file.HasContent, "retained file should have content");
4995+
Assert(file.HasValidDigestValues, "retained file should use SHA-256 values");
4996+
Assert(file.DigestMatches, "retained file digest should match expected digest");
4997+
Assert(!mismatch.IsVerified, "digest mismatch should block retained file verification");
4998+
}
4999+
5000+
static SigtranCommercialEvidencePromotionHandoff CreateDefaultCommercialEvidencePromotionHandoff()
5001+
{
5002+
return SigtranCommercialEvidencePromotionHandoffs.CreateDefault(
5003+
CreateDefaultCommercialEvidenceDossierIntakeReport(),
5004+
new string('b', 64),
5005+
"release-review",
5006+
DateTimeOffset.UtcNow);
5007+
}
5008+
49785009
static SigtranCommercialEvidenceDossierIntakeReport CreateDefaultCommercialEvidenceDossierIntakeReport()
49795010
{
49805011
return SigtranCommercialEvidenceDossierIntakeReports.CreateDefault(CreateDefaultCommercialEvidenceArtifactCompletenessResult());
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
namespace Sigtran.NET.Core.Utilities;
2+
3+
/// <summary>
4+
/// Describes one retained commercial evidence file observation.
5+
/// </summary>
6+
public sealed class SigtranCommercialEvidenceRetainedFile
7+
{
8+
/// <summary>Creates a retained commercial evidence file observation.</summary>
9+
/// <param name="kind">The checklist artifact kind.</param>
10+
/// <param name="retainedPath">The retained artifact path.</param>
11+
/// <param name="expectedSha256">The expected SHA-256 digest from promotion handoff.</param>
12+
/// <param name="actualSha256">The observed SHA-256 digest from the retained file.</param>
13+
/// <param name="sizeBytes">The observed file size in bytes.</param>
14+
/// <param name="observedAtUtc">The UTC observation time.</param>
15+
/// <param name="exists">Whether the retained file exists.</param>
16+
public SigtranCommercialEvidenceRetainedFile(
17+
SigtranCommercialEvidenceChecklistKind kind,
18+
string retainedPath,
19+
string expectedSha256,
20+
string actualSha256,
21+
long sizeBytes,
22+
DateTimeOffset observedAtUtc,
23+
bool exists)
24+
{
25+
Kind = kind;
26+
RetainedPath = string.IsNullOrWhiteSpace(retainedPath) ? throw new ArgumentException("Retained path is required.", nameof(retainedPath)) : retainedPath;
27+
ExpectedSha256 = string.IsNullOrWhiteSpace(expectedSha256) ? throw new ArgumentException("Expected SHA-256 digest is required.", nameof(expectedSha256)) : expectedSha256;
28+
ActualSha256 = string.IsNullOrWhiteSpace(actualSha256) ? throw new ArgumentException("Actual SHA-256 digest is required.", nameof(actualSha256)) : actualSha256;
29+
SizeBytes = sizeBytes;
30+
ObservedAtUtc = observedAtUtc.Offset == TimeSpan.Zero ? observedAtUtc : observedAtUtc.ToUniversalTime();
31+
Exists = exists;
32+
}
33+
34+
/// <summary>The checklist artifact kind.</summary>
35+
public SigtranCommercialEvidenceChecklistKind Kind { get; }
36+
37+
/// <summary>The retained artifact path.</summary>
38+
public string RetainedPath { get; }
39+
40+
/// <summary>The expected SHA-256 digest from promotion handoff.</summary>
41+
public string ExpectedSha256 { get; }
42+
43+
/// <summary>The observed SHA-256 digest from the retained file.</summary>
44+
public string ActualSha256 { get; }
45+
46+
/// <summary>The observed file size in bytes.</summary>
47+
public long SizeBytes { get; }
48+
49+
/// <summary>The UTC observation time.</summary>
50+
public DateTimeOffset ObservedAtUtc { get; }
51+
52+
/// <summary>Whether the retained file exists.</summary>
53+
public bool Exists { get; }
54+
55+
/// <summary>Whether the expected and actual digests are valid SHA-256 hex values.</summary>
56+
public bool HasValidDigestValues => IsSha256(ExpectedSha256)
57+
&& IsSha256(ActualSha256);
58+
59+
/// <summary>Whether the observed digest matches the expected digest.</summary>
60+
public bool DigestMatches => string.Equals(ExpectedSha256, ActualSha256, StringComparison.OrdinalIgnoreCase);
61+
62+
/// <summary>Whether the retained file has a non-empty payload.</summary>
63+
public bool HasContent => SizeBytes > 0;
64+
65+
/// <summary>Whether the observation timestamp is normalized to UTC.</summary>
66+
public bool HasUtcObservationTime => ObservedAtUtc.Offset == TimeSpan.Zero;
67+
68+
/// <summary>Whether the retained file observation is verified.</summary>
69+
public bool IsVerified => Exists
70+
&& HasContent
71+
&& HasValidDigestValues
72+
&& DigestMatches
73+
&& HasUtcObservationTime;
74+
75+
/// <summary>Formats a compact retained file summary.</summary>
76+
/// <returns>The retained file summary.</returns>
77+
public string Describe()
78+
{
79+
return $"commercialEvidenceRetainedFile={RetainedPath} verified={IsVerified} sizeBytes={SizeBytes}";
80+
}
81+
82+
private static bool IsSha256(string value)
83+
{
84+
return value.Length == 64
85+
&& value.All(Uri.IsHexDigit);
86+
}
87+
}
88+
89+
/// <summary>
90+
/// Provides commercial evidence retained file helpers.
91+
/// </summary>
92+
public static class SigtranCommercialEvidenceRetainedFiles
93+
{
94+
/// <summary>Creates a verified retained file observation from a promotion handoff item.</summary>
95+
/// <param name="item">The promotion handoff item.</param>
96+
/// <param name="sizeBytes">The observed file size in bytes.</param>
97+
/// <param name="observedAtUtc">The UTC observation time.</param>
98+
/// <returns>The retained file observation.</returns>
99+
public static SigtranCommercialEvidenceRetainedFile CreateVerified(
100+
SigtranCommercialEvidencePromotionHandoffItem item,
101+
long sizeBytes,
102+
DateTimeOffset observedAtUtc)
103+
{
104+
ArgumentNullException.ThrowIfNull(item);
105+
106+
return new(
107+
item.Kind,
108+
item.RetainedPath,
109+
item.Sha256,
110+
item.Sha256,
111+
sizeBytes,
112+
observedAtUtc,
113+
exists: true);
114+
}
115+
}

0 commit comments

Comments
 (0)