Skip to content

v0.10.31.

Complete release notes · 2026-10-01. Read upgrade instructions and runtime limits before deploying.

The chain-guard release (r475): the release chain audited itself. The last never-audited surface produced this round's only P1 — and the guards it shipped are the ones yesterday's v0.10.30 escape proved were missing.

Security / Release integrity

  • Version provenance is verified before anything is built or pushed (P1). Tags are created by hand (git tag vX <commit>), and nothing in the chain compared the tag's VALUE to what the checkout contains — a typo or a stale SHA would pass every check (it IS a green commit), push a mislabeled image whose panel reports a different VERSION, silently roll :latest backward, and create a GitHub Release the CHANGELOG asset contradicts. release-publish.yml now asserts tag == package.json == version.ts immediately after checkout, before install/build/push; release-workflows.test.ts pins the step's existence, its content and its position before pnpm install.

Fixed

  • The local gate now means what CI's gate means (P2). pnpm release:check was a single turbo run typecheck lint build test — turbo has no dependency edges between those task names, so the phases could interleave (and a warm tree could satisfy server#test from a stale apps/web/dist). CI's verify job has always run the four invocations sequentially; release:check now mirrors it: pnpm typecheck && pnpm lint && pnpm build && pnpm turbo run test --concurrency=1. This is exactly the gap the 0.10.30 unparseable-version.ts escape slipped through locally.

  • bump-version.js refuses to lie (P2). A pattern miss on the load-bearing VERSION literal printed a warning and exited 0 — ten package.jsons saying 0.10.31 while the panel kept reporting 0.10.30, every gate green. That miss is now fatal, and the script closes by asserting every package.json and the VERSION literal actually landed on the new version before printing its success banner.

Added

  • pnpm release:tag — the local tag gate. Wraps git tag with the checks the drill previously held as discipline: clean working tree; the tag does not already exist (re-tagging stays an explicit delete-and-recreate); tag == package.json == version.ts == CHANGELOG[0] read from the exact commitish via git show (not the working tree); no unfilled stub survives; and the server typechecks — the precise step an unescaped-apostrophe changelog fails. Used for this very release.

Verified sound (for the record)

CI's structure held under the audit: build-before-checks, checks-before-push, needs-gated edge publish, least-privilege permissions, no pull_request_target/fork-secret exposure, strict tag-shape validation; bump-version.js is idempotent with no flag bypass of the >=1.0.0 owner policy. The parked dependency majors stay parked with evidence: drizzle-kit 0.31.11 still depends on the deprecated @esbuild-kit/esm-loader (our patch remains required; the bump buys nothing), and js-yaml 4.3.2 carries no advisory while pm2 pins the 4.x line.

Source CHANGELOG.md at 6046cfe8