Skip to content

Fix yarn berry hosted pin leaking npm auth (#404) - #465

Merged
Mikola Lysenko (mikolalysenko) merged 16 commits into
mainfrom
agent/fix-yarn-berry-hosted-auth-leak
Oct 2, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 16 commits into
mainfrom
agent/fix-yarn-berry-hosted-auth-leak

Conversation

@mikolalysenko

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

Copy link
Copy Markdown
Collaborator

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

Fixes #404

Root cause

On yarn berry, hosted mode pinned a patched package by rewriting its lock
entry's resolution to <name>@npm:<v>::__archiveUrl=<hosted tgz>. That is
still an npm: locator, so yarn fetches it with its npm fetcher. The npm
fetcher attaches the configured registry credentials (npmAuthToken,
YARN_NPM_AUTH_TOKEN, npmScopes.*.npmAuthToken) to every scoped package's
request, and to every request under npmAlwaysAuth: true. Those requests go
to the patch host, so the registry token was sent there on every cold install.

Fix: pin the way yarn does for a root resolutions entry

This follows the maintainer's decision on
option C.
A tarball locator under the untouched npm: key (the first version of this
PR) stops the leak, but yarn's hardened mode rejects it with YN0078.
Yarn turns hardened mode on by itself for public-PR CI, so hosted mode now
assumes every berry project may run hardened. For each patched package:

  • package.json: one descriptor-specific selector per range the lock entry
    carries, routed to the hosted tarball, e.g.
    "resolutions": {"left-pad@npm:^1.3.0": "https://patch.socket.dev/…/left-pad-1.3.0.tgz"}.
    This is the minimal edit. Other locked versions of the same package and every
    other file are untouched.
  • yarn.lock: only that entry is re-keyed "left-pad@<url>":, with the
    same URL as its resolution: and the patched 10c0 checksum. version:,
    dependencies: and every dependent's descriptors stay byte-identical. The
    entry moves to yarn's key order, because yarn sorts entries and --immutable
    would otherwise rewrite the lock.

This is exactly what yarn writes itself, verified with real yarn. Yarn then
uses its tarball fetcher, which sends no registry auth and builds the same
cache zip.

Scope and safety:

  • Yarn berry only. package.json is read only beside a berry yarn.lock,
    and the memory host fetches it only there. Yarn classic, npm, pnpm, bun and
    vlt are unchanged.
  • Refusals. Each of these writes nothing and names the cause in a warning:
    • redirect_yarn_berry_resolutions_conflict: a user-authored resolutions
      entry for the package (bare, ranged or nested). It is never overwritten.
    • redirect_yarn_berry_manifest_missing: no root package.json object.
    • redirect_yarn_berry_shared_descriptor: yarn's builtin patch: entries
      (resolve, typescript, fsevents) wrap the same descriptor, so pinning
      it would change that entry too.
    • redirect_yarn_berry_artifact_url_unsupported: a URL yarn can't fetch as
      a tarball.
  • Rollback / remove: rebuilds the original lock key from the selectors,
    restores the registry resolution and checksum, moves the entry back, and
    drops the selectors. An emptied resolutions table is removed.
  • Older locks: a lock pinned by an older release (::__archiveUrl=) is
    still recognized by rollback, VEX and the takeovers, and the next hosted scan
    re-pins it.
  • Inventory and takeovers: lock-only inventory keeps the URL-keyed entry
    (Bugbot's finding on the first version). Vendored ⇄ hosted takeovers work in
    both directions.

Evidence

Measured with real yarn 4.12.0 (fresh checkout, cold cache,
YARN_NPM_AUTH_TOKEN + npmAlwaysAuth, logging tarball server):

pin shape token sent to patch host --immutable hardened mode
npm:…::__archiveUrl= (main) yes ok ok
tarball locator under npm: key (first version of this PR) no ok YN0078
resolutions selector + URL-keyed entry (this PR) no ok, lock untouched ok (direct + transitive)

A project locking is-number@6.0.0 (patched) and is-number@7.0.0 kept the
7.0.0 registry entry.

Per-issue checklist (#404)

  • Unit tests: rewriter shape, descriptor precision and re-sorting, repeat-run
    stability, re-pin on a new uuid, legacy migration, and every refusal. These
    live in patch/redirect/mod.rs; the shape tests fail on main.
  • Layering: the builtin patch: package (resolve) is now left untouched,
    with both reasons named.
  • Inventory regression test for Bugbot's finding (red → green).
  • CLI in-process tests: the pin, CRLF/BOM pin + rollback round-trip (lock
    byte-exact, resolutions dropped), and legacy rollback + re-pin.
  • Takeovers: vendored → hosted and back, with BOM + CRLF kept.
  • Real-yarn e2e: e2e_redirect_yarn_berry_build runs the fresh
    install --immutable --check-cache in hardened mode
    (YARN_ENABLE_HARDENED_MODE) with a registry token configured, and asserts
    the patch host got no Authorization header. With the same env, the first
    version of this PR fails with YN0078.

Local runs

  • clippy -D warnings: clean.
  • socket-patch-core: 4714 lib tests pass plus all integration tests,
    including the regenerated redirect and VEX goldens.
  • CLI suites: the lib tests plus in_process_redirect, in_process_vendor,
    in_process_rollback_hosted/vendored, in_process_scan, e2e_vex_lockfile,
    hosted_memory_*, and the covgap suites for scan, rollback, vendor and vex.
  • Real yarn 4.12.0, SOCKET_PATCH_YARN_E2E_REQUIRED=1: redirect, vendor,
    pnpm-linker and workspaces suites, 53/53.
  • Known sandbox-only failures: the write-failure / permission tests fail here
    because the sandbox runs as root, and fail the same way on main.
  • mode_migration_npm's two berry legs can't reach the real registry from
    this sandbox (TLS through the proxy), so CI runs them.

Follow-ups


Note

Medium Risk
Changes Yarn Berry hosted lockfile and root package.json rewriting and redirect confirmation/VEX behavior; scoped to Berry hosted mode but affects real installs and rollback/migration paths.

Overview
Fixes #404 by changing how Yarn Berry hosted mode pins patched packages so installs no longer use an npm: locator (::__archiveUrl=), which caused Yarn’s npm fetcher to send registry tokens to the patch host.

Hosted redirects now mirror a root resolutions pin: package.json gets descriptor-specific selectors (e.g. "left-pad@npm:^1.3.0" → hosted tarball URL), and yarn.lock re-keys the entry to "<name>@<url>" with a tarball resolution: and 10c0 checksum (entries re-sorted when needed for --immutable / hardened mode). Legacy ::__archiveUrl= pins are still recognized for rollback/takeover and are re-pinned on the next hosted scan.

The hosted engine reads package.json strictly beside a Berry lock, tracks confirmed_yarn_berry_uuids so a URL in the lock or manifest alone cannot confirm a redirect, and lock inventory/takeover logic treats tarball-keyed hosted entries as registry packages. Docs (CHANGELOG, CLI_CONTRACT) and broad unit/e2e tests (including no Authorization to the patch host under hardened mode + registry token env) are updated accordingly.

Reviewed by Cursor Bugbot for commit 8d52ba6. Configure here.


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
Hosted mode pinned a patched yarn berry package as an npm: locator
(npm:<v>::__archiveUrl=<url>). Yarn fetches npm: locators with its
npm fetcher, which attaches the configured registry token
(npmAuthToken, YARN_NPM_AUTH_TOKEN, npmScopes) to every scoped
package request, and to every request under npmAlwaysAuth, so the
token was sent to the patch server on each cold install.

The lock now pins a plain tarball-URL locator (<name>@<url>). Yarn
fetches it with its tarball fetcher, which sends no registry auth
and builds the same cache zip, so the 10c0 checksum is unchanged and
--immutable still passes. Rollback, VEX and the mode takeovers keep
recognizing the old form, and the next hosted scan re-pins it. An
artifact URL yarn could not fetch as a tarball is refused instead of
written.

Fixes #404

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) force-pushed the agent/fix-yarn-berry-hosted-auth-leak branch from 896a700 to e20d139 Compare October 1, 2026 12:49
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 1, 2026 13:05
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@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.

Stale Bugbot comment from a previous run.

Comment thread crates/socket-patch-core/src/patch/redirect/mod.rs Outdated
Lock-only discovery skipped a berry entry whose resolution is a
tarball URL, so a package already pinned by hosted mode dropped out of
the inventory. Treat a tarball-URL resolution under npm: descriptor
keys as the registry package. Also refresh the redirect and VEX
goldens and the vendor takeover test for the new pin form.

WIP: yarn's hardened mode rejects this pin form (YN0078), see #465.

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as draft October 1, 2026 13:15
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] Blocked: needs a maintainer decision on the hosted yarn berry pin shape.

The tarball-URL locator in this PR does stop the token leak, but CI's hosted-e2e (yarn_berry_hosted_install_proof) found that yarn's hardened mode rejects it:

YN0078: Invalid resolution minimist@npm:1.2.2 → https://patch.socket.dev/patch/npm/minimist/1.2.2/…/minimist-1.2.2.tgz

Yarn enables hardened mode automatically for GitHub Actions runs on public pull requests, and enableHardenedMode: true turns it on anywhere. I reproduced it locally with yarn 4.12.0. Hardened mode checks that each lock resolution is valid for its descriptor, and a URL locator is not valid for an npm: descriptor. So this PR as written would break installs in that common setup. It must not merge as is.

Measured options (yarn 4.12.0, fresh checkout, cold cache, YARN_NPM_AUTH_TOKEN + npmAlwaysAuth, logging tarball server):

pin shape sends registry token to patch host --immutable hardened mode
A. npm:<v>::__archiveUrl=<url> (main today) yes (scoped always; all under npmAlwaysAuth) ok ok
B. tarball locator under the npm: key (this PR) no ok YN0078, fails
C. root package.json resolutions: {"<name>@npm:<range>": "<url>"} + lock entry keyed by the URL descriptor (what yarn itself writes) no ok, lock untouched, same 10c0 checksum ok

Option C is the only shape that fixes the leak and works everywhere. But hosted mode would then edit package.json, not just the yarn.lock entry the CLI contract promises today. That is the same resolutions + lock wiring that vendored berry mode already uses with file:. The change also affects rollback/remove, the vendored⇄hosted takeovers, users' own resolutions entries, and workspaces. The other option is to keep A and refuse or warn when registry auth is configured. That can't see CI-only tokens like YARN_NPM_AUTH_TOKEN, so it would only partly help.

Decision needed: (1) move hosted berry to option C (I can rework this PR, since most of the detection, rollback and VEX changes carry over), (2) keep A with a warn/refuse gate plus docs, or (3) something else.

WIP is pushed (5229052). The PR is back in draft with state: blocked.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[burn-down agent] Adding agent:needs-human: this PR is waiting on the maintainer decision in #465 (comment). The question: should the hosted yarn berry pin switch to option C (root resolutions + a URL-keyed lock entry), which stops the token leak and passes hardened mode, or stay on npm: + a gate? Option B (this PR as written) fails hardened mode with YN0078. Burn-down runs will skip this PR until the label is removed. It also conflicts with main; that will be resolved after the decision.


Generated by Claude Code

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

Copy link
Copy Markdown
Collaborator Author

[agent] test (macos-latest) on 0c461dc failed in socket-patch-core --lib on one test, api::vendor_prefetch::tests::an_outage_mid_list_opens_the_breaker_at_the_same_package (left: 16, right: 12: "a mid-list outage must not be amplified by the plan either"). This is not caused by this PR.

  • This PR doesn't touch crates/socket-patch-core/src/api/.
  • The test scripts mock-server latencies of 10–30 ms and asserts an exact request count. On a slow runner, the prefetch can start more downloads before the circuit breaker opens, so the count is sensitive to timing.
  • On this same head it passes on test (ubuntu-latest) and in coverage. It passed 5/5 runs locally, and recent main runs are green.

No fix exists yet. The robust fix would be to make the test's request-count assertion independent of wall-clock latency, which belongs in its own PR. I'll re-run the macOS job once when the rest of this workflow finishes (GitHub refuses a job re-run while the run is still in progress).

hosted-e2e is still red for the hardened-mode reason in the decision comment above. This PR stays blocked on that decision.


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] Blocked: needs a maintainer decision on the hosted yarn berry pin shape.

