Skip to content

Fix mirror archiveUrl dropped on berry restore (#1465) - #1466

Merged
Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
agent/fix-registry-derived-tarball-base
Oct 13, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 4 commits into
mainfrom
agent/fix-registry-derived-tarball-base

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Fixes #1465

Summary

Some projects sit behind a registry mirror that passes npmjs metadata through unchanged, so the tarball URLs still point at registry.npmjs.org. In those projects, hosted rollback and remove dropped yarn berry's ::__archiveUrl= binding (and pnpm's tarball:) while exiting 0. The next cold install then fetched the conventional path under the mirror, which 404s (YN0035). After this PR the restore writes back what the package manager itself wrote.

Root cause

registry_derives_tarball (crates/socket-patch-core/src/patch/redirect/upstream/npm.rs) decides whether the package manager derives a tarball URL itself and so leaves it out of the lock. It accepted a URL that was conventional under either the project's registry or npm_registry_base() (npmjs, or SOCKET_NPM_REGISTRY). Yarn (isConventionalTarballUrl via getScopeRegistry) and pnpm compare only against the package's own registry. So an npmjs URL served by a mirror was wrongly treated as derived.

The same helper drives three call sites, and the fix covers all of them:

  • the berry npm: locator restore (berry_registry_locator)
  • pnpm's tarball: restore
  • pnpm's lock evidence for lockfile-include-tarball-url

Fix

registry_derives_tarball now takes from_project, which says whether the version document was read from the project's own registry (ProjectDist::from_project).

  • If it was, only the project registry counts.
  • If it wasn't, the default base still counts too. That covers two cases: the project resolves from the default registry (where SOCKET_NPM_REGISTRY stands in for npmjs), and the mirror could not be read so its document is the fallback guess.

The lock-evidence path reads no document, so it uses non_default_registry, the same test fetch_dists_on uses to decide whether to read the project registry.

Tests (red → green)

Issue case Test Without fix With fix
#1465 berry rollback + remove, top-level npmRegistryServer mirror in_process_redirect::yarn_berry_unwind_keeps_a_default_registry_url_behind_a_mirror FAIL (binding dropped) pass
#1465 real yarn 4 behind a pass-through mirror: rollback restores yarn's own locator, cold --immutable --check-cache install succeeds e2e_redirect_yarn_berry_build::berry_hosted_rollback_keeps_archive_url_behind_passthrough_mirror FAIL (bare locator) pass on yarn 4.18.0 and 4.0.2
#1465 npmScopes form / scoped name npm::tests::project_registry_decides_a_mirrors_tarball_urls (scoped @s/p behind a mirror), with scope-registry lookup already covered by #1017 tests FAIL pass
pnpm sibling (npm.rs:1846) in_process_redirect::pnpm_rollback_keeps_a_default_registry_tarball_behind_a_mirror FAIL (tarball: dropped) pass
pnpm lock evidence (npm.rs:1484) npm::tests::npmjs_tarballs_behind_a_mirror_are_no_tarball_setting_evidence Some(true) None
berry locator npm::tests::berry_locator_binds_only_an_underived_tarball FAIL pass

Commands run locally:

  • cargo fmt --all -- --check: ok
  • cargo clippy --workspace --all-features -- -D warnings: ok
  • cargo test -p socket-patch-core --all-features --lib: 6407 pass. 4 fail only as root (chmod-based write-failure tests) and pass as an unprivileged user.
  • in_process_redirect: 142 pass. 3 fail only as root, same as above, and pass as non-root. in_process_rollback_hosted 38/38, hosted_memory_engine 39/39.
  • yarn-berry e2e leg (SOCKET_PATCH_YARN_E2E_REQUIRED=1, yarn 4.18.0): e2e_redirect_yarn_berry_build 35/35, e2e_vendor_yarn_berry_build 39/39, e2e_yarn4_pnpm_linker_build 38/38, e2e_yarn4_workspaces_build 37/37.
  • The full cargo test --workspace doesn't fit this sandbox's disk, so CI covers the rest. mode_migration_npm's two berry tests can't reach npmjs through the sandbox proxy's CA from their test-side reqwest::Client. That is unrelated to this change.

No npm/pypi/gem wrapper changes are needed: the wrappers only dispatch to the binary.

Review findings not fixed

