Skip to content

fix(pm): verify and content-key managed package-manager installs - #3400

Merged
fengmk2 merged 1 commit into
mainfrom
feat/content-keyed-pm-installs
Nov 9, 2026
Merged

fengmk2 merged 1 commit into
mainfrom
feat/content-keyed-pm-installs

Conversation

@fengmk2

@fengmk2 fengmk2 commented Nov 9, 2026

Copy link
Copy Markdown
Member

Summary

When Vite+ downloads a managed package manager (pnpm, Yarn 2+, bun, and
native pnpm 12+), it now verifies the downloaded bytes against the integrity
the project declares in its packageManager field — or, for the pnpm that
global setup bootstraps, against the hash the CLI carries — rather than the
integrity the registry reports. A verified install is cached in a
content-addressed directory keyed by that pin (and, for a platform-binary
manager, the registry origin), so a different pin always resolves to a
different, independently verified directory.

This makes managed installs reproducible regardless of the user's global
package-manager version or a project's registry configuration, and keeps
private registries and mirrors working: a genuine mirror serves identical
bytes and matches the pin.

What changed

  • Verification against the declared pin. The generic, bun, and
    native-pnpm download paths verify the download against the packageManager
    integrity hash. Yarn 2+ pins cover the CLI file; bun and pnpm 12+ pins cover
    the main tarball, with the platform binary verified against the registry's
    dist.integrity. Setup's bootstrap pnpm is verified against the hash pinned
    in the binary.
  • Content-keyed layout. A pinned install lives at
    <DATA>/package_manager/<name>/.verified-v1/<version>/<key>/<name>, a hidden
    namespace only a verified download writes to; an unpinned install stays at
    <DATA>/package_manager/<name>/<version>/<name>. A complete keyed directory
    is reused without re-reading the pin; a different pin resolves elsewhere and
    triggers a fresh, verified download.
  • Immutable publish. A complete install is never replaced; downloads stage
    in a sibling temp directory and publish under a per-version lock.
  • Archive extraction skips link entries (as npm does), so a package
    tarball writes only regular files into its own install directory.
  • vp env commands (which, current, doctor, list, clean,
    uninstall) understand both layouts: reporting selects the install the shim
    runs for the project pin, and inventory and removal cover the unpinned root
    and the verified namespace.

Compatibility

  • Unpinned installs and existing version-directory paths are unchanged.
  • The pinned-install location moves under the .verified-v1 namespace;
    existing unpinned caches are reused as-is.

🤖 Generated with Claude Code

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://feat-content-keyed-pm-installs-viteplus-dev.voidzero-docs.workers.dev (commit fffa2f4)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://6df99568-viteplus-dev.voidzero-docs.workers.dev fffa2f4 2026-11-09T11:03:07.346Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://089c0bd8-viteplus-dev.voidzero-docs.workers.dev 96fe846 2026-11-09T10:59:05.924Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://95178fb4-viteplus-dev.voidzero-docs.workers.dev eee2bec 2026-11-09T10:34:33.689Z Visit the dashboard ↗

@fengmk2 fengmk2 self-assigned this Nov 9, 2026
@fengmk2 fengmk2 changed the title feat(pm): verify and content-key managed package-manager installs fix(pm): verify and content-key managed package-manager installs Nov 9, 2026
@github-actions

github-actions Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

CLI artifact sizes (fffa2f4)

Final release artifacts built by the canonical build-upstream and build-windows-cli actions.
The dist rows use the Linux build. The core total excludes .node files to match the release artifact.

Artifact Format Base PR Change
packages/cli/dist Directory total 2.33 MiB 2.33 MiB 0 B (0.00%)
packages/core/dist Directory total 4.09 MiB 4.09 MiB 0 B (0.00%)
Combined package dist Directory total 6.42 MiB 6.42 MiB 0 B (0.00%)
vp (Linux x64) Binary 8.31 MiB 8.31 MiB -120 B (-0.00%)
vp (Linux x64) gzip -9 3.80 MiB 3.80 MiB +1.10 KiB (+0.03%)
NAPI (Linux x64) Binary 36.26 MiB 36.27 MiB +7.89 KiB (+0.02%)
NAPI (Linux x64) gzip -9 14.47 MiB 14.48 MiB +7.09 KiB (+0.05%)
vp (macOS ARM64) Binary 5.42 MiB 5.42 MiB -64 B (-0.00%)
vp (macOS ARM64) gzip -9 3.23 MiB 3.24 MiB +2.76 KiB (+0.08%)
NAPI (macOS ARM64) Binary 43.05 MiB 43.05 MiB -48 B (-0.00%)
NAPI (macOS ARM64) gzip -9 18.68 MiB 18.68 MiB -2.60 KiB (-0.01%)
vp (Windows x64) Binary 6.16 MiB 6.16 MiB +2.50 KiB (+0.04%)
vp (Windows x64) gzip -9 2.85 MiB 2.85 MiB +3.10 KiB (+0.11%)
NAPI (Windows x64) Binary 32.37 MiB 32.38 MiB +3.50 KiB (+0.01%)
NAPI (Windows x64) gzip -9 13.25 MiB 13.25 MiB +4.46 KiB (+0.03%)
Trampoline (Windows x64) Binary 13.50 KiB 13.50 KiB 0 B (0.00%)
Trampoline (Windows x64) gzip -9 7.09 KiB 7.09 KiB -2 B (-0.03%)
Installer (Windows x64) Binary 4.66 MiB 4.66 MiB +4.00 KiB (+0.08%)
Installer (Windows x64) gzip -9 2.23 MiB 2.24 MiB +3.78 KiB (+0.17%)