The tarball-URL locator in this PR does stop the token leak, but CI's hosted-e2e (yarn_berry_hosted_install_proof) found that yarn's hardened mode rejects it:

YN0078: Invalid resolution minimist@npm:1.2.2 → https://patch.socket.dev/patch/npm/minimist/1.2.2/…/minimist-1.2.2.tgz

Yarn enables hardened mode automatically for GitHub Actions runs on public pull requests, and enableHardenedMode: true turns it on anywhere. I reproduced it locally with yarn 4.12.0. Hardened mode checks that each lock resolution is valid for its descriptor, and a URL locator is not valid for an npm: descriptor. So this PR as written would break installs in that common setup. It must not merge as is.

Measured options (yarn 4.12.0, fresh checkout, cold cache, YARN_NPM_AUTH_TOKEN + npmAlwaysAuth, logging tarball server):

pin shape sends registry token to patch host --immutable hardened mode
A. npm:<v>::__archiveUrl=<url> (main today) yes (scoped always; all under npmAlwaysAuth) ok ok
B. tarball locator under the npm: key (this PR) no ok YN0078, fails
C. root package.json resolutions: {"<name>@npm:<range>": "<url>"} + lock entry keyed by the URL descriptor (what yarn itself writes) no ok, lock untouched, same 10c0 checksum ok
Option C is the only shape that fixes the leak and works everywhere. But hosted mode would then edit package.json, not just the yarn.lock entry the CLI contract promises today. That is the same resolutions + lock wiring that vendored berry mode already uses with file:. The change also affects rollback/remove, the vendored⇄hosted takeovers, users' own resolutions entries, and workspaces. The other option is to keep A and refuse or warn when registry auth is configured. That can't see CI-only tokens like YARN_NPM_AUTH_TOKEN, so it would only partly help.