From /code-review high:

  • Fallback still guesses "derived" when the mirror can't be read. That path has no document from the project registry, so the URL scheme the mirror serves is unknown. Most mirrors (Artifactory, Verdaccio, Nexus) rewrite tarball URLs to themselves, so the bare locator stays the better guess. upstream_registry_fallback already warns, and the Hosted pnpm rollback/remove restores pnpm-lock.yaml from npmjs's version document instead of the project's .npmrc registry, so a mirror project loses its tarball: URL (cold frozen install 404s) or is moved to npmjs #919 fallback test pins this behaviour.
  • SOCKET_NPM_REGISTRY counted on the evidence path. It stands in for npmjs throughout this module (non_default_registry, fetch_dists_on). The behaviour is unchanged from main.
  • Carry the source registry in ProjectDist instead of a bool. It's a reasonable refactor, but it's wider than this fix.
  • e2e uses curl. The test-side reqwest client uses webpki roots only, so it fails behind TLS-intercepting proxies. curl ships on every CI runner OS.
  • e2e rewrites .yarnrc.yml. The new rc repeats every key the fixture writes.
  • Empty start commit. The agent claim protocol requires it, and the PR squash-merges.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QT2WDJPU22ezCv8jCEUNSP


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
Behind a registry mirror that passes npmjs metadata through, tarball
URLs still point at registry.npmjs.org. Yarn berry binds those with
::__archiveUrl= and pnpm records them as tarball:, because each
compares only against the package's own registry. Hosted rollback and
remove treated an npmjs-conventional URL as derived whatever the
project's registry, so they dropped the binding and the next cold
install fetched a path the mirror 404s.

The derived check now compares only against the project's registry
when the version document came from it. The default registry still
counts when the project resolves from it, or when the mirror could not
be read and its document was a fallback guess.

Fixes #1465

Assisted-by: Claude Code:claude-opus-5-5
Real yarn 4 behind a mirror that passes npmjs packuments through binds
the dependency to its npmjs tarball with ::__archiveUrl=. The new e2e
pins it hosted, rolls back, checks the restored lock carries yarn's own
binding, and runs a cold immutable install behind the mirror, which
404s on the conventional mirror path if the binding is lost.

Refs #1465

Assisted-by: Claude Code:claude-opus-5-5
Skip the default-registry lookup when the document came from the
project's registry, read the dist once in the berry restore, and add a
unit test that npmjs tarballs recorded behind a mirror are no longer
read as proof that lockfile-include-tarball-url is on.

Refs #1465

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 13, 2026 05:18

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit bbc9ccf. Configure here.

@mikolalysenko Mikola Lysenko (mikolalysenko) added the Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review label Oct 13, 2026
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Labeled Ready for review by the burn-down agent.

  • Head: bbc9ccf574 (mergeable against main, no conflicts; CHANGELOG.md untouched)
  • CI: 35/35 green + 50 path-skipped; no main-wide failures
  • Bugbot: reviewed bbc9ccf, no findings; no unresolved review threads
  • Reviewer focus: registry_derives_tarball's new from_project flag in upstream/npm.rs, and the lock-evidence path that uses non_default_registry instead of a document read.

Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

Final review brief

What it does. Behind a registry mirror that passes npmjs metadata through unchanged (tarball URLs still on registry.npmjs.org), hosted rollback/remove wrote back a bare yarn berry locator (and dropped pnpm's tarball:), so the next cold install fetched a 404 path under the mirror. registry_derives_tarball now only counts the project's own registry when the version document came from it (from_project), matching how yarn and pnpm decide whether a URL is derived.

Risk: low. One predicate in npm.rs gains a bool; the three callers pass it from data they already had. Behaviour only changes for a non-default project registry whose document was read successfully and serves non-conventional (npmjs) URLs. The mirror-unreachable fallback keeps today's "derived" guess.

Look here

  • npm.rs:449:`` the predicate change.
  • npm.rs:911 and npm.rs:1861:```` berry and pnpm restores pass found.from_project.
  • npm.rs:1492:````` pnpm lock evidence (no document read) uses non_default_registry, the same test `fetch_dists_on` uses.
  • e2e_redirect_yarn_berry_build.rs:896:`````` real yarn 4 behind a wiremock pass-through mirror; rollback must restore yarn's own ::__archiveUrl= line and a cold `--immutable --check-cache` install must succeed.

Verified

  • Read the full diff (3 files, +346/-17). Traced ProjectDist.from_project through fetch_dists_on: true only when the non-default (or credentialed) project registry answered; SOCKET_NPM_REGISTRY-as-project and npmjs/yarnpkg aliases still count as derived.
  • New tests cover berry rollback + remove, pnpm rollback, scoped names, the lock-evidence path, and the fallback case; the PR body records each as red before the fix.
  • CHANGELOG.md untouched; no debug leftovers; no Windows-path or untrusted-input concerns (test-only curl use, skips cleanly if npmjs is unreachable).
  • CI on bbc9ccf: 35 pass, 50 skipped (matrix placeholders), ci-ok and clippy green, yarn-berry 4.18.0 (ubuntu-latest) green. Cursor Bugbot finished with no findings. All review threads resolved.

Changes I made: none.

Open questions: none blocking. The author lists declined /code-review suggestions in the PR body (the fallback guess, the bool instead of carrying the registry); I agree with those calls.

Auto-merge is armed, so approving sends this straight to the merge queue.


Generated by Claude Code

Merged via the queue into main with commit 4221796 Oct 13, 2026
86 checks passed
@mikolalysenko
Mikola Lysenko (mikolalysenko) deleted the agent/fix-registry-derived-tarball-base branch October 13, 2026 13:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Ready for review Agent-verified: mergeable, CI green, Bugbot clean — awaiting human review

Projects

None yet

3 participants