Verify a downloaded managed package manager (pnpm, Yarn 2+, bun, and native
pnpm 12+) against the integrity the project declares in its `packageManager`
field -- or, for the pnpm global setup bootstraps, against the hash the CLI
carries -- rather than the integrity the registry reports. Cache a verified
install in a content-addressed directory keyed by that pin (and, for a
platform-binary manager, the registry origin), under a hidden `.verified-v1`
namespace that only a verified download writes to; an unpinned install stays at
the version-directory root. A different pin resolves to a different, verified
directory.

- Reuse a complete keyed directory without re-reading the pin; a different pin
  triggers a fresh, verified download. A complete install is never replaced.
- Skip link entries when extracting package-manager archives, as npm does, so a
  tarball writes only regular files into its own install directory.
- Keep the Windows `.cmd` fallback on the shim's cached fast path.
- `vp env which`/`current`/`doctor`/`list`/`clean`/`uninstall` understand both
  the unpinned version-directory root and the verified namespace.

Co-Authored-By: arkmarta <arkadiuszmarta@proton.me>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@fengmk2
fengmk2 force-pushed the feat/content-keyed-pm-installs branch from 96fe846 to fffa2f4 Compare November 9, 2026 11:02
@fengmk2 fengmk2 added test: e2e Auto run e2e tests test: install-e2e run vite install e2e test test: create-e2e Run `vp create` e2e tests test: sfw labels Nov 9, 2026
@fengmk2
fengmk2 merged commit a110977 into main Nov 9, 2026
201 of 225 checks passed
@fengmk2
fengmk2 deleted the feat/content-keyed-pm-installs branch November 9, 2026 11:20
@fengmk2 fengmk2 mentioned this pull request Nov 9, 2026
fengmk2 added a commit that referenced this pull request Nov 9, 2026
Vite+ 1.5.1 checks managed package-manager downloads against the
integrity hash in `packageManager`, restores interactive input in `vp
run` tasks, fixes `vp migrate` config merges, and adds a reference page
for each package command.

### Features