Decision needed: (1) move hosted berry to option C (I can rework this PR, since most of the detection, rollback and VEX changes carry over), (2) keep A with a warn/refuse gate plus docs, or (3) something else.

WIP is pushed (5229052). The PR is back in draft with state: blocked.

Generated by Claude Code

Option C seems like the best choice, leaking auth tokens is not really acceptable. However we should avoid unnecessary package.json edits if we can avoid it. These changes should only be used if we are in yarn. If we do see a yarn project we should aslo default assume they may be running in hardened mode since we can't easily check otherwise. See if you can rework this and keep things working similarly for other versions of yarn. It sucks that yarn is so complicated.

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] Thanks, reworking to option C. I checked the shape with real yarn 4.12 (fresh checkout, cold cache, enableHardenedMode: true, YARN_NPM_AUTH_TOKEN + npmAlwaysAuth):

  • package.json gets one bare-name resolutions entry per patched package ("left-pad": "<hosted tgz url>"). This is the same wiring vendored berry mode already writes with file:, so it goes through the same gates: a user-authored entry for the package, alias consumers, or more than one locked version of the package means refuse rather than overwrite.
  • In yarn.lock only that entry's key and resolution: change, to name@<url>. The checksum, version: and the parents' dependencies: stay byte-identical, exactly what yarn itself writes.
  • Result: yarn install --immutable --check-cache passes in hardened mode for both direct and transitive packages, the lock stays untouched, and the patch host gets no Authorization header.

