Skip to content

Commit 04182ee

Browse files
committed
Gate package publication credentials
1 parent 22ad68b commit 04182ee

5 files changed

Lines changed: 146 additions & 4 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ The first production milestone is M3UA over a transport abstraction. SCCP, TCAP,
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 |
7878
| Commercial evidence filesystem execution | Phase 40 foundation-complete: filesystem observation, manifest execution, verification report execution, artifact writing, ledger execution, seal execution, publication attachment execution, promotion execution, command materialization, status reporting, documentation, and final validation are complete, reading retained files from disk, computing real SHA-256 digests, reporting file existence and size, supporting retained-path-to-local-path overrides, building retained file manifests from real observations, exposing blocker-aware retained file reports from filesystem evidence, writing retained Markdown/TSV verification artifacts, creating retention ledgers from filesystem-backed reports, sealing those ledgers with deterministic aggregate SHA-256 digests, creating release dossier attachments with redaction approval gates, evaluating reviewer-approved promotion gates, and writing ordered execution scripts; commercial publication still requires a real approved commercial run |
7979
| Approved commercial run publication handoff | Phase 41 foundation-complete: approved run target identity, approval checklist, reviewer approval manifest, approval report writing, promotion package, publication handoff, handoff gate, approval audit trail, command materialization, status reporting, documentation, and final validation are complete, binding package version, source commit, operator identity, UTC run timing, retained artifact root, filesystem-backed promotion execution, verified report, ready ledger/seal/attachments, redaction approval, promotion approval, release/security/operations reviewer approvals, UTC approval timestamps, checklist digest coverage, retained Markdown report output, report SHA-256 digest coverage, approved package references, requested publication channel, requester identity, UTC handoff time, explicit publish intent, channel version policy, handoff blocker reporting, digest-covered audit lifecycle events, and ordered approval workflow scripts; package publication still requires a real approved commercial run |
80-
| Commercial package publication gate integration | Phase 42 in progress: handoff-derived package publication request and digest-covered package artifact binding are available, binding package version, channel, requester identity, run id, promotion package id, UTC request time, nupkg/snupkg paths, retained sizes, SHA-256 digests, version-matched paths, and package integrity manifest projection; package publication remains blocked until credential readiness, evidence assembly, release guard, channel policy, gate execution, dry-run rehearsal, guarded commands, and status reporting are complete |
80+
| Commercial package publication gate integration | Phase 42 in progress: handoff-derived package publication request, digest-covered package artifact binding, and secret-name based credential readiness are available, binding package version, channel, requester identity, run id, promotion package id, UTC request time, nupkg/snupkg paths, retained sizes, SHA-256 digests, version-matched paths, package integrity manifest projection, NuGet API key presence, signing secret presence, missing-secret reporting, and UTC credential evaluation; package publication remains blocked until evidence assembly, release guard, channel policy, gate execution, dry-run rehearsal, guarded commands, and status reporting are complete |
8181

8282
## Requirements
8383

docs/PHASE42_COMMERCIAL_PACKAGE_PUBLICATION_GATE_INTEGRATION.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Phase 42 connects an approved commercial evidence publication handoff to the pac
88
| --- | --- | --- |
99
| 1 | Package publication request derived from approved handoff gate | Complete |
1010
| 2 | Package artifact binding with package and symbols digests | Complete |
11-
| 3 | Credential readiness bridge for required publication secrets | Pending |
11+
| 3 | Credential readiness bridge for required publication secrets | Complete |
1212
| 4 | Publication evidence assembly from approved run and artifacts | Pending |
1313
| 5 | Release publish guard bridge | Pending |
1414
| 6 | Publication channel policy evaluation bridge | Pending |
@@ -25,6 +25,8 @@ The request can only move to package artifact binding when the upstream handoff
2525

