Skip to content

release hardening: tested-is-shipped, pinned inputs, build-once, honest identity - #13

Merged
y1o1 merged 1 commit into
developfrom
chore/release-hardening-workflows
Jul 27, 2026
Merged

release hardening: tested-is-shipped, pinned inputs, build-once, honest identity#13
y1o1 merged 1 commit into
developfrom
chore/release-hardening-workflows

Conversation

@y1o1

@y1o1 y1o1 commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Workflow slice of the release-engineering track (dplaax.spec release.*
rules), shaped by a Codex plan review. Everything is repo-local; no image
changes until the next deliberate version cut
— no cut happens here.

change rule what was wrong
Node 24 in ci.yml (×3 jobs) + release.yml, engines: >=24 <25 in root package.json toolchain.tested-is-shipped CI tested on 22, every image stage ships node:24-alpine — each green check meant "green somewhere else"
corepack@0.35.0 in generated-instance Dockerfile ×2 + both scaffold templates (unpinned build input, named by the spec) npm install -g corepack --force floated to whatever npm served that day
release.ymlif: false with the reason provenance.per-ecosystem precondition it was only accidentally inert: tag pattern never matches and NPM_TOKEN doesn't exist. Neither accident is a gate
build-once guard + concurrency group in publish-images.yml build.once re-running a version tag would republish different bytes under the same name; now it fails with "cut a new version"
sha-tag wording rewritten; digests printed to job summary docs.match-artifacts, subject.exact-digest the header called sha-<sha> immutable — it names the source commit but is still a mutable registry tag; the digest is the identity
sbom: true sbom.subject-bound (partial) per-platform final-stage SPDX attestations, described as inventory, not completeness

Consciously deferred (recorded, not forgotten)

  • Base-image digest pins — digest-pinning bases without a scan/refresh loop
    freezes CVE fixes; net loss at this maturity. Comes with the P0-7 scanner
    track, which also owns index-digest evidence binding, provenance
    verification, and the scan/waiver state machine (the conformance ledger
    already declares all release.* unimplemented).
  • Compose GHCR references stay on the moving v0.2 tag — maintainer
    decision: cross-repo digest choreography costs more than it buys here. The
    wording fix (this PR + an oss-side follow-up) makes the claim honest instead.

Test plan

All workflows parse (yaml.safe_load ×5), package.json parses. CI on this PR
runs the Node-24 toolchain for the first time — build-and-test + both smokes
going green is the tested-is-shipped verification. The publish-images
changes are exercised at the next version cut; the build-once guard's
failure path was designed against the registry API responses verified today
(anonymous token + manifest HEAD, 200 vs 404).

🤖 Generated with Claude Code

…st identity

Workflow slice of the release-engineering track (dplaax.spec release.* rules).
Everything here is repo-local; nothing changes the published images until the
next deliberate version cut.

**Node 24 everywhere** (release.toolchain.tested-is-shipped): CI tested on 22
while every image stage ships node:24-alpine, which narrowed each green check
to "green somewhere else". CI and release.yml now test 24, and the root
package.json declares engines >=24 <25.

**corepack@0.35.0** in the generated-instance Dockerfile and both scaffold
templates: `npm install -g corepack --force` floated to whatever npm served
that day — an unpinned build input the spec calls out by name.

**release.yml explicitly disabled** (if: false): nothing is on npm and the
preconditions for publishing (trusted publishing, per-ecosystem provenance)
are not built. Until now it was only accidentally inert — its tag pattern
never matched and the NPM_TOKEN secret does not exist. Neither accident is a
gate; the if: line is. Re-enabling means building trusted publishing, not
restoring a token.

**build-once guard** (release.build.once): publishing a version tag now fails
if that tag already resolves in GHCR — the scanned bytes and a rebuild's bytes
are different artifacts sharing a name, and the exit is a new version. Plus a
concurrency group so two runs on one ref cannot interleave a multi-arch push.

**sha-<sha> is not "immutable"** (release.docs.match-artifacts): the header
called the sha tag immutable and the quickstart called it exactly
reproducible. It names the source commit but is still a registry tag — this
workflow itself would move it if re-run on the same commit. The docs now say
what is true: the digest is the identity, tags are locators. Each run prints
its digests to the job summary (release.subject.exact-digest, the cheap half).

**sbom: true**: per-platform final-stage SPDX attestations. Deliberately
described as inventory, not completeness — binding evidence to the index
digest is the release-evidence manifest's job and stays on the P0-7 track,
alongside base-image digest pins (consciously deferred: digest-pinning bases
without a scan/refresh loop freezes CVE fixes, a net loss at this maturity).
@y1o1
y1o1 merged commit ee9a29a into develop Jul 27, 2026
3 checks passed
@y1o1
y1o1 deleted the chore/release-hardening-workflows branch July 27, 2026 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant