Skip to content

Fix pnpm 12.0–12.12 scoped tarball: restore (#1619) - #1678

Merged
Mikola Lysenko (mikolalysenko) merged 3 commits into
mainfrom
agent/fix-pnpm12-scoped-tarball-restore
Oct 23, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 3 commits into
mainfrom
agent/fix-pnpm12-scoped-tarball-restore

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Fixes #1619

Summary

pnpm 12.0.0 through 12.12.x write tarball: for every package from a scoped registry (@scope:registry= in .npmrc, or registries."@scope" in pnpm-workspace.yaml), even with lockfileIncludeTarballUrl off. Until now, a hosted rollback, a remove of the scoped pin and the hosted → vendored takeover all wrote those entries back without tarball:, so the restored pnpm-lock.yaml no longer matched what pnpm wrote. With this change they write the URL back. pnpm ≤ 11 and pnpm ≥ 12.13 behave as before.

Root cause

pnpm 12.0–12.12 decide whether to record a tarball by comparing it with the conventional URL under the default registry, not under the package's scope registry. pnpm 12.13.0 fixed this upstream (pnpm#16866). restore_pnpm_locks (patch/redirect/upstream/npm.rs) always compared with the scope registry, so it treated the URL as one pnpm derives and dropped it. pnpm_lock_tarball_evidence had the same blind spot: in a lock with only scoped entries, it would read such a URL as proof that lockfileIncludeTarballUrl is on.

All three paths (rollback, remove, takeover) go through upstream::restore_upstream → restore_pnpm_locks, so one fix covers them.

Change

Test evidence

  • in_process_redirect::pnpm_12_restore_keeps_the_scoped_registry_tarball: covers rollback and remove pkg:npm/%40socktest/scoped-pkg@1.0.0 on a lock with a scoped entry plus a bare npmjs entry (the shape of the issue's repro). pnpm 12.12.1, 12.0.0 and 12.11.2 keep tarball:; 12.13.0, 12.14.0 and 11.28.6 stay bare. The pnpm version comes from .modules.yaml or the package.json pin, and the scope registry from .npmrc or pnpm-workspace.yaml registries.
    • Red before the fix: pnpm 12.12.1 rollback (modules true, workspace false) restored {integrity: sha512-UPSTREAMupstream==} where pnpm had written {integrity: …, tarball: http://127.0.0.1:…/scoped/@socktest/scoped-pkg/-/scoped-pkg-1.0.0.tgz}. Green after.
  • Unit tests (upstream::npm::tests): pnpm_12_before_13_records_scoped_tarballs (version bounds), pnpm_12_scoped_tarball_is_no_include_tarball_evidence (evidence check), pnpm_12_policy_compares_scoped_tarballs_with_the_default_registry (policy with a non-npmjs default mirror).
  • Local runs:
    • cargo fmt --all -- --check: ok
    • cargo clippy --workspace --all-features -- -D warnings: ok
    • cargo test -p socket-patch-cli --all-features --test e2e_redirect_pnpm_build -- --ignored --skip pnpm_pinned_matrix: 11/11 passed
    • all 24 pnpm tests in in_process_redirect: passed
    • cargo test --workspace --all-features --no-fail-fast: 234 test binaries ok. The failures are all from this sandbox, not the change: 9 permission-denial tests can't fail when run as root (chmod 0o555 doesn't stop root; e.g. repair_cleanup_failure_is_reported…, an_unremovable_hidden_lock…, wire_write_failure_maps_error…), and e2e_bun_lockb::binary_shared_bundled_record_hosted_pin_is_managed fetches a blob from the live patches-api.socket.dev, which this sandbox can't reach. None of them touch pnpm code. CI runs as non-root with network access.

Per-issue checklist

Review notes (/code-review high)

Fixed: merged the two duplicate derivability calls into one, shared the "own registry" rule (pnpm_registry_is_own), and added a unit test of the policy branch with a non-npmjs default. Not fixed, with reasons:

https://claude.ai/code/session_01SRLnkLy52eFiW2Un4SHYXU


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
pnpm 12.0.0 through 12.12.x record the tarball URL of every package
installed from a scoped registry, because they compare it with the
default registry's conventional URL instead of the scope's. Rollback,
remove and the hosted to vendored takeover dropped that URL from the
restored pnpm-lock.yaml, so the lock no longer matched what pnpm wrote.

The restore now reads the pnpm minor from the same install record,
package.json pin or rush.json pnpmVersion it already uses, and for
those releases judges a scoped package's URL against the default
registry, both when restoring the entry and when reading the lock's
lockfileIncludeTarballUrl evidence. pnpm 11 and 12.13+ are unchanged.

Fixes #1619

Assisted-by: Claude Code:claude-opus-5-5
Fold the two derivability calls in the pnpm restore policy into one,
share the rule for whether a pnpm-named registry is the project's own
with the lock-evidence check, and unit-test the policy with a non-npmjs
default registry next to the scope registry.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ 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 87750af. Configure here.

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 23, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Ready for review at 87750af. CI: 86/86 checks settled green on this head (36 passed, 50 skipped by path filters); no main-wide failures. Bugbot reviewed 87750af and found no issues; no open review threads. Reviewer focus: the pnpm 12.0–12.12 version gate in pnpm_records_scoped_tarballs and how pnpm_tarball_registry falls back to the default registry for scoped names (crates/socket-patch-core/src/patch/redirect/upstream/npm.rs).


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Final review brief

What it does. pnpm 12.0–12.12 record tarball: for every package from a scoped registry (they compare against the default registry's URL; fixed upstream in 12.13). The hosted restore (rollback, remove, hosted → vendored takeover) compared against the scope registry and so dropped those URLs. This reads the pnpm minor from the existing tier-2 evidence (.modules.yaml, package.json pin, rush.json) and, for 12.0–12.12 only, compares scoped names with the default registry, in both the restore and the lock-evidence check.

Risk: low. Behavior changes only when the pnpm version is known to be 12.0–12.12 and the package is scoped; every other version takes the old path (scoped_tarballs = false). Unknown version keeps the old behavior.

Look here

Verified. Read the full diff and registry_derives_tarball it feeds. Version parsing handles +sha suffixes and leaves a bare pnpm@12 out of the gate (conservative). Unscoped names are unaffected; a scope registry equal to the default stays derived. Ran cargo test -p socket-patch-core --lib pnpm locally: 458/458 pass. CI green on 87750af (ci-ok, clippy), Bugbot clean, no review threads, CHANGELOG.md untouched. Tests would fail without the change (PR shows the red run).

Changes I made. None.

Open questions. None blocking. Known limits (documented in the PR): no version evidence → old behavior; .modules.yaml names the last installer, same assumption as #902.

Auto-merge is armed, so approving sends it straight to the merge queue.


Generated by Claude Code

Merged via the queue into main with commit 7714c7c Oct 23, 2026
86 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the agent/fix-pnpm12-scoped-tarball-restore branch October 23, 2026 14:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hosted pnpm 12.0–12.12 rollback drops the scoped-registry tarball: URL pnpm recorded, so the restored lock isn't byte-exact

3 participants