fix(release): derive DSH bootstrap version from installer bytes - #7107
Merged
Conversation
The production landing-page promotion pinned DSH_BOOTSTRAP_VERSION: v1 in the workflow, while the publisher refuses to overwrite an already-published immutable version with different bytes. PR #6983 renamed the brand inside install-dsh.ps1 and install-dsh.sh without bumping that pin, so the next production deploy failed closed on immutable bootstrap object already exists with different content: bootstrap/dsh/v1/install-dsh.ps1 and skipped every later step, including the Cloudflare Pages deploy. The version is a function of the installer bytes, so maintaining it as a hand-written constant guarantees this drift. The publisher now resolves the version itself: it probes published versions in order using SHA256SUMS as the fingerprint for the whole set, reuses the version that already holds these exact bytes, and mints the next one when the bytes changed. Every published version keeps if-none-match: * and the immutable cache header, so history stays permanent and unoverwritable -- only the manual bump is gone. A mutable bootstrap/dsh/latest.json pointer records the current version, per-file sha256, and the publishing run, and the verify step reads the resolved version instead of naming one. DSH_BOOTSTRAP_VERSION survives as an explicit escape hatch: setting it forces one version and still fails closed on a content mismatch.
Contributor
🚀 Landing page previewThis PR is deployed to a Cloudflare Pages preview — not staging or production:
|
nettee
approved these changes
Aug 19, 2026
nettee
left a comment
Contributor
There was a problem hiding this comment.
I reviewed all five changed files and verified the byte-derived version resolution, immutable R2 writes, latest pointer, workflow output handoff, documentation, and regression coverage. I ran pnpm guard, pnpm typecheck, the focused DSH bootstrap publisher test (2 passed), and the packaged workflow smoke test (70 passed, 1 skipped); everything passed. This is a thoughtful fix for the production version-drift failure—nice work preserving the fail-closed path while making normal promotions self-healing.
🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The last production landing-page promotion (run 32213116590) failed and never reached Cloudflare Pages, so open-design.ai is still serving the 08-14 build.
The failing step was
Publish immutable DeepSeek Harness bootstrap installers to R2:landing-page-production.ymlpinnedDSH_BOOTSTRAP_VERSION: v1, while the publisher refuses to overwrite an already-published immutable version whose bytes differ. #6983 renamed the brand to OpenDesign insideinstall-dsh.ps1andinstall-dsh.sh(5 copy lines total) without bumping that pin, so the very next production deploy failed closed — and because the step sits before the deploy, every later step was skipped, including the Pages publish and the D1 migration.The fail-closed behavior is correct and worth keeping: these bytes get an immutable one-year cache header and act as the supply-chain archive for the
open-design.ai/install-dsh.*entry points. The defect is that the version is a function of the installer bytes but was maintained as a hand-written constant. Anyone editing a line of installer copy has to remember to bump a version in a workflow they are not touching, and the failure surfaces only at production promotion time with an error that never names the fix.What users will see
Nothing changes about the one-click install commands themselves — they still point at
open-design.ai/install-dsh.*.Operationally, editing an installer no longer breaks the production deploy. The promotion resolves the bootstrap version on its own: unchanged installers reuse the published version, changed installers roll forward to the next one.
https://releases.open-design.ai/bootstrap/dsh/latest.jsonis new and names the current version plus each file's sha256 and the publishing run.On the next production run this failure clears itself: the publisher sees that
v1holds different bytes, mintsv2with the OpenDesign copy, and leavesv1intact as the historical archive. No brand rename gets reverted.Surface area
Bug fix verification
tools/serve/tests/dsh-bootstrap-publish.test.tsmain, green on this branch: yesThe existing suite already ended with an assertion that changed bytes must throw. That assertion is inverted into the new expected behavior (auto-mint
v2,v1keeps its original bytes, pointer follows), plus a rollback case proving previously-published bytes reuse their original version instead of minting a third copy. Run against the pre-fix publisher it fails on the missingDSH_BOOTSTRAP_VERSION; against this branch both tests pass.A second test pins
DSH_BOOTSTRAP_VERSIONexplicitly and asserts the old fail-closed error still fires, so the escape hatch keeps its guarantee.How it resolves the version
SHA256SUMSfingerprints all three installers, so one GET per version decides the whole set. The publisher probesv1,v2, … and settles on the first version that either does not exist (mint it) or already holds exactly these bytes (reuse it).This needs no new R2 permissions — the storage layer only signs
GET/PUTand has noListObjectsV2, and the probe is GET-only. Every published version still goes up withif-none-match: *and the immutable cache header, so history stays permanent and unoverwritable; only the manual bump is gone. Concurrent promotions of different bytes still collide on the 412 path and fail loudly rather than clobbering.Adjacent issues
Not addressed here: the R2 archive has no consumer that actually diffs it against what Pages serves, so its supply-chain value is currently latent. Worth deciding separately whether to publish these checksums to users or drop the archive.
Validation
pnpm guard— exit 0pnpm typecheck— exit 0pnpm --filter @open-design/tools-serve typecheck/@open-design/tools-release typecheck— exit 0tools/serve→vitest run tests/dsh-bootstrap-publish.test.ts— 2 passed (red before the fix)e2e→vitest run tests/packaged-smoke-workflow.test.ts— 70 passed, 1 skippedNot run: the real R2 publish path. It needs production credentials, so it is exercised through the storage fixture server rather than end-to-end.