Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 19 additions & 6 deletions specs/2026-08-10_normalize-package-lock-resolved-urls/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -472,14 +472,27 @@ through the proxy):
| **10.2.4** | runner, node 18.19.1 | installs | the **proxy** — the rewrite preserves its path prefix |
| **11.3.0** | developer machine, node 22.15.0 | **`E404`** | — prefix dropped |

Every pipeline pins node 18.19.1 (this repo's reusable workflows; paw-fe's `.nvmrc`), so all of them are on npm 10,
~~Every pipeline pins node 18.19.1 (this repo's reusable workflows; paw-fe's `.nvmrc`), so all of them are on npm 10,
and paw-fe's run history contains no failure of this shape. The original `E404` was real — it was reproduced on a
developer machine, where npm is newer.
developer machine, where npm is newer.~~

**The consequence is a sequencing one:** the prefix drop is a *regression in newer npm*, so nothing breaks in CI today
and everything un-normalized breaks the moment runners move to node 24 / npm 11
(`specs/2026-06-05_node24-workflow-migration`). Normalization is a **prerequisite for that migration**, not a cleanup
after it.
**Corrected again 2026-08-14, later the same day — the "not failing today" reading was wrong.** The node version is
pinned **per branch** by the reusable workflows, and only `release/25.2` is still on the old one:

| branch | node pinned | npm | un-normalized behaviour |
| --- | --- | --- | --- |
| `release/25.2` | 18.19.1 | 10 | works without the flag |
| `release/25.3`, `25.4`, `26.1`, `26.2`, `26.3`, `master` | 22.15.0 | **11** | **fails** without the flag |

