Skip to content

Vendored-reference scan never sees NuGet or Maven wiring, so the orphan sweep deletes a still-wired unit #832

Description

[agent] Filed by the scheduled architecture audit routine (ecosystems and formats). Register: discussion #560 register.

Kind: bug. Source: new finding, register E61 (related to the backend-trait tracking row E21).

Problem

scan_vendor_references is the one check that keeps a .socket/vendor/<eco>/<uuid>/ directory with no ledger entry from being deleted while a project file still points at it. It is used by the orphan sweeps (vendor --revert, the vendored gc pass), by repair (vendor_ledger_missing), by vendor (vendor_ledger_entry_missing) and by rollback. It recognizes NuGet and Maven wiring in neither of the two ways it would need to:

  1. The file list. It reads registry::paths_with(VENDORED) (repair.rs#L100-L104).`` The three nuget.config spellings and `pom.xml` are `HOSTED | PROBE`, without `VENDORED` (`registry.rs#L123-L125`, `#L142`). Yet those are exactly the files the NuGet and Maven vendored backends rewire.

  2. The reference grammar. Even if the files were read, both backends point at the uuid directory, not at a leaf inside it:

    parse_vendor_path requires a non-empty leaf after the uuid (path.rs#L102-L108), and the scanner's terminator set has no < (repair.rs#L73-L77),`` so …/maven/<uuid></url> doesn't parse either.

Meanwhile sweep_vendor_dirs does enumerate nuget/ and maven/ (ECOSYSTEM_DIRS), and sweep_orphan_vendor_dirs deletes every unrecorded unit the scan didn't report (vendor.rs#L294-L333). Its doc comment states the invariant this breaks: "Deleting such a dir would break the next install, so every candidate is checked against the wiring-bearing files first".

Also dead: the vendor stranded-reference gate matches eco == "maven2" (vendor.rs#L2134-L2139), but parse_vendor_path only ever yields maven.

Proof by execution (a throwaway #[tokio::test] in commands/vendor.rs, run twice on 045d7ec, then removed). It uses an empty VendorState, one artifact file in the uuid dir, and the backend's own wiring text:

PROBE nuget: refs=[] still_wired=0 removed=1 artifact_exists=false
PROBE maven: refs=[] still_wired=0 removed=1 artifact_exists=false
PROBE npm: refs=[("npm", "1a2b…", ".socket/vendor/npm/1a2b…/left-pad-1.3.0.tgz")] still_wired=1 removed=0 artifact_exists=true

The npm control is kept as still wired; the NuGet and Maven units are deleted while nuget.config / pom.xml still name them.

Symptoms

None filed. When a NuGet or Maven ledger entry is missing (state.json lost, a partial commit, or a merge that drops a row: the case the sweep guards against for every other ecosystem):

  • vendor --revert and the vendored gc delete the feed or repository, and the next dotnet restore / mvn fails with a missing source;
  • repair reports nothing (no vendor_ledger_missing);
  • vendor re-vendors without the vendor_ledger_entry_missing refusal.

Impact: destructive, but it needs a missing ledger entry first. Small fix.

Proposed change

  • Give the NuGet config spellings and pom.xml the VENDORED role (check every reader of paths_with(VENDORED) / has(VENDORED) first). The Maven reactor's module poms live below the root, so add them the way wiring_files already adds the dynamic sets (vlt importers, requirements includes), or from the ledger's recorded wiring files.
  • Recognize a uuid-directory reference: a parse_vendor_dir_ref (or an optional leaf in parse_vendor_path) that yields (eco, uuid) for .socket/vendor/<eco>/<uuid> terminated by ", < or end of value, and add < to the scanner's terminators. Repair can fall back to the uuid dir as the path for these.
  • Delete the dead eco == "maven2" arm.
  • Longer term, E21 (the VendorBackend trait) should own "which files carry my references and how they are spelled", so that this table can't drift from the writers again.

Size and scope

formats/registry.rs, vendor/path.rs, commands/vendored_backend/repair.rs, commands/vendor.rs; under ~80 production lines. The Gradle tree (.socket/vendor/gradle/) is outside ECOSYSTEM_DIRS and out of scope. The registry role change must not widen hosted reads (HOSTED is unchanged).

Acceptance criteria

  • scan_vendor_references reports (nuget, uuid) for a vendored nuget.config (all three spellings) and (maven, uuid) for a vendored root pom.xml and a reactor module pom.
  • sweep_orphan_vendor_dirs with an empty ledger keeps such units in still_wired (regression test mirroring orphan_sweep_keeps_include_referenced_dir), and still removes them once the reference is gone.
  • repair reports vendor_ledger_missing for a NuGet/Maven reference with no ledger entry.
  • scan_ignores_non_vendor_socket_mentions and the existing repair/orphan tests stay green, and the vendored NuGet/Maven e2e suites pass.

Dependencies

None. It touches nuget_feed.rs and maven_repo.rs only for tests. Coordinate with #597 (hosted NuGet) only if it changes registry.rs.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    agent:triagedarch-auditFiled by a scheduled architecture audit routine (see the architecture review discussion)bugSomething isn't workingpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions