Commit Graph
6 Commits
Author SHA1 Message Date
Juan Manuel Martinez OrtizandZoltan Kochan ae349ec502 feat: cap the unpacked size of package archives with maxTarballUnpackedSize in v11 and for zips (#17014)
A gzip bomb inflates a kilobyte-sized tarball into hundreds of gigabytes
during extraction. pnpm v12 bounds what an archive may unpack to with
maxTarballUnpackedSize since pnpm/pnpm#17054; pnpm v11 had no such
bound, so an install could still exhaust the disk.

pnpm v11 now adds up the sizes that the regular-file entries of a
package archive declare in their tar headers and fails the extraction
with ERR_PNPM_TARBALL_TOO_LARGE once the total passes
maxTarballUnpackedSize (default 4 GiB). Header sizes stand in for
written bytes: the tar parser never yields more payload than a header
declares, so their sum bounds what can reach the store, and checking it
before the payload is read keeps the crossing entry out of the store.
Entries the ignore filter drops count as well. The error is
deterministic for a given archive, so the fetch retry loop does not
retry it. The zip archives that runtimes are installed from are held to
the same limit. The setting name, default, error code, message and hint
match pnpm v12.

pnpm v12's zip extractor bounded each entry by its central-directory
size but not their sum. Every stored zip entry now counts against the
payload ceiling of the TarLimits that tarballs use.

The "Added in" line in the v11 docs assumes the next release is 11.28.7.

Completes https://github.com/pnpm/tasks/issues/81.

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-10-18 19:05:42 +02:00
KhảiandClaude Opus 5 1606ba03fb docs: add the documentation and comment principles and apply them (#16516)
* docs(agents): add the documentation and comment principles

Import the principles that transfer from KSXGitHub/perfectionist's
contributor guide, plus four of our own: concise and non-repeating text,
structured text over prose, removal over addition when reviewing or
fixing nitpicks, and a definition of the user-facing text that must not
name implementation details.

The root guide's "Comments" section gains "Register", "Prose that cannot
go stale", "User-facing text", and "Reviewing documentation and
comments". The pacquet style guide adds the Rust specifics (clap and
napi doc comments are user-facing; a default is documented on the
field, not the variant). DOCUMENTATION.md gains the renderer and link
table for each markdown surface.

The guides themselves are brought in line: counts over growable lists
become plain references, a quoted heading becomes an anchor link, and
the size limits are stated once, in the style guide, instead of three
times.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs: keep user-facing text free of implementation names

The `@pnpm/napi` README and type declarations named the Rust engine, the
in-repo package name, and TypeScript internals (`filterPkgsDiff`,
`nameFormatter`) that a user of the addon cannot reach. The pnpmfile
page in both docs trees explained a limitation by the IPC mechanism
behind it. Four changesets named the release line or implementation,
which the package targets already express.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs(crates): cut restating and stale comments in pack, modules-yaml and nine more crates

Apply the comment principles to pack, versioning, pnpr-client,
package-is-installable, fs-packlist, workspace-task-scheduler,
engine-runtime-node-resolver, exportable-manifest, modules-yaml,
pnpr-registry, and pnpr-auth. Removed: call-site comments that repeat
the callee's doc, module rosters of exports that the `pub use` lines
already list, "not yet implemented" notes for behaviour that exists
(`beforePacking`, `hoistedLocations`), body narration, and history
framing. Comment-only; no code changes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs(crates): cut restating and stale comments in the small resolver, catalog and pnpr crates

Apply the comment principles to the local, tarball, default, deno and
jsr resolvers, the catalog crates, detect-libc, config-parse-overrides,
env-replace, git-utils, matcher, diagnostics, and the pnpr policy,
cargo, error, osv and fixture crates. Removed: parentheticals that
repeat a `#[diagnostic(code)]` attribute, counts over lists of
variants, callers and entry points, rosters of callers, doc paragraphs
that repeat a sibling's or the module's text, comments narrating the
match arms or condition below them, and history framing. The
`pnpr-prepare --help` text no longer names the test harness.
Comment-only; no code changes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs(crates): cut restating and stale comments in publish, workspace, registry and graph-hasher

Apply the comment principles to publish, auth-commands, registry,
workspace, lockfile-verification, default-reporter, the git resolver,
deps-inspection, hooks, graph-hasher, package-manifest, and the pnpr
shared-artifacts and route crates. Removed: a module roster of every
export, counts over lists, plan notes for work that landed ("Phase 5",
"Phase 6"), call-site comments repeating the callee's doc, docs
narrating match arms, a default claim on a `#[default]` variant, a
misattached doc, and history framing. Comment-only; no code changes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs(crates): cut restating comments in napi, reporter and pnpr crates

Apply the comment principles to napi, reporter, resolving-resolver-base,
real-hoist, git-fetcher, workspace-manifest-writer, and the pnpr config
and storage crates. Removed: "Mirrors X in index.d.ts" sentences on
`#[napi]` items and other implementation names in addon-facing docs,
stale "not emitted yet" and "when it lands" notes for behaviour that
exists, step-by-step comments narrating the body, emit-site and caller
rosters, docs duplicated from a sibling or the module, a doc attached to
the wrong item, and history framing. Comment-only; no code changes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs: cut restating and stale comments across the remaining crates and pnpm11

Apply the comment principles to the rest of the Rust workspace and to the
TypeScript CLI: the cli crate and its clap definitions, package-manager,
config, patching, the deps resolver, lockfile, pnpr, the npm resolver,
tarball, network, executor, cmd-shim, the benchmark and fixture tooling,
and the pnpm11 packages.

Removed: comments narrating the body, docs repeating a callee's, a
sibling's or the module's text, counts over growable lists, rosters of
callers and exports, "not yet implemented" notes for behaviour that
exists, history framing, and `@param` lines restating a signature.

One exception to comment-only: in `pnpr/crates/pnpr/src/resolver/resolve.rs`
the `Workspace` struct sat inside the doc block written for `resolve`, so
the struct moved above it and each doc now attaches to its own item.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs(crates): cut body narration and duplicated docs in resolver, fs and package-manager

Removed: a numbered "Sequence:" list narrating `ensure_file`'s body and
the paragraph restating its backoff constants, the stress-test module
doc's roster of its own tests, refactor-history paragraphs in the peer
walk's finalize pass, call-site and caller-side copies of a callee's doc
(the `optional` AND-fold stays documented on `register_seeded_package`
and on `ResolvedPackage`), a verbatim quotation of a TypeScript test's
expected output in the pnpr search module doc, and field and digest-input
rosters in the package-manager.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs(deps-restorer): cut plan references and re-attach misplaced docs

Removed the "slice 4" plan references and the comments narrating the
bodies they sat above. The `Auto` downgrade-chain doc moved from
`copy_and_log` to `auto_link`, the function it describes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs(deps-restorer): cut the remaining body narration in the hoist path

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs: cut the last body narration and a history clause in the cmd-shim test

`build_graph.rs` kept a `patches` parameter doc that re-derived what
`BuildOptions::patches` documents. The PowerShell-arguments test on main
said the arguments survived "before the shim ended its batch context
too", which describes the change rather than the behaviour.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs(cmd-shim): point the PowerShell-shim link at its current module

Main moved `wants_powershell_shim` into `windows_shim_policy`, so the
shim writer's link to it no longer resolved and `cargo doc` failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs(cli): link the fixture the ignored-build setup installs

The shortened doc named `workspace_with_unapproved_build` in backticks,
which `perfectionist::bare_identifier_reference` rejects for an item that
resolves in scope. It is an intra-doc link now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs(crates): restore two contracts and fix four dangling references

A review of this branch's sweep flagged seven places. Six needed a
change:

- `from_ini` documents again that a relative `cafile=` resolves against
  `npmrc_dir`, a precondition its callers have to honour.
- `hash_object` documents again that the private serializer's bytestream
  has to match pnpm 11's, because the digest is persisted and read by
  both.
- The hooked-manifests note no longer says "above" of a gate that lives
  in another module.
- The store-dir race test states its synchronization contract instead of
  labelling it "Post-Option-C".
- `GraphNodeHashOptions.nodeVersion` keeps `undefined` as a literal.
- The pnpr streaming module drops the sentence fragment that introduced
  its list.

The seventh, a `beforePacking` limitation in exportable-manifest, stays
removed: the note said the pnpmfile bridge cannot supply that hook, and
`pnpm_pack::lifecycle::apply_before_packing` has been running it since
before this branch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs(cli): say in `pnpm why --help` that `--exclude-peers` is ignored

Demoting the caveat to an ordinary comment took it out of the help,
which then advertised a flag that does nothing: `WhyArgs::run` never
reads `exclude_peers`, and pnpm 11's `why` handler never forwards its
`excludePeers` either. The doc comment states that behavior in the words
a user sees, and the parity reason stays in a comment beside it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

* docs(cli): drop the doc comment that described the wrong module

The comment described the `pnpm_deps_inspection as deps_tree` re-export
above it, but a doc comment attaches to the item that follows, so rustdoc
showed it as the description of `mod dispatch`. The `use` item already
names the alias, so the comment goes rather than moving.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QYTBQo8HY7xD2iz6hjo1CW

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-02 20:28:21 +02:00
f588fa0f95 fix(deploy): avoid hard-linking workspace deps to source (#12182)
With a shared lockfile, pnpm deploy installs the deployed project from
directory resolutions that point at the workspace sources. The default
import method for local directories is a hard link, so the deployed
workspace dependencies shared inodes with their sources. Editing a
source file silently changed the deployment.

v11: the deploy install passes localDirPackageImportMethod:
'clone-or-copy' to the directory fetcher. createPackageImporter treats a
local-dir files response that asks for clone-or-copy like a package
that a build will write to, so an explicit global
packageImportMethod: hardlink cannot override it. Store packages keep
the configured method, which limits the extra I/O to workspace packages.

v12: the shared deploy install sets
Config::isolate_local_directory_imports (runtime-only, never read from
config files). PackageImportOptions carries it as
isolate_mutable_sources. method_for() resolves the effective method for
a slot from it, from the slot's mutability, and from whether a build
will write to it. The isolated virtual-store importer and the hoisted
linker both use it. Mutability comes from the fetch's effective
resolution, which can be a directory that a custom fetcher delegated to.
So CasPathsByPkgId entries now carry source_is_mutable for the hoisted
linker.

Closes pnpm/pnpm#12176

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 23:40:03 +02:00
Zoltan Kochan 3af5322039 fix: authenticate node.js mirror downloads (#14375)
Reuse the existing URL-scoped registry credential lookup for every Node.js mirror request instead of introducing a separate authentication setting.

This covers release indexes, SHASUMS files and signatures, and runtime archives in both implementations while retaining longest-path-prefix scoping and cross-origin redirect protections. Authenticated checksum metadata bypasses the URL-keyed disk cache so it cannot cross credential contexts.

Closes pnpm/pnpm#14334.
2026-08-31 21:31:28 +02:00
Abdullah Alaqeel d47ab916ad fix(self-update): stop the project config from steering the pnpm download (#12813)
Fixes pnpm/pnpm#12803.

`pnpm self-update` resolved the pnpm download through the project's own
registry/auth config, loaded the repo's default `.pnpmfile.(c|m)js`, and took
its `minimumReleaseAge` policy from the active workspace — so the outcome of a
global tooling operation depended on the directory it ran in, and on config a
checkout controls.

Route the fetch through the trusted package-manager bootstrap config — the
channel `switchCliVersion` already uses, which excludes the project `.npmrc`
and workspace manifest — and stop auto-loading the repo pnpmfile, whose
`updateConfig` hook and custom resolvers/fetchers reach the same requests.
`getPackageManagerBootstrapConfig` moves into `@pnpm/config.reader` so the
command package can reuse it.

Stop reading the project's `minimumReleaseAge` and `trustPolicy` settings, and
its `ci` flag, for self-update. Each is dangerous in both directions for a
command that replaces the global binary: a cooldown lowered waives the
protection the user configured, raised it pins the machine to the installed
pnpm, including past a release that fixes a vulnerability in it; a trust policy
turned off accepts a release whose evidence the user meant to reject, turned on
blocks the update the same way; and `ci` decides whether an immature pick may be
confirmed at the keyboard at all. Unlike a blocked dependency upgrade, those
decisions follow the user into every other project. The policies come from the
built-in defaults, the global config, the environment, and CLI flags instead.
Other commands keep reading them from `pnpm-workspace.yaml`, and there is no new
default.

When an immature version is refused, an interactive run offers to update
anyway, matching how a strict install prompts; non-interactive runs still fail
closed.

Mirrored in pacquet: `Config::current_for_self_update` skips the same settings,
and `self-update` gained the matching prompt and error.
2026-07-25 01:34:27 +02:00
Zoltan Kochan fc2f33912e refactor: move the TypeScript pnpm CLI into a pnpm11/ directory (#12537)
The TypeScript pnpm CLI freezes at v11; pnpm 12 will be the Rust pacquet
port. To make that split legible, all TypeScript source, test, and build
directories move under a new top-level pnpm11/ directory. The name states
the version boundary rather than implying a behavioral fork, since the two
stacks are meant to behave identically.

Scope is source-only: the shared workspace root stays at the repo root.
pnpm-workspace.yaml, package.json, pnpm-lock.yaml, .pnpmfile.cjs,
.meta-updater, __patches__, .changeset, .husky, and the lint/spell configs
remain in place, so one pnpm workspace and one Cargo workspace still span
all three products. pnpr/client and pacquet/tasks/registry-mock stay as
cross-product workspace members.

Rewiring the move required:
- pnpm-workspace.yaml globs prefixed with pnpm11/
- root package.json script paths, eslint.config.mjs, tsconfig.lint.json,
  .gitignore, and CODEOWNERS updated
- .meta-updater/src/index.ts literals repointed (pnpm11/pnpm/package.json,
  pnpm11/__utils__, pnpm11/__typings__, and the main package directory)
- regenerated every moved package's repository/homepage URL via meta-updater
- pnpm11/pnpm/bundle-deps.ts and __utils__/scripts/src/typecheck-only.ts
  climb one more level to reach the repo root

.meta-updater stays at the repo root because @pnpm/meta-updater resolves
its config at <cwd>/.meta-updater/main.mjs.

TS CI (.github/workflows/ci.yml) now only runs when pnpm11/-relevant paths
change, via a dorny/paths-filter changes job plus a TS CI / Success
aggregate gate; branch protection should require only that gate.
2026-06-20 14:36:25 +02:00