Scope:

  • Yarn berry only. Classic yarn, npm, pnpm, bun and vlt are unchanged, and package.json is never edited for them.
  • I'll assume hardened mode for every berry project.
  • rollback / remove, the vendored ⇄ hosted takeovers, VEX discovery, and locks pinned by older releases (npm:…::__archiveUrl=) will all be handled.

I'll push in steps and keep the status block current.


Generated by Claude Code

The tarball-URL pin stopped the registry token leak, but yarn's
hardened mode (on by default for public pull request CI) rejects a
tarball resolution under an npm: lock key (YN0078), breaking installs.

Hosted mode now pins a yarn berry package the way yarn itself does for
a root resolutions entry: package.json routes each locked descriptor
(name@npm:<range>) to the hosted tarball, and the lock entry is
re-keyed name@<url>, moved to yarn's sort order. Only that package's
descriptors move; other versions and other files stay untouched.
Rollback rebuilds the original key from those selectors and removes
them. A user-authored resolutions entry for the package, a missing
manifest, or a builtin patch: entry wrapping the same descriptor
refuse the pin instead of overwriting anything.

Other npm flavors are unchanged; package.json is only read beside a
yarn berry lock.

Assisted-by: Claude Code:claude-opus-5-5
Lock-only inventory now keeps a berry entry keyed by its hosted
tarball, so already-pinned packages stay visible to later scans. The
yarn berry redirect goldens gain a root package.json and expect the
resolutions selectors plus the re-keyed entry; the VEX discovery
golden, the vendor takeover test and the docs, CLI contract and
changelog describe the new pin shape and its refusals.

Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko
Mikola Lysenko (mikolalysenko) marked this pull request as ready for review October 1, 2026 17:55
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@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.