- Vite+ checks a downloaded pnpm, Yarn 2+, or bun against the integrity
hash in the project's `packageManager` field instead of the hash that
the registry reports, and rejects a download that does not match.
Mirrors and private registries that serve the same package still pass.
Each pinned version gets its own cache directory, so a project with a
pinned package manager downloads it once more after the upgrade.
Unpinned installs keep their current location
([#3400](#3400)), by
@fengmk2 and @arkmarta.
- Upgrade the bundled Vite and Rolldown
([#3390](#3390)), by
@voidzero-guard[bot] and @fengmk2:
- `vite@8.3.5` to `vite@8.3.7`. A pnpm install no longer turns every
cached build into a cache miss, because Vite tells Vite Task to ignore
`node_modules/.modules.yaml`. It also fixes named imports from Node.js
built-ins and reloads in bundled dev mode, subpath imports (`#`) in the
dependency optimizer, SSR builds with `build.ssr: true`, and chunks
shared with workers.
- `rolldown@1.2.16` to `rolldown@1.2.18`, with module source maps that
keep only the sources and names that they trace.
- `@voidzero-dev/vite-plus-core` requires `postcss@^8.5.32`, as the
bundled Vite does.

### Fixes & Enhancements

- Scripts that `vp run` starts get a blocking stdin again when the `run`
block of `vite.config.ts` is not statically analyzable (for example, a
task command held in a constant), so interactive prompts such as `vp
update --interactive` wait for input instead of failing with `EAGAIN`
([#3361](#3361)), by
@everton-dgn.
- `vp migrate` changes only the `return` statements of a `defineConfig`
callback, so functions inside the config, such as Rolldown
`codeSplitting.groups[].name` callbacks, keep their return values and
the build no longer fails. When a callback return cannot receive the
merged settings, migration keeps the standalone config files and asks
for a manual merge. Pack and task cache migration also recognize configs
wrapped in parentheses, `as`, `satisfies`, `<T>`, or `!`
([#3325](#3325),
[#3372](#3372)), by
@jong-kyung.
- `vp create react-router` passes `--no-git-init` to
`create-react-router`, so the generator's initial commit no longer stops
the Vite+ setup when no Git identity is configured
([#3363](#3363)), by
@chbaefront.
- `env.fish` calls fish built-ins through `builtin`, so `vp env use`
changes the Node.js version even when a user function has the name of a
built-in such as `count`
([#3353](#3353)), by
@naokihaba.
- Shell completion suggests full command names before aliases, so `vp
i<Tab>` offers `install` and `vp up<Tab>` offers `update`. An alias
stays available when no full name matches
([#3337](#3337)), by
@nekomoyi.
- Completion for `vp run` and `vpr` skips comment keys such as `"# docs
#"` in `package.json` scripts, matches task names that contain `:`, and
shows each task's command as its description in Zsh and Fish
([#3354](#3354)), by
@nekomoyi.
- `vp pm dist-tag rm` works with Yarn Berry, because Vite+ passes
`remove` to `yarn npm tag`
([#3358](#3358)), by
@jong-kyung.
- A package-manager version that resolves through a dist-tag, such as
`pnpm@latest` in `vp env use`, must be a valid semver version. Vite+
rejects any other registry reply with an error, including a version with
surrounding whitespace
([#3395](#3395)), by
@fengmk2 and @arkmarta.

### Docs

- Add a Package Management section to the guide, with a reference page
for each of the 38 package commands that lists its options,
package-manager support, version requirements, and npm fallbacks. Help
output for package commands and the old package management and install
URLs point to the new pages
([docs](https://viteplus.dev/guide/package-management/))
([#3105](#3105)), by
@jong-kyung.
- Show the README logo that matches the GitHub theme, so the logo stays
visible after a theme change
([#3350](#3350)), by
@fengmk2.

### Chore

- Build Linux native bindings against the napi-cross glibc 2.17 sysroot
with `@napi-rs/cli@3.10.12`, let the linker reject unresolved symbols,
and run Linux CI on `ubuntu-latest` again. Let the dependency upgrade
workflow change workflow files
([#3349](#3349),
[#3384](#3384)), by
@fengmk2.
- Refine contributor guidance: `AGENTS.md` separates the `vite-plus`
package from the global `vp` CLI and replaces `CLAUDE.md`, and the
Node.js version RFCs describe `.nvmrc` support
([#3388](#3388),
[#3383](#3383)), by
@liangmiQwQ and @hyunbinseo.
- Resolve the docs theme aliases from `import.meta.dirname`, so the docs
dev server no longer warns about `__dirname`
([#3379](#3379)), by
@liangmiQwQ.
- Fold the `.node-version` parse tests into one table
([#3355](#3355)), by
@Brooooooklyn.

### Bundled Versions

| Tool | Version | Source | Changelog |
| --------------- | ---------- |
----------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------------------
|
| vite | `8.3.7` |
[`5def936`](vitejs/vite@5def936)
| [8.3.6](https://github.com/vitejs/vite/releases/tag/v8.3.6),
[8.3.7](https://github.com/vitejs/vite/releases/tag/v8.3.7) |
| rolldown | `1.2.18` |
[`f9a49d6`](rolldown/rolldown@f9a49d6)
| [1.2.18](https://github.com/rolldown/rolldown/releases/tag/v1.2.18) |
| oxc-node | `1.0.1` |
[`7ff14c3`](oxc-project/oxc-node@7ff14c3)
| unchanged |
| tsdown | `0.23.4` | [npm](https://npmx.dev/package/tsdown/v/0.23.4) |
unchanged |
| vitest | `5.1.0` | [npm](https://npmx.dev/package/vitest/v/5.1.0) |
unchanged |
| oxlint | `1.91.0` | [npm](https://npmx.dev/package/oxlint/v/1.91.0) |
unchanged |
| oxlint-tsgolint | `7.0.2005` |
[npm](https://npmx.dev/package/oxlint-tsgolint/v/7.0.2005) | unchanged |
| oxfmt | `0.76.0` | [npm](https://npmx.dev/package/oxfmt/v/0.76.0) |
unchanged |

### Upgrade

```bash
vp upgrade
```

### New Contributors

@chbaefront, @everton-dgn

**Full Changelog**:
v1.5.0...v1.5.1

---

Merging this PR will trigger the release workflow.

---------

Co-authored-by: voidzero-guard[bot] <278573678+voidzero-guard[bot]@users.noreply.github.com>
Co-authored-by: MK (fengmk2) <fengmk2@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test: create-e2e Run `vp create` e2e tests test: e2e Auto run e2e tests test: install-e2e run vite install e2e test test: sfw

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants