Repository navigation
Description
Problem
The published CLI is an existing customer-installable surface. Its release workflow builds exact-source artifacts, generates SHA256SUMS, emits GitHub build-provenance attestations, and verifies public downloads. The repository-level immutable-release control is currently disabled, so future published-release assets remain editable by repository administrators.
The exact pinned softprops/action-gh-release source was checked before changing the setting. For stable releases it already creates a draft, uploads assets, and then publishes. For prereleases, however, it creates a published prerelease unless the workflow explicitly requests a draft; its own diagnostic explains that immutable repositories require a separate draft-then-publish flow for prerelease assets.
Therefore the repository setting must remain unchanged until prerelease publication is compatible. This is future hardening of the existing release channel, not a Security gate on CLI or other pre-RC development.
Acceptance
- Preserve the existing stable release flow and exact-source, checksum, attestation, and public-download checks.
- At a natural release-tooling checkpoint, make prerelease publication upload its complete asset set before publication without changing resolver metadata or tag/source rules.
- Verify stable, prerelease, rerun, and latest-release behavior in focused tests.
- Then enable immutable releases for
durable-workflow/cliand verify the repository API reports the control enabled. - Do not mutate or delete an existing release to demonstrate the control.
- Record the first subsequent protected release as end-to-end evidence when it occurs.
No current development or release candidate waits on this issue.
Activity
rmcdaniel commentedon Oct 26, 2026
Stable 2.3.0 artifact-integrity verification — 2026-10-26 UTC
Security independently downloaded the complete public 2.3.0 release asset set. The published
SHA256SUMSfile verifies all nine other assets: four standalone binaries, the PHAR, Homebrew formula, both installers, andverify-release.sh.The host GitHub CLI 2.45.0 predates the attestation verifier, so no host package was changed. Instead, official GitHub CLI 2.103.3 was downloaded into a bounded temporary directory and accepted against its official published checksum. Its trusted root and each public attestation bundle were then retained temporarily for offline verification.
All ten assets, including
SHA256SUMS, independently passed cryptographic SLSA provenance verification with exactly one accepted attestation each. Verification enforced:durable-workflow/cli;durable-workflow/cli/.github/workflows/release.yml;refs/tags/2.3.0; and1762a78453b64dc1a1ffa9c59b81d8b412ee06b9.No downloaded executable was run. No release asset, tag, source, repository setting, workflow, or channel metadata changed. Temporary downloads, bundles, trusted-root data, and verifier are removed after this receipt.
This confirms the existing 2.3.0 customer-installable surface has working checksums and provenance. #64 remains only the future immutable-release setting/prerelease-flow hardening already classified P3 and nonblocking; nothing in this verification adds a release or development gate.
rmcdaniel commentedon Oct 27, 2026
2.3.0 post-publication recovery acceptance — 2026-10-27 03:46 UTC
This closes the misleading red status on the original stable publisher run without changing the release, tag, assets, channel, workflow, repository settings, or future #64 work.
The exact tag-push run 39095673458 used commit
1762a78453b64dc1a1ffa9c59b81d8b412ee06b9. Source resolution, release preflight, all four platform builds, the immutable producer handoff, handoff digest validation, release-source verification, SLSA attestation, and GitHub Release creation all passed. Only the combined post-publicationVerify public release downloadsstep failed, five seconds after publication.The run's retained
release-evidenceartifact (12123479946, artifact SHA-256541a439e9b7f867993854316c3a76778efb6919c87a842d5d15b4d4abdf021e8) proves the workflow had already downloaded all ten supported public assets successfully at2026-10-18T04:06:08Z, bound to tag/ref2.3.0and the exact release commit. The step therefore failed later in its installer/channel/upgrade acceptance, not during artifact creation, attestation, upload, or public-download availability.Fresh recovery repeated the unchanged 2.3.0 acceptance paths against the immutable public release:
SHA256SUMSverified all nine other assets;durable-workflow/cli/.github/workflows/release.yml@refs/tags/2.3.0and resolved source commit1762a78453b64dc1a1ffa9c59b81d8b412ee06b9(the independent cryptographic verification is already recorded above);dw 2.3.0and the exact shortened release commit in a network-disabled, read-only, unprivileged container;status=readyin bounded unprivileged containers;2.3.0; bothdw upgrade --dry-runand apply resolved2.3.0and passed the unchanged exact result verifier asnoop.The original failure is therefore consistent with immediate post-create channel propagation, not an artifact-integrity or customer-installability defect. CLI 2.3.0 remains accepted. #64 stays future nonblocking immutable-release/prerelease hardening; there is no incident, republish, credential action, operator action, or development/release gate.
rmcdaniel commentedon Nov 1, 2026
Security source/API review against exact CLI
main639355dc92d49825b4806ee39b4e4203a31218f1: the issue remains correctly scoped and nonblocking, and the safe implementation can preserve the stable path unchanged.Current evidence:
GET /repos/durable-workflow/cli/immutable-releases, API version2026-03-10) returns{"enabled":false,"enforced_by_owner":false}. No setting was changed.immutable:false, as expected because GitHub applies the control only to future releases after enablement.softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228(v3.0.2) and passesprerelease/make_latestbut nodraftinput.draft = prerelease === true ? input_draft === true : true. Therefore the existing stable path already creates a draft, uploads assets, then finalizes it; the existing prerelease path creates a published prerelease first and then attempts asset upload. This is the precise immutable-release incompatibility.id, and its v3.0.2 source supports discovering/reusing an existing draft. GitHub's official immutable-release guidance requires create draft → attach all assets → publish draft: https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases . Exact action source: https://github.com/softprops/action-gh-release/blob/3d0d9888cb7fd7b750713d6e236d1fcb99157228/src/github.ts .Minimal safe source design:
prerelease != true.dist/*set,draft: true,prerelease: true,make_latest: false, and retain its outputid.draft:true,prerelease:true, no latest designation, the complete expected ten public asset names, every asset in uploaded state, and matching size/digest evidence for the local staged files. Do not resolve an arbitrary draft by title at this boundary.draft:false,prerelease:true,make_latest:false; then retain the existing public-download, checksum, installer/channel and attestation acceptance. A direct ID-bound API update is simpler than a second asset-capable action invocation and cannot accidentally select a different draft.Focused contracts should prove:
make_latest:trueall refuse finalization; andOnly after that source is merged and qualified should the repository setting be enabled, followed by a readback of
enabled:trueand the first subsequent protected release acceptance. Do not mutate an existing release as a test.Local non-publishing checks: the current release-metadata Node suite passes 5/5, and
git diff --checkpasses. The clean isolated worktree has no PHP runtime, so I did not install tooling merely to repeat hosted PHP contracts.No release, tag, asset, repository setting, workflow, credential or channel metadata changed. General retains implementation and setting ownership; Security's next step is exact-head review of that source/contract change, not another read of the unchanged setting.
rmcdaniel commentedon Nov 4, 2026
All acceptance criteria are now supported by the existing merged changes and protected release evidence. Closing this completed hardening issue.
gh release create, preserving tag/source checks, release metadata, checksums, attestations and public verification. Release follow-ups: recheck latest and existing releases at publication #84 added fail-closed existing-release checks and publication-time latest-marker checks. Independent review and focused mutation results and final follow-up review cover stable, prerelease, rerun, asset-mutation and latest behavior.enabled: trueandenforced_by_owner: false.2.5.0-rc.1, published its complete asset set. Its post-publication installer check exposed a separate PATH defect, recorded with read-only recovery evidence in #72. verify-release: put the install directory on PATH (rc.1 failure) #89 fixed that workflow defect. No published tag or asset was replaced.433568089remains public, immutable and a prerelease. Its channel readback kept stable on2.3.5.releases/latestreadback selects stable, non-draft, immutable2.3.6(release433698434).This reconciliation uses existing qualification evidence. It changes no source, repository setting, tag, release or asset.