2626
`SigtranPackagePublicationArtifactSet` binds the request to the retained NuGet package and symbols package. It requires unique artifact kinds, package and symbols coverage, non-empty retained sizes, SHA-256 hex digests, and paths that match the requested package version. The artifact set can also project into the existing `SigtranPackageIntegrityManifest` contract used by the package publication gate.
2727

28+
`SigtranPackagePublicationCredentialReadiness` evaluates required publication credentials by secret name only. It uses the default NuGet publication credential policy, reports missing secret names, tracks NuGet API key and signing secret availability, and requires a UTC evaluation time before moving into evidence assembly.
29+
2830
## Commercial Gate Position
2931

30-
Phase 42 is still in progress. Units 1 and 2 establish the handoff-to-publication request boundary and digest-covered package artifact binding. Real package publication remains blocked until required credentials, retained evidence, release guard, channel policy, and the final publication gate all pass.
32+
Phase 42 is still in progress. Units 1 through 3 establish the handoff-to-publication request boundary, digest-covered package artifact binding, and secret-name based credential readiness. Real package publication remains blocked until retained evidence, release guard, channel policy, and the final publication gate all pass.

docs/PHASE42_SUMMARY.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ Phase 42 is in progress. It connects approved commercial evidence handoff record
66

77
- Package publication request that derives package version, channel, requester identity, run id, promotion package id, UTC request time, and artifact-binding readiness from an approved handoff gate.
88
- Package publication artifact set that binds the request to nupkg/snupkg paths, retained sizes, SHA-256 digests, requested package version matching, and the existing package integrity manifest.
9+
- Package publication credential readiness that evaluates NuGet and signing secret availability by secret name without storing secret values.
910

1011
## Readiness Position
1112

12-
Units 1 and 2 are complete. The SDK can now represent the publication request boundary after commercial approval handoff and bind digest-covered package artifacts to that request. Package publication still requires credential readiness, evidence assembly, release guard evaluation, channel policy evaluation, final gate execution, dry-run rehearsal, guarded command materialization, status reporting, and retained real release evidence.
13+
Units 1 through 3 are complete. The SDK can now represent the publication request boundary after commercial approval handoff, bind digest-covered package artifacts to that request, and gate the next step on required publication secret names. Package publication still requires evidence assembly, release guard evaluation, channel policy evaluation, final gate execution, dry-run rehearsal, guarded command materialization, status reporting, and retained real release evidence.

src/Sigtran.NET.Tests/Program.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@
324324
Run("SIGTRAN commercial evidence publication handoff gate reports blockers", SigtranCommercialEvidencePublicationHandoffGateReportsBlockers);
325325
Run("SIGTRAN package publication request derives from approved handoff", SigtranPackagePublicationRequestDerivesFromApprovedHandoff);
326326
Run("SIGTRAN package publication artifacts bind package and symbols digests", SigtranPackagePublicationArtifactsBindPackageAndSymbolsDigests);
327+
Run("SIGTRAN package publication credential readiness gates required secrets", SigtranPackagePublicationCredentialReadinessGatesRequiredSecrets);
327328
Run("SIGTRAN commercial evidence approval audit trail covers lifecycle", SigtranCommercialEvidenceApprovalAuditTrailCoversLifecycle);
328329
Run("SIGTRAN commercial evidence approval command materializer writes script", SigtranCommercialEvidenceApprovalCommandMaterializerWritesScript);
329330
Run("SIGTRAN commercial evidence approval handoff status summarizes final validation", SigtranCommercialEvidenceApprovalHandoffStatusSummarizesFinalValidation);
@@ -5779,6 +5780,47 @@ static void SigtranPackagePublicationArtifactsBindPackageAndSymbolsDigests()
57795780
}
57805781
}
57815782

