Skip to content

chore: drop the packageManager pin and relocate pnpm overrides - #96

Merged
hakula139 merged 1 commit into
mainfrom
chore/remove-package-manager-pin
Aug 19, 2026
Merged

chore: drop the packageManager pin and relocate pnpm overrides#96
hakula139 merged 1 commit into
mainfrom
chore/remove-package-manager-pin

Conversation

@hakula139

@hakula139 hakula139 commented Aug 18, 2026

Copy link
Copy Markdown
Owner

Summary

Remove the packageManager pin from package.json so pnpm comes from the Nix flake instead of the registry. Moving off pnpm 10 forces the DoS advisory overrides into pnpm-workspace.yaml, because pnpm 11 no longer reads the pnpm field in package.json.

Why the pin has to go

pnpm 10+ self-manages its version from this field by default: every invocation downloads that exact pnpm from the registry and re-execs into it, so the pnpm that runs is never the one the environment provides. The same flake binary, with and without the field:

$ pnpm --version   # /nix/store/...-pnpm-11.21.0/bin/pnpm, packageManager present
10.30.3
$ pnpm --version   # identical binary, field removed
11.21.0

Offline it fails outright ([ERROR] GET https://registry.npmjs.org/pnpm: fetch failed). There is no opt-out: manage-package-manager-versions=false in a project .npmrc is read back correctly by pnpm config get, yet pnpm switches anyway. Matching the pin to a developer's pnpm is no fix either, since pnpm skips the download only on an exact version match, so the next upgrade re-triggers it. Absence of the field is the only stable state.

Design decisions

  • The overrides move rather than being duplicated. pnpm 11 ignores pnpm.overrides in package.json ([WARN] The "pnpm" field in package.json is no longer read by pnpm). With the overrides dropped, the config no longer matches the lockfile and pnpm install --frozen-lockfile fails hard with ERR_PNPM_LOCKFILE_CONFIG_MISMATCH, so the node-check job would break the moment the pin is removed. Keeping a copy in both places would leave a permanent pnpm 11 warning and invite drift.
  • Still compatible with pnpm 10. pnpm 10.30.3 reads overrides from pnpm-workspace.yaml too. A negative control confirms the file is genuinely read rather than merely tolerated: deleting it makes 10.30.3 fail with the same ERR_PNPM_LOCKFILE_CONFIG_MISMATCH.
  • Nothing else consumed the field. There is no Dockerfile, no corepack, and no pnpm/action-setup. CI already runs nix develop -c pnpm ..., so pnpm came from the flake and the pin was only overriding it. A tree-wide grep for packageManager, corepack, and 10.30 now returns no matches.
  • No allowBuilds entries needed. pnpm 11 escalates ignored dependency build scripts to a hard error, but this tree has none, so the pnpm 11 install is clean.

Changes

File Description
package.json Drop packageManager and the now-ignored pnpm.overrides block
pnpm-workspace.yaml New: overrides pinning the patched js-yaml and markdown-it

Test plan

Run against real pnpm binaries with no --ignore-scripts, capturing each exit code separately rather than through a pipe. CI's pnpm is the flake's 11.6.0; also checked on 11.21.0 and the previously pinned 10.30.3.

  • nix develop -c pnpm install --frozen-lockfile: rc=0 on pnpm 11.6.0, and pnpm-lock.yaml stays byte-identical, checked against the committed blob rather than a copy (git show origin/main:pnpm-lock.yaml | cmp - pnpm-lock.yaml rc=0, git diff origin/main -- pnpm-lock.yaml empty), with lockfileVersion: '9.0' unchanged
  • nix develop -c pnpm lint: rc=0, 48 files, 0 errors
  • nix develop -c pnpm spellcheck: 185 files, 0 issues, rc=0 (see Notes)
  • nix flake check: rc=0, all hooks pass
  • pre-commit run --files package.json pnpm-workspace.yaml: rc=0
  • pnpm 11.21.0 install --frozen-lockfile: rc=0, lockfile unchanged
  • pnpm 10.30.3 install --frozen-lockfile against the new workspace file: rc=0. Negative control with the file removed: rc=1, ERR_PNPM_LOCKFILE_CONFIG_MISMATCH
  • Overrides still in force: pnpm why resolves a single js-yaml@4.2.0 and markdown-it@14.2.0, and the lock holds zero js-yaml@4.1.1 / markdown-it@14.1.1 entries

Notes

  • A spellcheck rc=1 during validation was an artifact, not a regression. Validation ran in a worktree under a gitignored path, so cspell's useGitignore: true discovered 0 files and exited 1 (git check-ignore points at .gitignore:28:.claude/worktrees/). From a non-ignored path, and with --no-gitignore, it reports 185 files and 0 issues at rc=0. CI checks out at the repo root, so it is unaffected.

Not verified: the Rust gates (cargo fmt, clippy, cargo test, llvm-cov) and nix build .#oxide-code were not run, since this change touches only package.json and pnpm-workspace.yaml and feeds no Rust input. The offline registry failure and the .npmrc opt-out attempt were not reproduced in this run; both carry over from the original investigation.

`packageManager` made pnpm self-manage its own version: every invocation
downloaded pnpm 10.30.3 from the registry and re-exec'd into it, so the
pnpm that ran was never the one the flake provided. Offline that fails
outright, and there is no opt-out.

Removing the pin moves the project onto the flake's pnpm 11, which no
longer reads the `pnpm` field in package.json. The DoS overrides from
the js-yaml and markdown-it advisories move to pnpm-workspace.yaml,
where both pnpm 10 and 11 read them.
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@hakula139 hakula139 self-assigned this Aug 19, 2026
@hakula139
hakula139 merged commit 77b69f3 into main Aug 19, 2026
7 checks passed
@hakula139
hakula139 deleted the chore/remove-package-manager-pin branch August 19, 2026 03:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant