diff --git a/crates/socket-patch-core/src/vendor/lock_inventory/mod.rs b/crates/socket-patch-core/src/vendor/lock_inventory/mod.rs index a73578882..3d4bc58fb 100644 --- a/crates/socket-patch-core/src/vendor/lock_inventory/mod.rs +++ b/crates/socket-patch-core/src/vendor/lock_inventory/mod.rs @@ -10,9 +10,7 @@ //! with no installed copy ([`super::registry_fetch`]), verifying the bytes //! against the integrity the lock records — FAIL-CLOSED: an entry whose //! lock carries no content verifier is never fetched; -//! * `repair` recovers ledger entries ([`recover_lock_entry`]) and the pin a -//! rewired lock records for a vendored artifact -//! ([`wired_vendor_integrity`]); +//! * `repair` recovers ledger entries ([`recover_lock_entry`]); //! * ledger liveness (`vex::discover`) reads EVERY lock's instance //! ([`inventory_project_every_lock`]) as evidence that a package resolves //! from somewhere other than its patch. @@ -66,7 +64,6 @@ pub(crate) mod pypi; pub(crate) mod recover; pub mod view; pub(crate) mod vlt; -pub(crate) mod wired; pub(crate) mod yarn; pub use self::bun::{bun_binary_lock_drives, bun_text_lock_drives}; @@ -79,7 +76,6 @@ pub(crate) use self::npm_family::inventory_npm_lock; pub(crate) use self::pypi::pipfile_lock_entries; pub use self::recover::recover_lock_entry; pub use self::view::{DiskSnapshot, MemoryEntry, MemoryProject, ProjectView, ReadSet}; -pub use self::wired::wired_vendor_integrity; // The per-format views `inventory_project_diagnosed` unions (and the test // modules reach through `super::*`). diff --git a/crates/socket-patch-core/src/vendor/lock_inventory/tests.rs b/crates/socket-patch-core/src/vendor/lock_inventory/tests.rs index fe957baaf..a6a731bcc 100644 --- a/crates/socket-patch-core/src/vendor/lock_inventory/tests.rs +++ b/crates/socket-patch-core/src/vendor/lock_inventory/tests.rs @@ -470,54 +470,6 @@ async fn bun_binary_inventory_works_without_an_install_or_runtime() { } } -#[tokio::test] -async fn bun_binary_vendor_integrity_follows_live_package_records() { - let bytes = include_bytes!("../../../tests/fixtures/bun-lockb/1.1.45/bun.lockb"); - let mut lock = super::super::bun_lockb::BunLockb::parse(bytes).unwrap(); - let package = lock - .packages() - .unwrap() - .into_iter() - .find(|package| package.name == "minimist") - .unwrap(); - let tmp = tempfile::tempdir().unwrap(); - let rel = ".socket/vendor/npm/11111111-1111-4111-8111-111111111111/minimist-1.2.2.tgz"; - let first = format!("sha512-{}", "A".repeat(86) + "=="); - lock.set_package(package.id, rel, &first).unwrap(); - tokio::fs::write(tmp.path().join("bun.lockb"), lock.bytes()) - .await - .unwrap(); - assert_eq!( - wired_vendor_integrity(tmp.path(), rel).await, - Some(LockIntegrity::Sri(first)) - ); - let next = rel.replace( - "11111111-1111-4111-8111-111111111111", - "22222222-2222-4222-8222-222222222222", - ); - lock.set_package( - package.id, - &next, - &format!("sha512-{}", "A".repeat(86) + "=="), - ) - .unwrap(); - tokio::fs::write(tmp.path().join("bun.lockb"), lock.bytes()) - .await - .unwrap(); - assert_eq!( - wired_vendor_integrity(tmp.path(), rel).await, - None, - "retired strings are not active resolutions" - ); - assert!(wired_vendor_integrity(tmp.path(), &next).await.is_some()); - write(tmp.path(), "bun.lock", BUN_LOCK).await; - assert_eq!( - wired_vendor_integrity(tmp.path(), &next).await, - None, - "text lock takes precedence" - ); -} - /// A pnpm-lock.yaml whose lockfileVersion the probe refuses — pnpm 6 /// wrote 5.3; only 5.4/6.0/9.0 route to a backend. This is the shape /// that reaches the version-refusal discovery fallback, where a live @@ -1792,35 +1744,6 @@ async fn inventories_script_and_pylock_files_without_installed_packages() { assert!(!entries.iter().any(|entry| entry.name == "local")); } -#[tokio::test] -async fn pylock_repair_uses_the_exact_artifact_hash_and_refuses_conflicts() { - let tmp = tempfile::tempdir().unwrap(); - let path = ".socket/vendor/pypi/uuid/alpha-1-py3-none-any.whl"; - let sha = "a".repeat(64); - let pylock = format!("lock-version='1.0'\n[[packages]]\nname='alpha'\nversion='1'\narchive={{path='{path}',hashes={{sha256='{sha}'}}}}\n"); - write(tmp.path(), "pylock.toml", &pylock).await; - assert_eq!( - wired_vendor_integrity(tmp.path(), path).await, - Some(LockIntegrity::Sha256Hex(sha.clone())) - ); - assert_eq!( - wired_vendor_integrity(tmp.path(), &format!("{path}.other")).await, - None - ); - write(tmp.path(), "example.py.lock", &format!("version=1\n[[package]]\nname='alpha'\nversion='1'\nsource={{path='{path}'}}\nwheels=[{{filename='alpha-1-py3-none-any.whl',hash='sha256:{sha}'}}]\n")).await; - assert_eq!( - wired_vendor_integrity(tmp.path(), path).await, - Some(LockIntegrity::Sha256Hex(sha.clone())) - ); - write( - tmp.path(), - "pylock.toml", - &pylock.replace(&sha, &"b".repeat(64)), - ) - .await; - assert_eq!(wired_vendor_integrity(tmp.path(), path).await, None); -} - #[test] fn legacy_and_pep751_archive_hashes_stay_with_their_own_wheels() { let sha = "b".repeat(64); @@ -2276,8 +2199,7 @@ async fn fifo_lockfiles_fail_fast_instead_of_wedging() { let root = tmp.path().to_path_buf(); // Every filename this module opens: the per-ecosystem inventories, // the npm-family readers (reached without the flavor probe touching - // the same file via the shrinkwrap/sibling/rush fallbacks), and - // wired_vendor_integrity (no probe at all). + // the same file via the shrinkwrap/sibling/rush fallbacks). let names = [ "Cargo.lock", "go.sum", @@ -2317,7 +2239,6 @@ async fn fifo_lockfiles_fail_fast_instead_of_wedging() { inventory_vlt(&root).await, inventory_pnpm_lock_at(&root.join("shrinkwrap.yaml")).await, gem_remotes(&root).await, - wired_vendor_integrity(&root, ".socket/vendor/npm/x/x.tgz").await, ) }; let Ok(results) = tokio::time::timeout(deadline, all).await else { @@ -2330,22 +2251,8 @@ async fn fifo_lockfiles_fail_fast_instead_of_wedging() { } panic!("lockfile inventories must fail fast on FIFO lockfiles"); }; - let ( - cargo, - go, - composer, - gem, - pypi, - npm, - pnpm, - yarn_c, - yarn_b, - bun, - vlt, - legacy, - remotes, - wired, - ) = results; + let (cargo, go, composer, gem, pypi, npm, pnpm, yarn_c, yarn_b, bun, vlt, legacy, remotes) = + results; for (label, opt) in [ ("cargo", cargo), ("go", go), @@ -2366,7 +2273,6 @@ async fn fifo_lockfiles_fail_fast_instead_of_wedging() { ); } assert!(remotes.is_empty(), "{remotes:?}"); - assert!(wired.is_none(), "{wired:?}"); } #[tokio::test] @@ -2972,119 +2878,6 @@ async fn pure_wheel_rejects_short_hash_missing_hash_and_non_http_url() { assert_eq!(pure_wheel_from_uv_unit(&ftp), None, "non-http url"); } -/// The yarn-classic `integrity ` branch of `wired_vendor_integrity` -/// — the trust anchor for repair's no-ledger reconstruction on -/// yarn-classic projects (rewired classic locks carry exactly this -/// line). Rides along fail-soft: an unparseable JSON lock and a v1 lock -/// without a `packages` map are both skipped, not fatal. -#[tokio::test] -async fn wired_vendor_integrity_reads_rewired_yarn_classic_and_skips_bad_json_locks() { - let tmp = tempfile::tempdir().unwrap(); - let rel = ".socket/vendor/npm/9f6b2c4e-1d3a-4f6b-8c2d-7e5a9b1c3d5f/left-pad-1.3.0.tgz"; - // Unparseable JSON lock: skipped fail-soft. - write(tmp.path(), "npm-shrinkwrap.json", "not json").await; - // v1 lock without a packages map: skipped fail-soft. - write( - tmp.path(), - "package-lock.json", - r#"{"lockfileVersion":1,"dependencies":{}}"#, - ) - .await; - // The rewired classic block, exactly as yarn_classic_lock rewires it. - write( - tmp.path(), - "yarn.lock", - &format!( - "# yarn lockfile v1\n\n\ - \"left-pad@file:./{rel}\":\n \ - version \"1.3.0\"\n \ - resolved \"file:./{rel}#0000000000000000000000000000000000000000\"\n \ - integrity sha512-ours==\n" - ), - ) - .await; - - assert_eq!( - wired_vendor_integrity(tmp.path(), rel).await, - Some(LockIntegrity::Sri("sha512-ours==".into())), - "the classic `integrity ` line is the wired trust anchor" - ); -} - -/// The yarn / bun branches of `wired_vendor_integrity` read the entry -/// models lockfile discovery reads, not a line window: a berry block whose -/// carried sections push `checksum:` far below the reference, yarn 4.0.x's -/// bare-hex checksum, a CRLF classic lock, a shadowed classic block (yarn -/// keeps the last one) and bun's digest-less re-save (which must never -/// borrow the next tuple's sha512). -#[tokio::test] -async fn wired_vendor_integrity_reads_yarn_and_bun_entries_structurally() { - let rel = ".socket/vendor/npm/9f6b2c4e-1d3a-4f6b-8c2d-7e5a9b1c3d5f/left-pad-1.3.0.tgz"; - let hex = "ab".repeat(64); - let berry = |checksum: &str| { - format!( - "__metadata:\n version: 8\n cacheKey: 10c0\n\n\ - \"left-pad@file:./{rel}::locator=app%40workspace%3A.\":\n \ - version: 1.3.0\n \ - resolution: \"left-pad@file:./{rel}#./{rel}::hash=abc&locator=app%40workspace%3A.\"\n \ - dependencies:\n a: \"npm:1.0.0\"\n b: \"npm:1.0.0\"\n c: \"npm:1.0.0\"\n d: \"npm:1.0.0\"\n e: \"npm:1.0.0\"\n \ - checksum: {checksum}\n \ - languageName: node\n \ - linkType: hard\n" - ) - }; - for (checksum, want) in [ - (format!("10c0/{hex}"), format!("10c0/{hex}")), - (hex.clone(), format!("10c0/{hex}")), - ] { - let tmp = tempfile::tempdir().unwrap(); - write(tmp.path(), "yarn.lock", &berry(&checksum)).await; - assert_eq!( - wired_vendor_integrity(tmp.path(), rel).await, - Some(LockIntegrity::BerryChecksum(want)), - "{checksum}" - ); - } - - let classic = |key: &str, sri: &str| { - format!( - "{key}:\n version \"1.3.0\"\n resolved \"file:./{rel}#0000000000000000000000000000000000000000\"\n integrity {sri}\n" - ) - }; - let tmp = tempfile::tempdir().unwrap(); - let lock = format!( - "# yarn lockfile v1\n\n{}\n{}", - classic("left-pad@^1.3.0", "sha512-shadowed=="), - classic("left-pad@^1.3.0", "sha512-live==") - ) - .replace('\n', "\r\n"); - write(tmp.path(), "yarn.lock", &lock).await; - assert_eq!( - wired_vendor_integrity(tmp.path(), rel).await, - Some(LockIntegrity::Sri("sha512-live==".into())), - "the live (last) block of a CRLF lock" - ); - - let bun = |ours: &str| { - format!( - "{{\n \"lockfileVersion\": 1,\n \"workspaces\": {{\n \"\": {{\n \"name\": \"app\",\n }},\n }},\n \"packages\": {{\n \"left-pad\": [\"left-pad@./{rel}\", {{}}{ours}],\n\n \"right-pad\": [\"right-pad@1.0.0\", \"\", {{}}, \"sha512-theirs==\"],\n }}\n}}\n" - ) - }; - let tmp = tempfile::tempdir().unwrap(); - write(tmp.path(), "bun.lock", &bun(", \"sha512-ours==\"")).await; - assert_eq!( - wired_vendor_integrity(tmp.path(), rel).await, - Some(LockIntegrity::Sri("sha512-ours==".into())) - ); - let tmp = tempfile::tempdir().unwrap(); - write(tmp.path(), "bun.lock", &bun("")).await; - assert_eq!( - wired_vendor_integrity(tmp.path(), rel).await, - None, - "a digest-less re-save pins nothing" - ); -} - /// `PnpmPackage::resolution_tokens` exposes the raw `resolution:` value the /// grammar refused (a nested map, a duplicate key, a wrapped flow map), so /// lockfile discovery can still tell a Socket-shaped entry from anything @@ -3768,8 +3561,7 @@ async fn requirements_index_option_in_an_include_spans_the_tree() { /// dangling `bun.lock` link is absent to it and it installs from the /// `bun.lockb` beside it (verified with Bun 1.2.23 and 1.3.14: /// `bun install --frozen-lockfile` installs from the binary lock). The -/// inventory, the wired-integrity probe and vendored routing must all pick -/// `bun.lockb` too, instead of losing every package of the live lock. +/// inventory and vendored routing must both pick `bun.lockb` too, instead of losing every package of the live lock. #[cfg(unix)] #[tokio::test] async fn bun_dangling_text_lock_link_leaves_the_binary_lock_live() { @@ -3797,10 +3589,6 @@ async fn bun_dangling_text_lock_link_leaves_the_binary_lock_live() { vec![("is-number".into(), "7.0.0".into())], "the binary lock's registry packages (minimist is vendored)" ); - assert_eq!( - wired_vendor_integrity(tmp.path(), rel).await, - Some(LockIntegrity::Sri(sri)) - ); assert!(super::super::bun_lock::binary_lock_drives(tmp.path())); // The hosted engine's view-level answer (disk and snapshot) agrees. assert!(!bun_text_lock_drives(&ProjectView::Disk(tmp.path()))); diff --git a/crates/socket-patch-core/src/vendor/lock_inventory/wired.rs b/crates/socket-patch-core/src/vendor/lock_inventory/wired.rs deleted file mode 100644 index 252b5b27a..000000000 --- a/crates/socket-patch-core/src/vendor/lock_inventory/wired.rs +++ /dev/null @@ -1,260 +0,0 @@ -//! The integrity a rewired lockfile records for a vendored artifact -//! ([`wired_vendor_integrity`]). - -use std::path::Path; - -use toml_edit::{DocumentMut, Item}; - -use crate::constants::npm_family::{BUN_LOCK, BUN_LOCKB, NPM_LOCKS, PNPM_LOCK}; -use crate::formats::pnpm::PnpmLock; -use crate::formats::yarn::blocks::{berry_field, classic_field}; -use crate::formats::yarn::is_berry_lock; -use crate::utils::digest::is_sri_pin; -use crate::utils::fs::{read_regular_to_bytes, read_regular_to_string}; -use crate::utils::python_lock::{ - lock_artifact, lock_package_collection, package_artifacts, uv_source_location, -}; -use crate::vendor::bun_lock_text::{decode_json_string, split_name_spec}; -use crate::vendor::bun_lockb::BunLockb; -use crate::vex::discover::{vendor_ref, vendor_ref_decorated}; - -use super::bun::bun_text_entries; -use super::npm::npm_lock_nodes; -use super::yarn::{berry_checksum_pin, berry_entries, classic_entries}; -use super::LockIntegrity; - -/// The integrity the REWIRED npm-family lockfile records for a vendored -/// artifact at `artifact_rel` (forward-slashed, no `./` prefix). This is -/// the integrity of OUR deterministically packed tarball — the trust -/// anchor for repair's no-ledger reconstruction: a rebuilt tarball that -/// matches it is exactly what the package manager would have installed. -/// -/// package-lock/shrinkwrap are parsed as JSON, pnpm through its format -/// model, yarn (classic and berry) and bun.lock through the entry models -/// lockfile discovery reads. vlt yields `None`: its `file` nodes pin no -/// integrity (slot [2] is `null`). -pub async fn wired_vendor_integrity( - project_root: &Path, - artifact_rel: &str, -) -> Option { - let rel = artifact_rel.trim_start_matches("./"); - - if rel.starts_with(".socket/vendor/pypi/") { - let mut pinned = None; - for path in crate::utils::python_lock::python_lock_paths(project_root).ok()? { - let Ok(text) = read_regular_to_string(&project_root.join(path)).await else { - continue; - }; - let Ok(document) = text.parse::() else { - continue; - }; - // The shared lock model: the package array, pylock `archive` - // paths, uv `source` locations and artifact tables. - let (collection, pep751) = lock_package_collection(&document); - let Some(packages) = document.get(collection).and_then(Item::as_array_of_tables) else { - continue; - }; - for package in packages.iter() { - let archive = package - .get("archive") - .and_then(Item::as_table_like) - .map(lock_artifact); - let location = match &archive { - Some(archive) => archive.path, - None if !pep751 => uv_source_location(package), - None => None, - }; - if location.is_none_or(|path| path.trim_start_matches("./") != rel) { - continue; - } - let leaf = rel.rsplit('/').next(); - let sha = match archive { - Some(archive) => archive.sha256, - None => package_artifacts(package, &["wheels", "wheel", "sdist"]) - .into_iter() - .find(|wheel| wheel.filename.is_some() && wheel.filename == leaf) - .and_then(|wheel| wheel.sha256), - }; - let sha = sha?; - if pinned.as_ref().is_some_and(|previous| previous != &sha) { - return None; - } - pinned = Some(sha); - } - } - return pinned.map(LockIntegrity::Sha256Hex); - } - - // Read active binary resolution records, never the append-only string - // pool: it can retain paths and digests from earlier patch generations. - if !super::bun::bun_text_lock_drives(&super::ProjectView::Disk(project_root)) { - if let Ok(bytes) = read_regular_to_bytes(&project_root.join(BUN_LOCKB)).await { - if let Ok(packages) = BunLockb::parse_packages(&bytes) { - let mut pinned: Option = None; - for package in packages { - if package - .resolution - .trim_start_matches("file:") - .trim_start_matches("./") - != rel - { - continue; - } - let sri = package.integrity.filter(|sri| is_sri_pin(sri))?; - if pinned.as_ref().is_some_and(|previous| previous != &sri) { - return None; - } - pinned = Some(sri); - } - if let Some(sri) = pinned { - return Some(LockIntegrity::Sri(sri)); - } - } - } - } - - // JSON locks: resolved == "file:" (npm writes exactly this form), - // read through the inventory's own entry walk (v1 `dependencies` - // included, which the legacy vendored backend rewires). - for lock in NPM_LOCKS { - let Ok(bytes) = read_regular_to_bytes(&project_root.join(lock)).await else { - continue; - }; - let Ok(v) = serde_json::from_slice::(&bytes) else { - continue; - }; - for node in npm_lock_nodes(&v) { - if node - .resolved - .is_some_and(|r| r.trim_start_matches("file:") == rel) - { - if let Some(sri) = node.integrity.filter(|s| is_sri_pin(s)) { - return Some(LockIntegrity::Sri(sri.to_string())); - } - } - } - } - - // pnpm: the format model's vendored entry (every key generation). - if let Ok(text) = read_regular_to_string(&project_root.join(PNPM_LOCK)).await { - if let Some(sri) = PnpmLock::parse(&text).wired_integrity(rel) { - return Some(LockIntegrity::Sri(sri)); - } - } - - // yarn: the entry models lockfile discovery reads (live blocks only — - // yarn keeps the last block per pattern), classic `integrity` SRI or - // berry `checksum:` (yarn 4.0.x bare hex promoted under cacheKey 10c0). - if let Ok(text) = read_regular_to_string(&project_root.join("yarn.lock")).await { - let pins: Vec = if is_berry_lock(&text) { - let lock = berry_entries(&text); - lock.entries - .iter() - .filter(|e| e.live) - .filter(|e| { - e.locator() - .and_then(|l| vendor_ref_decorated(l.reference)) - .is_some_and(|v| v.artifact_rel == rel) - }) - .filter_map(|e| { - berry_field(&e.block.lines, "checksum") - .and_then(|c| berry_checksum_pin(c, lock.cache_key.as_deref())) - }) - .collect() - } else { - classic_entries(&text) - .iter() - .filter(|e| e.live) - .filter(|e| { - classic_field(&e.block.lines, "resolved") - .and_then(vendor_ref_decorated) - .is_some_and(|v| v.artifact_rel == rel) - }) - .filter_map(|e| classic_field(&e.block.lines, "integrity")) - .filter(|sri| is_sri_pin(sri)) - .map(|sri| LockIntegrity::Sri(sri.to_string())) - .collect() - }; - if let Some(pin) = unanimous(pins) { - return Some(pin); - } - } - - // bun.lock: our tarball tuple `[spec, {meta}, "sha512-…"]` (bun - // < 1.3.10 re-saves it digest-less, which pins nothing). - if let Ok(text) = read_regular_to_string(&project_root.join(BUN_LOCK)).await { - if let Ok(entries) = bun_text_entries(&text) { - let pins: Vec = entries - .iter() - .filter(|e| { - matches!(e.elems.len(), 2 | 3) - && e.elems[1].starts_with('{') - && e.elems - .first() - .and_then(|spec| decode_json_string(spec)) - .is_some_and(|spec| { - split_name_spec(&spec) - .and_then(|(_, target)| vendor_ref(target)) - .is_some_and(|v| v.artifact_rel == rel) - }) - }) - .filter_map(|e| e.elems.get(2).and_then(|sri| decode_json_string(sri))) - .filter(|sri| is_sri_pin(sri)) - .map(LockIntegrity::Sri) - .collect(); - if let Some(pin) = unanimous(pins) { - return Some(pin); - } - } - } - None -} - -/// The one pin every entry agrees on; `None` when there is none or the -/// entries disagree (no anchor beats a wrong one). -fn unanimous(pins: Vec) -> Option { - let mut pins = pins.into_iter(); - let first = pins.next()?; - pins.all(|p| p == first).then_some(first) -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::vendor::bun_lockb::BunLockb; - use crate::vex::discover::testing::{fixture_path, Project, UUID_A}; - - const SRI_A: &str = "sha512-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="; - const SRI_B: &str = "sha512-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBA=="; - - /// The `two-versions` bun.lockb with both `minimist` records pointed at - /// ONE vendored artifact path: agreeing pins are the anchor, disagreeing - /// ones (which record is the artifact?) are none. - #[tokio::test] - async fn bun_lockb_records_sharing_an_artifact_must_agree_on_its_pin() { - let fixture = std::fs::read(fixture_path("bun-lockb/two-versions/bun.lockb")) - .expect("two-versions fixture"); - let artifact = format!(".socket/vendor/npm/{UUID_A}/minimist-1.2.2.tgz"); - let minimist: Vec = BunLockb::parse_packages(&fixture) - .expect("fixture parses") - .iter() - .enumerate() - .filter(|(_, p)| p.name == "minimist") - .map(|(id, _)| id) - .collect(); - assert_eq!(minimist.len(), 2, "the fixture's two minimist records"); - for (second, want) in [ - (SRI_A, Some(LockIntegrity::Sri(SRI_A.to_string()))), - (SRI_B, None), - ] { - let mut lock = BunLockb::parse(&fixture).expect("fixture parses"); - lock.set_package(minimist[0], &artifact, SRI_A) - .expect("rewire the first record"); - lock.set_package(minimist[1], &artifact, second) - .expect("rewire the second record"); - let p = Project::new(); - p.write("bun.lockb", lock.bytes()); - assert_eq!(wired_vendor_integrity(p.root(), &artifact).await, want); - } - } -} diff --git a/crates/socket-patch-core/src/vex/discover/bun.rs b/crates/socket-patch-core/src/vex/discover/bun.rs index f2d01fb1d..cbbe14f09 100644 --- a/crates/socket-patch-core/src/vex/discover/bun.rs +++ b/crates/socket-patch-core/src/vex/discover/bun.rs @@ -9,8 +9,8 @@ //! unreadable; a dangling link does not, #735), else `bun.lockb`: the //! shared [`bun_text_lock_drives`] predicate. A //! stale binary lock left beside a text lock wires nothing, so it must not -//! become a ref (rule 10 — the same gate `vendor::bun_workspace` and -//! `lock_inventory::wired_vendor_integrity` apply). +//! become a ref (rule 10 — the same gate `vendor::bun_workspace` +//! applies). //! //! ## Shapes recognized //!