Stale Bugbot comment from a previous run.

Comment thread crates/socket-patch-core/src/vex/discover/yarn.rs
Comment thread crates/socket-patch-core/src/patch/redirect/mod.rs
Comment thread crates/socket-patch-core/src/patch/redirect/mod.rs
Comment thread crates/socket-patch-core/src/hosted/engine.rs
A yarn.lock entry already keyed by a tarball URL is now only treated
as ours when it points at the patch host or names the exact artifact.
A mirror tarball of the same version is left alone and refused as a
user resolution instead of being re-pinned.

VEX discovery no longer reports a hosted patch from a URL-keyed lock
entry unless package.json still routes the package there. A lock that
lost its resolutions entry is flagged as orphaned rather than counted
as patched, and a resolutions value on its own does not confirm a
redirect either.

The orphan refusal now tells users to restore yarn.lock and
package.json from version control, or delete the entry and reinstall.

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

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@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.

Stale Bugbot comment from a previous run.

The real-yarn berry suites run on CRLF files on Windows, as yarn
writes them there. The new check that the lock entry is keyed by the
hosted tarball expected an LF right after the key, so it failed on
every Windows run even though the lock was rewritten correctly. The
check now compares whole lines with the CR stripped.

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

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@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.

Stale Bugbot comment from a previous run.

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

@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.

Stale Bugbot comment from a previous run.

