From 059c4fc8d4578b3bd680451abfb810b7d2f64133 Mon Sep 17 00:00:00 2001 From: Dave Thompson Date: Thu, 17 Sep 2026 09:25:18 -0400 Subject: [PATCH] chore(release): prepare v0.4.12 Set the release identity and verified-bootstrap ceiling to v0.4.12. Add matching changelog, release notes, and detailed release documentation for the dependency refresh, immutable CI pins, and release-key cutover. Verification: make precommit Generated by GPT-5.6 Sol (https://openai.com) running OpenCode (https://opencode.ai) under supervision of [@3leapsdave](https://github.com/3leapsdave) Co-Authored-By: GPT-5.6 Sol Role: devlead Committer-of-Record: Dave Thompson [@3leapsdave] --- CHANGELOG.md | 25 +++++++++++- README.md | 22 +++++------ RELEASE_NOTES.md | 46 ++++++++++++++++++++++ VERSION | 2 +- docs/releases/v0.4.12.md | 47 +++++++++++++++++++++++ docs/security.md | 12 +++--- scripts/bootstrap-sfetch-verified.sh | 2 +- scripts/test-bootstrap-sfetch-verified.sh | 8 ++-- 8 files changed, 139 insertions(+), 25 deletions(-) create mode 100644 docs/releases/v0.4.12.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f1dcd0..18c3b78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.4.12] - 2026-09-17 + +### Changed + +- **Release trust anchors rotated to the current organization keys.** Within + the bootstrap engine and installer's supported v0.4.9–v0.4.12 pin range, + v0.4.12 selects only the new minisign and OpenPGP anchors. Pins through + v0.4.11 select only the previous anchors; these install paths never fall + back between keys. +- **Go and module refresh.** The module now declares Go 1.26.0 with the Go + 1.26.8 toolchain, jsonschema/v6 6.0.3, and current `x/crypto`, `x/sys`, and + `x/text` releases. +- **CI and security tooling refreshed.** Goneat moves to v0.6.0, + govulncheck to v1.8.0, and GitHub Actions use immutable commit pins. + +### Fixed + +- **Security-scanner compatibility for archive extraction.** Scoped G703 + dispositions document the existing path-containment checks at filesystem + sinks while the zip-slip rejection tests continue to enforce the boundary. + ## [0.4.11] - 2026-07-31 ### Added @@ -183,7 +204,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 > **Maintenance note:** This file is pruned to the latest 10 releases. For older entries, see `docs/releases/`. -[Unreleased]: https://github.com/3leaps/sfetch/compare/v0.4.10...HEAD +[Unreleased]: https://github.com/3leaps/sfetch/compare/v0.4.12...HEAD +[0.4.12]: https://github.com/3leaps/sfetch/compare/v0.4.11...v0.4.12 +[0.4.11]: https://github.com/3leaps/sfetch/compare/v0.4.10...v0.4.11 [0.4.10]: https://github.com/3leaps/sfetch/compare/v0.4.9...v0.4.10 [0.4.9]: https://github.com/3leaps/sfetch/compare/v0.4.8...v0.4.9 [0.4.8]: https://github.com/3leaps/sfetch/compare/v0.4.7...v0.4.8 diff --git a/README.md b/README.md index ed6db3d..4f56d41 100644 --- a/README.md +++ b/README.md @@ -214,14 +214,14 @@ Match `-P` to the tag: tags ≤ v0.4.11 verify under the previous key; newer tag ```bash # Three-step path when install-sfetch.sh.minisig is published (v0.4.11+) -TAG=v0.4.11 +TAG=v0.4.12 curl -fsSL "https://github.com/3leaps/sfetch/releases/download/${TAG}/install-sfetch.sh" -o install-sfetch.sh curl -fsSL "https://github.com/3leaps/sfetch/releases/download/${TAG}/install-sfetch.sh.minisig" -o install-sfetch.sh.minisig -minisign -Vm install-sfetch.sh -P RWTAoUJ007VE3h8tbHlBCyk2+y0nn7kyA4QP34LTzdtk8M6A2sryQtZC +minisign -Vm install-sfetch.sh -P RWTqUZ/PtmfAbQ3RKIlp/YTKT6zFeNMAZ8iAMelhlmqEsVqjKj3ctSA1 bash install-sfetch.sh --tag "$TAG" --yes # Or use the shared engine (CI/Makefile; refuses "latest"): -# ./scripts/bootstrap-sfetch-verified.sh --version v0.4.11 --dir ~/.local/bin +# ./scripts/bootstrap-sfetch-verified.sh --version v0.4.12 --dir ~/.local/bin ``` **GitHub Actions:** pin the composite action by commit SHA — see [CI/CD Usage Guide](docs/cicd-usage-guide.md). @@ -229,7 +229,7 @@ bash install-sfetch.sh --tag "$TAG" --yes ```yaml - uses: 3leaps/sfetch/.github/actions/setup-sfetch@ with: - sfetch-version: v0.4.11 + sfetch-version: v0.4.12 ``` #### Quick install (interactive humans) @@ -254,7 +254,7 @@ Pass arguments using `bash -s --`: curl -sSfL .../install-sfetch.sh | bash -s -- --dir ~/bin # Install specific version -curl -sSfL .../install-sfetch.sh | bash -s -- --tag v0.4.11 +curl -sSfL .../install-sfetch.sh | bash -s -- --tag v0.4.12 # Dry run (download and verify, don't install) curl -sSfL .../install-sfetch.sh | bash -s -- --dry-run @@ -302,13 +302,13 @@ Tag CI creates a **draft** release with unsigned archives. Maintainers generate export SFETCH_MINISIGN_KEY=/path/to/sfetch.key export SFETCH_PGP_KEY_ID=security@fulmenhq.dev # optional -RELEASE_TAG=v0.4.11 make release-download -RELEASE_TAG=v0.4.11 make release-checksums -RELEASE_TAG=v0.4.11 make release-sign # signs manifests + install-sfetch.sh +RELEASE_TAG=v0.4.12 make release-download +RELEASE_TAG=v0.4.12 make release-checksums +RELEASE_TAG=v0.4.12 make release-sign # signs manifests + install-sfetch.sh make release-verify -RELEASE_TAG=v0.4.11 make release-notes -RELEASE_TAG=v0.4.11 make release-upload -gh release edit v0.4.11 --draft=false # publish only after signatures upload +RELEASE_TAG=v0.4.12 make release-notes +RELEASE_TAG=v0.4.12 make release-upload +gh release edit v0.4.12 --draft=false # publish only after signatures upload ``` Set `RELEASE_TAG` to the tag you're publishing. The scripts in `scripts/` can be used individually if you prefer manual control. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index ba613fc..51fb7fe 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,3 +1,49 @@ +## v0.4.12 + +### Summary + +Supply-chain maintenance release with refreshed Go dependencies and immutable +CI action pins. It also completes the release-key rotation for verified +installation: within the bootstrap engine and installer's supported +v0.4.9–v0.4.12 range, v0.4.12 selects only the current organization keys while +pins through v0.4.11 select only the previous keys, without fallback. + +### Highlights + +**Trust anchors** +- The embedded minisign key and installer OpenPGP fingerprint now match the + current organization release-signing keys. +- For supported bootstrap and installer pins, exactly one key generation is + selected: v0.4.9–v0.4.11 use the previous keys; v0.4.12 uses the current + keys. Releases are not dual-signed and these install paths do not fall back + between anchors. + +**Toolchain and dependencies** +- Go module baseline 1.26.0 with toolchain 1.26.8. +- jsonschema/v6 6.0.3 plus refreshed `x/crypto`, `x/sys`, and `x/text` modules. +- Goneat v0.6.0 and govulncheck v1.8.0. + +**CI and security checks** +- GitHub Actions are pinned to immutable commit SHAs. +- Archive-extraction G703 dispositions are scoped to sinks already protected + by path-containment checks and zip-slip rejection tests. + +### Install + +Use the verified bootstrap engine with an exact tag: + +```bash +./scripts/bootstrap-sfetch-verified.sh --version v0.4.12 --dir "$HOME/.local/bin" +``` + +The action revision and `sfetch-version` pin are coupled: consumers advancing +to v0.4.12 must also select an action revision whose declared range includes +v0.4.12. Outside a checkout, retrieve the bootstrap engine at an immutable +revision and verify its pinned digest before execution; see the +[CI/CD Usage Guide](docs/cicd-usage-guide.md). + +--- + ## v0.4.10 ### Summary diff --git a/VERSION b/VERSION index 5f749c1..75274d8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.4.11 +0.4.12 diff --git a/docs/releases/v0.4.12.md b/docs/releases/v0.4.12.md new file mode 100644 index 0000000..3916c87 --- /dev/null +++ b/docs/releases/v0.4.12.md @@ -0,0 +1,47 @@ +# sfetch v0.4.12 + +Supply-chain maintenance and release trust-anchor rotation. + +## Highlights + +### Trust anchors + +- The embedded minisign key and installer OpenPGP fingerprint now match the + current organization release-signing keys. +- For bootstrap engine and installer pins in the supported v0.4.9–v0.4.12 + range, exactly one key generation is selected: v0.4.9–v0.4.11 use the + previous keys; v0.4.12 uses the current keys. Releases are not dual-signed + and these install paths do not fall back between anchors. + +### Toolchain and dependencies + +- Go module baseline 1.26.0 with toolchain 1.26.8. +- jsonschema/v6 6.0.3 plus refreshed `x/crypto`, `x/sys`, and `x/text` modules. +- Goneat v0.6.0 and govulncheck v1.8.0. + +### CI and security checks + +- GitHub Actions are pinned to immutable commit SHAs. +- Archive-extraction G703 dispositions are scoped to sinks already protected + by path-containment checks and zip-slip rejection tests. + +## Verified bootstrap + +Use the release's bootstrap engine with an exact tag: + +```bash +./scripts/bootstrap-sfetch-verified.sh --version v0.4.12 --dir "$HOME/.local/bin" +``` + +The action revision and `sfetch-version` pin are coupled: consumers advancing +to v0.4.12 must also select an action revision whose declared range includes +v0.4.12. Outside a checkout, retrieve the bootstrap engine at an immutable +revision and verify its pinned digest before execution; see the +[CI/CD Usage Guide](../cicd-usage-guide.md). + +## Compatibility + +There are no CLI or configuration contract changes. The key-selection statement +above applies to the bootstrap engine and installer within their declared +supported pin range; it does not change the CLI's general verification +contract. diff --git a/docs/security.md b/docs/security.md index a115c3b..6bbc6e5 100644 --- a/docs/security.md +++ b/docs/security.md @@ -140,15 +140,15 @@ export SFETCH_MINISIGN_KEY=/path/to/key.key export SFETCH_MINISIGN_PUB=/path/to/key.pub export SFETCH_PGP_KEY_ID=your-key-id # optional -RELEASE_TAG=v0.4.11 make release-download -RELEASE_TAG=v0.4.11 make release-checksums -RELEASE_TAG=v0.4.11 make release-sign +RELEASE_TAG=v0.4.12 make release-download +RELEASE_TAG=v0.4.12 make release-checksums +RELEASE_TAG=v0.4.12 make release-sign make release-verify-signatures make release-export-keys make release-verify-keys -RELEASE_TAG=v0.4.11 make release-notes -RELEASE_TAG=v0.4.11 make release-upload -gh release edit v0.4.11 --draft=false +RELEASE_TAG=v0.4.12 make release-notes +RELEASE_TAG=v0.4.12 make release-upload +gh release edit v0.4.12 --draft=false ``` ### What is signed (v0.4.11+) diff --git a/scripts/bootstrap-sfetch-verified.sh b/scripts/bootstrap-sfetch-verified.sh index f965006..df9e0de 100755 --- a/scripts/bootstrap-sfetch-verified.sh +++ b/scripts/bootstrap-sfetch-verified.sh @@ -43,7 +43,7 @@ set -euo pipefail # make test-bootstrap-range-release asserts MAX == v$(cat VERSION) using two # committed values at the same SHA (never self-advancing at install time). readonly SFETCH_BOOTSTRAP_MIN="v0.4.9" -readonly SFETCH_BOOTSTRAP_MAX="v0.4.11" +readonly SFETCH_BOOTSTRAP_MAX="v0.4.12" # First release that publishes install-sfetch.sh.minisig (route selection). # Keep this accurate: too low → minisig route without asset; too high → 5-step # when 3-step exists. Both routes verify; neither silently falls back. diff --git a/scripts/test-bootstrap-sfetch-verified.sh b/scripts/test-bootstrap-sfetch-verified.sh index 0906c46..989649a 100755 --- a/scripts/test-bootstrap-sfetch-verified.sh +++ b/scripts/test-bootstrap-sfetch-verified.sh @@ -46,7 +46,7 @@ if "$SCRIPT" --version latest --dir /tmp 2>/dev/null; then fail "latest should f if "$SCRIPT" --version main --dir /tmp 2>/dev/null; then fail "main should fail"; else pass "rejects main"; fi if "$SCRIPT" --version v0.4.11-rc1 --dir /tmp 2>/dev/null; then fail "prerelease should fail"; else pass "rejects prerelease"; fi if "$SCRIPT" --version v0.4.8 --dir /tmp 2>/dev/null; then fail "below min should fail"; else pass "rejects below min"; fi -if "$SCRIPT" --version v0.4.12 --dir /tmp 2>/dev/null; then fail "above max should fail"; else pass "rejects above max"; fi +if "$SCRIPT" --version v0.4.13 --dir /tmp 2>/dev/null; then fail "above max should fail"; else pass "rejects above max"; fi # F2: leading-zero components must not pass range/route selection if "$SCRIPT" --version v0.4.09 --dir /tmp 2>/dev/null; then fail "v0.4.09 leading zero should fail"; else pass "rejects v0.4.09 leading zero"; fi if "$SCRIPT" --version v0.04.11 --dir /tmp 2>/dev/null; then fail "v0.04.11 leading zero should fail"; else pass "rejects v0.04.11 leading zero"; fi @@ -337,7 +337,7 @@ grep -Eq 'anchor=legacy' "$OUT_CURONLY" || fail "expected anchor=legacy selectio if grep -q '^route=' "$OUT_CURONLY"; then fail "failed run must not emit machine route="; fi pass "old pin ignores current anchor (no fallback)" -# Post-cutover selection: fake v0.4.12 pin (MAX patched in temp copy only). +# Post-cutover selection: v0.4.12 is in the production engine's supported range. # Stand-in keys prove the rule: new pins use current, previous-key sigs fail. NEWENG="$WORKDIR/newpin-engine.sh" make_fixture_engine "$NEWENG" "$BASE" "$OLD_EPHEMERAL_PUBKEY" "SFETCH_MINISIGN_PUBKEY_LEGACY" @@ -345,9 +345,7 @@ sed -i.bak "s|${PROD_PUBKEY}|${NEW_EPHEMERAL_PUBKEY}|g" "$NEWENG" grep -q "$NEW_EPHEMERAL_PUBKEY" "$NEWENG" || fail "new-pin engine missing current stand-in" grep -q "$PROD_PUBKEY" "$NEWENG" && fail "new-pin engine still has production current key" grep -q "$OLD_EPHEMERAL_PUBKEY" "$NEWENG" || fail "new-pin engine lost legacy stand-in" -sed -i.bak 's|SFETCH_BOOTSTRAP_MAX="v0.4.11"|SFETCH_BOOTSTRAP_MAX="v0.4.12"|' "$NEWENG" -grep -q 'SFETCH_BOOTSTRAP_MAX="v0.4.12"' "$NEWENG" || fail "new-pin engine MAX patch failed" -rm -f "${NEWENG}.bak" +grep -q 'SFETCH_BOOTSTRAP_MAX="v0.4.12"' "$NEWENG" || fail "new-pin engine MAX drifted" # Positive: post-cutover pin verifies against the current anchor. minisign -S -s "$NEWKEY" -t "test-v0.4.12-new" -m "$SRV_ROOT/v0.4.12/install-sfetch.sh"