From 87e3f1f9bfd083b067c868d13f1883acca6f2fd7 Mon Sep 17 00:00:00 2001 From: Andrei Hasna Date: Wed, 5 Aug 2026 09:51:08 +0300 Subject: [PATCH 1/2] =?UTF-8?q?chore(release):=200.5.26=20=E2=80=94=20ship?= =?UTF-8?q?=20the=20merged=20publish-time=20supply-chain=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cuts 0.5.26 so the merged prepublishOnly hardening reaches installs. main has carried the fix since 1afd0f97 (PR #88) but stayed at 0.5.25, which is already the published npm version — so the fix reached nobody. The merge is NEWER than the tarball (merge 2026-08-05T04:44:21Z, publish 2026-08-05T01:27:21Z), which is exactly why this is invisible: every version surface reads all-green and comparing version strings finds nothing. The fix: `prepublishOnly` ran `cd dashboard && bun install` with no flags, so `npm publish` performed a dependency resolution AFTER Typecheck, Test and Build had all passed — the reviewed tree and the published tree separated by a resolution no gate could observe. `build:dashboard` now passes --frozen-lockfile and --minimum-release-age 604800, release.yml builds the dashboard inside the gated part of the workflow and fails if dashboard/dist is missing, and ci.yml exercises that dependency tree on the pull request. This bumps package.json and nothing else. Scope of the release, measured rather than inferred: the tag npm/conversations/v0.5.25 points at e83fd2e (#86), and `git log npm/conversations/v0.5.25..origin/main` is exactly two commits — #88 above, and #87, a test-only change. Tests are not packaged (`files` is dist/, bin/, dashboard/dist/, LICENSE, README.md), so #87 does not alter the tarball. Publishing is by tag through release.yml's OIDC trusted-publisher binding (trigger `npm/conversations/v*`, environment npm-release). This PR neither publishes nor tags, and takes no token. Agent: Silvanus --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ebe0164..da1bb93 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@hasna/conversations", - "version": "0.5.25", + "version": "0.5.26", "description": "Real-time CLI messaging for AI agents", "type": "module", "bin": { From 4dc8835737361f7091b0a0d273e0d0cda2dcb7ff Mon Sep 17 00:00:00 2001 From: Andrei Hasna Date: Wed, 5 Aug 2026 10:15:08 +0300 Subject: [PATCH 2/2] =?UTF-8?q?docs(changelog):=20record=200.5.26=20?= =?UTF-8?q?=E2=80=94=20the=20publish-time=20supply-chain=20fix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remediation of the P1 raised by adversarial review (reviewer Vespasian, lens version-bump-correctness, NO_GO on #89). The review measured that this repo's recent releases carry a CHANGELOG entry — 12 of the last 14 package.json-touching commits do — and that #89 omitted one with no stated reason, unlike its sibling hasna/emails#203, which justifies the identical-looking omission with a concrete gate. Verified independently before acting: this repo does section per release (`## 0.5.25 - 2026-08-05` exists), and `git grep CHANGELOG origin/main -- src scripts .github` returns nothing, so there is no digest tripwire here of the kind that makes the emails omission mandatory. The two repos genuinely differ; the finding is correct. Also note #88 itself never touched CHANGELOG.md, so its fix was undocumented entirely rather than merely unsectioned. Adds a `## 0.5.26 - 2026-08-05` section above 0.5.25 describing the prepublishOnly hardening: the unpinned and unquarantined dashboard install, what each of --frozen-lockfile and --minimum-release-age actually buys (they are not interchangeable, and the latter does not re-validate versions already pinned in the lockfile), and the release.yml/ci.yml changes that move that dependency tree inside the gated part of the workflow. Agent: Silvanus --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9faace7..a1148e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file. ## Unreleased +## 0.5.26 - 2026-08-05 + +### Fixed + +- **The dashboard install at publish time is pinned and quarantined.** `prepublishOnly` ran `cd dashboard && bun install` with no flags, so `npm publish` performed a dependency resolution *after* Typecheck, Test and Build had all passed — the reviewed tree and the published tree were separated by a resolution no gate could observe. `dashboard/` is a second dependency tree with its own lockfile that no CI job installed or built, so its first and only install happened inside the publish itself. + + Two distinct exposures, both measured on bun 1.3.14. **Unpinned:** on a drifted lockfile, plain `bun install` exits 0, silently re-resolves and rewrites `bun.lock` ("Saved lockfile"); with `--frozen-lockfile` the same state exits 1 and leaves the lockfile untouched. **Unquarantined:** the release-age quarantine on a workstation comes entirely from `~/.bunfig.toml`, which does not exist on a GitHub runner — the identical install of a 5-day-old package exits 1 with a real `HOME` and exits 0 with an empty one. + + `build:dashboard` now passes `--frozen-lockfile --minimum-release-age 604800`. The two flags are not interchangeable and this does not pretend they are: `--frozen-lockfile` is load-bearing and removes resolution from the publish boundary entirely, while `--minimum-release-age` is defence in depth enforced at resolution time only — it does **not** re-validate versions already pinned in the lockfile. A lockfile pinning a too-new version is caught by review of the lockfile diff, not by these flags. + + `release.yml` now builds the dashboard inside the gated part of the workflow, before the publish boundary, and fails if `dashboard/dist` is missing: `files` ships `dashboard/dist/`, and npm silently omits a listed path that does not exist rather than failing, so a dashboard that never built would publish as a tarball quietly missing its web UI. `ci.yml` runs the same command so a drifted `dashboard/bun.lock` surfaces as a red check on the pull request that caused it, rather than as a late release failure. + ## 0.5.25 - 2026-08-05 ### Fixed