5783+
static void SigtranPackagePublicationCredentialReadinessGatesRequiredSecrets()
5784+
{
5785+
string tempRoot = Path.Combine(Path.GetTempPath(), "sigtran-commercial-evidence-" + Guid.NewGuid().ToString("N"));
5786+
Directory.CreateDirectory(tempRoot);
5787+
5788+
try
5789+
{
5790+
SigtranPackagePublicationArtifactSet artifacts = CreateReadyPackagePublicationArtifactSet(CreateReadyPackagePublicationRequest(tempRoot));
5791+
5792+
SigtranPackagePublicationCredentialReadiness ready = SigtranPackagePublicationCredentialReadinessEvaluator.EvaluateDefault(
5793+
artifacts,
5794+
new HashSet<string>(StringComparer.Ordinal)
5795+
{
5796+
"NUGET_API_KEY",
5797+
"SIGNING_CERTIFICATE",
5798+
"SIGNING_CERTIFICATE_PASSWORD"
5799+
},
5800+
DateTimeOffset.UtcNow);
5801+
SigtranPackagePublicationCredentialReadiness blocked = SigtranPackagePublicationCredentialReadinessEvaluator.EvaluateDefault(
5802+
artifacts,
5803+
new HashSet<string>(StringComparer.Ordinal)
5804+
{
5805+
"NUGET_API_KEY"
5806+
},
5807+
DateTimeOffset.UtcNow);
5808+
5809+
Assert(ready.IsReadyForEvidenceAssembly, ready.Describe());
5810+
Assert(ready.HasRequiredSecrets, "credential readiness should have every required secret");
5811+
Assert(ready.HasNuGetApiKey, "credential readiness should expose NuGet API key availability");
5812+
Assert(ready.HasSigningSecrets, "credential readiness should expose signing secret availability");
5813+
Assert(ready.HasUtcEvaluationTime, "credential readiness evaluation should be UTC");
5814+
Assert(!blocked.IsReadyForEvidenceAssembly, "missing signing secrets should block publication credential readiness");
5815+
Assert(blocked.MissingSecretNames.Contains("SIGNING_CERTIFICATE"), "credential readiness should report missing signing certificate");
5816+
Assert(blocked.MissingSecretNames.Contains("SIGNING_CERTIFICATE_PASSWORD"), "credential readiness should report missing signing password");
5817+
}
5818+
finally
5819+
{
5820+
DeleteTempEvidenceRoot(tempRoot);
5821+
}
5822+
}
5823+
57825824
static void SigtranCommercialEvidenceApprovalAuditTrailCoversLifecycle()
57835825
{
57845826
string tempRoot = Path.Combine(Path.GetTempPath(), "sigtran-commercial-evidence-" + Guid.NewGuid().ToString("N"));
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
namespace Sigtran.NET.Core.Utilities;
2+
3+
/// <summary>
4+
/// Describes publication credential readiness for a package artifact set.
5+
/// </summary>
6+
public sealed class SigtranPackagePublicationCredentialReadiness
7+
{
8+
/// <summary>Creates package publication credential readiness.</summary>
9+
/// <param name="artifactSet">The package publication artifact set.</param>
10+
/// <param name="credentialPolicy">The publication credential policy.</param>
11+
/// <param name="availableSecretNames">The available secret names.</param>
12+
/// <param name="evaluatedAtUtc">The UTC evaluation time.</param>
13+
public SigtranPackagePublicationCredentialReadiness(
14+
SigtranPackagePublicationArtifactSet artifactSet,
15+
SigtranPublicationCredentialPolicy credentialPolicy,
16+
IReadOnlySet<string> availableSecretNames,
17+
DateTimeOffset evaluatedAtUtc)
18+
{
19+
ArtifactSet = artifactSet ?? throw new ArgumentNullException(nameof(artifactSet));
20+
CredentialPolicy = credentialPolicy ?? throw new ArgumentNullException(nameof(credentialPolicy));
21+
ArgumentNullException.ThrowIfNull(availableSecretNames);
22+
AvailableSecretNames = availableSecretNames.ToHashSet(StringComparer.Ordinal);
23+
MissingSecretNames = CredentialPolicy.GetMissingSecrets(AvailableSecretNames);
24+
EvaluatedAtUtc = evaluatedAtUtc.Offset == TimeSpan.Zero ? evaluatedAtUtc : evaluatedAtUtc.ToUniversalTime();
25+
}
26+
27+
/// <summary>The package publication artifact set.</summary>
28+
public SigtranPackagePublicationArtifactSet ArtifactSet { get; }
29+
30+
/// <summary>The publication credential policy.</summary>
31+
public SigtranPublicationCredentialPolicy CredentialPolicy { get; }
32+
33+
/// <summary>The available secret names.</summary>
34+
public IReadOnlySet<string> AvailableSecretNames { get; }
35+
36+
/// <summary>The missing secret names.</summary>
37+
public IReadOnlyList<string> MissingSecretNames { get; }
38+
39+
/// <summary>The UTC evaluation time.</summary>
40+
public DateTimeOffset EvaluatedAtUtc { get; }
41+
42+
/// <summary>Whether the evaluation time is normalized to UTC.</summary>
43+
public bool HasUtcEvaluationTime => EvaluatedAtUtc.Offset == TimeSpan.Zero;
44+
45+
/// <summary>Whether every required publication secret is available by name.</summary>
46+
public bool HasRequiredSecrets => MissingSecretNames.Count == 0;
47+
48+
/// <summary>Whether the NuGet API key secret is available by name.</summary>
49+
public bool HasNuGetApiKey => HasSecret(SigtranPublicationCredentialKind.NuGetApiKey);
50+
51+
/// <summary>Whether signing certificate secrets are available by name.</summary>
52+
public bool HasSigningSecrets => HasSecret(SigtranPublicationCredentialKind.SigningCertificate)
53+
&& HasSecret(SigtranPublicationCredentialKind.SigningCertificatePassword);
54+
55+
/// <summary>Whether credential readiness can move into evidence assembly.</summary>
56+
public bool IsReadyForEvidenceAssembly => ArtifactSet.IsReadyForCredentialEvaluation
57+
&& CredentialPolicy.RequiresCommercialSecrets
58+
&& HasRequiredSecrets
59+
&& HasUtcEvaluationTime;
60+
61+
/// <summary>Formats a compact credential readiness summary.</summary>
62+
/// <returns>The credential readiness summary.</returns>
63+
public string Describe()
64+
{
65+
return $"packagePublicationCredentialsReady={IsReadyForEvidenceAssembly} missingSecrets={MissingSecretNames.Count} hasNuGetApiKey={HasNuGetApiKey} hasSigningSecrets={HasSigningSecrets}";
66+
}
67+
68+
private bool HasSecret(SigtranPublicationCredentialKind kind)
69+
{
70+
return CredentialPolicy.Credentials
71+
.Where(credential => credential.Kind == kind)
72+
.All(credential => AvailableSecretNames.Contains(credential.SecretName));
73+
}
74+
}
75+
76+
/// <summary>
77+
/// Provides package publication credential readiness helpers.
78+
/// </summary>
79+
public static class SigtranPackagePublicationCredentialReadinessEvaluator
80+
{
81+
/// <summary>Evaluates package publication credential readiness using the default publication policy.</summary>
82+
/// <param name="artifactSet">The package publication artifact set.</param>
83+
/// <param name="availableSecretNames">The available secret names.</param>
84+
/// <param name="evaluatedAtUtc">The UTC evaluation time.</param>
85+
/// <returns>The package publication credential readiness.</returns>
86+
public static SigtranPackagePublicationCredentialReadiness EvaluateDefault(
87+
SigtranPackagePublicationArtifactSet artifactSet,
88+
IReadOnlySet<string> availableSecretNames,
89+
DateTimeOffset evaluatedAtUtc)
90+
{
91+
return new(
92+
artifactSet,
93+
SigtranPublicationCredentials.CreateDefaultPolicy(),
94+
availableSecretNames,
95+
evaluatedAtUtc);
96+
}
97+
}

0 commit comments

Comments
 (0)