[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: discussion #560 register.
Kind: bug. Source: new finding; register C57. A #[ignore = "RED: …"] test added in #708 already pins this bug, but no issue tracks it and no CI job runs it.
Problem (main @ 9c43dfc)
remove resolves its identifier separately in each store:
The ledger is never matched by the manifest purls that remove is actually deleting. A uuid identifier is exactly the case where the two diverge: the manifest records the newer patch uuid, and the ledger still records the uuid that was vendored. remove <new uuid> therefore matches the manifest entry, matches no ledger entry, skips the vendored revert, and reports success. The nested rollback skips vendor-owned purls by design, so nothing compensates.
Proof by execution: remove_by_uuid_reverts_vendoring_when_ledger_generation_is_older,`` run with cargo test -p socket-patch-cli --test remove … -- --ignored, failed both times:
remove must revert the vendoring of the entry it deleted; envelope={"command":"remove","status":"success",…
"events":[{"action":"removed","purl":"pkg:npm/__remove_vendored__@1.0.0"}],"summary":{…"removed":1…}}
.socket/vendor/state.json and the vendored artifact both survive, and there is no vendor_reverted event. The control test remove_by_purl_reverts_vendoring, which uses the same fixture by purl, passes.
Symptoms
None filed. #745 (wrong ledger root under --manifest-path) is a different selection bug in the same function.
Impact
After remove <uuid>, the lockfile still resolves to the committed .socket/vendor/ artifact, but the manifest no longer records any patch for it. The dependency stays patched with no record and no command reports it. Exit 0 and status: success hide this. It happens whenever the manifest's generation has moved past the ledger's, for example after get/scan records a superseding patch while vendoring is offline or fails.
Proposed change
- In
remove, compute the vendored (and hosted) leg's targets from the purls of the manifest entries being deleted, plus the raw identifier for the ledger-only and hosted-only paths. Don't re-match the identifier in each store.
- The natural home is
Ledgers::matching in core: one entry point returns the matched manifest purls and every ledger or hosted record that covers them (VendorEntry::covers_purl), so remove and rollback share it.
- Delete the separate
vendor_entries_matching(&state, &args.identifier) lookup on the manifest path.
Size and scope
About 30–60 production lines in remove.rs and ledgers.rs, plus tests. Out of scope:
rollback <uuid> resolves through the same per-store Ledgers::matching. The fix should add a rollback twin of the test, and fix rollback in the same PR if that test fails.
Acceptance criteria
Dependencies
None. This touches the same function as #745, so whichever lands second rebases.
[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: discussion #560 register.
Kind: bug. Source: new finding; register C57. A
#[ignore = "RED: …"]test added in #708 already pins this bug, but no issue tracks it and no CI job runs it.Problem (main @
9c43dfc)removeresolves its identifier separately in each store:patch_matches(purl, &patch.uuid, identifier);vendor_entries_matching(&vendor_state, &args.identifier), which wrapsLedgers::matching.The ledger is never matched by the manifest purls that
removeis actually deleting. A uuid identifier is exactly the case where the two diverge: the manifest records the newer patch uuid, and the ledger still records the uuid that was vendored.remove <new uuid>therefore matches the manifest entry, matches no ledger entry, skips the vendored revert, and reports success. The nested rollback skips vendor-owned purls by design, so nothing compensates.Proof by execution:
remove_by_uuid_reverts_vendoring_when_ledger_generation_is_older,`` run withcargo test -p socket-patch-cli --test remove … -- --ignored, failed both times:.socket/vendor/state.jsonand the vendored artifact both survive, and there is novendor_revertedevent. The control testremove_by_purl_reverts_vendoring, which uses the same fixture by purl, passes.Symptoms
None filed. #745 (wrong ledger root under
--manifest-path) is a different selection bug in the same function.Impact
After
remove <uuid>, the lockfile still resolves to the committed.socket/vendor/artifact, but the manifest no longer records any patch for it. The dependency stays patched with no record and no command reports it. Exit 0 andstatus: successhide this. It happens whenever the manifest's generation has moved past the ledger's, for example afterget/scanrecords a superseding patch while vendoring is offline or fails.Proposed change
remove, compute the vendored (and hosted) leg's targets from the purls of the manifest entries being deleted, plus the raw identifier for the ledger-only and hosted-only paths. Don't re-match the identifier in each store.Ledgers::matchingin core: one entry point returns the matched manifest purls and every ledger or hosted record that covers them (VendorEntry::covers_purl), soremoveandrollbackshare it.vendor_entries_matching(&state, &args.identifier)lookup on the manifest path.Size and scope
About 30–60 production lines in
remove.rsandledgers.rs, plus tests. Out of scope:--manifest-pathroot selection (With --manifest-path into another project, rollback, remove, repair, vex, scan and get read the vendored ledger from --cwd #745);rollback <uuid>resolves through the same per-storeLedgers::matching. The fix should add a rollback twin of the test, and fix rollback in the same PR if that test fails.Acceptance criteria
remove_by_uuid_reverts_vendoring_when_ledger_generation_is_olderis no longer#[ignore]d, and it passes.remove_by_purl_reverts_vendoringand the otherremove_invariants/removesuites stay green.rollback <new uuid>with an older ledger generation) is added and passes.Dependencies
None. This touches the same function as #745, so whichever lands second rebases.