Skip to content

Fix pnpm hosted redirects across legacy and peer lock entries - #240

Merged
Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
fix/pnpm-hosted-compatibility
Sep 16, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
fix/pnpm-hosted-compatibility

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

Hosted pnpm redirects missed block-style resolutions in older lockfiles and refused nested peer keys and CRLF files. A separate confirmation bug allowed an already-hosted URL in one instance to report a patch as redirected even when another instance of the same dependency was refused.

This change reads pnpm package blocks without reserializing unrelated YAML, supports legacy shrinkwrap.yaml and modern lock formats, and rewrites every matching peer instance atomically across the lockfile set. Refused pnpm patch UUIDs are excluded from CLI confirmation. Exact original resolution fragments remain available for rollback.

The sweep also found two installation constraints:

  • pnpm 1.0.0 discards hosted URLs even during frozen installation. Its early shrinkwrap format now produces an explicit refusal with no lock edits or successful redirect recorded, plus upgrade/agent-mode guidance.
  • Several pnpm versions can retain upstream files after a successful warm install. The CLI and documentation now prescribe a clean install tree and empty store followed by installed-file VEX verification; --force alone is not portable.

Adds a CI matrix with 25 pinned releases across pnpm majors 1–12, exact-version checks, and setup failures treated as failures. The suite covers cold and warm installs, verified VEX, scan and explicit-UUID entry points, idempotency, lock-only discovery, byte-exact rollback, and rejection of tampered tarballs. Workspace cases on majors 6–12 include scoped packages, npm aliases, multiple peer contexts, and peers of peers. Captured locks preserve offline grammar coverage.

The atomic-refusal regression uses a malformed peer key, preserving the refusal check while valid nested peers now succeed. The alternate-installer fixture also recognizes Bundler 1's direct vendor/bundle/gems layout alongside the Ruby ABI subdirectory layout; both Bundler 1.17.2 and 2.4.22 were verified.

Validation completed locally on macOS:

  • 24 positive pinned-version installation cases and the expected pnpm 1.0.0 refusal passed.
  • Workspace/alias/peer proofs passed on all 15 pinned releases in majors 6–12.
  • 345 core redirect tests, pnpm fixtures and shared goldens, CLI pnpm unit/integration tests, verified VEX tests, and hosted rollback tests passed.
  • The strict production-service install proof passed with pnpm 10.33.0 and Node 24.11.1.
  • Targeted Clippy with warnings denied, formatting, actionlint, and diff whitespace checks passed. The 25-version Ubuntu matrix has also passed in GitHub Actions.

The matrix samples major boundaries and representative releases; it does not claim exhaustive coverage of every historical release or configuration. Hosted SBOM recognition and dashboard alert action/count behavior are outside this repository and are not changed by this PR.


Note

Medium Risk
Changes core hosted lockfile rewrite and confirmation logic that directly affects which tarballs install; mitigated by fail-closed partial rewrites, explicit legacy refusals, and a broad pinned-version CI matrix.

Overview
Expands hosted pnpm lock rewriting from modern pnpm-lock.yaml flow mappings to legacy shrinkwrap.yaml, block-style resolutions, LF/CRLF, scoped keys, aliases, and nested peer instance keys—rewriting every matching instance atomically or refusing the dependency across the whole lockfile set.

The redirect engine moves pnpm parsing into a dedicated pnpm module (byte-range splices instead of the old regex writer). pnpm 1.0.0 early shrinkwrapVersion: 3 locks are now explicitly refused (redirect_pnpm_legacy_lockfile_unsupported) because those installers drop hosted URLs. refused_pnpm_uuids stops the CLI from confirming/VEX-attesting a patch when another instance was left upstream or the rewrite was incomplete.

Trust and install guidance now treats legacy locks as pnpm 1–8 (no trust step), includes clean node_modules/empty-store reinstall advice in redirect_pnpm_trust_lockfile, and documents limits (VEX vs dashboard SBOM).

CI and tests: new pnpm-compatibility workflow with 25 pinned pnpm releases (majors 1–12), required e2e matrix legs (install, VEX, rollback, tamper, workspace peers), captured lock fixtures, and updated contracts/docs (CLI_CONTRACT.md, pnpm-compatibility.md, ecosystems.md).

Reviewed by Cursor Bugbot for commit 3b176c2. Configure here.

@mikolalysenko
Mikola Lysenko (mikolalysenko) merged commit b19c968 into main Sep 16, 2026
95 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the fix/pnpm-hosted-compatibility branch September 16, 2026 20:40
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.

2 participants