[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: discussion #560 register.
Kind: bug. Source: new finding, register E56 (related to review Part 5.4 on gem section models, E19).
Problem
Bundler loads one manifest/lock pair. When there is no BUNDLE_GEMFILE, that is gems.rb + gems.locked if gems.rb exists, and Gemfile + Gemfile.lock otherwise. socket-patch has a shared resolver for this, LoadedManifest::pair.`` Hosted mode uses it through keep_bundler_loaded_gem_files, which also works over a memory view. The vendored refusal (`gem_manifest_refusal`) and the crawler use it as well.
Two other readers each choose the lock their own way:
- Lock inventory reads only
Gemfile.lock: lock_inventory/gem.rs#L46-L53 (view.read_text("Gemfile.lock")). gem_remotes does the same.
- VEX discovery reads both locks whatever Bundler loads:
vex/discover/gem.rs#L133-L138 (for file in BUNDLER_LOCKS).
That makes three rules for one question.
Proof by execution (a unit probe at 045d7ec, run twice, not committed). The project has gems.rb (gem "rack", "2.2.8") and a valid gems.locked locking rack (2.2.8):
gems.locked only: inventory_project = []
same text via GemfileLock::parse: ["pkg:gem/rack@2.2.8"]
bundler_loaded_manifest().pair(): ("gems.rb", "gems.locked")
+ stale Gemfile.lock (rack 2.0.0): inventory_project = ["pkg:gem/rack@2.0.0"]
Consumers that see the wrong set
- The in-memory hosted engine builds its purl set from this inventory (
hosted/memory/mod.rs#L571-L578).`` So for a gems.rb project it finds no gems, even though its own gem rewriter would edit `gems.locked`. With a leftover `Gemfile.lock`, it plans versions Bundler doesn't use.
- Scan's lockfile supplement (
scan/discovery.rs#L71-L95) and apply's lockfile_resolved (apply.rs#L2304-L2306) miss lockfile-only gems, or count stale ones.
- VEX ledger liveness (
vex/discover/mod.rs#L1611-L1613) judges a hosted gem pin against the wrong lock.
Symptoms
None filed. #341 and #390 fixed the same "wrong pair" class for the vendored and hosted writers but not for the readers.
Impact
Medium for gems.rb projects, which are Bundler's documented alternate spelling. For a stale-twin project it is incorrect data rather than missing data.
Proposed change
- Move the pair selection that
keep_bundler_loaded_gem_files does into formats::gem::manifest as loaded_lock(view: &ProjectView) -> Option<&'static str> (disk: bundler_loaded_manifest; memory: .bundle/config only, as today).
- Make
inventory_gemfile_lock_raw_in, gem_remotes and VEX discovery's extract read only that lock. VEX may still diagnose the ignored twin.
- Delete the hard-coded
"Gemfile.lock" reads in lock_inventory/gem.rs and the BUNDLER_LOCKS loop's both-locks rule.
Size and scope
4 files and under 120 changed production lines. Out of scope: the three gem section models (E19) and BUNDLE_GEMFILE pointing outside the root, which stays unsupported.
Acceptance criteria
Dependencies
None. It touches files near open #712, #684 and #621 (gem settings), but not the same functions.
[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: discussion #560 register.
Kind: bug. Source: new finding, register
E56(related to review Part 5.4 on gem section models,E19).Problem
Bundler loads one manifest/lock pair. When there is no
BUNDLE_GEMFILE, that isgems.rb+gems.lockedifgems.rbexists, andGemfile+Gemfile.lockotherwise. socket-patch has a shared resolver for this,LoadedManifest::pair.`` Hosted mode uses it throughkeep_bundler_loaded_gem_files, which also works over a memory view. The vendored refusal (`gem_manifest_refusal`) and the crawler use it as well.Two other readers each choose the lock their own way:
Gemfile.lock:lock_inventory/gem.rs#L46-L53(view.read_text("Gemfile.lock")).gem_remotesdoes the same.vex/discover/gem.rs#L133-L138(for file in BUNDLER_LOCKS).That makes three rules for one question.
Proof by execution (a unit probe at
045d7ec, run twice, not committed). The project hasgems.rb(gem "rack", "2.2.8") and a validgems.lockedlockingrack (2.2.8):Consumers that see the wrong set
hosted/memory/mod.rs#L571-L578).`` So for agems.rbproject it finds no gems, even though its own gem rewriter would edit `gems.locked`. With a leftover `Gemfile.lock`, it plans versions Bundler doesn't use.scan/discovery.rs#L71-L95) and apply'slockfile_resolved(apply.rs#L2304-L2306) miss lockfile-only gems, or count stale ones.vex/discover/mod.rs#L1611-L1613) judges a hosted gem pin against the wrong lock.Symptoms
None filed. #341 and #390 fixed the same "wrong pair" class for the vendored and hosted writers but not for the readers.
Impact
Medium for
gems.rbprojects, which are Bundler's documented alternate spelling. For a stale-twin project it is incorrect data rather than missing data.Proposed change
keep_bundler_loaded_gem_filesdoes intoformats::gem::manifestasloaded_lock(view: &ProjectView) -> Option<&'static str>(disk:bundler_loaded_manifest; memory:.bundle/configonly, as today).inventory_gemfile_lock_raw_in,gem_remotesand VEX discovery'sextractread only that lock. VEX may still diagnose the ignored twin."Gemfile.lock"reads inlock_inventory/gem.rsand theBUNDLER_LOCKSloop's both-locks rule.Size and scope
4 files and under 120 changed production lines. Out of scope: the three gem section models (E19) and
BUNDLE_GEMFILEpointing outside the root, which stays unsupported.Acceptance criteria
inventory_projecton agems.rb+gems.lockedproject returns its gems.Gemfile.lockbesidegems.rb+gems.locked, inventory and VEX discovery read onlygems.locked..bundle/configBUNDLE_GEMFILE: Gemfilebeside agems.rbreadsGemfile.lock(disk and memory views).gems.rbproject yields a gem candidate.lock_inventory,vex::discover::gem,formats::gem::manifestand hosted gem tests stay green.Dependencies
None. It touches files near open #712, #684 and #621 (gem settings), but not the same functions.