24 Commits
Author SHA1 Message Date
Marie Ramlow 553fb879c3 fetchNpmDeps: assert fetcherVersion is not higher than latest version
If we introduce version 3, current packages that use the non-existent
version 3 will get their hashes broken. Prevent stupid LLMs from
introducing more trouble when hallucinating more non-existent versions.
2026-08-02 12:38:47 +02:00
Doron BeharandGitHub 903158447f prefetch-npm-deps: support file: scheme for dependencies (#484423) 2026-06-17 07:59:14 +00:00
@mjonesandGitHub 9b331020db treewide: fix typo of NPM → npm (#506286) 2026-04-05 23:50:21 +00:00
·𐑑𐑴𐑕𐑑𐑩𐑤 a0d0b06495 treewide: fix typo of NPM → npm 2026-04-03 19:08:04 +07:00
JoandGitHub c9bffa83b0 build-support/node: prepare for structuredAttrs (#487974) 2026-04-01 11:05:15 +00:00
Diogo Correia 2c52816160 prefetch-npm-deps: support file: scheme for dependencies
Fixes #484067
2026-03-12 15:03:52 +00:00
Doron BeharandGitHub e26385b40c prefetch-npm-deps: warn about unresolved lockfile deps (#479805) 2026-02-16 15:33:49 +00:00
Doron BeharandJörg Thalheim 17aec4cda9 prefetch-npm-deps: warn about unresolved lockfile deps
Upstream projects' `package-lock.json` file might include many deps with
no resolved line in them, as described here:

https://github.com/npm/cli/issues/6301

This can cause dependencies to be missing after generating a hash for
`.npmDeps`. If such dependencies are encountered, it's nice to print
them and warn the user that an upstream patch might be needed.

Co-Authored-By: Jörg Thalheim <joerg@thalheim.io>
2026-02-16 12:00:34 +02:00
Jörg Thalheim 203662a570 prefetch-npm-deps: strip volatile fields from dist objects in packuments
The dist object in npm packuments contains fields that can change
after a package is published, causing hash mismatches in
fixed-output derivations:

  - signatures: changes when npm rotates registry signing keys
    (old key SHA256:jl3bwswu80Pjj... expired 2025-01-29)
  - npm-signature: legacy format being progressively removed
  - attestations: provenance metadata added post-publication

Only keep the three fields npm actually needs during install:
tarball, integrity, and shasum. Also strip the informational-only
fileCount and unpackedSize fields.

This is the same approach already used for top-level and
version-level field whitelisting.

Ref: https://github.com/numtide/llm-agents.nix/issues/2459
2026-02-15 18:09:32 +01:00
Stefan Frijters 611910f00c build-support/node/prefetch-npm-deps: prepare for structuredAttrs
Move env variables into env, explicitly provide outputHash to
prefetch-npm-deps.
2026-02-07 15:07:00 +01:00
Jörg Thalheim e11702f1f1 prefetch-npm-deps: exclude deprecated field from packument whitelist
The 'deprecated' field can be modified by package maintainers at any time
via 'npm deprecate', even for already-published versions. This causes
hash mismatches when the npm registry adds deprecation notices to packages
that were previously not deprecated.

For lockfile-based installs, the version is already resolved, so the
deprecation hint used by npm-pick-manifest for version selection is not
needed. The only behavioral change is that users won't see deprecation
warnings during 'npm install', which is an acceptable tradeoff for
reproducible builds.

This was discovered when tar@7.5.2 was deprecated upstream, breaking
builds in downstream projects using fetcherVersion=2.
2026-01-20 09:11:24 +01:00
Jörg Thalheim 08e805c550 prefetch-npm-deps: normalize packuments using whitelist approach
Switch from stripping known volatile fields to using an explicit whitelist
of allowed fields. This is more robust against upstream changes that add
new fields which could affect hash stability.

Top-level: only name and versions (dist-tags and time not needed for
lockfile installs where versions are already resolved)

Version-level: identity, all dependency types, dist, bin, platform
constraints (engines/os/cpu), scripts, and deprecated flag.

Based on analysis of pacote, npm-pick-manifest, npm-install-checks, and
arborist - only fields actually read during npm install are included.
2026-01-11 21:20:39 +01:00
Jörg Thalheim dbc8a3bc5c prefetch-npm-deps: normalize packuments for deterministic hashes
Fixed-output derivations for npm dependencies fail with hash mismatches
when rebuilt on different days. The root cause is that npm registry
metadata (packuments) contain volatile fields that change whenever
upstream publishes a new version.

For example, the TypeScript packument changes daily due to nightly
releases, even though the lockfile pins a specific version. The cached
packument includes _rev, time, modified, and the full versions list -
all of which drift over time.

Strip these volatile fields and filter the versions map to only include
versions actually referenced in the lockfile.

Signed-off-by: Jörg Thalheim <joerg@thalheim.io>
2026-01-04 13:57:43 +00:00
Jörg Thalheim ab89ffc4b1 fetchNpmDeps: rename cacheVersion to fetcherVersion
To align with pnpm tooling.
2026-01-03 18:45:33 +00:00
Jörg Thalheim 0cb5de2d62 prefetch-npm-deps: use package name field for aliases
npm lockfiles can contain package aliases where the lockfile key differs
from the actual package name (e.g., "string-width-cjs" aliasing
"string-width"). Previously we always used the lockfile key, causing us
to fetch packuments for the wrong package.

Use the package's own "name" field when present, falling back to the
lockfile key. This ensures we fetch the correct packument for aliased
packages, fixing non-deterministic builds where the wrong packument
fetch could succeed or fail depending on network timing.
2025-12-31 07:53:32 +00:00
Jörg Thalheim 40f1b80ac7 prefetch-npm-deps: clarify backwards compatibility comment 2025-12-31 06:57:27 +00:00
Jörg Thalheim 3fb4fe294b prefetch-npm-deps: extract package names from lockfile keys
The current approach parses tarball URLs to extract package names for
packument fetching. This is fragile as it only handles npmjs.org URLs
and requires special-casing other registries.

Use lockfile keys directly instead. The lockfile already contains the
canonical package names in the form "node_modules/@scope/name", so we
can simply strip the prefix rather than parsing URLs.

This handles all registries uniformly and eliminates the URL parsing
code along with its tests.
2025-12-31 06:37:24 +00:00
Winter 0b66fed9d7 buildNpmPackage: add diagnostic for cache version mismatch 2025-12-31 00:37:52 -05:00
Jörg ThalheimandWinter 5c99ffcb8e prefetch-npm-deps: add cacheVersion for packument support
Add a cacheVersion parameter to fetchNpmDeps and npmDepsCacheVersion to
buildNpmPackage. When set to 2, prefetch-npm-deps will also fetch and
cache packuments (package metadata) in addition to tarballs.

npm can request packuments with two different Accept headers:
- corgiDoc: abbreviated metadata (default)
- fullDoc: full metadata (used for workspaces)

npm's cache policy requires headers to match, so we cache both versions.

This is opt-in via cacheVersion to avoid breaking existing hashes.
Set npmDepsCacheVersion = 2 for projects using npm workspaces.

Also fix cacache index format to properly separate multiple entries
with newlines, and update map_cache() to parse multi-line index files.
2025-12-31 00:37:52 -05:00
Jonathan Davies 22526da87d prefetch-npm-deps: Enable full LTO 2025-12-19 21:53:26 +00:00
Jonathan Davies bb37dfe300 prefetch-npm-deps: Bump edition to 2024 and apply cargo clippy and rustfmt fixes 2025-12-19 21:53:22 +00:00
Jonathan Davies 1cfd281c2c prefetch-npm-deps: Run cargo update 2025-12-19 21:53:21 +00:00
Jonathan Davies ca4684c9a3 prefetch-npm-deps: Fix isahc default-features 2024 warning 2025-12-19 21:53:13 +00:00
Jonathan Davies ff1906466c prefetch-npm-deps: Rename directory to match name 2025-12-19 21:53:02 +00:00