Comment thread crates/socket-patch-core/src/patch/redirect/mod.rs Outdated
Mikola Lysenko (mikolalysenko) pushed a commit that referenced this pull request Oct 2, 2026
The hosted->vendored takeover's per-package preflight read the
still-hosted package.json / yarn.lock. Hosted wiring that also writes a
Socket-owned package.json resolutions pin (#465) was then mistaken for a
user override (vendor_override_conflict) and the takeover refused.

The preflight now dry-runs the takeover's own restore_upstream and runs
resolutions_gate / scan_berry_target on the restored text
(RestoreOutcome.staged_text), so only the user's own wiring can refuse.
The #369 regression test now mounts the upstream entry the restore reads
and drops a leftover debug eprintln.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014hMbzxwUnf5voAqbc8g4df
The berry rewriter claimed every npm patch as its own before looking
at yarn.lock. A grant without a yarnBerry10c0 checksum, or with a URL
yarn cannot fetch as a tarball, was then left owned but unconfirmed,
so hosted mode stopped counting a package the lock does not pin (and
that another lockfile may have rewritten).

Ownership is now taken only once the lock is known to pin the
package version. The checksum is required only when the entry has to
be rewritten, so a rescan with a checksumless grant still confirms a
pin an earlier run completed.

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

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@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.

Stale Bugbot comment from a previous run.

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

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@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.

Stale Bugbot comment from a previous run.

Comment thread crates/socket-patch-core/src/patch/redirect/mod.rs
Comment thread crates/socket-patch-core/src/hosted/engine.rs
A patch server URL containing "$" was expanded as a regex capture
reference when written into the berry lock entry, corrupting its
resolution and checksum lines. The URL is now written literally.

When the berry preflight refuses a lock (mixed line endings, an
unsupported cacheKey), packages that lock pins are still decided by
the berry rewriter, and left unconfirmed. Before, a URL from an
earlier run in such a lock could confirm the package through the
hosted text probe.

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

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@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.

Stale Bugbot comment from a previous run.

@mikolalysenko

Mikola Lysenko (mikolalysenko) commented Oct 2, 2026 •

Copy link
Copy Markdown
Collaborator Author

Second pass reviewed dc9330f4c6371b209a9993a0a54a18dc51e3c764 together with the pushed #470 fix 852472c7119a0f6f275db9525a1f4111d3875929. The prior code and cross-PR findings are resolved; code review is clear, pending latest-head CI.

The orphaned/refused-pin handling, complete-pin checksum handling, and literal $ URL writes are correct. The author's subsequent main merge also correctly preserves Berry's guarded package.json read and npm's advisory override input, including memory-file selection and both regression families. No additional #465 commit was needed.

The current #465/#470 heads merge cleanly. Their exact combined tree (a3fbd2fabcf4b712bae7aeade0adb80966d40506) passes 140 core Berry tests, all 7 Berry vendor/takeover tests, the original independent orphaned-pin/VEX reproduction, and the Poetry/PDM golden checks. The previously failing hosted → vendored CRLF round trip succeeds; missing-checksum and user-override refusals preserve the existing mode. On #465 itself, 11 engine, 6 memory-selection, 14 npm-routing, and 2 Python-equivalence tests also pass.

This supersedes my earlier recommendation not to merge the pair unchanged: the compatibility fix is on #470 and the current pair is validated. Full platform CI remains required; the local checks ran on macOS.

Follow-up on final merged head 8d52ba6d5cc02624234d2c5335de9c4c777977d8: reviewed the additional fork-alias guard and its regression test. A descriptor such as left-pad@npm:other@^1.3.0 is now excluded from both rewrite targets and refused-lock ownership, preserving the user’s fork. No new finding. Exact-head CI has 484 successful checks and 6 skipped. The local combined-tree counts above apply to the earlier dc9330f4/852472c7 pair; this final delta was checked by inspection and existing CI.

Main now reads the root package.json for the npm lock rewriter as
advisory input (#490/#491). Beside a berry yarn.lock the manifest is
still read strictly, since the berry pin writes it; otherwise the
advisory read applies. The berry-only memory selection rule is dropped
because main always fetches package.json.

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

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

The npm lock rewriter now also reads the root package.json (#490), so
the contract says the berry pin is the one that edits it, not the only
reader.

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

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] CI note on dc9330f: native (ubuntu-latest, 2.3.4) in Poetry patch compatibility failed one case, 2.3.4 crlf vendored (appliedExactlyOne). The other four Poetry 2.3.4 cases passed, including direct vendored and crlf hosted.

I don't believe this failure comes from this PR:

  • The PR's changes beyond main are yarn berry and hosted-confirmation code that the Poetry vendored path never runs. The only Poetry-related change is the test-only equivalence golden.
  • The same workflow passed on main's current head (run 37033625924) and on this branch at 3bc0d7e earlier today.

No fix exists to port. I'm re-running the failed job once, after the run finishes, since GitHub won't re-run a job while its run is still going. If it fails again, I'll treat it as real and dig into the captures.


Generated by Claude Code

@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.

Stale Bugbot comment from a previous run.

Comment thread crates/socket-patch-core/src/patch/redirect/upstream/npm.rs
Comment thread crates/socket-patch-core/src/patch/redirect/mod.rs
A lock entry keyed `left-pad@npm:other@^1.3.0` installs the package
`other` under the left-pad name. If that fork happened to be at the
patched version, the hosted rewrite re-keyed it to the left-pad
tarball, replacing the user's fork with the patched package. Fork
aliases are now skipped and do not make the real entry ambiguous.

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

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@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 8d52ba6. Configure here.

@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

[agent] CI note on 8d52ba6: native (ubuntu-latest, 0.0.0-32) in vlt patch compatibility finished 32/36 as expected. The log shows repeated transport failure; retrying across hosted, vendored and agent cases. The four that stayed wrong after retries (hosted-dev, hosted-two-versions, hosted-direct, agent-workspace) ended as safe-refusal.

I don't believe this failure comes from this PR:

  • The same workflow passed on this branch's previous head dc9330f earlier today, and on main.
  • The only change since dc9330f is the berry fork-alias guard in rewrite_yarn_berry. vlt projects have no yarn.lock, so that code never runs for them, and agent mode doesn't use the hosted rewriter at all.

No fix exists to port. I'm re-running the failed job once after the run finishes. If it fails again, I'll treat it as real and dig into the captures.


Generated by Claude Code

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

Development

Successfully merging this pull request may close these issues.

Hosted yarn berry redirect makes yarn send the project's npm registry auth token to the patch host

3 participants