Repository navigation
Commit cf8150b
feat(vex): manifest-less VEX from hosted/vendored lockfiles + npm 12 allow-remote auto-config (v5) (#251)
* fix(core): hosted/vendored rewriter fixes found by the real-PM matrices
First of seven commits that land the manifest-less VEX branch
(feat/vex-lockfile-inventory) on top of #247. The branch's ~165-commit
history, built on the pre-#247 main 9489b18 with per-PM merge commits, was
squashed onto 09956d9 and re-split by concern; the full pre-rebase history
is preserved on branch backup/vex-lockfile-pre-rebase.
These are the product bugs the per-PM real-toolchain matrices turned up
while the manifest-less VEX suites were written. Each is independent of
VEX and pinned by a core regression test:
- composer (hosted): the rewriter drops the entry's `source` block when it
immediately precedes `dist` (one `redirect_composer_dist` fragment edit
spanning both, reverted byte-for-byte). Composer 1 and 2.2 LTS silently
installed the pristine upstream commit from git whenever the hosted
download failed; a hand-ordered source that cannot be dropped warns
`redirect_composer_source_kept`. Golden fixture: `source-and-dist`.
- gem (hosted): the patch-registry `GEM` section is inserted in bundler's
source order (sorted by remote), so a frozen `bundle install` on bundler
>= 4.0.19 accepts the converged lock. The `basic` golden and the exact
lock expectations move the Socket section first.
- cargo (hosted + vendored): a v1 `Cargo.lock` (checksums in `[metadata]`,
dependents naming the crate by its full package id) is redirected and
vendored correctly: the `[metadata]` line and every dependent's full-id
reference follow the source, each fragment its own ledger edit, and
`cargo --locked` accepts the result; the vendored detach/restore of a v1
entry is byte-identical. `plan_cargo_lock` keeps #247's multi-source
twin disambiguation (`Ambiguous`) and hoisted regexes; the block end now
also stops at a trailing `[metadata]` / `[[patch.unused]]`, and the
checksum is inserted after a block-final `source` line too.
- yarn berry (hosted + vendored): written checksums follow the lock's own
spelling — yarn 4.0.0–4.0.2 spell `10c0` checksums as bare hex, so the
prefixed form failed `yarn install --immutable` with YN0028.
- npm (vendored): npm 12 reifies from the `package-lock.json` it creates
beside a committed shrinkwrap, so `vendor` now rewires every present npm
lock (siblings first, primary last; an unrewirable sibling warns
`vendor_npm_sibling_lock_unwired`), and the in-use/revert probes read
every npm lock before deleting an artifact. `select_lockfile` reads
through #247's guarded `read_regular_to_bytes`.
- npm (hosted): a lockfileVersion 1 redirect warns
`redirect_npm_legacy_client` — npm 6 ignores a v1 lock's `resolved` and
fails EINTEGRITY against the patched pin.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* feat(hosted): auto-configure npm 12 allow-remote in the project .npmrc
npm >= 12 defaults to `allow-remote=none` and refuses (EALLOWREMOTE) every
lockfile entry whose tarball is not served by the configured registry —
exactly what a hosted redirect writes. When `scan --mode hosted` / `get
--mode hosted` leaves a root package-lock.json / npm-shrinkwrap.json
carrying a granted hosted artifact URL, the run now ensures
`allow-remote=all` in the project `.npmrc` (creating the file, or
appending one line with the BOM, CRLF and every other byte preserved) and
records it in the redirect ledger as `redirect_npmrc_allow_remote`
(`created` / `added`).
- core `patch::redirect::npmrc`: npm's `.npmrc` grammar as measured
against npm 12.1.0 (exact `allow-remote` key, last top-level assignment
wins, `[section]` bodies are not top-level, bare-CR line splits, case-
sensitive value), the plan (create / append / already-all / respected
user / env / outer-layer value / unsupported), and the unwinds.
- Every reversal removes exactly what was added once no package-lock
entry needs it: the whole-ledger replay (a new `NpmrcAllowRemote`
inverse, grouped with the npm lock kinds), the per-purl npm revert
behind scoped rollback / remove / the vendored takeover ("last one
out", same transaction, flushed after the lock through #247's shared
`staged::flush_staged`), and the vendored-supersedes-hosted reconcile.
A modified created file keeps the user's lines
(`redirect_npmrc_allow_remote_modified`, surfaced by rollback, remove,
vendor and the reconcile). A symlinked `.npmrc` refuses an unwind at
plan time, before anything is written.
- Hosted run: the `.npmrc` edit rides `rewrite.files` / `rewrite.edits`,
so it is written under #247's apply-lock window, after its whole-run
SYMLINK GUARD, and only after the ledger persisted — never on
`--dry-run` (which previews the write, also for a vendored → hosted
takeover; the root locks are now read for such a preview so the pnpm
`trustLockfile` preview sees the lock the wet run splices). An explicit
user value (project `.npmrc`, user/global/builtin config, or an
`npm_config_allow_remote` env var) is respected and named; a symlinked,
unreadable or bare-CR `.npmrc` is left alone; `--no-npm-allow-remote-
config` / `SOCKET_NO_NPM_ALLOW_REMOTE_CONFIG` opts out. Every variant
warns `redirect_npm_allow_remote` with the whole-tree tradeoff.
- `atomic_write_bytes_preserving_mode` creates its stage with the
destination's permission bits (kept inside #247's `commit_stage`
structure), so a 0600 token-bearing `.npmrc` is never staged world-
readable.
- remove: the hosted leg's advisories are printed inside #247's
`unwind_hosted` (so a run that then fails still reports them) and carried
into the success envelope's `warnings[]`.
Tests: npmrc/replay/takeover/scan unit tests, the flag's parse coverage,
`redirect_npm_allow_remote` (plus #247's invariants: the lock never
outlives the run, dry runs create no `.socket/`, a full rollback leaves no
`.socket/` and never the user's `.npmrc`), and the dry-run takeover
previews in `coverage_fix_scan_hosted_dryrun_vendored`.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* refactor(core/vendor): split lock_inventory into per-format submodules
A verbatim move with no behavior change, so the next commit can give each
lock format its shared entry model beside its registry view:
`vendor/lock_inventory.rs` becomes a directory module with one file per
format (`npm`, `npm_family`, `pnpm`, `yarn`, `bun`, `cargo`, `golang`,
`composer`, `gem`, `pypi`), ledger recovery (`recover`) and the rewired-lock
trust anchor (`wired`). `mod.rs` keeps the public API (`LockIntegrity`,
`LockfileEntry`, `UnsupportedNpmLayout`, `lookup`,
`inventory_project(_diagnosed)`, `recover_lock_entry`,
`wired_vendor_integrity`); the three test modules move to `tests.rs`,
`recover_tests.rs` and `python_lock_union_tests.rs`.
Only imports, visibility (helpers another file calls become `pub(super)`),
sibling-module paths (`super::state` -> `crate::vendor::state`), module
docs and the single-file section banners changed; the test modules lost
one indentation level and were re-wrapped by rustfmt. `git show
--color-moved` shows everything else as moved.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* feat(core/vex): discover hosted and vendored patch references from lockfiles
New read-only module `vex::discover`: `discover_patched_refs(_with)`
reads every supported ROOT lockfile / package-manager config and returns
the Socket patch wiring it finds — `Discovery { refs, diagnostics,
recognized, unlocked_pins, elsewhere }`, one `PatchedRef { purl, uuid, mode
(Hosted | Vendored), source_file, artifact_rel, locked_integrity,
integrity_required, url }` per live reference. It never touches the
network, never writes, and never fails the run: a malformed file is a
diagnostic (`lockfile_unreadable`, `lockfile_unparseable`,
`patched_ref_invalid`, `patched_ref_unattributable`).
One extractor per package-manager family: npm (package-lock /
shrinkwrap, pnpm every lock generation + Rush locks), yarn classic and
berry, bun (`bun.lock` / `bun.lockb`), cargo, golang (go.mod / go.work +
sums), pypi locks (uv, PEP 723 script locks, pylock, poetry, pdm), pypi
other (Pipfile.lock, requirements + `-r`, Hatch / PEP 621 direct refs),
gem, composer, maven, nuget; deno is explicitly empty. Every file present
is read — no precedence chain — because the hosted rewriter edits every
candidate it finds.
Every value is committed, tamperable data and is validated fail-closed:
- hosted: `hosted_patch_uuid` accepts only `https://patch.socket.dev` or
a configured `--patch-server-url` origin, no userinfo, and takes the
LAST canonical-uuid path segment (grant tokens may be uuid-shaped);
percent-encoding, `\/` escapes and fragments are handled;
- vendored: root-anchored `.socket/vendor/<eco>/<uuid>/…` paths whose
leaf names the entry's own artifact (`vendor_ref` takes the path
literally; only yarn / URL-form pip strip their `#…` / `::…` decorations);
- pins, not definitions: a registry / index / source definition alone
(cargo `[registries]`, nuget `<add>`, pom `<repository>`, uv index
tables, `.npmrc`) never makes a reference;
- contested locks: a lock that resolves the same name@version from a
non-Socket source drops the ref (`patched_ref_unattributable`);
- lockless cargo pins / exclusive nuget mappings are recorded as
`UnlockedPin`s that can only keep a ledger record live, never create a
ref; `recognized` lists every uuid a read file mentions, so a rejected
mention keeps nothing alive downstream.
Supporting core changes: `patch::redirect::{SOCKET_PATCH_SERVER_HOST,
hosted_patch_uuid, hosted_patch_url_uuids}` (the pipenv owner check uses
the shared host constant); the pnpm lock grammar and `hosted_url_version`
exported crate-wide so readers parse exactly what the writers write;
`utils::digest` (the SRI pin rule and the hex digest shapes — one copy for
the inventory, discovery, ledger recovery and the rewriters, each call
site keeping its case policy); and `utils::purl`'s validating purl
builders, which discovery and the inventory's registry views share. A few
writer helpers become `pub(crate)` so the extractors' tests derive their
fixtures from the writers themselves.
One lockfile traversal layer: discovery and `vendor::lock_inventory` (the
scan / get / vendor / repair inventory) read each format through ONE
reader that yields every entry, Socket-owned ones included — the
inventory's registry views drop those, the extractors classify them:
- `lock_inventory` becomes a directory module, one file per format, each
laid out as a pure entry model, a stat-only file-selection section and
the registry view (an architecture test enforces the layering). Entry
models: `npm_lock_nodes`; `pnpm_packages` over the hosted rewriter's
pnpm grammar (every key generation, CRLF included); the yarn
`classic_entries` / `berry_entries` models with one berry locator,
cache-key and checksum rule; `BunLockb::parse_packages`; and
`composer_lock_packages`, whose array index the composer writer's lock
walks use too.
- Every other format reads through the reader its writer owns:
`cargo_lock::locked_packages` and `cargo_config`'s `[patch]` /
`[registries]` walks; `go_mod_edit` / `go_sum_edit` read helpers; a new
`vendor::gemfile_lock` model; the `utils::python_lock` / `poetry_lock` /
`hatch` readers (uv source fields, script-lock pairing, the pyproject /
Hatch declaration walk); a new `utils::requirements` lexer lifted out of
the vendored requirements planner; and two new XML readers,
`vendor::maven_pom` and `vendor::nuget_config`, with
`nuget_feed::nuget_lock_entries` shared by discovery and the feed
writer.
- `DiscoverCtx::locate` classifies a lock location once (vendored path,
hosted uuid, decorated leaf) for every extractor. The npm-family
extractors iterate the entry models only, never the grammar primitives,
and every extractor reads content only through the recognizing ctx
(rule 11) — both enforced by architecture tests.
Ledger liveness is one rule too: `Discovery::{wires_package,
vendor_entry_live, redirect_record_live}`, held per call site by
`LedgerLiveness` (the sorted redirect-ledger files, the lock inventory
loaded lazily at most once), which the CLI's vex and scan both use. Cargo
crates.io provenance is explicit (`LockfileEntry::source_kind`), not
inferred from the checksum variant.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* feat(vex): manifest-less VEX — attest hosted and vendored patches from lockfiles
`socket-patch vex` and the embedded `apply` / `scan` / `vendor --vex` now
attest hosted and vendored patches with no `.socket/manifest.json` — and
with no `.socket/vendor` ledgers either — by reading the wiring out of the
project's lockfiles (`vex::discover`). This covers a depscan-opened PR, a
clone that never committed its ledgers, and a lock-only CI checkout.
Record view (`commands::vex_sources::plan`): four sources — the manifest,
the redirect ledger's records, the vendor ledger's embedded records and
lockfile discovery — merge into one view. A candidate's record must carry
the uuid the lockfile actually WIRES; it comes from the first source that
has one, else (online only) from the patch API by uuid, 10 fetches at a
time with `get`'s one-shot 401/403 → public-proxy fallback (#247's
uuid-only `ApiClient::fetch_patch`). Nothing is written: vex never takes
the apply lock, never creates `.socket/`, never writes the manifest, and
the `socket-patch.vendor.json` marker is never a record.
Gates, applied before hashing and kept under `--no-verify` (which now
skips only the hashing):
- a vendor-ledger entry attests only while a lockfile still wires its
artifact (`vendor_unwired`); a redirect-ledger record only while a
lockfile wires its hosted patch (`redirect_unwired`); discovery is
authoritative for every uuid a read file mentions, so a rejected
mention keeps nothing alive;
- `record_unavailable` (offline, 404, refused, transport error — the run
continues), `record_mismatch`, `wiring_conflict` (lockfiles wire one
package to several patches);
- a malformed / unreadable `.socket/vendor/state.json` is the hard error
`vendor_ledger_corrupt` (exit 2), mirroring `redirect_ledger_corrupt` —
this supersedes #247's degrade-and-disclose posture for `vex` only;
`setup --check` keeps #247's `vendor_context_from` /
`warn_unreadable_vendor_state` path.
Evidence: vendored refs hash the committed artifact (the ledger entry when
it names the wired artifact, else one synthesized from the ref); hosted
refs hash the installed copies the build CONSUMES
(`vex_consumed::hosted_consumed_copies` → core `VendorContext::hosted` /
`HostedCopies`: the Go replacement module, the Socket-registry cargo src
dir, maven's suffixed version — never a pristine sibling), and with
nothing installed a discovered pinned reference attests from its lockfile
pin, like in-run `scan --mode hosted --vex`. Discovered refs bypass the
Property 7 ecosystem filter.
Commands:
- `apply --vex` / `vendor --vex` with no manifest attest what the
lockfiles and ledgers wire (nothing anywhere keeps the calm exit 0 and
removes a stale document; `apply --check` and `--dry-run` never
generate); #247's no-manifest lines ("No patch manifest found; nothing
to apply.", "No manifest found, nothing to vendor.") are kept;
- failed VEX runs carry the discovery diagnostics into `warnings[]`
(standalone envelope, embedded envelopes, scan JSON — hosted included);
- `manifest_not_found` now means no manifest AND nothing wired;
- human output: `Note:` lines for superseded records / fetch failures,
phrased omission reasons.
Writer hardening: the manifest-driven standalone `vendor` now embeds the
patch `record` in its ledger entries too (vendored mode already does, as
`detached` entries). `detached` stays the "no manifest owner" flag, so
the manifest reconcile, legacy-manifest migration and get/scan
idempotency from #247 are unaffected. Every reader of embedded records
shares one ownership rule (`commands::vendor_record_is_unowned`): a
detached entry's record always stands alone, a standalone `vendor`
entry's fallback copy only when no manifest entry covers it (by ledger
key or base purl). `vex`, `list` and `setup --check`
(`fold_vendor_records`, formerly `fold_detached_records`) all apply it,
so one tree never lists "no patches" while its VEX document attests one.
`repair` stays narrower: it keeps preferring a manifest that moved on to
a newer uuid and falls back to the embedded copy only with no manifest
at all.
One liveness rule for vex and scan: `scan`'s cross-mode takeover
classification (`classify_overlap_takeover`), its
`hosted_wiring_retained` warning and `redirectState.wiringLive` ask the
same core discovery (`commands::discover_wiring`) and liveness rule
(`Discovery::redirect_record_live` / `vendor_entry_live` /
`wires_package`, through one `LedgerLiveness` holder per call site) that
gate attestation, replacing scan's private cargo / hosted / vendored
checks and its looser text scan. The CLI also shares one purl splitter
(`utils::purl::purl_parts`), one vendor-ledger lookup
(`vendor::state::lookup_entry_kv`) and one npm alias-aware identity crawl
(`ecosystem_dispatch::npm_paths_by_identity`) across vex, scan and
vendor, and pairs PEP 723 script locks through
`utils::python_lock::script_of_lock` like the rewriters do.
Output follows the conventions from #248: `ui::plural` counts, a
`ui::StatusLine` progress line for record fetches, and the shared
`format_vex_written` / `format_vex_dry_run_skip` lines on the
manifest-less `apply --vex` / `vendor --vex` paths. Manifest-less `vex`
honours `--dry-run` and `-O -` like the manifest path.
Product auto-detection adds go.mod, composer.json, pom.xml, a single
`*.csproj` and a single `*.gemspec`, after the existing probes.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test(cli): manifest-less VEX suites, real-PM capstones and shared helpers
Hermetic suites (wiremock patch API, run in the default `test` job on
every OS): one `e2e_vex_lockfile_<pm>` per package manager — npm, pnpm,
yarn (classic + berry), bun, cargo, golang, uv, poetry, pdm, hatch,
pipenv, pip, gem, composer, maven, nuget, deno (negative) — covering
spoofed hosts, record mismatch, pristine / tampered installs, contested
and orphaned wiring, `--offline`, reverted locks (also `--no-verify`) and
the embedded commands; plus the cross-cutting `e2e_vex_manifestless_
embedded`, `e2e_vex_redirect`, `e2e_vex_vendor` and the
`vex_e2e_common_selftest` harness checks.
Real-PM capstones (gated like the existing suites, `_REQUIRED` env
pattern): every hosted / vendored build suite now ends in the manifest-
less VEX matrix over a fresh checkout — manifest absent (ledgers kept),
ledgers deleted (lockfile + API), offline (`record_unavailable`, zero
requests), reverted lock (never attested, verify or not) — through shared
helpers: `vex_e2e_common` (+ bun / uv matrices), `npm_e2e_common`
(+ `manifestless`), `yarn_berry_common`, `common/yarn_classic_vex`,
`common/bundler_e2e`, `cargo_e2e_matrix`, `golang_e2e_matrix`,
`maven_build_common`, `composer_e2e_common`, `vex_pdm_hatch_common`,
`vex_pipenv_pip_*`, `vex_pypi_real_common`. New real-toolchain suites:
`e2e_redirect_{composer,maven,uv}_build`, `e2e_vendor_maven_build`,
`e2e_golang_workspace_build`, `e2e_nuget_dotnet_build`,
`e2e_poetry_vex_build`, `e2e_vex_{pdm,pip,pipenv,hatch}_build`,
`e2e_deno_vex_build`; the docker / setup-matrix / production legs gain
their manifest-less VEX steps.
Re-pinned to #247 while rebasing:
- vendored mode writes no manifest: the "manifest deleted" steps are
naturally manifest-free, so the npm manifest-less matrix and the uv /
poetry vendored suites add a `legacy-manifest` cell (the record a
pre-5.0 vendored run left beside its ledger, via
`vex_e2e_common::seed_legacy_manifest`, must attest the same way), the
yarn 2/3 refusal suite seeds that legacy record explicitly (and still
requires `not_applied`, never an attestation), and `--detached` twins
assert no manifest in either spelling;
- a fully reverted project keeps no `.socket/`: suites that plant a stale
ledger back after a rollback recreate the directory first, and the
hosted rollback suite checks that `vex` does not recreate it;
- the no-manifest human lines follow #247's wording;
- a corrupt vendor ledger on a manifest-free project is now
`vendor_ledger_corrupt` (exit 2, the ledger named, never rewritten),
replacing #247's disclose-then-`manifest_not_found` expectation;
- repair: two tests pin the standalone-`vendor` embedded record (a
moved-on manifest still wins; with no manifest the embedded copy stands
in offline), replacing the pre-rebase test that assumed a non-detached
`scan --vendor` entry.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* ci: run the manifest-less VEX real-PM matrices and backtest steps
ci.yml:
- `test` exports `SOCKET_PATCH_GO_E2E_REQUIRED` / `_VERSION` so the
real-go hosted/vendored suites fail instead of skipping on the Go that
is already installed for vexctl;
- `e2e` gains pinned-toolchain legs, each ending in the manifest-less VEX
matrix: composer 1 / 2.2 / 2 (hosted + vendored), bundler 1.17.3 →
4.0.21 (hosted + vendored + setup_matrix_gem), bun text/binary-lock
eras, the named corepack pnpm legs (3 OS), uv 0.1.45 → 0.12.x hosted +
vendored, poetry / pdm / hatch / pipenv / pip, maven 3.6.3 → 4.0.0-rc-6,
dotnet 6 → 10, deno; npm legs hard-require npm where
`Command::new("npm")` can resolve it;
- new jobs: `yarn-classic-matrix` (1.0.2 → 1.22.22), `yarn-berry-e2e`
(4.0.2 → 4.18.0 + macOS/Windows), `cargo-vex-matrix` (toolchains ×
Cargo.lock v1–v4); `e2e-docker` also runs the pypi vendored-PM suite.
Compatibility workflows: npm (npm 6–12 capstones, new), go (1.18.10 →
1.26.3, new), poetry (new), and the pnpm / pdm / pipenv / bun ones run
the manifest-less VEX steps and trigger on the vex sources. The bun
workflow keeps #247's two modes (hosted, vendored — the vendored-
detached leg collapsed into vendored).
Scripts: the bun / pdm / pipenv / poetry / uv backtests gain the
manifest-less VEX checks (a fresh checkout of the committed state must be
attested, also with the ledgers deleted; `--offline` with no ledger omits
`record_unavailable`; a reverted lock never attests, also under
`--no-verify`; a refused lock format attests nothing — the pdm refusal
check follows #247's manifest-free footprint), plus the
`{uv,yarn-berry,yarn-classic}-vex-matrix.sh` drivers and harness unit
tests.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* docs: manifest-less VEX, npm 12 allow-remote and the v5 changelog
- CHANGELOG [Unreleased] (both entries are v5 MAJOR): the semver note now
lists #247's changes and `vex` refusing stale ledger records and corrupt
vendor ledgers; Changed (BREAKING) gains the ledger-liveness /
`vendor_ledger_corrupt` entry (and #247's Fixed bullet that had `vex`
disclose an unreadable ledger now points at it); Added gains the npm
12 `allow-remote` auto-config, manifest-less VEX, standalone `vendor`
record embedding and the new product probes; Fixed gains the composer /
gem / cargo v1 / yarn 4.0 / npm dual-lock rewriter fixes after #247's
own entries.
- CLI_CONTRACT.md: new "Manifest-less VEX (lockfile discovery)" section
(inputs, per-ecosystem recognition table, record resolution,
verification basis, liveness gates, run warnings), "Patch hosts", the
embedded-VEX no-manifest rules, `manifest_not_found` for `vex`, the
vendor ledger's `record` semantics (vendored-mode `detached` entries
plus the standalone `vendor` fallback copy; the reconcile exemption keys
on `detached`), and the new rollback warning code.
- README: "No manifest needed for hosted and vendored patches", the
rewritten `vex` how-it-works steps and product probes, "npm
compatibility (hosted mode and npm 12)", the hosted `.npmrc` commit
hint, and the ledger-liveness note under "Undo things".
- docs/testing: npm-compatibility.md (npm 6–12, new), uv and bun tables,
ecosystems.md.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
* test(vex): golden snapshot of discovery over committed fixtures
Pin the exact output of lockfile discovery over every committed fixture
project, so a behavior change to discovery (or to the lock readers it
shares with the rewriters and vendor::lock_inventory) shows up as a golden
diff to review.
- Corpus: 182 projects under crates/socket-patch-core/tests/fixtures/ —
every redirect case's input/ and expected/ tree, pnpm-hosted, poetry,
pipenv, bun-lockb captures, and each pdm-native lock staged as pdm.lock —
run through the full orchestrator and checked against rule 11's
recognition-covers-refs invariant.
- Rendering (src/vex/discover/testing/golden.rs): every PatchedRef field
(plus lockfile_basis_ok), diagnostics (tempdir root and OS error numbers
normalized), recognized identities, unlocked pins, resolved-elsewhere
entries, and the live hosted / vendored ledger claims. The destructuring
is exhaustive, so a new field fails to compile until the golden covers it.
- Goldens: one JSON per fixture family (redirect-<eco>, bun-lockb,
pdm-native, pipenv, pnpm-hosted, poetry) under
tests/fixtures/vex-discover-golden/, mapping fixture path to output.
Missing and orphaned entries fail.
Regenerate after an intended change with
SOCKET_PATCH_UPDATE_GOLDEN=1 cargo test -p socket-patch-core --lib
vex::discover::testing::golden. Unix only: Windows checkouts convert some
fixtures' line endings.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>1 parent e024629 commit cf8150b
275 files changed
Lines changed: 94244 additions & 8282 deletions
File tree
- .github/workflows
- crates
- socket-patch-cli
- src
- commands
- scan
- tests
- cargo_e2e_matrix
- common
- composer_e2e_common
- e2e_vex_build
- e2e_vex_lockfile
- golang_e2e_matrix
- maven_build_common
- npm_e2e_common
- vex_e2e_common
- vex_pdm_hatch_common
- vex_pipenv_pip_common
- vex_pipenv_pip_real
- vex_pipenv_pip_steps
- vex_pypi_real_common
- yarn_berry_common
- socket-patch-core
- src
- crawlers
- patch/redirect
- utils
- vendor
- lock_inventory
- vex
- discover
- testing
- tests/fixtures
- redirect
- composer/composer-lock/source-and-dist
- expected
- input
- gem/bundler/basic/expected
- vex-discover-golden
- docs
- testing
- scripts
- tests
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
34 | 34 | | |
35 | 35 | | |
36 | 36 | | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
37 | 43 | | |
38 | 44 | | |
39 | 45 | | |
| |||
60 | 66 | | |
61 | 67 | | |
62 | 68 | | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
63 | 75 | | |
64 | 76 | | |
65 | 77 | | |
| |||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
23 | 28 | | |
24 | 29 | | |
25 | 30 | | |
| |||
83 | 88 | | |
84 | 89 | | |
85 | 90 | | |
86 | | - | |
| 91 | + | |
87 | 92 | | |
88 | 93 | | |
89 | 94 | | |
| |||
143 | 148 | | |
144 | 149 | | |
145 | 150 | | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
26 | 29 | | |
27 | 30 | | |
28 | 31 | | |
| |||
70 | 73 | | |
71 | 74 | | |
72 | 75 | | |
| 76 | + | |
| 77 | + | |
73 | 78 | | |
74 | 79 | | |
75 | 80 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
| 20 | + | |
21 | 21 | | |
22 | | - | |
| 22 | + | |
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| 28 | + | |
28 | 29 | | |
29 | 30 | | |
30 | | - | |
31 | | - | |
32 | | - | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
33 | 36 | | |
34 | 37 | | |
35 | 38 | | |
| |||
41 | 44 | | |
42 | 45 | | |
43 | 46 | | |
44 | | - | |
| 47 | + | |
45 | 48 | | |
46 | 49 | | |
47 | 50 | | |
| |||
100 | 103 | | |
101 | 104 | | |
102 | 105 | | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
0 commit comments