Repository navigation
Fix vendored pnpm losing build approvals (#1597) - #1668
Mikola Lysenko (mikolalysenko) merged 5 commits into
Conversation
Assisted-by: Claude Code:claude-opus-5-5
pnpm 10.34.2+ matches allowBuilds / onlyBuiltDependencies against the id it installs a package under. A vendored package installs as name@file:.socket/vendor/npm/<uuid>/..., so a decision keyed by the package name stopped applying: pnpm 10 skipped the approved install script and pnpm 11/12 failed every frozen install with ERR_PNPM_IGNORED_BUILDS, while the scan exited 0. Vendoring now adds the same decision under the vendored key, next to the user's entry in pnpm-workspace.yaml or package.json#pnpm, and replaces a key an older patch left. Revert, rollback and remove take the added keys out again. A flow-style value the line surgery can't extend is left alone with a vendor_pnpm_build_approval_lost warning naming the key to add. Refs #1597 Assisted-by: Claude Code:claude-opus-5-5
Adds a real-pnpm e2e: a package with an approved postinstall is vendored on pnpm 11 (allowBuilds) and pnpm 10 (onlyBuiltDependencies), then a fresh frozen offline install of the committed files must land the patched bytes and still run the script, and revert must restore pnpm-workspace.yaml byte for byte. Documents the carry-over and the vendor_pnpm_build_approval_lost warning, and passes the ledger entry to revert_workspace instead of three of its fields. Refs #1597 Assisted-by: Claude Code:claude-opus-5-5
pnpm 10.20 through 10.34.1 refuse a name@file: key in allowBuilds or onlyBuiltDependencies (ERR_PNPM_INVALID_VERSION_UNION) and still match the vendored copy by name, so writing the key there would break every install. The key is now written only when the project's pnpm pins (packageManager, devEngines, engines.pnpm, node_modules/.modules.yaml) admit nothing older than 10.34.2. Without a usable pin the setting is left alone and vendor_pnpm_build_approval_lost names the key to add. Also from review: an added key follows the user's decision when it flips, multi-line flow values are parsed instead of substring-matched, non-boolean allowBuilds values are reported instead of copied, and the package.json key sits next to the user's entry. Refs #1597 Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
|
Burn-down agent: labeled Ready for review at
Generated by Claude Code |
pnpm matches a build decision against a file: tarball's own id from 11.5.3 on; 10.34.2 is its backport. 11.0.0 through 11.5.2 sort after 10.34.2 but still refuse a name@file: key with ERR_PNPM_INVALID_VERSION_UNION, so a project pinned there (for example packageManager pnpm@11.2.0) would have had every install broken by the added key. The gate now uses a threshold per major, and a pin range decides only when both ends agree within one major (^11.0.0 is unknown). Verified on real pnpm 11.5.2 (file: key rejected, name key builds) and 11.5.3 (file: key builds) in the e2e capstone. Refs #1597 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NDKy3guPS8y9iNNhPQGyR2
|
bugbot run Generated by Claude Code |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 7e1a1ae. Configure here.
|
Burn-down agent: Ready for review re-confirmed at new head
Generated by Claude Code |
Final review briefWhat it does. When a vendored pnpm scan rewires a package to Risk: low–medium. The change only touches the vendored pnpm v9 path and never edits the user's own entries. The riskiest part is the version gate: older pnpm (10.20–10.34.1, 11.0–11.5.2) rejects a Look here
Verified
Changes I made. None. Open questions. None blocking. Nit: a prerelease such as Auto-merge (squash) is armed, so approving sends this straight to the merge queue. Generated by Claude Code |
LLM Description written by Claude Code:claude-opus-5-5
Fixes #1597
Summary
A vendored pnpm scan no longer breaks the project's build approvals.
Before this change, vendoring a package whose install script the project
approves (
allowBuilds: {sp-build: true},onlyBuiltDependencies: [sp-build]) exited 0 with no warning. The next install on pnpm 10.34.2+silently skipped the script, and on pnpm 11/12 every frozen install failed
with
ERR_PNPM_IGNORED_BUILDSuntil the patch was rolled back.Vendoring now adds the same decision under the vendored key
(
sp-build@file:.socket/vendor/npm/<uuid>/sp-build-1.0.0.tgz) next tothe user's entry, and revert / rollback / remove take it out again.
Root cause
Vendored pnpm wires the package through a
file:override, so pnpminstalls it as
name@file:<spec>. Since pnpm 11.5.3 (backported to 10.34.2), build decisionsare matched against that id: a key naming the registry package
(
name,name@1.0.0) no longer applies, and only the fullname@file:<spec>key does. Nothing in the vendored pnpm path read thesesettings.
A second constraint, found while reviewing: pnpm 10.20–10.34.1 and 11.0–11.5.2 refuse
a
name@file:key outright (ERR_PNPM_INVALID_VERSION_UNION). Thoseversions still match the vendored copy by name, so they need no key.
That means the key can only be written when we know which pnpm runs.
Measured with real pnpm and a
file:tarball dependency with apostinstall:name@file:keyallowBuilds)pnpm 11+ reads only
allowBuilds;onlyBuiltDependencies,ignoredBuiltDependenciesandneverBuiltDependenciesare ignored therewhether or not the package is vendored.
Fix
New module
vendor/pnpm_build_approvals.rs, called from the pnpm (lock9.0) wiring step:
pnpm-workspace.yaml(
allowBuilds:block map,onlyBuiltDependencies:block list,column-0 items included) and
package.json#pnpm(same two fields). Apinned
name@x || ykey beats a name-only one.true/falsedecision rightafter the user's entry, only when every parseable pnpm pin
(
packageManager,devEngines,engines.pnpm,node_modules/.modules.yaml) admits only 10.34.2+ (within 10.x),11.5.3+ (within 11.x) or 12+. A pin admitting only older pnpm needs
nothing; a range crossing a threshold (
^11.0.0) counts as unknown. Without a usable pin, nothingis written and
vendor_pnpm_build_approval_lostnames the key to add.name@version)left, carrying its decision when it's the only one. An added key
follows the user's decision on re-runs when it flips.
[pkg], multi-line too) or a non-booleanallowBuildsvalue is left alone with the same warning.pnpm_ws_allow_build,pnpm_ws_only_built,pnpm_pkg_allow_build,pnpm_pkg_only_built)that revert removes; the workspace file and package.json byte-restore.
The version gate lives in
formats/pnpm/version.rs(
matches_file_id_build_keys), which now reads pins at patch precision.Docs:
CLI_CONTRACT.mdwarning table,docs/ecosystems.mdpnpm notes.No wrapper (
npm/,pypi/,gem/) change is needed: they onlydispatch the binary.
Test evidence
consumercopy too)pnpm_lock::tests::ws_build_approval_is_carried_to_the_vendored_key_and_revertedpnpm.onlyBuiltDependencies(pnpm 10)pnpm_lock::tests::package_json_only_built_approval_is_carried_and_revertedpnpm_lock::tests::superseding_patch_replaces_the_older_vendored_approval_keypnpm_lock::tests::inline_build_approval_warns_with_the_key_to_addpnpm_lock::tests::build_approval_key_is_written_only_for_a_pnpm_that_reads_ite2e_vendor_pnpm_build::pnpm_vendor_keeps_approved_build_scripts_runningpnpm_build_approvals::tests(13)formats::pnpm::version::tests::file_id_build_keys_start_at_10_34_2_and_11_5_3; e2e 11.5.2 leg fails on the old gateLocally (Linux):
cargo fmt --all -- --checkok,cargo clippy --workspace --all-features -- -D warningsok,full
cargo test --workspace --all-features --no-fail-fast: 14689passed, 10 failed, none in pnpm code. Nine are write-failure tests that
use chmod and can't fail when run as root (this container runs as uid 0):
copy_treesymlinked root,vlt_healunremovable lock,pypi_poetry/pypi_requirementswire failures, threein_process_redirectwrite-failure cases and two
repaircleanup failures. The tenth ise2e_bun_lockb::binary_shared_bundled_record_hosted_pin_is_managed, whichneeds to reach patches-api.socket.dev (blocked by this sandbox's proxy).
CI runs all of them unprivileged with network.
/code-review high
Fixed: version gate (finding 1, the largest: confirmed on real pnpm),
multi-line flow values and substring matching (3, 6), flipped decision
sync (4), non-boolean / anchored values (7), package.json key placement
(8), duplicated selection logic and repeated path parsing (10).
Not fixed, with reasons:
ignoredBuiltDependencies/neverBuiltDependencies(2): pnpm 10still matches those by name for the vendored copy (measured: 10.34.7
with
strictDepBuildsexits 0), and pnpm 11+ does not read them atall, vendored or not, so there is no decision to carry.
name@file:key for another uuid is removedwithout a record (5): it names a superseded patch's artifact, which the
supersede deletes, so the key is dead; restoring it on revert would only
re-add a key pointing at nothing.
package_globs(9): thatreader also handles flow values and returns globs for a different
caller; merging them is a separate refactor.
https://claude.ai/code/session_01NDKy3guPS8y9iNNhPQGyR2
Note
Medium Risk
Changes vendored pnpm workspace/package.json wiring and install-script behavior; version-gated with revert ledger records and warnings for ambiguous cases.
Overview
Fixes #1597: vendored pnpm no longer drops build script approvals when a package is wired as
name@file:.socket/vendor/....On pnpm 10.34.2+ / 11.5.3+,
allowBuildsandonlyBuiltDependenciesmatch the installed id, so name-only keys stopped applying after vendoring (skipped scripts on 10,ERR_PNPM_IGNORED_BUILDSon 11+). Vendoring now mirrors the same decision under the vendored key inpnpm-workspace.yamlandpackage.json#pnpm, records it in the wiring ledger, and revert/rollback removes those entries. A newmatches_file_id_build_keysgate informats/pnpm/version.rsonly writes thefile:key when project pins say pnpm needs it; older pnpm (or unparseable pins / flow-style values) getvendor_pnpm_build_approval_lostinstead of a silent break.Docs (
CLI_CONTRACT.md,docs/ecosystems.md) and unit/e2e tests cover carry, revert, superseded keys, and real pnpm installs.Reviewed by Cursor Bugbot for commit 7e1a1ae. Configure here.
Generated by Claude Code