socket-patch supports hosted, vendored and agent-mode npm patches in
vlt projects (vlt-lock.json, the node_modules/.vlt
store and, from vlt 1.2.0, the global content store). This page records the
real-vlt evidence: which releases are supported, which capstone legs run on
which release, and the vlt behaviors the legs pin. What each mode does with a
vlt project, and the caveats users meet, are in
vlt notes.
| Era | Releases | lockfileVersion |
DepID grammar | Default-registry node slot [3] |
|---|---|---|---|---|
| A0 | 0.0.0-1, 0.0.0-11 … 0.0.0-18 | absent | · / § + encodeURIComponent (··name@ver) |
absent |
| A | 0.0.0-19 … 1.0.0-rc.8 | 0 |
as A0; ṗ:N peer extras from rc.6 |
absent (3-tuples) |
| B | 1.0.0-rc.9 … 1.0.0-rc.14 | 0 |
as A, default segment npm (·npm·name@ver) |
absent |
| C | 1.0.0-rc.15 … 1.0.0-rc.32 | 1 |
~ / + + _x escapes (~npm~name@ver), peer.N |
absent |
| D | 1.0.0-rc.33 … 1.0.7 | 1 |
as C | the registry URL |
| E | 1.0.8 … 1.1.1 | 1 |
as C, peer.<16 hex> |
the registry URL |
| F | 1.2.0 | 1 |
as E; the global store (store-linker) |
the registry URL |
On every release that writes slot [3], it is omitted when the project
configures registry and the node's tarball URL starts with it (vlt's
lockfile/save.ts; the lock then records options.registry): with
config.registry and registries.npm both set to the default registry,
1.0.0-rc.33, 1.0.4, 1.0.10 and 1.2.0 all write a byte-identical 3-tuple lock
(fixture capture-1.2.0-config-registry). The upstream restore follows the
same rule.
Hosted mode writes the patched sha512 into slot [2] and the hosted URL into
slot [3] of every default-registry node (appending slot [3] to a 3-tuple);
vendored mode turns the node into a file node for the D19 directory
.socket/vendor/npm/<uuid>/<name>-<version>/node_modules/<name>. vlt reads
CRLF locks and writes LF; a BOM-prefixed lock is unreadable by vlt and by
socket-patch alike.
| Layer | Where | What it proves |
|---|---|---|
| Unit and golden | socket-patch-core lib tests; tests/redirect_golden.rs (npm/vlt/*, shared with depscan's TS rewriter), tests/redirect_golden_reverse_replay.rs, tests/vlt_locks.rs (captured locks of every era, and vendored wiring byte for byte against what real vlt ci, vlt install --frozen-lockfile and vlt install <new> keep on 1.2.0, 1.0.10, 1.0.4, 1.0.0-rc.32 and 1.0.0-rc.14) |
DepID codec, collation (tests/fixtures/vlt/collation-golden.json), the node-line grammar, the hosted slot rewrite and its slot revert, vendored lock surgery and its inverse, lock inventory, VEX discovery |
| Hermetic suites | in_process_redirect, in_process_vendor, in_process_rollback_hosted, in_process_vendor_bun_takeover, repair::repair_vendor_flavors_e2e, e2e_vex_lockfile, … (the 3-OS test job) |
every code of the vlt support, the artifact preflight against a wiremock server, the heal, takeovers, repair, the CLI surface |
| Real-vlt capstones | the five binaries below plus the vlt legs of e2e_hosted_production / e2e_vendored_production |
real installs: vlt ci and frozen installs of patched locks, byte-stable locks, integrity enforcement, the heal on a warm tree, re-saves, upgrades, the hardlinked global store |
| Native backtest | scripts/backtest-vlt.py |
the production service end to end, per release, mode and project shape, against an oracle of the documented boundaries |
docs/testing/vlt-coverage.json maps every vlt code and advisory variant,
every mode × command cell and every era × OS cell to the tests or CI rows that
assert it; scripts/tests/test_vlt_coverage.py checks that each code is
asserted and each named test or row exists.
- Required: ci.yml's
e2ejob has 35 vlt rows (vlt:pins the release,vlt_store_linker:/vlt_upgrade:the knobs;test_filter: --include-ignored vlt_pinned_matrix). "Setup vlt" packs the release, checks its sha512 against the registry andscripts/vlt-historical-integrity.json(scripts/install-vlt.sh), installs it under a prefix and exportsSOCKET_PATCH_VLT_E2E_JS/_VERSION/_REQUIRED=1withLANG=C. Every row's output goes throughscripts/check-vlt-legs.py.scripts/tests/test_ci_vlt_rows.py(run bylint-ecosystems) pins the rows. - Required:
hosted-e2einstalls vlt 1.2.0 the same way, runsvlt_pinned_matrix_production_hosted_install_proofinside the production suite (probe-driven: the clean refusal while patch.socket.dev re-encodes the artifact, the full install proof once it does not) andvlt_pinned_matrix_production_vendored_install_proof, both through the leg checker.SOCKET_PATCH_VLT_HOSTED_PRODUCTION_REQUIREDstays unset until the serve fix is verified. - Advisory:
.github/workflows/vlt-compatibility.yml(path-filtered pull requests and pushes to main, nightly, andworkflow_dispatchwithversions/shapes/modes). A path-filtered workflow cannot be a required check. Jobs:build(the capstones and the CLI, once per OS);install-proof(every capstone on 31 Linux, 11 macOS and 15 Windows releases, the Node floors 22.22.0 / 22.13.0 / 22.7.0 / 22.0.0 with the collation golden, and the store linkers auto / hardlink / copy / unpack / a/dev/shmcache root; a cellci.yml'se2erows run identically is left to them, seescripts/ci-vlt-proof-suites.py, except on dispatch);native(the backtest against production, artifactsvlt-results-<os>-<vlt>in depscan's captureresult.jsonshape; on macOS it first pins the TLS-verified patch hosts in/etc/hoststhrough.github/actions/pin-socket-hosts, because the hosted macOS resolver intermittently losespatch.socket.devfor minutes while the service is up);lock-diff(the same cell'svlt-lock.jsonmust be byte-identical on Linux, macOS and Windows);matrix-coverage(every era × suite × OS). - Nightly:
canaryruns every capstone onvlt@lateston 3 OS (only the exact-version pin is relaxed), fails when npm lists a vlt release that the Releases table below neither supports nor excludes, and, once a release writes alockfileVersionother than 0 or 1, requires hosted mode to refuse it (redirect_vlt_lock_unsupported).downgrade(advisory) has the latest published socket-patch runrollbackandvendor --reverton vlt ledgers written by the build: each must leave the project untouched or fully reverted, never half-reverted. - Watchdog:
.github/workflows/vlt-serve-watchdog.ymlprobes the public minimist artifact every 6 hours as vlt fetches it and fails on a content-encoded response or a sha512 other than the API's. It iscontinue-on-erroruntil the serve fix is verified in production.
export SOCKET_PATCH_VLT_E2E_JS=$(scripts/install-vlt.sh 1.2.0 /tmp/vlt-1.2.0)
export SOCKET_PATCH_VLT_E2E_VERSION=1.2.0 SOCKET_PATCH_VLT_E2E_REQUIRED=1 LANG=C LC_ALL=C
for s in e2e_redirect_vlt_build e2e_vendor_vlt_build mode_migration_vlt e2e_safety_vlt e2e_vlt; do
cargo test -p socket-patch-cli --test $s -- --include-ignored vlt_pinned_matrix 2>&1 | tee vlt-leg.log
python3 scripts/check-vlt-legs.py --manifest crates/socket-patch-cli/tests/vlt-leg-manifest.json vlt-leg.log
done
# The production backtest (no Socket API token needed):
python3 scripts/backtest-vlt.py --cli target/debug/socket-patch \
--versions 1.2.0 1.0.0-rc.14 --modes hosted vendored agent --jobs 2 --out /tmp/vlt-btThe backtest writes captures/<vlt>-<mode>-<shape>/{result.json,cli-output.json,tree/,logs/}
and summary.{json,md}, and exits non-zero when any cell's verdict differs
from the oracle. While patch.socket.dev re-encodes the artifact, hosted cells
record blocked-by-server-encoding, and only when the cell's own probe saw a
non-identity Content-Encoding and the CLI refused cleanly. A blocked cell
must carry only redirect_vlt_artifact_unverifiable: the withheld dependency
never reaches a rewriter, so its lock-level and vendored codes are not due.
--identity-mirror previews the hosted proof through a loopback mirror that
fetches the artifact un-encoded (never an import source). --serve-probe is
the watchdog's probe, --canary-checks the canary's watchdogs, and
--downgrade-cli <published socket-patch> the downgrade scenario.
The capstones serve npmjs bytes from a local wiremock registry R and write
vlt.json per era, because before rc.33 bare specs ignore registries.npm:
| Era window | vlt.json | Hermetic | Notes |
|---|---|---|---|
| ≤ 0.0.0-13 | flat {"registry": R} |
yes | vlt-workspaces.json for workspaces ≤ 0.0.0-12 |
| 0.0.0-14 … rc.6 | {"config":{"registry": R}} (+ "modifiers":{} for 0.0.0-16 … 24, except the ignored-lock leg) |
yes | URL-segment DepIDs carry R's port |
| rc.7 … rc.29 | {"config":{"registry": "https://registry.npmjs.org/"}} |
no: lock-driven installs reach public npm | the dead-registry assertions log skip:non-hermetic-registry; the patch service stays local |
| rc.30 … rc.32 | {"config":{"registry": R}} |
yes | URL-segment DepIDs |
| ≥ rc.33 | {"config":{"registries":{"npm": R}}} (+ config.registry = R for rc.33 … 1.0.4) |
yes |
The 0.0.0-1 and 0.0.0-11 writers can record an explicit npmjs tarball URL despite the configured harness registry. v5 rollback reconstructs the upstream pin without a saved lock fragment, so the rollback assertions allow that target URL to be omitted or restored on the harness registry. They still compare every other byte, including bystanders and CRLF line endings, and verify pristine package contents after a real install from the restored lock.
scripts/backtest-vlt.py's write_vlt_json follows the same table against
public npm (a registry equal to vlt's npmjs default is left out: vlt strips
it from the lock anyway).
depscan's TypeScript rewriter (registry-rewrite/vlt.ts) and its SBOM
recognition implement the same spec.
crates/socket-patch-core/tests/fixtures/redirect/npm/vlt/* is the single source of truth: depscan runs every case through its golden
test from the submodules/socket-patch pin, with no TS_LAGGING or
TS_WARNING_DRIFT entry for vlt, and redirect_golden_reverse_replay.rs
proves that socket-patch rolls back what either implementation wrote. The
vlt-results-* artifacts and the cross-OS locks are imported into depscan's
fixtures (audit-captures.py, generate-fixtures.py --captures) once the serve
fix is live.
Five #[ignore]-gated test binaries drive the REAL vlt under test
(SOCKET_PATCH_VLT_E2E_JS=<path to vlt.js>, SOCKET_PATCH_VLT_E2E_VERSION
for an exact --version match) against a local npm registry (bytes fetched
once from npmjs, or built by the harness for the synthetic packages) and a
mock patch service, plus one leg in each production suite:
cargo test -p socket-patch-cli --test e2e_redirect_vlt_build -- --include-ignored vlt_pinned_matrix 2>&1 \
| tee vlt-leg.log
python3 scripts/check-vlt-legs.py --manifest crates/socket-patch-cli/tests/vlt-leg-manifest.json vlt-leg.logvlt finishes some work in detached children after a command returns: the
global-store explode on 1.2.0 (Linux auto, hardlink, copy), the cache
unzip, cache revalidation and the deletion of .VLT.DELETE.* staging dirs.
Every harness vlt run preloads a hook (node --import, not inherited by those
children) that spawns them attached and waits for them, so a leg asserts the
tree vlt leaves once its work is done, never a race with it.
Every leg is a test named vlt_pinned_matrix_<suite>_<leg> that prints one
VLT-LEG <vlt-version> <os> <suite> <leg> ran|skip:<reason> line.
scripts/check-vlt-legs.py fails a run on 0 passed, on a binary that
prints no test result: line (a crash), on a missing ran, on a skip the
manifest does not predict, and on an unknown leg. The manifest
crates/socket-patch-cli/tests/vlt-leg-manifest.json is generated from the
three tables below (python3 scripts/check-vlt-legs.py --derive docs/testing/vlt-compatibility.md), never written by hand;
scripts/tests/test_check_vlt_legs.py re-derives it and diffs.
Knobs (applied after the harness scrubs the ambient VLT_* environment):
SOCKET_PATCH_VLT_E2E_STORE_LINKER ∈ {auto, hardlink, copy, unpack},
SOCKET_PATCH_VLT_E2E_CACHE_ROOT (a cache on another filesystem),
SOCKET_PATCH_VLT_E2E_UPGRADE_JS / _UPGRADE_VERSION (the second vlt of the
upgrade legs) and SOCKET_PATCH_VLT_E2E_SOCKET_BIN. A set _JS makes every
toolchain problem a failure, and so does CI=true with _JS unset.
| Status | Versions |
|---|---|
| supported | 0.0.0-1, 0.0.0-11, 0.0.0-12, 0.0.0-13, 0.0.0-14, 0.0.0-15, 0.0.0-16, 0.0.0-17, 0.0.0-18, 0.0.0-19, 0.0.0-20, 0.0.0-21, 0.0.0-23, 0.0.0-24, 0.0.0-25, 0.0.0-26, 0.0.0-27, 0.0.0-28, 0.0.0-29, 0.0.0-30, 0.0.0-31, 0.0.0-32 |
| supported | 1.0.0-rc.1, 1.0.0-rc.2, 1.0.0-rc.3, 1.0.0-rc.4, 1.0.0-rc.5, 1.0.0-rc.6, 1.0.0-rc.7, 1.0.0-rc.8, 1.0.0-rc.9, 1.0.0-rc.10, 1.0.0-rc.11, 1.0.0-rc.12, 1.0.0-rc.13, 1.0.0-rc.14, 1.0.0-rc.15, 1.0.0-rc.16, 1.0.0-rc.17, 1.0.0-rc.18 |
| supported | 1.0.0-rc.22, 1.0.0-rc.23, 1.0.0-rc.24, 1.0.0-rc.25, 1.0.0-rc.26, 1.0.0-rc.27, 1.0.0-rc.28, 1.0.0-rc.29, 1.0.0-rc.30, 1.0.0-rc.31, 1.0.0-rc.32, 1.0.0-rc.33, 1.0.0-rc.34 |
| supported | 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7, 1.0.8, 1.0.9, 1.0.10, 1.1.0, 1.1.1, 1.2.0 |
| excluded (broken install) | 0.0.0-0 |
| excluded (Deno-compiled wrappers) | 0.0.0-2, 0.0.0-3, 0.0.0-4, 0.0.0-5, 0.0.0-6, 0.0.0-7, 0.0.0-8, 0.0.0-9, 0.0.0-10 |
excluded (vlt install exits 13 on Node 24 after "Done") |
0.0.0-22 |
| excluded (never published) | 1.0.0-rc.19, 1.0.0-rc.20, 1.0.0-rc.21 |
| excluded (unrelated 2017 publishes) | 0.0.1, 1.0.0 |
0.0.0-0.<timestamp> builds are excluded too. Every supported release was
run through all five capstones on macOS during SP-9 (the CI matrix samples
them per OS).
| Binary | Suite | Legs |
|---|---|---|
e2e_redirect_vlt_build |
hosted |
scan_fresh_ci, frozen_dead_registry, ordinary_install_stable, get_uuid_fresh_ci, tamper_cold_eintegrity, rollback_byte_exact, rerun_noop, warm_tree_invalidates, no_cleanup_stays_stale, heal_rule_b_hidden_lock_without_node, heal_rule_c_no_hidden_lock, heal_rule_c_no_record, scoped, peer_workspace_instances, peer_rekey_rollback, install_newdep_preserves, update_drops, resave_install_rollback, resave_crlf_rollback, resave_update_rollback, crlf_lock, mirror_registries_npm, scalar_registry, named_alias_untouched, scoped_registry_untouched, jsr_untouched, default_registry_alias, registry_from_env, registry_from_user_config, content_encoding_refused, old_lockfile_ignored, warm_cache_hazard, idempotence, manifestless_vex, ts_written_lock, optional_dependency_heal, then_vendored_optional_takeover, platform_optional_skipped |
e2e_vendor_vlt_build |
vendored |
scan_fresh_ci, get_auto_fresh_ci, get_service_fresh_ci, durability, workspace_member_selfref, alias_selfref, peer_root_selfref, peer_member_selfref, single_peer_context, optional_warm_reinstall, dep_with_deps, hostile_gitignore, autocrlf_checkout, bin_bearing, package_json_devdeps_patch, repair_rebuilds, idempotency, revert_byte_exact, resave_install_revert, resave_uninstall_revert, resave_crlf_revert, tamper_planted_file, tamper_file_content, tamper_payload_package_json, tamper_symlink_outside, tamper_deleted_gitignore, tamper_lock_file_node_path, transitive_refused, legacy_lockfile_warning, absent_version_refused, lockless_reinstall, manifestless_vex |
mode_migration_vlt |
migration |
vendored_then_hosted, hosted_then_vendored, dry_run_parity, scoped_unwind_one_of_two, rollback_from_mixed, agent_apply_yields_to_vendored, agent_apply_after_hosted, hosted_scan_keeps_agent_patched_tree, agent_rollback_after_takeovers, pm_switch_npm_to_vlt, pm_switch_vlt_to_npm, flavor_changed, upgrade_hosted, upgrade_vendored |
e2e_safety_vlt |
safety |
linux_auto, explicit_hardlink, private_copies, cross_device_cache, agent_rollback, peer_fanout, hosted_heal, vendored_build, vendor_revert_and_repair, layout_note |
e2e_vlt |
agent |
scan_apply_rollback_list, get_and_remove, install_then_apply_patches_file, transitive_only_dep_apply_patches_store, lockfile_supplement, launcher, persistence_survives, persistence_reverted_by_reinstall, reruns_and_vex |
e2e_hosted_production |
production |
hosted_install_proof |
e2e_vendored_production |
production |
vendored_install_proof |
The DESIGN §1.1 boundaries, extended with what SP-9 measured on every
supported release. A row with a skip reason is a manifest rule: the first
row matching a leg, the vlt version, the OS and the knobs decides that leg's
skip:<reason> (rows are ordered the way the legs test them); every other
leg must print ran. Rows without a skip reason are behaviors the legs
assert in place.
Versions: < V, <= V, > V, >= V, == V, A … B (inclusive) or
all. Conditions: os (linux, macos, windows), linker (the
store-linker knob, unset when not given), cache_root and upgrade
(set/unset), and upgrade<V (the upgrade vlt's version); in / notin take +-separated values and , joins conditions.
| Boundary | Versions | Condition | Suite | Legs | Skip reason |
|---|---|---|---|---|---|
A0 locks (no lockfileVersion) are refused by vendored mode |
<= 0.0.0-18 |
— | vendored | * except absent_version_refused |
a0-vendored-unsupported |
| A0 locks are refused by vendored mode | <= 0.0.0-18 |
— | migration | * |
a0-vendored-unsupported |
| A0 locks are refused by vendored mode | <= 0.0.0-18 |
— | production | vendored_install_proof |
a0-vendored-unsupported |
the global store and store-linker |
< 1.2.0 |
— | safety | * |
no-global-store |
vlt install needs Node >= 22.7.0, above engines (>=22): the CLI is ESM without "type": "module", and Node detects module syntax unflagged only from 22.7.0 (22.6.0: SyntaxError: Cannot use import statement outside a module); install-proof runs 0.0.0-30 on 22.7.0 |
0.0.0-11 … 0.0.0-30 |
— | — | — | — |
vlt install loads node:sqlite, unflagged from Node 22.13.0, above engines (>=22 through rc.9, >=22.9.0 for rc.10 … rc.18; 22.12.0: ERR_UNKNOWN_BUILTIN_MODULE); install-proof runs rc.18 on 22.13.0 |
0.0.0-31 … 1.0.0-rc.18 |
— | — | — | — |
vlt ci, --frozen-lockfile, --expect-lockfile exist |
< 0.0.0-19 |
— | hosted | frozen_dead_registry, optional_dependency_heal, then_vendored_optional_takeover |
no-vlt-ci |
a scalar registry makes lock-driven installs re-resolve from public npm |
1.0.0-rc.7 … 1.0.0-rc.29 |
— | hosted | frozen_dead_registry |
non-hermetic-registry |
the same re-resolution makes vlt ci rewrite a vendored era-A lock's scalar-registry ids to ·· (measured on rc.7 and rc.8; the vendored file: node and payload survive it), so legacy_lockfile_warning's scalar arm asserts the patched payload after vlt ci and a frozen install that keeps the lock vlt ci wrote, and only logs the re-keyed bystander |
1.0.0-rc.7 … 1.0.0-rc.8 |
— | — | — | — |
| registry tarball integrity is not enforced on a cold fetch | == 0.0.0-1 |
— | hosted | tamper_cold_eintegrity |
integrity-unenforced |
bare specs honor registries.npm |
< 1.0.0-rc.33 |
— | hosted | mirror_registries_npm |
registries-npm-ignored |
named registry specs (acme:x@1), scoped registries and URL-segment DepIDs exist (flat-config releases record every registry node under the default segment) |
< 0.0.0-14 |
— | hosted | named_alias_untouched |
no-named-registry-specs |
| as above | < 0.0.0-14 |
— | hosted | scoped_registry_untouched, jsr_untouched |
registry-not-in-dep-id |
jsr: specs resolve through jsr-registries (0.0.0-14 … rc.6 send the @jsr scope to npm.jsr.io; rc.7 … rc.32 cannot run the leg hermetically, below) |
< 1.0.0-rc.7 |
— | hosted | jsr_untouched |
jsr-registry-not-configurable |
a scalar registry makes lock-driven installs re-resolve from public npm |
1.0.0-rc.7 … 1.0.0-rc.29 |
— | hosted | jsr_untouched |
non-hermetic-registry |
npm: alias specs resolve against public npm even with registries.npm |
1.0.0-rc.30 … 1.0.0-rc.32 |
— | hosted | jsr_untouched |
non-hermetic-registry |
default-registry-alias exists |
< 1.0.0-rc.33 |
— | hosted | default_registry_alias |
no-default-registry-alias |
the lock is ignored unless vlt.json declares "modifiers": {} |
< 0.0.0-16 |
— | hosted | old_lockfile_ignored |
lock-not-ignored |
| as above | > 0.0.0-24 |
— | hosted | old_lockfile_ignored |
lock-not-ignored |
vlt update exists |
< 0.0.0-20 |
— | hosted | update_drops, resave_update_rollback |
no-vlt-update |
the golden basic lock (registries.npm, no scalar registry) is what the release writes |
< 1.0.5 |
— | hosted | ts_written_lock |
golden-grammar |
a platform-skipped optional dependency makes the install fail (Dependency node could not be found) |
0.0.0-31 … 1.0.0-rc.1 |
— | hosted | platform_optional_skipped |
vlt-platform-optional-bug |
the root importer's direct dependency with resolved peers has no peer extra, so bumping its peer never re-keys the pinned node (peer_rekey_rollback pins the re-key and the rollback that follows it) |
< 1.0.8 |
— | hosted | peer_rekey_rollback |
no-root-peer-extra |
a scalar registry makes lock-driven installs re-resolve from public npm |
1.0.0-rc.7 … 1.0.0-rc.29 |
— | vendored | workspace_member_selfref, alias_selfref |
non-hermetic-registry |
npm: alias specs resolve against public npm even with registries.npm |
1.0.0-rc.30 … 1.0.0-rc.32 |
— | vendored | alias_selfref |
npm-alias-non-hermetic |
era A (·· ids, or scalar-registry URL-segment ids with no ·npm· id): vendor_vlt_legacy_lockfile |
> 1.0.0-rc.8 |
— | vendored | legacy_lockfile_warning |
not-legacy-lockfile |
lockfileVersion is written |
>= 0.0.0-19 |
— | vendored | absent_version_refused |
lockfile-version-present |
| the upgrade legs need a second vlt | all |
upgrade=unset |
migration | upgrade_hosted, upgrade_vendored |
no-upgrade-vlt |
| only a v0 lock (0.0.0-19 … rc.14) meets a grammar change | > 1.0.0-rc.14 |
— | migration | upgrade_hosted, upgrade_vendored |
no-grammar-upgrade |
the upgrade vlt must check lockfileVersion |
all |
upgrade<1.0.0-rc.15 |
migration | upgrade_hosted, upgrade_vendored |
no-grammar-upgrade |
store-linker=auto hardlinks on Linux only |
all |
os!=linux |
safety | linux_auto |
not-linux-auto |
| as above | all |
linker notin unset+auto |
safety | linux_auto |
not-linux-auto |
| as above | all |
cache_root=set |
safety | linux_auto |
not-linux-auto |
| the explicit hardlink leg | all |
linker!=hardlink |
safety | explicit_hardlink |
store-linker-not-hardlink |
| as above | all |
cache_root=set |
safety | explicit_hardlink |
store-linker-not-hardlink |
| the store is hardlinked | all |
linker=hardlink, cache_root=unset |
safety | private_copies |
store-linker-hardlinks |
| as above | all |
linker in unset+auto, os=linux, cache_root=unset |
safety | private_copies |
store-linker-hardlinks |
| a cache on another filesystem falls back to copies | all |
cache_root=set |
safety | private_copies |
store-linker-hardlinks |
| as above | all |
cache_root=unset |
safety | cross_device_cache |
no-cache-root |
a scalar registry makes lock-driven installs re-resolve from public npm |
1.0.0-rc.7 … 1.0.0-rc.29 |
— | agent | scan_apply_rollback_list, launcher |
non-hermetic-registry |
npm: alias specs resolve against public npm even with registries.npm |
1.0.0-rc.30 … 1.0.0-rc.32 |
— | agent | scan_apply_rollback_list |
non-hermetic-registry |
lockfileVersion 0 with legacy (·/§) DepIDs |
0.0.0-19 … 1.0.0-rc.14 |
— | — | — | — |
lockfileVersion 1, tilde DepIDs |
>= 1.0.0-rc.15 |
— | — | — | — |
a plain vlt install re-extracts a stale installed copy (no_cleanup_stays_stale expects the patch there) |
== 0.0.0-14 |
— | — | — | — |
| an optional-only project: installs from the lock | <= 0.0.0-23 |
— | — | — | — |
an optional-only project: the first install writes no vlt-lock.json |
0.0.0-24 … 0.0.0-29 |
— | — | — | — |
| an optional-only project: lock-driven installs install nothing | 0.0.0-30 … 1.0.4 |
— | — | — | — |
| an optional-only project installs from the lock again | >= 1.0.5 |
— | — | — | — |
after a hosted→vendored takeover a plain vlt install already links the vendored dir |
<= 0.0.0-29 |
— | — | — | — |
a plain vlt install keeps an installed optional dependency whose spec moved to a vendored file: directory (the upstream copy stays linked until vlt ci); vendored mode says so with vendor_vlt_reinstall_required, which optional_warm_reinstall pins; the same holds in reverse after vendor --revert (the link to the removed vendored directory stays until vlt ci), and the revert repeats the advisory |
>= 0.0.0-30 |
— | — | — | — |
lockless file: directory dependencies fail to resolve |
0.0.0-31 … 1.0.0-rc.5 |
— | — | — | — |
a re-save (vlt install <new>) drops slot [3] of default-registry nodes (the hosted URL; the patched integrity stays, so vlt ci fails EINTEGRITY until a rescan re-pins, and rollback reports drift) |
1.0.0-rc.6 … 1.0.0-rc.17 |
— | — | — | — |
| a warm cache re-fetches a changed tarball and fails its integrity (no stale-bytes hazard) | 1.0.0-rc.27 … 1.0.2 |
— | — | — | — |
vlt update re-resolves an unchanged exact spec (dropping a hosted pin); earlier releases keep the locked node |
>= 1.0.8 |
— | — | — | — |
vlt.json spells the scope map scoped-registries (scope-registries before) |
>= 1.0.0-rc.28 |
— | — | — | — |
a workspace member's direct dependency with resolved peers (use-sync-external-store beside react) gets a peer extra (~peer.1); vendored mode writes its file node without the extra, as vlt writes file: dependencies, and single_peer_context / peer_member_selfref pin the lock byte-stable through vlt ci, vlt install --frozen-lockfile and vlt install <new> |
>= 1.0.0-rc.15 |
— | — | — | — |
the root importer's direct dependency with resolved peers gets a peer extra (~peer.<16 hex>); vendored mode drops it the same way (single_peer_context, peer_root_selfref) |
>= 1.0.8 |
— | — | — | — |
two workspaces with use-sync-external-store beside react 17 and react 18 share ONE peer instance (peer_workspace_instances pins the count); no real-vlt shape was found that writes several instances of one name@version, so multi-instance pinning is covered by the in-process goldens only |
all |
— | — | — | — |
The legs run on Linux, macOS and Windows. The Linux-default auto store
linker (hardlinks, safety/linux_auto) cannot run on macOS or Windows; it is
covered on Linux by the CI e2e row e2e_safety_vlt on ubuntu with vlt
1.2.0 and by vlt-compatibility.yml's store-linker rows, and was also run
locally in node:24-slim under Docker. Windows-only cases
(the junction and dir-symlink store cases) run on the Windows rows.