The first correction generalised from `release/25.2` — the branch checked out at the time — and from `cplace-paw-fe`,
whose pipelines pin `25.2`. Six of the seven branches were on npm 11 and therefore **were** failing, which is what
Dimension 9 originally claimed. Confirmed by a real report: `cplace-vwg-ptm-fe`
[run 31167462200](https://github.com/collaborationFactory/cplace-vwg-ptm-fe/actions/runs/31167462200) failed on
`release/26.2` with `E404 … update-browserslist-db`, inside the composite's own `npm ci`, on node 22.15.0.

**The consequence is still a sequencing one, but sharper:** the prefix drop is a regression in newer npm, and most
branches already run it. Normalization was overdue rather than pre-emptive, and it remains a **prerequisite** for the
rest of `specs/2026-06-05_node24-workflow-migration`.

**And the mitigation's cost is unconditional.** Measured in the same runs: under `replace-registry-host=never` the
tarball came from `registry.npmjs.org` (proxy fetches: 0) on *both* npm versions. On npm 11 that buys compatibility;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,13 +316,16 @@ <h2>The fix</h2>
The fix has two parts, and they attack the same rewrite from opposite ends.
</p>
<p>
<strong>The version qualifier is load-bearing.</strong> Measured 2026-08-14 with a one-package fixture, on a
runner and locally: <strong>npm 10.2.4</strong> — node 18.19.1, what every pipeline pins today — rewrites the
host onto the configured registry correctly and installs <em>through the proxy</em>, while
<strong>npm 11.3.0</strong> — developer machines, and any runner on node 24 — drops the prefix and fails. The
prefix drop is a <strong>regression in newer npm</strong>: nothing is failing in CI today, and everything
un-normalized fails the moment runners move to node 24. That makes this work a prerequisite for the Node 24
migration rather than a cleanup after it.
<strong>The version qualifier is load-bearing.</strong> Measured 2026-08-14 with a one-package fixture, on
a runner and locally: <strong>npm 10.2.4</strong> rewrites the host onto the configured registry correctly and
installs <em>through the proxy</em>, while <strong>npm 11.3.0</strong> drops the prefix and fails. The prefix
drop is a <strong>regression in newer npm</strong> — and which npm a pipeline gets is decided
<strong>per branch</strong> by the reusable workflows: only <code>release/25.2</code> still pins node 18.19.1
(npm 10); <code>release/25.3</code>, <code>25.4</code>, <code>26.1</code>, <code>26.2</code>,
<code>26.3</code> and <code>master</code> all pin node 22.15.0, which is npm 11. Six of the seven branches
were therefore already failing on un-normalized lockfiles — as <code>cplace-vwg-ptm-fe</code> reported against
<code>release/26.2</code>: <code>E404</code> on <code>update-browserslist-db</code>, inside the composite's own
<code>npm ci</code>. This work is a prerequisite for the rest of the Node 24 migration, not a cleanup after it.
</p>
</div>

Expand Down Expand Up @@ -448,7 +451,8 @@ <h3><code>replace-registry-host=never</code></h3>
</svg>
</div>
<figcaption>
Lane 1 is npm 11; on npm 10.2.4 the same rewrite lands on the proxy correctly and installs. Lane 2 removes
Lane 1 is npm 11 — what <code>release/25.3</code> and every newer branch pin; on npm 10.2.4
(<code>release/25.2</code> only) the same rewrite lands on the proxy correctly and installs. Lane 2 removes
the rewrite; lane 3 removes the <em>need</em> for it. The pairing is what makes the rollout
lazy rather than a coordinated switchover: on a normalized lockfile the flag changes nothing, so the two
compose in either order and the flag can come out per branch — once the advisory stops reporting anywhere.
Expand Down
21 changes: 15 additions & 6 deletions specs/2026-08-10_normalize-package-lock-resolved-urls/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,20 @@ request 404s, and because that prefix is the `JFROG_URL` secret, CI prints the w

| npm | un-normalized entry, no mitigation | tarball served by |
| --- | --- | --- |
| 10.2.4 — node 18.19.1, what every pipeline pins today | installs | the **proxy**; the rewrite keeps the path prefix |
| 11.3.0 — developer machines, and any runner on node 24 | **`E404`** | — prefix dropped |
| 10.2.4 | installs | the **proxy**; the rewrite keeps the path prefix |
| 11.3.0 | **`E404`** | — prefix dropped |

So the prefix drop is a **regression in newer npm**: nothing is failing in CI today, and everything un-normalized
fails the moment runners move to node 24. That makes this work a **prerequisite for the Node 24 migration** rather
than a cleanup after it.
The prefix drop is a **regression in newer npm** — and which npm a pipeline gets is decided **per branch** by the
reusable workflows:

| branch | node pinned | npm | un-normalized behaviour |
| --- | --- | --- | --- |
| `release/25.2` | 18.19.1 | 10 | works without the flag |
| `release/25.3`, `25.4`, `26.1`, `26.2`, `26.3`, `master` | 22.15.0 | **11** | **fails** without the flag |

Six of the seven branches were already on npm 11, so un-normalized lockfiles **were** failing there — as
`cplace-vwg-ptm-fe` reported against `release/26.2`: `E404` on `update-browserslist-db`, inside the composite's own
`npm ci`. This work is a **prerequisite for the rest of the Node 24 migration**, not a cleanup after it.

The fix has two parts, attacking the same rewrite from opposite ends:

Expand Down Expand Up @@ -77,7 +85,8 @@ flowchart TB
class C2,C3,C4 ok;
```

Lane 1 is npm 11; on npm 10.2.4 the same rewrite lands on the proxy correctly and installs. Lane 2 removes the
Lane 1 is npm 11 — which is what `release/25.3` and every newer branch pin; on npm 10.2.4 (`release/25.2` only)
the same rewrite lands on the proxy correctly and installs. Lane 2 removes the
rewrite; lane 3 removes the *need* for it. Because the flag is a no-op on a normalized lockfile, the two compose in
either order and the flag can be dropped **per branch** rather than in a coordinated switchover — once the advisory
stops reporting anywhere.
Expand Down
23 changes: 17 additions & 6 deletions tools/scripts/lockfile/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,21 +55,32 @@ This tells npm to fetch each `resolved` URL **verbatim** rather than rewriting i
It makes an un-normalized lockfile install on any npm version, so it protects **consumer** repositories too, not just
this one. JFrog URLs stay authenticated by the secret, so it introduces no dependency on anonymous JFrog access.

**The rewrite it disables is only broken on newer npm.** Measured 2026-08-14 with a one-package fixture, on a runner
and locally:
**The rewrite it disables is broken on npm 11, not on npm 10.** Measured 2026-08-14 with a one-package fixture, on a
runner and locally:

| npm | un-normalized entry, no mitigation | tarball served by |
| --- | --- | --- |
| 10.2.4 (node 18.19.1 — what every pipeline pins today) | installs | the **proxy** — the rewrite keeps its path prefix |
| 11.3.0 (developer machines; any runner on node 24) | **`E404`**, masked as `***` | — prefix dropped |
| 10.2.4 | installs | the **proxy** — the rewrite keeps its path prefix |
| 11.3.0 | **`E404`**, masked as `***` | — prefix dropped |

**Which npm a pipeline gets is decided per branch, and most branches are on the broken one.** The reusable workflows
pin the node version, and only `release/25.2` is still on the old one:

| branch | node pinned | npm | un-normalized behaviour |
| --- | --- | --- | --- |
| `release/25.2` | 18.19.1 | 10 | worked without the flag |
| `release/25.3`, `25.4`, `26.1`, `26.2`, `26.3`, `master` | 22.15.0 | 11 | **failed** without the flag |

That is not hypothetical: `cplace-vwg-ptm-fe` reported exactly this against `release/26.2` — `E404` on
`update-browserslist-db`, inside the composite's own `npm ci`, on node 22.15.0.

**It is a mitigation, not the fix**, and it is not free on either version. Under it, an entry still pointing at
`registry.npmjs.org` is fetched *directly from npmjs*, bypassing the proxy — no Xray, no curation. On npm 10 that is
its only effect, because the rewrite it disables was working. On npm 11 it buys compatibility and spends proxy
routing. Normalizing buys both: the entry resolves through the proxy on every version, flag or no flag.

**This is why the Node 24 migration depends on the rollout, not the other way round.** Nothing fails in CI today;
everything un-normalized fails the moment runners move to npm 11.
**The Node 24 migration and this rollout are the same problem.** Six of the seven branches already run npm 11, which
is why un-normalized lockfiles were failing there before this landed.

Because of that, `use-npmrc` also runs `warn-foreign-registry.sh` against the consumer's own `package-lock.json` and
emits a `::warning` annotation plus a job summary listing the offending package paths. **Those warnings are the
Expand Down
5 changes: 3 additions & 2 deletions tools/scripts/lockfile/warn-foreign-registry.sh
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,9 @@ main() {
printf 'What would happen without that flag depends on the npm version: **npm 10.2.4** rewrites the '
printf 'host onto the configured registry correctly, and the entry resolves *through* the proxy; '
printf '**npm 11.3.0** drops the path prefix and fails with an `E404` masked as `***`. Both measured '
printf '2026-08-14. Runners pinned to node 18.19.1 are on npm 10; developer machines, and any runner '
printf 'moving to node 24, are not.\n\n'
printf '2026-08-14. Only `release/25.2` still pins node 18.19.1 (npm 10) - `release/25.3` and every '
printf 'newer branch pin node 22.15.0, which is npm 11. So most pipelines are on the version that '
printf 'fails, and un-normalized entries there depend on this flag.\n\n'
printf 'Fix by normalizing the lockfile onto the proxy (PFM-ISSUE-34453) - it then resolves through '
printf 'the proxy on every npm version, with or without the flag, and the mitigation can be removed '
printf 'once no lockfile reports this.\n\n'
Expand Down