Repository navigation
Carry scan's lockfile-only and vendored-ledger candidates without a fabricated node_modules path #1113
Description
[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: discussion #560 register.
Kind: refactor. Source: Part 6.2 ("fabricated CrawledPackages"); register E36, child 1 of #1112.
Problem
scan turns lock-inventory entries and vendor-ledger entries into fake installed packages:
scan/discovery.rs#L111-L133crawled_from_purlsetspath: cwd.join("node_modules").join(name_part)for every ecosystem. A lockfile-onlypkg:cargo/serde@1.0.0orpkg:pypi/six@1.16.0gets<cwd>/node_modules/serdeor<cwd>/node_modules/six.- It is called by
lockfile_supplement(#L88) andvendored_ledger_supplement(#L215).``
Because the paths are fake, the caller keeps parallel sets that say which entries to distrust:
supplement_purls(scan/mod.rs#L1807-L1835),`` which exists only so the PATH-scope filter (#L1926-L1962) can skip them;lockfile_only.purls, consulted throughlockfile_only_containsatscan/mod.rs801, 2821 and 3121 and atdiscovery.rs299.
Every new consumer of all_crawled that reads .path (for example gradle_cache::installed_copies(&pkg.path, …) in preverify_vendor_baselines, or is_gradle_version_dir(&p.path) at scan/mod.rs 1206) has to remember that some paths are placeholders. Today these happen to degrade safely, because Maven and Gradle never reach the inventory.
Proposed change
- Add a scan-local candidate type, for example:
Alternatively, keep
enum Candidate { Installed(CrawledPackage), LockOnly { purl, eco }, Vendored { purl, eco } }
CrawledPackagefor crawler output only and carry the supplement aspurl-only records beside it. - The PATH-scope filter matches
Installedonly. "Not installed" ismatches!(c, Candidate::LockOnly { .. }). - Delete:
crawled_from_purl,supplement_purlsand theLockfileSupplement::packages/LedgerSupplement::packagesvectors of fabricated packages. - Keep
lockfile_only.purlsonly where API-spelled purls are matched (lockfile_only_containsbridges the percent-encoding and composer padding). Where the candidate itself is at hand, derive the answer from the candidate. - No behavior change: same JSON (
lockfileOnlyPackages,notInstalled, the[NOT INSTALLED]marker,path_scope_excluded_supplements), same exit codes.
Size and scope
crates/socket-patch-cli/src/commands/scan/{mod.rs,discovery.rs}, plus any scan helper typed on&[CrawledPackage]that receives supplements. Estimate about 150–300 changed production lines.- Out of scope: the core inventory model (later children of the tracking issue),
apply.rs's ownlockfile_resolvedset, and crawler changes.
Acceptance criteria
-
crawled_from_purlandsupplement_purlsare deleted, and noCrawledPackageis constructed incommands/scan/outside tests. - The existing
scan/discovery.rsunit tests (ledger_supplement_*,corrupt_ledger_*) are ported and green. - The CLI scan e2e suites stay green, including
scan_paths_e2e(path scope and thepath_scope_excluded_supplementswarning), the lockfile-only/notInstalledtests, and the vendored-ledger fresh-clone tests. - A regression test: a path-scoped scan over a project with a lockfile-only cargo or pypi package excludes it with the counted warning, and never treats
<cwd>/node_modules/<name>as its location, even when such a directory exists.
Dependencies
- Decide vendored-entry liveness through one discovery verdict #1050 edits
vendored_ledger_supplement(liveness verdict). Rebase after it lands. - Fix 15 open pnpm issues across hosted, vendored and agent modes #1007, Fix open npm issues #1008, Route JVM layout through one module and fix three JVM scope bugs #1032 and Decide whether a hosted patch is pinned through lockfile discovery alone #1058 touch
scan/mod.rselsewhere; expect small rebases. - Blocks the later checklist items of Tracking: derive scan candidates, lock entries and hosted refs from one project inventory instead of four discovery systems #1112, which replace the candidate's source with core
Instances.
Backlog review — 2026-10-08
Consolidated into #1112. The retained tracker(s) preserve this issue’s implementation scope and acceptance criteria. Closing this separate scheduling item as not planned, not as completed.
Explicit candidate-type child of the unified inventory tracker; one parent issue is enough to schedule it.
Activity
audit-ecosystems: E36 tracking #1112/#1113, E91 #1114; E71/E72/E75 pa…