chore: migrate from npm to pnpm 11 with 2-day release-age cooldown#274
Conversation
Pins pnpm@11.1.2 via packageManager (Corepack) and sets minimum-release-age=2880 in .npmrc so dependency resolution skips versions younger than 2 days, mitigating supply-chain attacks via quickly-yanked malicious releases. Dependabot gets a matching cooldown.default-days: 2 across all five ecosystems. GitHub Actions enable Corepack before setup-node and use cache: pnpm with pnpm install --frozen-lockfile. Release publish uses pnpm publish --no-git-checks since tag-based release runs from detached HEAD. @eslint/js is added as an explicit devDependency pinned to ^9.39.4 — pnpm's strict node_modules layout no longer satisfies it via npm's flat hoisting. esbuild's install script is allowlisted via pnpm-workspace.yaml (pnpm 11 blocks dependency build scripts by default). Taskfile, devcontainer setup, bump-version script, and CONTRIBUTING.md updated for pnpm. package-lock.json replaced by pnpm-lock.yaml.
🧪 CI ResultsFormatting
Linting
TestsJavaScript Runtimes
Rust Library
Overall Status: ✅ All checks passing Last updated: 2026-05-16 00:24:54 UTC | View CI Run 🤖 |
pnpm 11.1.2 uses node:sqlite, a builtin added in Node 22. Workflows were pinned to Node 20, causing Corepack to fail with ERR_UNKNOWN_BUILTIN_MODULE when downloading pnpm. Library engines stays at >= 20 — consumers are unaffected. NAPI binaries are not Node-version-coupled, so building on Node 22 is safe. The publish job stays on Node 24.
pnpm publish writes to stderr only — it does not produce log files at ~/.npm/_logs/ like npm does. The upload step would always find zero files. Failure diagnostics remain available via the GitHub Actions step log for 'Publish to npm'.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bb9eb35. Configure here.
| @@ -1 +1,2 @@ | |||
| @jsr:registry=https://npm.jsr.io | |||
| minimum-release-age=2880 | |||
There was a problem hiding this comment.
Supply-chain cooldown setting silently ignored by pnpm 11
High Severity
pnpm 11 only reads authentication and registry settings from .npmrc; all other settings must be in pnpm-workspace.yaml. The minimum-release-age=2880 line in .npmrc is silently ignored, so the intended 2-day supply-chain cooldown never takes effect. The setting belongs in pnpm-workspace.yaml as minimumReleaseAge: 2880 (camelCase). pnpm 11's built-in default of 1440 minutes (1 day) still applies, but the explicit 2-day policy matching the Dependabot cooldown.default-days: 2 configuration is not enforced, creating a false sense of security.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit bb9eb35. Configure here.
#287) * ci(release): pin publish job to Node 24 for npm OIDC trusted publisher Node 22 ships npm 10.9.x, which lacks OIDC trusted publisher support (introduced in npm 11.5.1). #274 unintentionally regressed the publish job from node-version: 24 to node-version-file: .node-version (= 22), causing v2.0.0 publish to fail with 404 because no NPM_TOKEN exists and the OIDC handshake never ran. Restore node-version: 24 on the publish job only. Build/test jobs continue to use .node-version so the minimum-supported-runtime guarantee remains tested. * style: fix oxfmt quote style


Summary
packageManager+ Corepack).minimum-release-age=2880(2 days, in minutes) to.npmrcso pnpm refuses to resolve dependency versions younger than 2 days — mitigates supply-chain attacks via quickly-yanked malicious releases.cooldown.default-days: 2across all five ecosystems (cargo, devcontainers, github-actions, npm, rust-toolchain).package-ecosystem: "npm"— it auto-detects pnpm frompnpm-lock.yaml.Notable changes
corepack enableadded beforesetup-node;cache: pnpm;npm install/npm ci→pnpm install --frozen-lockfile; CI path triggers updated topnpm-lock.yaml. Release publish usespnpm publish --no-git-checks(tag-based release runs from detached HEAD).@eslint/jsadded as explicit devDependency (pinned to^9.39.4to match the version previously hoisted by npm). pnpm's strictnode_moduleslayout no longer satisfies it transitively viaeslint.esbuildinstall script allowlisted inpnpm-workspace.yaml— pnpm 11 blocks dependency build scripts by default.Taskfile.ymlusespnpm execinstead ofnpx; devcontainer setup,bump-version.js, andCONTRIBUTING.mdupdated.package-lock.jsonremoved,pnpm-lock.yamladded.Test plan
pnpm install --frozen-lockfileclean (no ignored-build warnings)task fmt:prettier:checkpassestask lint:eslintpassestask check:typescriptpassestask compilepassesNote
Medium Risk
Medium risk because it changes the project’s dependency manager and updates CI/release workflows (including Node version bumps and publishing via
pnpm), which can break installs, caching, or the release pipeline if any step differs from npm behavior.Overview
Migrates the repo’s JavaScript tooling from npm to
pnpm(via Corepack): devcontainer setup,Taskfile.ymlcommands (npx→pnpm exec), andpackage.json(packageManager,prepublishOnly) are updated accordingly, andpackage-lock.jsonis removed.GitHub Actions workflows are updated to enable Corepack, use Node 22 for most jobs, switch install steps to
pnpm install --frozen-lockfile, and adjust caching/CI triggers topnpm-lock.yaml; the release workflow also switches publishing topnpm publish --no-git-checks.Adds a 2-day dependency “cooldown” policy:
minimum-release-age=2880in.npmrcand matchingcooldown.default-days: 2across Dependabot ecosystems, plus minor repo hygiene updates (e.g., ignoringpnpm-lock.yamlin Prettier and adding@eslint/jsexplicitly).Reviewed by Cursor Bugbot for commit bb9eb35. Bugbot is set up for automated code reviews on this repo. Configure here.