Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/nuget-prepare.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Standby registration only. Preparation workflow ID 0 remains deliberately unregistered.
# Registered preparation workflow: 394955059 (NuGet preparation).
# Standby only. Activation and NuGet policy cutover require separate approval.
name: NuGet preparation

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/nuget-publish.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Standby registration only. Preparation workflow ID 0 remains deliberately unregistered.
# Registered preparation workflow: 394955059 (NuGet preparation).
# Publishing remains disabled; registration and cutover require separate review.
name: NuGet verified publication

Expand All @@ -15,7 +15,7 @@ concurrency:

jobs:
publish:
if: ${{ false && github.repository == 'andregoepel/core' && github.event.workflow_run.workflow_id == 0 && github.event.workflow_run.event == 'push' && github.event.workflow_run.conclusion == 'success' && startsWith(github.event.workflow_run.head_branch, 'v') }}
if: ${{ false && github.repository == 'andregoepel/core' && github.event.workflow_run.workflow_id == 394955059 && github.event.workflow_run.event == 'push' && github.event.workflow_run.conclusion == 'success' && startsWith(github.event.workflow_run.head_branch, 'v') }}
runs-on: ubuntu-24.04
environment: nuget-publish
timeout-minutes: 20
Expand Down Expand Up @@ -48,7 +48,7 @@ jobs:
.action == "completed" and .repository.full_name == "andregoepel/core" and
(.workflow_run | .repository.full_name == "andregoepel/core" and
.head_repository.full_name == "andregoepel/core" and
.workflow_id == 0 and .path == ".github/workflows/nuget-prepare.yml" and
.workflow_id == 394955059 and .path == ".github/workflows/nuget-prepare.yml" and
.name == "NuGet preparation" and .event == "push" and
.status == "completed" and .conclusion == "success" and .head_sha == $sha and
(.head_branch | test("^v(0|[1-9][0-9]{0,4})\\.(0|[1-9][0-9]{0,4})\\.(0|[1-9][0-9]{0,4})\\z")) and
Expand Down
56 changes: 41 additions & 15 deletions docs/nuget-quality-gate.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ own environment with a reviewed `v*` tag policy; it has no OIDC permission.
exact package inventory and the independently pinned publication verifier.
- `scripts/sonar/nuget-policy.json` pins preparation workflow identity, exact
content hash, required successful steps and a 120-minute maximum age.
- `.github/workflows/nuget-prepare.yml` and `nuget-publish.yml` are new standby
- `.github/workflows/nuget-prepare.yml` and `nuget-publish.yml` are registered standby
workflows with **literal-false job guards**. They cannot prepare or publish a
release. The existing CI, Sonar and Dependabot Actions are unchanged.
- `scripts/sonar/publication/release-tags.ruleset.json` is an unapplied proposal.
Expand All @@ -53,12 +53,21 @@ own environment with a reviewed `v*` tag policy; it has no OIDC permission.

The publication verifier is pinned to the reviewed merged workflows commit
`68683cdc6a268328ed6ce686d26c26ace479eab0`. Its main validation and all 1,086 tests
on each of Windows and Linux passed. The preparation content hash is recorded;
the preparation workflow ID and both publication-trigger identity checks remain
zero until GitHub registers the new workflow on main. This incomplete policy is
rejected by the verifier. After merge, read back the actual workflow ID and
review its replacement in the policy and both trigger checks together; never
guess IDs or reuse app-foundation's values. Keep all false guards in place.
on each of Windows and Linux passed. After [Core PR #32](https://github.com/andregoepel/core/pull/32)
merged, GitHub assigned these workflow identities, read back on 2026-10-24:

| Workflow | ID | Path |
| --- | --- | --- |
| NuGet preparation | `394955059` | `.github/workflows/nuget-prepare.yml` |
| NuGet verified publication | `394955060` | `.github/workflows/nuget-publish.yml` |

The preparation ID is bound in `nuget-policy.json` and both publication-trigger
checks. The policy also pins the exact preparation file bytes, including its
updated registration comment. Any subsequent preparation edit requires a reviewed
hash update. GitHub's workflow registration state does not enable its jobs: both
job guards and the publication step guards remain literal false. No release tag
or workflow dispatch is needed to register these identities.

The publication verifier pin is separate from
`main-policy.json.toolRevision`, which continues to identify the accepted analysis
runner. This avoids changing the existing Sonar Action for this preparation.
Expand Down Expand Up @@ -100,14 +109,14 @@ inventory: one `started` and one terminal event per package or symbol file.

Shared support and Core preparation were merged in their respective PR #31s.
Main CI passed in both repositories, and #30's nonempty central new-code check
is recorded in [the evidence report](sonar-new-code.md). The next registration
step is prepared for review; the production cutover remains unexecuted:

1. Review and merge the disabled standby workflows and reviewed verifier pin.
Read back GitHub's assigned preparation workflow ID, then submit its policy
and publication-trigger registration together for review, with false guards
retained. GitHub's assignment cannot be predicted before registration. Do not
change thresholds, exclusions or small-change policy.
is recorded in [the evidence report](sonar-new-code.md). Core PR #32 merged the
disabled standby workflows. The assigned-ID registration is prepared for review;
the production cutover remains unexecuted:

1. Review and merge the assigned preparation ID in the policy and both publication
trigger checks together, retaining all false guards. The two workflow IDs above
were read from GitHub after registration. Do not change thresholds, exclusions
or small-change policy.
2. Recheck the recorded NuGet owner/policy/API-key audit. Review the exact final
package-to-policy mapping and retire every identified alternative upload route.
3. After explicit authorization to change the existing CI, submit the cutover PR
Expand All @@ -134,6 +143,23 @@ never restore the unguarded legacy route as a rollback. Published package versio
are not transactional or safely overwriteable: reconcile NuGet state and use a
new reviewed version where necessary. External evidence storage remains deferred.

## Main verification after standby registration

Merged revision `06953d03815d5ae7152898abbbc91292505ec597` passed
[CI 40079546043, attempt 1](https://github.com/andregoepel/core/actions/runs/40079546043)
and [Sonar 40079586341, attempt 1](https://github.com/andregoepel/core/actions/runs/40079586341).
The existing CI publication job was skipped. Core has no separate E2E workflow.

The analysis and readiness artifacts were independently checked against the exact
source revision, CI job, run attempts, artifact hashes and live Sonar task. Analysis
`0be948bf-dfcd-48e7-bf79-316a78019339` passed with eight tests, 100% overall coverage,
100% new-code coverage across four new lines to cover, and no findings or hotspots.
The accepted baseline `e3555256-765a-4247-9489-9a22f02ff42b`, six gate conditions,
27 frozen profiles, disabled small-change exemption and absent coverage exclusions
were verified unchanged. The receipt remained `analysisReady: true` and
`releaseEligible: false`; its expiry was 2026-10-24 09:52:51 UTC. This is historical
validation evidence and cannot authorize a later publication.

## Remaining acceptance

#29 remains open until hosted integration, reviewed cutover and bypass removal
Expand Down
4 changes: 2 additions & 2 deletions scripts/sonar/nuget-policy.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"workflowId": 0,
"workflowSha256": "e37cf076466c862a445c82a597787f0ae4b82a96e2b74413bfea0fe6346143ca",
"workflowId": 394955059,
"workflowSha256": "5062bf43a381acb86da26048f548b109b3b76aba85998ef2a56e5e4fbfb17b5d",
"maximumAgeMinutes": 120,
"jobs": {
"prepare": ["Verify tag push", "Prepare NuGet batch", "Publish package batch", "Publish origin"]
Expand Down
Loading