Repository navigation
fix(cli,create-objectstack): scaffolds declare vitest ~4.1.12, outside GHSA-qxg6-89mg-rqv8, and still install on npm 10 - #25173
Conversation
…GHSA-qxg6-89mg-rqv8 SCAFFOLD_VITEST_RANGE moves from ~4.0.0 to ~4.1.12; the blank template's devDependencies.vitest and overrides.vitest are re-stamped from it by scripts/sync-scaffold-emission-policy.mjs. The npm override (unchanged in shape) is what keeps npm 10 installing vitest 4.1.12's contradictory optional peer set; measured on npm 10.9.4, 10.9.9 and 11.21.1. A floor pin keeps the range at or above the advisory's fixed release. Claude-Session: https://claude.ai/code/session_01AFrKwndmrCLtF5V9hNtrw3 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 12 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 6 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 30 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 8477db1bd320894594fe4c93c740e0be1b94e1f2 && git checkout 8477db1bd320894594fe4c93c740e0be1b94e1f2
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin ab488d9b7dff7a8da918973311f83c3bf443e51b f355f41a2c524a97eca689928c22d2cd5c7b801e && git checkout -B drift-repro ab488d9b7dff7a8da918973311f83c3bf443e51b && git merge --no-ff f355f41a2c524a97eca689928c22d2cd5c7b801e
node scripts/docs-audit/affected-docs.mjs --json ab488d9b7dff7a8da918973311f83c3bf443e51b
|
…affold-vitest-advisory
…ide at ~4.1.12 The troubleshooting entry told an npm 10 project to add overrides.vitest ~4.0.0, which installs vitest 4.0.18, inside GHSA-qxg6-89mg-rqv8, and contradicts the range the scaffolds now ship. It now prescribes ~4.1.12, names vitest 4.1.12's contradictory optional peer as the cause, says a direct vitest devDependency must move with the override (EOVERRIDE), and says how an existing ~4.0.0 project moves. Claude-Session: https://claude.ai/code/session_01AFrKwndmrCLtF5V9hNtrw3 Co-authored-by: Claude <noreply@anthropic.com>
席位核对 · ACCEPT (landing on green)
Generated by Claude Code |
Fixes #25165
Clause-②: no
Metadata-protocol: none
What this does
SCAFFOLD_VITEST_RANGEinpackages/cli/src/commands/init.tsmoves from~4.0.0to~4.1.12.os init -t pluginandos create plugindeclare it indevDependencies.SCAFFOLD_NPM_OVERRIDES, which is built from it, puts it in theoverridesof every standaloneos init/os create pluginmanifest. The override's shape is unchanged.devDependencies.vitestandoverrides.vitestare re-stamped from that constant by the write run ofscripts/sync-scaffold-emission-policy.mjs, the same runcreate-objectstack'sbuildinvokes. Both scaffolders read one constant, and no value is kept by hand.packages/cli/test/scaffold-npm-overrides.test.ts: the range's lowest admitted version must be at or above the advisory fix for its major (4.1.12 on 4.x, 5.0.3 on 5.x). A major with no row is refused, not passed..changeset/25165-scaffold-vitest-advisory.mdbumps@objectstack/cliandcreate-objectstackatpatchand gives the one-line move for existing projects.content/docs/deployment/troubleshooting.mdx(patch round): the npm 10edgesOutentry's fix 2 prescribedoverrides.vitest~4.0.0, which installs vitest 4.0.18, inside the advisory. It now prescribes~4.1.12. The entry names vitest 4.1.12's contradictory optional peer as the cause, says a directvitestdevDependency must move with the override (EOVERRIDE), and says how an existing~4.0.0project moves.The advisory
I read the advisory from the npm registry's bulk advisory endpoint (
registry.npmjs.org/-/npm/v1/security/advisories/bulk, 2026-10-22). This container's egress proxy refusesapi.osv.dev(403 at CONNECT).@vitest/mocker: affected from 2.1.0-beta.7 up to the fix in 4.1.12, and from 5.0.0-beta.1 up to the fix in 5.0.3. That confirms the card's range.npm auditof a baseline scaffold (~4.0.0, which resolves vitest and@vitest/mockerto 4.0.18) also lists:@vitest/mocker, from 2.1.0 up to the fix in 4.1.11);vitest, critical, from 4.0.0 up to the fix in 4.1.0).Route measurements
Method.
--cachefor every leg.@objectstack/*ranges are^18.0.0, which resolves to the published 18.0.0.vitestand every@vitest/mockercopy fromnode_modules, then rannpm audit --json.Manifests.
os init -t plugin,os create plugin,os init -t appandos init -t emptymanifests. Their dependency blocks are byte-equal to what this branch's source emits, driven throughpackages/cli/bin/run-dev.js.npm versions. 10.9.9 (the newest 10.x), 10.9.4 (the npm bundled with this container's Node 22) and 11.21.1 (the newest 11.x).
In the table, "4.1.12" means the tree holds exactly one
vitestand one@vitest/mocker, both at that version.~4.0.0+ overrideos init -t plugin,os create plugin~4.1.12, no overrideos init -t plugin,os create pluginCannot read properties of null (reading 'edgesOut')os init -t app(declares no vitest), no overrideedgesOut~4.1.12+ overrideos init -t plugin,os create pluginvitest/@vitest/*entryos init -t app,os init -t empty^5.0.5, no overrideedgesOut^5.0.5+ overrideos init -t plugin,os create plugin5.0.4+ override (simulateslatesthaving moved past the range)os create pluginaudits to 0 entries on routes B and D. The other manifests keep 9 moderate entries on every route, and all 9 trace to one advisory: GHSA-w5hq-g745-h8pq onuuid8.x, reached throughexceljsfrom@objectstack/rest(see Acceptance notes).Why route B holds on npm 10
The crash comes from vitest 4.1.12's own peer set. It peers
@vitest/browser-webdriverio ^4.1.11, and that package's only release, 4.1.11, peersvitest: 4.1.11exactly. With the range at~4.1.12, the root vitest reaches that peer set directly, so route A crashes every manifest that declares vitest.-t appcrashes too, through optional vitest peers deeper in its closure.The
vitestoverride alone settles it. Withoverrides.vitestequal to the declared range, npm 10.9.4 and 10.9.9 install every manifest. No@vitest/browser-webdriveriooverride is needed. The override is the existingSCAFFOLD_NPM_OVERRIDESmechanism, unchanged in shape.It does not depend on where
latestpoints.latestis vitest 5.0.5, outside~4.1.12, and the range still installs. The old comment's reading against^5.0.0("installs only because it resolves to exactly the versionlatestnames") was taken without an override. With the override, an exact pin belowlatest(5.0.4) installs too.Registry canary failed: fresh npx create-objectstack install is broken #24462's canary. On npm 10.9.9 the full blank template (every template file, with this PR's
package.json):npm test:RUN v4.1.12,Test Files 1 passed (1),Tests 1 passed (1);npm run build, exit 0,Artifact: dist/objectstack.json.The canary installs published artifacts, so it reads this change only after a release.
The plugin scaffolds. Each was emitted from this branch's source and installed on npm 10.9.9 (vitest and
@vitest/mocker4.1.12).npm run buildandnpm run typecheckexit 0 for both. Theirnpm testresult is in Acceptance notes.Why 4.1.x and not 5.x
Routes B and D both install on npm 10 and npm 11, and both clear the advisory. On the four axes:
note.test.ts) needs nothing from vitest 5. vitest 5.0.5 declaresengines.node^22.12.0 || ^24.0.0 || >=26.0.0, which is narrower than the>=22.0.0that@objectstack/cliandcreate-objectstackdeclare. vitest 4.1.12 declares^20.0.0 || ^22.0.0 || >=24.0.0, the same as 4.0.18. So only route D gives a new project on Node 22.0 to 22.11 an engine warning, or a refusal underengine-strict.vitest ^4.1.11, re-locked to 4.1.12 for the same advisory family ([finding] main's lockfile matches two new OSV advisories on @vitest/mocker 4.1.11 (GHSA-qxg6-89mg-rqv8, GHSA-xp26-3454-mjgp; fixed in 4.1.12): the scheduled OSV scan is red again #25163). A scaffold on that line runs the vitest the platform is tested with. Moving to 5 is a deliberate change of its own, for the monorepo and the scaffolds together.Tests (head
4eb2ff4c4)pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2, run under the verify lock.VERDICT command-exit 1,Test Files 2 failed | 320 passed (322),Tests 4728 passed | 29 skipped.test/published-subpath-console.pin.test.tsandtest/published-subpath-hook-body.pin.test.tsrefusing an unbuiltpackages/cli/dist: a missing build, not a test failure.test/scaffold-npm-overrides.test.ts(verbose):VERDICT command-exit 0,Test Files 3 passed (3),Tests 41 passed (41). That run includes the new floor case:its lowest admitted version is at or above the advisory fix for its major.pnpm --filter create-objectstack test:Test Files 18 passed (18),Tests 278 passed (278).pnpm --filter @objectstack/cli typecheck && pnpm --filter create-objectstack typecheck:VERDICT command-exit 0.tsc -p tsconfig.test.json --listFilesinpackages/clilistsscaffold-npm-overrides.test.tsonce.create-objectstack'stsc --listFilesliststemplate-consistency.test.tsonce.pnpm exec eslint --no-inline-configover the 3 changed TypeScript files: exit 0.scripts/ablation-replace.mjsin wrap mode.SCAFFOLD_VITEST_RANGE = '~4.1.12'became'~4.0.0'. The anchor went from 1 to 0 hits, and the blob changed from47a2518d9a21to8da3d5de0b48.Tests 1 failed | 11 passed (12), withSCAFFOLD_VITEST_RANGE "~4.0.0" admits 4.0.0, below the fix 4.1.12. The 11 derived-equality cases stay green under the mutation, which is why the floor pin is needed.47a2518d9a21),git diff HEADis empty andgit statusis clean.../src/commands/init.js, so nodistis on its path.Gates (head
4eb2ff4c4)node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 84 commands for 5 paths against merge base425c743fd.check:dual-build-cjs-loads,check:i18n,check:i18n-coverageandcheck:i18n-walk-parityexited 3 (PREREQUISITE NOT MET: no builtdist).turbo run build, 75/75 tasks, under the lock), all four re-ran to exit 0.--ran:84 derived, 84 run, 0 NOT-MEASURED, 0 UNRUN, exit 0.node scripts/pm/check-governed-merges.mjs --branch claude/issue-25165-scaffold-vitest-advisory: exit 0, 0 of 5 paths governed, 176 changed lines.check:scaffold-emission-policy(the template and the constant agree) andcheck:template-version-sync.Patch round (head
f355f41a2)origin/mainwas merged first (a22074c89), then the troubleshooting page was fixed (f355f41a2). The diff is now 6 paths against merge baseab488d9b7.dispatch-gates --commandsderives 112 commands. Each was run with its exit code captured before any pipe, after a full package build (75/75 tasks). All 112 exited 0.--ranreports112 run, 0 NOT-MEASURED, exit 0.check-governed-merges: 0 of 6 paths governed, 186 changed lines.test/scaffold-npm-overrides.test.tspasses 12/12 andcreate-objectstackpasses 278/278.f355f41a2: 39 check-runs succeeded and 7 were skipped. They includeCheck Documentation Links,Build Docs,Scaffold outside the monorepo, install, buildandCheck Changeset.Acceptance notes
scripts/sync-scaffold-emission-policy.mjs, the comment on thedevDependencies.vitestrow still says the constant "holds why it is~4.0.0". It is a comment outside the file surface, and the script reads the constant's value, not the comment.npm auditentries all come from GHSA-w5hq-g745-h8pq onuuid8.x, throughexceljs^4.4.0in the published@objectstack/rest. The workspace overridesuuidinpnpm-workspace.yaml, which npm consumers never read. That is not this card.npm test.os init -t pluginandos create pluginemit atestscript but no test file, sonpm testexits 1 with "No test files found". It does the same on the baseline 4.0.18 (measured on-t plugin). That is not this card.ab488d9b7) was merged into the branch in the patch round (merge commita22074c89). It had no conflicts.Generated by Claude Code