Skip to content

Commit 203e092

Browse files
Fix yarn berry hosted pin leaking npm auth (#404) (#465)
* Start fix for #404 Assisted-by: Claude Code:claude-opus-5-5 * Stop yarn berry pins leaking npm auth tokens 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 * Keep hosted berry pins in the lock inventory 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 * Pin yarn berry patches through resolutions 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 * Cover the resolutions pin in goldens and docs 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 * Address review findings on berry pin 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 * Match berry lock keys on CRLF locks too 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 * Confirm berry pins only with manifest routing A hosted yarn berry pin is two edits: the lock entry keyed by the patch tarball and the package.json resolutions entry that routes the package to it. If the resolutions entry is removed, yarn no longer installs the patch, but a rescan still counted the package as redirected because the tarball URL was in yarn.lock. That fed the in-run VEX, which then attested not_affected for an unpatched package. The berry rewriter now reports which packages its lock pins and which of those pins are complete, and hosted confirmation trusts only that report for them. An orphaned lock entry is refused as before and is no longer counted or attested. Assisted-by: Claude Code:claude-opus-5-5 * Own berry deps only when the lock pins them 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 * Harden berry pin writes and refused locks 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 * Clarify when the berry pin edits package.json 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 * Leave yarn berry fork aliases untouched 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 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 9d81139 commit 203e092

49 files changed

Lines changed: 2677 additions & 514 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎CHANGELOG.md‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,15 @@ limits, and required install commands.
169169
fetches honor `GOPROXY` and private-module settings.
170170
- Yarn Berry preserves supported line endings and checksum spellings. Mode
171171
preflights, including Bun's, run before discarding existing protection.
172+
- Yarn Berry hosted references no longer send npm registry credentials to the
173+
patch server. The old `npm:` locator made yarn attach `npmAuthToken` /
174+
`YARN_NPM_AUTH_TOKEN` to scoped packages (and to every package under
175+
`npmAlwaysAuth`). Hosted mode now pins the way yarn does for a root
176+
`resolutions` entry: `package.json` routes the locked descriptor to the
177+
hosted tarball and the lock entry is keyed by it, which also passes yarn's
178+
hardened mode (on by default for public pull request CI). A user-authored
179+
`resolutions` entry for the package is never overwritten. Locks pinned by
180+
earlier releases are re-pinned on the next hosted `scan`.
172181
- Composer hosted references remove upstream source fallbacks and mirrors;
173182
RubyGems hosted locks preserve source order; NuGet edits use the active config
174183
and survive `<clear />` entries.

‎crates/socket-patch-cli/CLI_CONTRACT.md‎

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.

‎crates/socket-patch-cli/src/commands/scan/mod.rs‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4343,6 +4343,32 @@ mod tests {
43434343
assert!(takeover.vendored.is_empty(), "{takeover:?}");
43444344
}
43454345

4346+
#[tokio::test]
4347+
async fn hosted_direction_provable_for_berry_tarball_locator() {
4348+
// Today's berry pin is the plain tarball-URL locator (#404).
4349+
let tmp = tempfile::tempdir().unwrap();
4350+
let root = tmp.path();
4351+
write_vendor_ledger_wired(root, &["pkg:npm/minimist@1.2.2"]).await;
4352+
tokio::fs::write(
4353+
root.join("yarn.lock"),
4354+
format!(
4355+
"__metadata:\n version: 8\n cacheKey: 10c0\n\n\
4356+
\"minimist@npm:1.2.2\":\n version: 1.2.2\n \
4357+
resolution: \"minimist@https://patch.socket.dev/patch/npm/{TAKEOVER_TOKEN}/{TAKEOVER_UUID}/minimist-1.2.2.tgz\"\n"
4358+
),
4359+
)
4360+
.await
4361+
.unwrap();
4362+
4363+
let takeover = classify_overlap_takeover(&common_at(root), root).await;
4364+
assert_eq!(
4365+
takeover.redirect,
4366+
vec!["pkg:npm/minimist@1.2.2".to_string()],
4367+
"a berry tarball locator must prove hosted is live"
4368+
);
4369+
assert!(takeover.vendored.is_empty(), "{takeover:?}");
4370+
}
4371+
43464372
#[tokio::test]
43474373
async fn vendored_path_uuid_is_not_a_hosted_pin() {
43484374
// The vendored wiring embeds the SAME patch uuid in its

‎crates/socket-patch-cli/tests/e2e_hosted_production.rs‎

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,16 +1467,19 @@ fn yarn_berry_hosted_install_proof() {
14671467
}
14681468
assert_pristine(&minimist_entry(&fx.proj), PATCH_MARKER, LEG);
14691469
let registry_lock = std::fs::read(fx.proj.join("yarn.lock")).expect("registry yarn.lock");
1470+
// The hosted pin also routes through package.json `resolutions` (#404),
1471+
// so a revert to the registry restores both files.
1472+
let registry_pkg = std::fs::read(fx.proj.join("package.json")).expect("registry package.json");
14701473

14711474
let env_json = scan_hosted(&fx.proj, &[]);
14721475
assert_redirected(&env_json, "yarn.lock");
14731476
let lock = read(&fx.proj.join("yarn.lock"));
1474-
// Berry pins the hosted artifact through a percent-encoded `__archiveUrl`
1475-
// resolution field, so the plain host string is encoded — check both the
1476-
// encoded host and the (unencoded) patch UUID.
1477+
// Berry pins the hosted artifact as a plain tarball-URL locator — never
1478+
// an `npm:` one (`::__archiveUrl=`), whose fetcher would send the npm
1479+
// registry token to the patch host (#404).
14771480
assert!(
1478-
lock.contains("__archiveUrl") && lock.contains("patch.socket.dev"),
1479-
"{LEG}: berry lock carries no __archiveUrl pointing at the patch \
1481+
lock.contains("@https://patch.socket.dev/") && !lock.contains("__archiveUrl"),
1482+
"{LEG}: berry lock carries no tarball locator pointing at the patch \
14801483
host:\n{lock}"
14811484
);
14821485
assert!(
@@ -1497,7 +1500,7 @@ fn yarn_berry_hosted_install_proof() {
14971500
);
14981501
assert_patched(&minimist_entry(&fx.proj), PATCH_MARKER, LEG);
14991502

1500-
yarn_berry_hosted_manifestless_vex(&fx, &registry_lock, &env);
1503+
yarn_berry_hosted_manifestless_vex(&fx, &registry_lock, &registry_pkg, &env);
15011504
}
15021505

15031506
/// One `vex --json --output <tmp>/berry.vex.json` run in `proj` (production
@@ -1582,7 +1585,12 @@ fn berry_skip_code(env: &serde_json::Value) -> String {
15821585
/// `--offline` (`record_unavailable`), and not once the lock is reverted to
15831586
/// the registry and reinstalled (nothing names the patch, even with
15841587
/// `--no-verify`).
1585-
fn yarn_berry_hosted_manifestless_vex(fx: &NpmFixture, registry_lock: &[u8], env: &[(&str, &str)]) {
1588+
fn yarn_berry_hosted_manifestless_vex(
1589+
fx: &NpmFixture,
1590+
registry_lock: &[u8],
1591+
registry_pkg: &[u8],
1592+
env: &[(&str, &str)],
1593+
) {
15861594
const LEG: &str = "yarn_berry_hosted_install_proof (manifest-less vex)";
15871595
let proj = &fx.proj;
15881596
assert!(
@@ -1600,8 +1608,10 @@ fn yarn_berry_hosted_manifestless_vex(fx: &NpmFixture, registry_lock: &[u8], env
16001608
assert_eq!(berry_skip_code(&env_json), "record_unavailable", "{LEG}");
16011609
assert!(doc.is_none(), "{LEG}: no document");
16021610

1603-
// Revert the lock to the registry and reinstall.
1611+
// Revert the lock and the package.json `resolutions` pin to the
1612+
// registry and reinstall.
16041613
std::fs::write(proj.join("yarn.lock"), registry_lock).unwrap();
1614+
std::fs::write(proj.join("package.json"), registry_pkg).unwrap();
16051615
std::fs::remove_dir_all(proj.join("node_modules")).ok();
16061616
let reinstall = tool(proj, "yarn", &["install", "--immutable"], env);
16071617
assert!(

‎crates/socket-patch-cli/tests/e2e_redirect_yarn_berry_build.rs‎

Lines changed: 103 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
//! `e2e_redirect_npm_build.rs`.
44
//!
55
//! `scan --mode hosted` never lands patched bytes in the repo: it rewrites
6-
//! `yarn.lock` so the patched dependency resolves via
7-
//! `npm:<v>::__archiveUrl=<hosted-tgz>` with `checksum: 10c0/<hex>` (yarn's
6+
//! `yarn.lock` so the patched dependency resolves via the tarball-URL
7+
//! locator `<name>@<hosted-tgz>` with `checksum: 10c0/<hex>` (yarn's
88
//! cache-zip sha512); v5 keeps no redirect ledger — the lock pin is the
99
//! whole hosted state. This test proves every link against the REAL
1010
//! `corepack yarn@4.12.0`:
@@ -16,16 +16,19 @@
1616
//! extract the EXACT `10c0/<hex>` checksum yarn computes for that
1717
//! tarball's cache zip — the value the redirect mock must hand back
1818
//! (yarn recomputes the same zip checksum whether the locator is `file:`
19-
//! or `::__archiveUrl=`, so `--check-cache` will accept it).
19+
//! or a tarball URL, so `--check-cache` will accept it).
2020
//! 3. `scan --mode hosted --json --vex` (the real binary): yarn.lock now
21-
//! pins the hosted `__archiveUrl` + the `10c0` checksum, NO ledger is
21+
//! pins the hosted tarball URL + the `10c0` checksum, NO ledger is
2222
//! written, the in-run VEX is the `(redirected)` attestation.
2323
//! 4. FRESH-CHECKOUT PROOF: only package.json + yarn.lock + .yarnrc.yml +
2424
//! .socket/ travel; `yarn install --immutable --check-cache` (offline
2525
//! from the registry, `unsafeHttpWhitelist` for the wiremock host) MUST
26-
//! install the patched bytes from the hosted tarball.
26+
//! install the patched bytes from the hosted tarball — with an npm
27+
//! registry token configured (`YARN_NPM_AUTH_TOKEN` + `npmAlwaysAuth`)
28+
//! that the patch host must never receive (#404: an `npm:` locator made
29+
//! yarn's npm fetcher send it).
2730
//!
28-
//! The negative twin serves a DIFFERENT tarball at the archiveUrl while the
31+
//! The negative twin serves a DIFFERENT tarball at the hosted URL while the
2932
//! lock keeps the real `10c0` checksum: the fresh `--check-cache` install MUST
3033
//! fail with a YN0018 checksum error — the lock pin is enforcement.
3134
//!
@@ -267,6 +270,9 @@ struct BerryRedirectFixture {
267270
host: String,
268271
/// `yarn.lock` as the real yarn wrote it, BEFORE the hosted rewrite.
269272
registry_lock: Vec<u8>,
273+
/// The root `package.json` BEFORE the hosted rewrite (#404 option C
274+
/// pins through its `resolutions`, so a revert restores both files).
275+
registry_pkg: Vec<u8>,
270276
_server: MockServer,
271277
}
272278

@@ -286,7 +292,7 @@ enum HostedDriver {
286292
/// Steps 1–3: real install, patched tarball + bootstrap checksum + API mocks,
287293
/// the hosted rewrite (per `driver`: `scan --mode hosted --vex` or
288294
/// `get <uuid> --mode hosted`), and the envelope/lockfile/ledger assertions.
289-
/// `tamper_served_tarball` serves DIFFERENT bytes at the archiveUrl than the
295+
/// `tamper_served_tarball` serves DIFFERENT bytes at the hosted URL than the
290296
/// checksum pins. `None` = skip (message printed).
291297
async fn berry_hosted_project(
292298
tag: &str,
@@ -347,6 +353,7 @@ async fn berry_hosted_project(
347353
let installed_dir = proj.join("node_modules").join(DEP);
348354
let orig = std::fs::read(installed_dir.join("index.js")).expect("installed index.js");
349355
let registry_lock = std::fs::read(proj.join("yarn.lock")).expect("registry yarn.lock");
356+
let registry_pkg = std::fs::read(proj.join("package.json")).expect("registry package.json");
350357
assert!(
351358
!orig.starts_with(MARKER.as_bytes()),
352359
"pristine install must not carry the marker"
@@ -549,12 +556,33 @@ async fn berry_hosted_project(
549556
);
550557
}
551558

552-
// Lockfile pin: the encoded __archiveUrl + the 10c0 checksum.
559+
// Lockfile pin: the tarball-URL locator + the 10c0 checksum. Never an
560+
// `npm:` locator (`::__archiveUrl=`): yarn's npm fetcher sends registry
561+
// auth to whatever host that locator names (#404).
553562
let lock = std::fs::read_to_string(proj.join("yarn.lock")).unwrap();
554-
let encoded = socket_patch_core::utils::uri::encode_uri_component(&hosted_url);
555563
assert!(
556-
lock.contains("::__archiveUrl=") && lock.contains(&encoded),
557-
"yarn.lock must carry the encoded __archiveUrl; got:\n{lock}"
564+
lock.contains(&format!("\n resolution: \"{DEP}@{hosted_url}\"")),
565+
"yarn.lock must pin the hosted tarball locator; got:\n{lock}"
566+
);
567+
// #404 option C: the entry is keyed by the tarball descriptor, and the
568+
// root package.json routes the locked descriptor there.
569+
assert!(
570+
lock.lines()
571+
.any(|l| l.trim_end_matches('\r') == format!("\"{DEP}@{hosted_url}\":")),
572+
"yarn.lock entry must be keyed by the tarball descriptor; got:\n{lock}"
573+
);
574+
let root_pkg = std::fs::read_to_string(proj.join("package.json")).unwrap();
575+
let root_pkg: serde_json::Value = serde_json::from_str(&root_pkg).unwrap();
576+
assert!(
577+
root_pkg["resolutions"]
578+
.as_object()
579+
.is_some_and(|r| r.iter().any(|(sel, v)| sel.starts_with(&format!("{DEP}@npm:"))
580+
&& v.as_str() == Some(hosted_url.as_str()))),
581+
"package.json must route {DEP} to the hosted tarball: {root_pkg}"
582+
);
583+
assert!(
584+
!lock.contains("__archiveUrl"),
585+
"the hosted pin must not be an npm: locator; got:\n{lock}"
558586
);
559587
let checksum_line = yarn_berry_common::expected_checksum_line(
560588
&String::from_utf8_lossy(&registry_lock),
@@ -579,6 +607,7 @@ async fn berry_hosted_project(
579607
patched,
580608
host,
581609
registry_lock,
610+
registry_pkg,
582611
_server: server,
583612
})
584613
}
@@ -598,7 +627,11 @@ fn fresh_yarnrc(fx: &BerryRedirectFixture) -> String {
598627

599628
/// Fresh dir with only the committable files, then `yarn install --immutable
600629
/// --check-cache` offline-from-registry (the wiremock host is whitelisted for
601-
/// http). Returns the fresh dir + the install output.
630+
/// http). The install runs with an npm registry token that yarn must apply to
631+
/// every registry request (`YARN_NPM_AUTH_TOKEN` + `YARN_NPM_ALWAYS_AUTH`),
632+
/// the CI shape #404 leaked to the patch host: [`assert_patch_host_got_no_auth`]
633+
/// checks the hosted tarball request carried none. Returns the fresh dir +
634+
/// the install output.
602635
fn fresh_checkout_yarn_install(fx: &BerryRedirectFixture) -> (PathBuf, Output) {
603636
let fresh = fx.tmp.path().join("fresh");
604637
std::fs::create_dir_all(&fresh).unwrap();
@@ -619,19 +652,73 @@ fn fresh_checkout_yarn_install(fx: &BerryRedirectFixture) -> (PathBuf, Output) {
619652
&[
620653
("YARN_GLOBAL_FOLDER", fresh_global.to_str().unwrap()),
621654
("YARN_ENABLE_GLOBAL_CACHE", "false"),
655+
("YARN_NPM_AUTH_TOKEN", REGISTRY_TOKEN),
656+
("YARN_NPM_ALWAYS_AUTH", "true"),
657+
// Hardened mode (yarn enables it on its own for public-PR CI)
658+
// re-validates every lock resolution against its descriptor; a
659+
// tarball locator under an `npm:` key fails it with YN0078 —
660+
// why the pin routes through `resolutions` (#404).
661+
("YARN_ENABLE_HARDENED_MODE", "true"),
622662
],
623663
);
624664
(fresh, ci)
625665
}
626666

667+
/// The npm registry token the fresh install is configured with.
668+
const REGISTRY_TOKEN: &str = "SOCKET-E2E-REGISTRY-TOKEN";
669+
670+
/// #404: the patch host fetched the hosted tarball, and no request it
671+
/// received carried an `Authorization` header (or the registry token in any
672+
/// header) — the hosted pin must never hand registry credentials to it.
673+
async fn assert_patch_host_got_no_auth(fx: &BerryRedirectFixture) {
674+
let requests = fx
675+
._server
676+
.received_requests()
677+
.await
678+
.expect("wiremock request recording is on");
679+
let tarball_gets: Vec<_> = requests
680+
.iter()
681+
.filter(|r| r.url.path().ends_with(".tgz"))
682+
.collect();
683+
assert!(
684+
!tarball_gets.is_empty(),
685+
"the fresh install must fetch the hosted tarball from the patch host"
686+
);
687+
// The same wiremock also plays the Socket API, whose requests carry the
688+
// CLI's own API token — only the yarn-made tarball fetches are judged
689+
// for an Authorization header; the registry token must appear nowhere.
690+
for r in &tarball_gets {
691+
assert!(
692+
!r.headers.contains_key("authorization"),
693+
"{} {} carried an Authorization header to the patch host: {:?}",
694+
r.method,
695+
r.url,
696+
r.headers.get("authorization")
697+
);
698+
}
699+
for r in &requests {
700+
for (name, value) in r.headers.iter() {
701+
assert!(
702+
!value.to_str().unwrap_or("").contains(REGISTRY_TOKEN),
703+
"{} {} leaked the registry token in header {name}",
704+
r.method,
705+
r.url
706+
);
707+
}
708+
}
709+
}
710+
627711
/// The manifest-less VEX matrix over the hosted rewrite `driver` produced
628712
/// (see `yarn_berry_common`): fresh checkouts without the manifest, without
629713
/// the ledgers, offline, tampered, reverted to the registry and installed
630714
/// under PnP — each installed by the REAL yarn and attested (or refused) by
631715
/// the REAL binary against a mock patch API.
632716
fn hosted_manifestless_vex_matrix(fx: &BerryRedirectFixture, driver: HostedDriver) {
633717
let yarnrc = fresh_yarnrc(fx);
634-
let registry_state = [("yarn.lock", fx.registry_lock.clone())];
718+
let registry_state = [
719+
("yarn.lock", fx.registry_lock.clone()),
720+
("package.json", fx.registry_pkg.clone()),
721+
];
635722
let yarn =
636723
|cwd: &Path, args: &[&str], env: &[(&str, &str)]| corepack(cwd, yarn_berry(), args, env);
637724
let api_url = fx._server.uri();
@@ -698,6 +785,7 @@ async fn berry_redirect_fresh_checkout_installs_patched_bytes() {
698785
installed, fx.patched,
699786
"fresh install must be byte-identical to the patched content"
700787
);
788+
assert_patch_host_got_no_auth(&fx).await;
701789

702790
hosted_manifestless_vex_matrix(&fx, HostedDriver::Scan);
703791
}
@@ -706,7 +794,7 @@ async fn berry_redirect_fresh_checkout_installs_patched_bytes() {
706794
/// routes through the SAME hosted engine as `scan --mode hosted`, so the
707795
/// berry chain must hold unchanged — including the `10c0` cacheKey bootstrap
708796
/// (the fixture still resolves the patched tarball with a real yarn to pin
709-
/// the exact cache-zip checksum) and the lock's `::__archiveUrl=` +
797+
/// the exact cache-zip checksum) and the lock's tarball-URL locator +
710798
/// `checksum: 10c0/<hex>` splice — and the fresh `yarn install --immutable
711799
/// --check-cache` pulls the patched bytes from the hosted tarball. The uuid
712800
/// identifier path is exempt from installed narrowing, so only the view +
@@ -740,7 +828,7 @@ async fn berry_get_uuid_hosted_fresh_checkout_installs() {
740828
hosted_manifestless_vex_matrix(&fx, HostedDriver::GetUuid);
741829
}
742830

743-
/// Negative twin: the archiveUrl serves a DIFFERENT tarball while the lock
831+
/// Negative twin: the hosted URL serves a DIFFERENT tarball while the lock
744832
/// pins the real `10c0` checksum — the fresh `--check-cache` install must fail
745833
/// with YN0018.
746834
#[tokio::test(flavor = "multi_thread")]

0 commit comments

Comments
 (0)