Skip to content

rfc: install-time manifest consistency check - #50

Draft
zkochan wants to merge 4 commits into
mainfrom
rfc/install-time-manifest-check
Draft

zkochan wants to merge 4 commits into
mainfrom
rfc/install-time-manifest-check

Conversation

@zkochan

@zkochan zkochan commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Summary

Before any dependency code runs, pnpm compares the install-critical fields in each package's package.json with the metadata that resolution used. A mismatch fails the install with the package and differing fields named. The check covers packages from any registry, including store hits and frozen installs.

This complements publish-time manifest verification (#47) and release records (#49), both merged. They make a pnpr registry serve archive-derived metadata for the packages it hosts and proxies; this check covers every other registry, such as the public npm registry, and is defense in depth for pnpr. It establishes consistency between metadata and contents, not that either is trustworthy.


Updated by an agent (Claude Code, claude-opus-5-5).

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

@zkochan

zkochan commented Oct 28, 2026

Copy link
Copy Markdown
Member Author

Updated in b1a25e1.

  • Added the survey this draft asked for: the 1,674 registry packages in pnpm/pnpm's lockfile, compared against their archives. Without normalization, 46 (2.7%) would fail, including eslint, glob, and fsevents. With the normalizations from rfc(pnpr): publish-time manifest verification #47, none fail.
  • Failure is now directional. The install fails only when the archive declares more than the metadata (a hidden dependency, script, or binding.gyp). When the metadata declares more, pnpm follows the archive, so fsevents@2.3.3 still installs.

Written by an agent (Claude Code, claude-opus-5-5).

@zkochan

zkochan commented Oct 29, 2026

Copy link
Copy Markdown
Member Author

Updated in 46fe43e: the survey now also covers the latest version of the 5,000 most-downloaded packages and a random older version of each of the top 2,000: 8,620 versions in total. 273 (about 3%) differ before normalization, and every one is explained by publisher-side normalization. The new rules: empty map versus absent field, directories.bin expanded into bin, semver build metadata stripped from version (lerna canary builds), and a git shorthand expanded to github:. The only version whose metadata claims a build its archive can't run is still fsevents@2.3.3. This supports failing by default.


Written by an agent (Claude Code, claude-opus-5-5).

zkochan added a commit that referenced this pull request Oct 31, 2026
zkochan added a commit that referenced this pull request Oct 31, 2026
* rfc(pnpr): publish-time manifest verification

Split from #44.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* rfc(pnpr): store profile upgrades beside accepted manifests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* rfc(pnpr): normalize npm publish documents before manifest comparison

npm publish uploads the output of @npmcli/package-json prepare(), not the
raw package.json, so a strict comparison would reject ordinary uploads
(bin refs, the gypfile install-script injection, bundleDependencies true,
version cleaning). Define these as profile normalizations, accept the one
benign direction (submitted claims a build the archive cannot run), add
name and version to the compared fields, and add evidence from the npm
trackers plus a 1,674-package survey of registry metadata vs archives.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* rfc: extend the manifest survey to the most-downloaded packages

Add the latest version of the 5,000 most-downloaded packages and a random
older version of each of the top 2,000. 273 of 8,620 versions differ
before normalization; all are explained by publisher-side normalization,
which adds empty-vs-absent maps, directories.bin expansion, stripped build
metadata, and git shorthand expansion to the profile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* rfc(pnpr): clarify lifecycle script comparison, engines normalization, and link #50

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
zkochan and others added 4 commits November 2, 2026 00:35
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Registry metadata is the publishing client's normalized manifest while the
archive keeps the raw package.json. A survey of the 1,674 registry packages
in pnpm/pnpm's lockfile found 46 differences, all explained by bin syntax,
optional dependencies copied into dependencies, the gypfile injection, and
an added engines default. Without normalization the check would fail
eslint, glob, and fsevents. Fail only when the archive declares more than
the metadata.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the latest version of the 5,000 most-downloaded packages and a random
older version of each of the top 2,000. 273 of 8,620 versions differ
before normalization; all are explained by publisher-side normalization,
which adds empty-vs-absent maps, directories.bin expansion, stripped build
metadata, and git shorthand expansion to the profile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ords

Publish-time manifest verification and release records have merged. The
links point at their files, and the motivation says what each covers: pnpr
hosted packages, pnpr's archive-derived records for proxied packages, and
this check for every other registry and as defense in depth for pnpr.

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant