Skip to content

Commit b32711f

Browse files
Support vlt in hosted, vendored and agent modes (#269)
* Fix Cargo hosted workspace redirects Resolve inherited dependency aliases through their workspace definitions and match local lockfile owners by both package name and version. This allows valid workspace patches while refusing consumers outside the editable project. Read quoted dependency values and annotated registry tables consistently so repeated application cannot leave an alias unpatched or create an invalid duplicate TOML table. Validated with 70 Cargo redirect unit tests and real service-backed hosted, vendored service, and vendored build installs using fresh Cargo caches, locked offline builds, integrity rejection, and revert. Assisted-by: Codex:gpt-6-astra * Refuse incomplete Cargo manifest redirects Validate planned dependency pins against parsed TOML before writing any files. Legal root and target dotted or inline declarations that the source-preserving editor cannot rewrite now refuse the entire patch instead of leaving a mixture of original and patched sources. Validate unchanged member manifests too, while preserving workspace inheritance and declarations for other package versions. Malformed TOML is refused without changing the project. Validated with 73 Cargo unit tests and the real converter/API/CLI matrix, including an actual Cargo build proving the dotted manifest is valid and remains byte-identical after refusal. Assisted-by: Codex:gpt-6-astra * Keep Cargo refusal checks lint-clean Combine identical refusal branches for dotted dependencies without changing which declarations are refused. Full workspace Clippy and all 73 Cargo redirect tests pass. Assisted-by: Codex:gpt-6-astra * Fail closed on ledger kinds this release lacks A redirect ledger written by a newer socket-patch (for example a vlt lock edit) could be half-reverted: rollback dropped the npm record and left the lockfile it did not understand still pointing at the hosted artifact, with nothing tracking it. Now an unknown hosted edit kind holds every record in the ledger, and rollback of one package, remove and the hosted-to-vendored takeover refuse with nothing written when that edit names the package. repair skips vendored npm entries whose flavor it does not know instead of judging or rebuilding them with the wrong layout rules. The contract and changelog say vlt ledgers need the release that adds vlt support. Assisted-by: Claude Code:claude-opus-5-5 * Keep unknown ledger edits out of vendor reconcile The end-of-run hosted-to-vendored reconcile in `vendor` and `scan --mode vendored` could still drop a redirect record together with a ledger edit this release does not understand (for example a vlt-lock.json edit), leaving that lockfile on the hosted URL with nothing tracking it while reporting the migration as reconciled. It now leaves such a package in the ledger and prints the manual cleanup advisory instead. An unknown edit now only blocks the package it actually names, so an edit for left-pad or @scope/pad no longer refuses a rollback of pad. Whole-ledger rollbacks that hit an unknown edit now say to upgrade socket-patch rather than suggesting a rescan that cannot help. The changelog and contract now say that such a rollback still unwinds the lockfiles this release understands while keeping every record. Assisted-by: Claude Code:claude-opus-5-5 * Route npm vendor flavors through one parser repair and the vendored health check decide whether an npm flavor is known from a hand-kept list that the revert dispatch did not share, so a release adding a flavor could revert its entries yet still skip them in repair as unknown. The known set, the revert routing and the in-use probe now all come from a single string-to-flavor mapping with exhaustive matches. Assisted-by: Claude Code:claude-opus-5-5 * Add vlt lockfile text and DepID primitives Lays the groundwork for vlt support without changing any behavior yet. socket-patch can now decode vlt's package ids in both lockfile encodings (vlt up to 1.0.0-rc.14 and every later release), recognize vlt's default registry the way vlt does, read vlt-lock.json strictly (a BOM, a non-object or an unknown lockfileVersion is refused, never parsed around), and read and write its one-entry-per-line node and edge lines without re-serializing the file. It also reproduces vlt's own lockfile ordering, pinned by a golden generated with Node's collator, so later vendored edits leave a lock that vlt ci keeps byte-identical. Fixture directories that hold tables rather than projects are kept out of the VEX golden corpus. Assisted-by: Claude Code:claude-opus-5-5 * Match depscan's npm name rule in vlt ids vlt lock ids now give a package identity to every name npm still accepts for existing packages, the same rule depscan uses. Scoped names whose scope or name starts with "." or "_" (such as the published @_koii/web3.js) and names over 214 characters were refused before, so hosted redirects, VEX and vendored-copy checks would have missed them while depscan patched them. Names npm blocks (node_modules, favicon.ico) and versions too large for npm to publish no longer get an identity. A refused lockfileVersion is now reported exactly as it is written in the lockfile (1e0 rather than 1.0), and tests now pin the default-registry scheme check and the fixture-corpus skip of the vlt tables. Assisted-by: Claude Code:claude-opus-5-5 * Patch vlt installs in agent mode socket-patch now recognizes a project installed by vlt (the node_modules/.vlt store or node_modules/.vlt-lock.json) ahead of any sibling bun, pnpm, yarn or npm marker, and apply prints a vlt layout note in human mode. scan, get, apply, rollback and vex now find every package in vlt's store in every DepID era: transitive-only packages, aliases, git, remote and file: entries, and workspace members whose node_modules hold only links. apply and rollback reach every store copy of a patched package, including vlt's peer and modifier variants, and each write replaces the file instead of writing through it, so vlt's machine-wide store stays untouched. The store-copy failure note now reads "store copy <path> failed to patch" for pnpm and vlt alike. In a vlt project, --update suggests vlt install @socketsecurity/socket-patch@latest, and in vlx's cache it suggests re-running vlx with @latest. The crawler tests stage real layouts captured from vlt 0.0.0-32, 1.0.0-rc.14, 1.0.10, 1.2.0 and a 1.0.0-rc.22 workspace. Assisted-by: Claude Code:claude-opus-5-5 * Stop counting store dependency links as copies When a git, remote or file: dependency in a vlt (or pnpm) store depended on a patched package, apply and rollback treated that dependency link as a second installed copy: the run reported an extra "already patched" or "already original" result, and get, vex, vendor and repair could pick the link as the package's location. An importer link into a git or tarball entry was also listed twice. The resolver now follows the store-entry rule the scan already uses: inside a store entry only real directories are copies, and a store copy an importer link already points at keeps the importer path. A node_modules/.vlt that is a link is never followed, and tests now pin the hoist-dir skip and the policy that a same-version git copy is patched as its own copy. Doc comments broken in the previous commit are rewrapped. Assisted-by: Claude Code:claude-opus-5-5 * Rewrite vlt locks for hosted patches The hosted rewriter now understands vlt-lock.json. For each patched package it points every default-registry node at the Socket-hosted tarball by splicing only the integrity and URL slots, so the DepID, the flags, the trailing slots, the edges and the options stay byte-identical and vlt ci keeps the lock as written. It reads every vlt lock era (no lockfileVersion, 0 with the legacy ids, 1), refuses a lock vlt itself could not read (BOM, unknown version, non-canonical layout), skips named-alias, scoped and jsr registry copies with a warning, and warns when an old vlt would ignore the lock. Rollback, remove and the vendored takeover now revert these edits, including ledgers the depscan PR flow writes: the registry slots go back on the node even after vlt re-laid the line, and a node vlt has re-locked away counts as already reverted. The scan and get commands start reading vlt-lock.json in a later change; until then this is reachable through the shared golden fixtures and the revert paths. Assisted-by: Claude Code:claude-opus-5-5 * Fix vlt hosted revert order and lock advisories Rolling back a vlt hosted redirect no longer refuses when vlt re-locked one peer or modifier variant away while an earlier instance of the same package still carries the pin. Every surviving instance is restored first, and only then is a vanished one checked for a leftover hosted URL, so rollback, remove and the vendored takeover succeed whatever order the ledger holds. The "vlt ignores this old lockfile" advisory now fires only for the empty or registry-URL segments the spec names, so v0 locks that use a named registry alias no longer get a spurious warning (and a withheld VEX attestation). A bun.lockb on disk now counts as a sibling lock when deciding whether vlt drives the install, without passing its bytes as text. New tests pin the slot-level revert through both revert entry points, the install-state sentinel on its own, both advisory alias cases and a CRLF copy of every captured vlt lock. Assisted-by: Claude Code:claude-opus-5-5 * Redirect vlt projects in hosted mode `scan --mode hosted` and `get --mode hosted` now repoint vlt-lock.json at Socket's hosted patches: every default-registry node of a patched package keeps its DepID and gets the patched sha512 and hosted URL, and vlt drives confirmation when its install state is present or no other npm-family lock is. Before anything is written, each artifact is fetched the way vlt fetches it. A response vlt would reject (re-gzipped, wrong sha512, HTTP error, unreachable) withholds the package instead of pinning a lock `vlt ci` cannot install. vlt never refreshes an installed copy, so after the rewrite socket-patch removes stale store entries and the hidden lock, and rollback and remove do the same once the registry pins are back. --no-vlt-install-cleanup (SOCKET_NO_VLT_INSTALL_CLEANUP) keeps them; the redirect_vlt_reinstall_required advisory says what to run. A same-run --vex no longer attests a vlt package whose installed copy is stale or unchecked, whose lock an older vlt may ignore, or which also resolves from another registry. Assisted-by: Claude Code:claude-opus-5-5 * Verify vlt takeovers before reverting them A vendored vlt package taken over by `scan --mode hosted` is now fetched and verified before its vendored state is reverted, dry runs included. An artifact vlt would reject keeps the package vendored instead of leaving a lock pinned to bytes nobody checked. A same-run --vex attests a vlt package only when the heal checked its installed copy; a pin on a host socket-patch does not own is left to a later `socket-patch vex`. When vlt-lock.json is withheld beside another lockfile, its old pin no longer confirms the package, and the warning says only vlt-lock.json was left unchanged. The heal keeps every store entry when node_modules/.vlt-lock.json cannot be removed, so vlt never trusts a hidden lock with dangling links, and packages that bundle dependencies are no longer re-invalidated on every run. Assisted-by: Claude Code:claude-opus-5-5 * Vendor vlt projects as patched package dirs `socket-patch vendor` now wires projects that install with vlt. A vlt-lock.json (lockfileVersion 0 or 1) routes npm vendoring to a new vlt backend ahead of every other lockfile, and a package already vendored through another lockfile refuses with vendor_flavor_changed. A direct dependency of the root or a workspace member is committed as the patched package directory under .socket/vendor/npm/<uuid>/<name>-<version>/node_modules/<name>/, so packages that require their own name keep resolving. Its devDependencies are dropped from the vendored package.json, and the uuid dir's .gitignore and .gitattributes keep the payload committable and byte-exact on every checkout. The lock node, its importer edges and the importers' package.json specs move to the file: path, placed where vlt itself writes them, so `vlt ci` leaves the lock unchanged; this is checked against locks real vlt 1.2.0, 1.0.10 and 1.0.0-rc.14 wrote. Transitive targets, peer or modifier variants, foreign registries, peer edges, multi-field declarations, stale specs, unreadable locks and git-ignored payloads refuse before any write. `vendor --revert` restores the registry node, edges and specs while keeping whatever vlt re-laid since, or leaves everything on drift. Health checks, reuse and repair judge the directory with its package.json exemption, and lock inventory reads vlt-lock.json. Assisted-by: Claude Code:claude-opus-5-5 * Harden vlt vendoring revert and rebuild paths `vendor --revert` on a vlt project no longer writes a lock with duplicate keys when `vlt install` has since added a registry copy of the vendored package beside it: the vendored entries fold into the matching registry ones, and a mismatching copy is reported as drift with nothing written and the artifact kept. Re-vendoring a new patch over a dir whose ledger entry lost its pre-vendor wiring now refuses with vendor_wiring_unknown and says how to recover, instead of recording wiring that could never be reverted. A rebuild of the committed package dir replaces the whole version-level directory, so stray files beside the package no longer cause an endless corrupt-then-rebuild loop, and it keeps vlt's dependency links (or says to run `vlt install` when they had to be discarded). Prebuilt service trees are pruned of node_modules and bundling packages refuse, as the local build already did. The git-ignore probe now parses rule sources that contain a colon, such as Windows drive-letter paths. New tests pin every revert inverse's already-reverted branch, the importer allowlist, dry-run revert, the rebuild branch, the reuse-time .gitignore restore, the gitignored refusal, both bundleDependencies refusals, the service layout fallback, local dir artifact staging and the FIFO-safe vlt-lock.json inventory. Assisted-by: Claude Code:claude-opus-5-5 * Attest vlt locks in manifest-less VEX `socket-patch vex` and every embedded `--vex` now read vlt-lock.json: a Socket-hosted registry node (patch URL plus sha512, any DepID era) and a vendored vlt package directory become attestation inputs, so a vlt project attests its patches without .socket/manifest.json or the ledgers, and a redirect or vendor ledger stays live only while the vlt lock still wires it. A lock vlt cannot read (BOM, unknown version) wires nothing. Hosted npm packages are now judged by every store variant of their installed copies (pnpm and vlt peer, modifier and registry-alias instances), and a vlt package that another registry also resolves at the same version no longer attests before install. Vendored vlt directories verify with the package.json exemption, including the out-of-sync check of the installed link, and setup.manual accepts `vlt`. Assisted-by: Claude Code:claude-opus-5-5 * Tighten vlt VEX refs and ledger-less checks A hosted vlt-lock.json node now attests only when its patch URL's embedded package name and version (scope included) match the node, so a lock pointing one package at another package's patch URL is no longer read as patched. A Socket-shaped node that fails these checks counts against its siblings of the same version: a hosted pin next to it no longer attests before install, and a vendored directory next to it is not attested. A vendored vlt directory checked without its vendor ledger now verifies a package.json with devDependencies stripped against the patched blob in .socket/blobs. When that blob is missing, the package is left out with the new reason vendor_manifest_unverifiable instead of a misleading hash mismatch. The warnings for an unreadable vlt-lock.json and for an unattributable vendored node now describe the actual cause and a fix that works. Assisted-by: Claude Code:claude-opus-5-5 * Preflight vendored vlt in every command vendor, scan --mode vendored and get --mode vendored now refuse every vlt project the vlt backend would refuse (lock version or layout, transitive, peer or foreign-registry targets, multi-field or out-of-sync declarations, a flavor switch, bundled or duplicate devDependencies, a git rule ignoring .socket/) before any patch is downloaded, anything is written, or a live hosted redirect is reverted for a takeover; dry runs preview the same codes. A fresh clone re-vendors from the committed vlt directory artifact, verified against the ledger inventory, and vlt's own link to that directory is never used as a pristine source. A hosted to vendored takeover removes the store copies vlt installed from the hosted pin. repair finds, rebuilds and reconstructs vlt directory artifacts and restores their .gitignore and .gitattributes; the human output names the vlt files to commit and `vlt install`. rollback now fetches a before-blob that only a pnpm or vlt store peer variant still needs instead of failing that copy. Assisted-by: Claude Code:claude-opus-5-5 * Fix vlt vendoring review findings A root .gitignore rule like `*.json` no longer makes vendored vlt refuse `vendor_artifact_gitignored`: the preflight now asks git only about the uuid directory, so it refuses just the rules (such as `.socket/`) that the directory's own .gitignore cannot override. Re-vendoring under a newer patch with nothing installed no longer builds the new artifact from the old patch's committed artifact, for every npm lockfile flavor. It fetches the pristine package instead, and `--offline` skips it with the reason. When vlt's link to the committed directory is the only installed copy, vendor now names it instead of claiming nothing is installed. A lost ledger entry fails `vendor_ledger_entry_missing` and points at `socket-patch repair`. A hosted to vendored takeover whose vendoring then fails still removes the store copies vlt installed from the hosted pin, and prints the reinstall advisory. Before, the redirect record was gone and nothing could find those copies again. The rollback before-blob fix is filed under Fixed, with a pnpm store peer-variant test beside the vlt one. New tests cover the get uuid-path refusal line, vlt references that only the lock or a workspace package.json carries, and restoring vlt wiring files after a failed repair post-verify. Assisted-by: Claude Code:claude-opus-5-5 * Wire vlt projects in setup `socket-patch setup` now recognizes a vlt project (vlt-lock.json, vlt.json, node_modules/.vlt-lock.json or a node_modules/.vlt directory in the project root, ahead of any pnpm marker) and writes npm's npx hook into its package.json. A vlt workspace, declared in vlt.json or the legacy vlt-workspaces.json, is wired at the root only, because vlt runs the root hook once per install. `setup --json` and the setup telemetry report the package manager as "vlt". vlt releases before 1.0.0-rc.13 never run a root postinstall, so setup now warns `vlt_root_scripts_not_run`: definitely when the vlt on PATH reports such a version (checked with telemetry off and a 5 second limit), and as a "may" when no usable vlt is found and vlt-lock.json has lockfileVersion 0 or none. The hook is still written. The setup-matrix gains vlt single-project and workspace cases, and the npm test image moves to Node 22 with vlt 1.2.0 installed. Assisted-by: Claude Code:claude-opus-5-5 * Fix vlt setup review findings `setup` now also warns `vlt_root_scripts_not_run` as a "may" when the vlt on PATH is recent but the committed vlt-lock.json is one it would never write: a lock without lockfileVersion, or a v0 lock beside vlt 1.0.0-rc.15 or later (which refuses v0, so an older vlt elsewhere installs the project). vlt rc.13 and rc.14 write v0 locks themselves and stay silent. `setup --remove` now also clears the hooks that earlier socket-patch releases wrote into vlt workspace members, so a removal that reports success no longer leaves member hooks running (and keeping npm counted as set up for VEX). Excluded and clean members are still left alone. The static check that the setup matrix routes vlt through the npm round trip now runs in the default test suite instead of only with the setup-e2e feature. Assisted-by: Claude Code:claude-opus-5-5 * Keep optional vlt copies out of the heal The hosted warm-tree heal removed stale store entries of optional dependencies too. vlt does not put a removed optional dependency back on `vlt install` unless the same install also reinstalls a non-optional package, so the dependency could silently vanish and its node_modules link dangle (measured on vlt 0.0.0-32 through 1.2.0). scan/get, rollback/remove and the vendored takeover now leave every optional copy (lock flags 1 or 3, or unreadable flags) in place. Such a copy stays out of the run's in-run VEX, and the redirect_vlt_reinstall_required advisory tells the user to run `vlt ci` (or delete node_modules and run `vlt install`), noting that vlt before 1.0.5 installs no optional dependency from the lock of a project that declares only optional dependencies. Assisted-by: Claude Code:claude-opus-5-5 * Report kept optional vlt copies in every advisory When a heal both removed stale vlt copies and kept an optional one, the redirect_vlt_reinstall_required advisory reported only the optional copy, so it no longer said node_modules was incomplete or that `vlt update` drops the redirects. With cleanup skipped, it counted the optional copies among those a re-run would refresh, which it never does. Every advisory now reports removed, skipped and unchecked copies as before and adds how many optional copies were kept and that `vlt ci` refreshes them. It also warns that on vlt before 1.0.5, in a project whose dependencies are all optional, `vlt ci` would drop the installed copy, so users should upgrade vlt first. Assisted-by: Claude Code:claude-opus-5-5 * Prove vlt support against real vlt releases vlt users get hosted, vendored and agent-mode patches that are checked against the real vlt releases they run, not only against hand-written lockfiles. Five new capstone suites install projects with the vlt under test and let vlt itself install what socket-patch wrote: fresh-checkout `vlt ci`, frozen and ordinary installs, tamper and warm-cache cases, rollback and heal, optional dependencies, registry shapes, takeovers between modes, the Linux hardlinked global store, the setup hook and the npm launcher. Two production legs prove the flow against the live patch service (the hosted one refuses cleanly while the server still re-encodes artifacts). Every leg reports whether it ran or why it skipped, and scripts/check-vlt-legs.py fails a run that skipped something it should have run, so a CI row can no longer pass without testing anything. The expected skips come from the release table in docs/testing/vlt-compatibility.md, which records the vlt behavior boundaries measured on every supported release. Assisted-by: Claude Code:claude-opus-5-5 * Fix vlt capstone review findings The Windows npx shim passed the package name through to socket-patch, so every setup-hook leg on Windows would have aborted vlt's install. It now forwards only the arguments after the package, and a harness self-test runs the shim. The capstones now also prove what they claimed but skipped: the optional-only hosted to vendored takeover runs on every vlt release that writes a lock, the vendored VEX of a package.json patch without the vendor ledger fails closed without the patched blob and attests with it, vendored to hosted takes over through both scan and get, the heal and rollback legs check that no other store entry changed, and the hook-failure leg pins exit 1. Two new vendored legs use the real peer-bearing use-sync-external-store and record where vendored mode still refuses it, so fixing that refusal flips a visible expectation. check-vlt-legs.py reads Windows cargo output and fails a run whose test binary crashed before printing its result line. Assisted-by: Claude Code:claude-opus-5-5 * Run vlt suites in CI and backtest production Pull requests now run the real-vlt capstones on 35 release and OS cells, each checked against the leg manifest, and the required hosted-e2e job proves vlt hosted and vendored installs against production. A new advisory workflow runs every capstone on every vlt era of Linux, macOS and Windows, backtests the production service per release, mode and project shape, compares the locks each OS writes, and nightly tries vlt@latest, watches for new vlt releases and checks that the published socket-patch never half-reverts a vlt ledger. A watchdog probes the public patch artifact every six hours the way vlt fetches it, so re-encoded artifacts are caught early. vlt releases are installed from a sha512-checked npm pack, and the docs now cover vlt in every mode: eras, the hosted heal, vendored package directories, setup and the known vlt limitations. Every vlt error code is documented in the CLI contract and mapped to the tests that assert it. Assisted-by: Claude Code:claude-opus-5-5 * Fix vlt backtest and CI review findings The vlt compatibility backtest no longer fails every hosted cell on 0.0.0-16 and 0.0.0-32 while the service re-encodes the artifact: a blocked cell now owes only its refusal code, since the withheld dependency never reaches a rewriter. The tampered-lock check accepts vlt 0.0.0-16's optional-skip failure the way the depscan capture does, so those cells pass once the serve fix ships. Vendored cells now also prove the user's existing tree: a plain `vlt install` and then `vlt ci` must land the vendored bytes. From 0.0.0-30 vlt keeps an installed optional dependency on a plain install; that is pinned in the boundary table and documented, and `vlt ci` must still link the patch. The production e2e retries in CI now actually retry, a narrowed compatibility dispatch no longer fails its lock diff, and the README and vlt notes say vendored mode needs a 0.0.0-19 or later lock. Assisted-by: Claude Code:claude-opus-5-5 * Vendor vlt deps that carry one peer context From vlt 1.0.8 a root dependency with resolved peers, and from rc.15 a workspace member's, gets a peer extra on its lock node even with a single peer context, so vendored mode refused them. Such a node is now vendored as a file node without the extra, exactly as vlt writes file: dependencies, with its peer edges moved along; revert restores the original node. Several instances or modifier variants still refuse. Vendoring an optional dependency now prints vendor_vlt_reinstall_required: from vlt 0.0.0-30 a plain vlt install keeps the old installed copy, so users are told to run vlt ci. The same advisory names any dependency whose link still points at vlt's store. Era-A locks with scalar-registry ids now warn vendor_vlt_legacy_lockfile, and the takeover advisory no longer calls kept registry copies hosted artifacts. The byte-stability fixtures now come from real vlt 1.2.0, 1.0.10, 1.0.4, rc.32 and rc.14, checked through vlt ci, warm and cold frozen installs and vlt install <new>, and the vendored capstone gains legs for a single peer context and an optional dependency on a warm tree. Assisted-by: Claude Code:claude-opus-5-5 * Ask for vlt ci after reverting optional vlt deps Reverting a vendored optional vlt dependency left node_modules linked to the removed vendored directory, and from vlt 0.0.0-30 a plain vlt install keeps that dangling link, so the dependency silently vanished. vendor --revert, and the revert a vendored-to-hosted takeover runs, now print vendor_vlt_reinstall_required telling users to run vlt ci; a revert whose importer links still point into the vendored directory says to reinstall too. A vendoring run whose patch fails to apply no longer prints the advisory, since nothing was vendored. The fixture oracle now requires vlt install <new> to keep the vendored node's edges byte-identical on every release except rc.14, and new tests cover the advisory on dry runs, workspace members and both takeover directions. Assisted-by: Claude Code:claude-opus-5-5 * Wait for vlt's background work in vlt tests The first CI run of the vlt suites failed on four real causes: - vlt finishes work in detached children after a command returns (the 1.2.0 global-store explode on Linux, cache unzip, deletion of .VLT.DELETE staging dirs). Legs raced them: the Linux 1.2.0 heal legs saw store entries appear, the Windows hook-abort leg saw a staging dir mid-delete, and the Windows hardlink leg reinstalled before the store was complete. Every harness vlt run now preloads a hook that waits for those children where vlt would exit. - git refuses the \\?\ verbatim leg root on Windows, so the vendored clone legs clone with root-relative paths; the Windows junction unit test passed a '/' path to mklink, which reads it as a switch. - vlt's engines field is not the Node it runs on: 0.0.0-11 ... -30 need 22.7.0 (ESM without "type": "module") and 0.0.0-31 ... rc.18 need 22.13.0 (node:sqlite). install-vlt.sh enforces the measured floors before running vlt and the Node-floor rows test them; those rows no longer install the 1.2.0 upgrade vlt, which cannot run there. - rc.8's scalar-registry vendored arm now configures the local registry, and pins that rc.7 ... rc.29 re-resolve such a lock on vlt ci instead of asserting a byte-stable lock. Assisted-by: Claude Code:claude-opus-5-5 * Retry backtest cells on patch API 5xx errors The vlt and bun backtests rerun a cell from a clean tree when the patch service's transport fails, but only recognized a request error. A 5xx from the production patch API (504 gateway timeouts, 503 upstream resets) is the same external failure, and it failed three native backtest jobs in the last two CI runs. Both harnesses now retry it too; a 4xx still fails the cell at once, and a 5xx that persists still fails after three attempts. Assisted-by: Claude Code:claude-opus-5-5 * Stop vendor hanging on large packages in git Vendoring a package with a few thousand files inside a git work tree (date-fns@2.30.0 has 5722) hung forever. The gitignore probe wrote the whole path list to `git check-ignore -v` before reading its answers, and git answers every path, so once its output pipe filled neither side could move. The probe now reads git's output while it writes the paths, and its 30 second limit covers the whole exchange. Assisted-by: Claude Code:claude-opus-5-5 * Roll back vlt pins that vlt moved or chained Two ledger states left a hosted vlt pin that rollback and remove refused forever, and the refusal's advice (re-run the scan) could not fix either one: - From vlt 1.0.8 a dependency with resolved peers is keyed by its peer context, so bumping its peer (`vlt install react@18.3.1`) re-keys the pinned node and carries the hosted pin to the new id. Rollback now restores the registry pin on every default-registry node of the same package that holds exactly the recorded pin, and heals the patched copy installed under the new id. A rescan that pins such a node again merges into the old ledger edit and keeps its registry entry instead of recording the Socket pin as the original. - The server's hosted PRs append one ledger edit per PR, and a later CLI rescan merged into the oldest one, leaving the newer link stale. The rescan now folds the whole chain into one edit. A real-vlt leg pins a peer-keyed package, bumps its peer, rescans and rolls back on 1.0.8 and later. Assisted-by: Claude Code:claude-opus-5-5 * Don't attest vlt packages also installed by URL A vlt project could install the same package twice: from the registry and from a git, remote-tarball or local-directory dependency (an lp2 alias pointing at left-pad's tarball URL, say). Only the registry copy is patched, yet hosted and vendored runs reported the package as patched, and `vex` attested it as not affected while `require('lp2')` still loaded the unpatched code. - `vex` no longer attests a vlt package from its lock pin or vendored directory when such a node of the same name exists, since vlt records no version for it. A remote tarball whose `<name>-<version>.tgz` leaf names another version does not count. - Hosted mode still pins the registry copy but warns `redirect_vlt_custom_registry_skipped` and keeps the package out of the run's `--vex`. - Vendored mode refuses the package, as it already refuses a copy from another registry. Assisted-by: Claude Code:claude-opus-5-5 * Warn when a vlt re-vendor strands node_modules Vendoring a new patch over an installed, already vendored vlt package removes the old patch's directory, but node_modules still linked into it, so `require()` failed until the next `vlt install`. The run reported success with no advisory. It now emits `vendor_vlt_reinstall_required` naming the links into the replaced directory and asking for `vlt install` (or `vlt ci`). Assisted-by: Claude Code:claude-opus-5-5 * Keep vlt's dependency links through repair `repair` moved a corrupt vlt payload aside, rebuilt it, then deleted the old copy, and vlt's links to the package's own dependencies went with it: `require('debug')` failed with "Cannot find module 'ms'" while repair reported success with no warning. Repair now moves those links back into the rebuilt payload when they are only links. When a rebuild cannot keep them (the old `node_modules/` held planted files), vendor and repair emit `vendor_vlt_reinstall_required` asking for `vlt ci`. The old hint said `vlt install`, which does not re-link them on any tested vlt release. The contract and coverage map also document the advisory for links into the directory a re-vendor replaces. Assisted-by: Claude Code:claude-opus-5-5 * Give repair a vlt remedy that works After `.socket/vendor/state.json` is lost in a vendored vlt project, repair restores the entry without a file fingerprint and told the user to run `socket-patch vendor` to record one. That run always refused: the rewired lock no longer holds a registry resolution and the only installed copy is the vendored dir. For vlt entries the advice now reads: restore the registry version spec in package.json, run `vlt install`, then run `socket-patch vendor`, which re-vendors the package and records the fingerprint (checked with vlt 1.2.0). Assisted-by: Claude Code:claude-opus-5-5 * Point vlt at vlt update for patched manifests When a vendored vlt patch changes package.json dependencies, `vendor_dep_manifest_stale` said `vlt install` would re-resolve them. It never does: vlt installs the vendored node's recorded edges, so a dependency the patch adds stayed uninstalled through `vlt install` and `vlt ci`. The advisory now names `vlt update`, the command that re-resolves them, and says it resolves the whole project. After such an update, `vendor --revert` left the edges vlt had added from the vendored node in the lock, pointing from a node that no longer existed. Revert now drops them, along with nodes only those edges kept, so the reverted lock matches the pre-vendor one and stays byte-stable through `vlt ci` (checked with vlt 1.2.0). Assisted-by: Claude Code:claude-opus-5-5 * Refuse to vendor vlt packages that vlt builds vlt builds a registry copy in the untracked `node_modules/.vlt` store but a `file:` dependency in place. After vendoring a package with an install script (esbuild's postinstall, a node-gyp addon) the `vlt build` that vlt asks for rewrote the committed payload: esbuild's 9 KB JS shim became a 9.7 MB Mach-O binary staged for commit, every later `vendor` failed on the inventory, and `repair` restored the shim only until the next build. Vendored mode now refuses a package that declares a `preinstall`, `install`, `postinstall` or `prepare` script or ships a `binding.gyp` (`vendor_vlt_build_scripts_unsupported`, remedy `--mode hosted`), in the preflight and on every build of the payload. Assisted-by: Claude Code:claude-opus-5-5 * Withhold vlt pins a vlt release may discard Standalone `socket-patch vex` attested a hosted vlt pin from the lock alone even when some vlt release ignores that lock and installs the registry package instead: a lock with no lockfileVersion (vlt >= rc.15 re-resolves it), a pre-v1 legacy-id lock without vlt.json "modifiers", or a scalar registry the lock cannot use. In-run `scan --vex` already withheld those deps, so the two disagreed. Discovery now runs the hosted rewriter's own lock-level conditions (one shared predicate, reading vlt.json for "modifiers"). In such a lock every hosted reference keeps no lock pin, so only an installed tree whose copies verify attests it, and one patched_ref_unattributable warning names the packages and why. Assisted-by: Claude Code:claude-opus-5-5 * Name the measured vlt reinstall windows The vendor_vlt_legacy_lockfile warning told every era-A vlt user that a vendored lock cannot be deleted and re-created, but only vlt 0.0.0-31 through 1.0.0-rc.5 fail that way; 0.0.0-19 through 0.0.0-30 and rc.6 through rc.8 reinstall the vendored directory fine. The optional dependency advisories likewise blamed every release before 1.0.5, although vlt 0.0.0-23 and older install such a project from its lock. The warning, the advisories, CLI_CONTRACT.md, docs/ecosystems.md and the changelog now name the measured windows (0.0.0-31 ... 1.0.0-rc.5 and 0.0.0-30 ... 1.0.4), matching the compatibility boundary table. Assisted-by: Claude Code:claude-opus-5-5 * Correct the vlt hosted confirmation contract CLI_CONTRACT.md said a dep refused by the vlt rewriter is refused for every lock only while vlt drives, and elsewhere that all four per-dep vlt codes leave a dep unconfirmed whichever lock drives. Neither matched the code: a dep the rewriter refuses (missing sha512, unsupported lock key) is never confirmed, even when package-lock.json already carries its hosted URL, while a dep vlt-lock.json merely lacks (entry not found or vendored) is confirmed by a sibling lock when vlt does not drive. Both passages now state that rule, and two in-process tests pin it. Assisted-by: Claude Code:claude-opus-5-5 * Check frozen installs in the vlt scalar legacy leg On vlt rc.7 and rc.8, the vendored era-A scalar-registry leg skipped the frozen-install half of its fresh-checkout check and hard-asserted that vlt ci re-keys the bystander package from public npm, a vlt quirk unrelated to socket-patch that was measured on rc.8 only. The leg now asserts that the vendored node and payload survive vlt ci, then clears node_modules and requires a frozen install to land the patch again without changing the lock vlt ci wrote. The bystander re-key is only logged. Measured on rc.7 and rc.8 (both re-key it to a `··` id); the boundary table row says so. Assisted-by: Claude Code:claude-opus-5-5 * Log when the vlt settle hook stops waiting The test harness hook that waits for vlt's detached children dropped a child silently after 120 s, so a leg that then saw a half-finished tree failed with no hint of why. The hook now writes a `vlt-settle:` line to stderr naming the child it stopped waiting for. The cap can be set with SOCKET_PATCH_VLT_SETTLE_CAP_MS, which a new test uses to check the line and that a quick child is still awaited silently. Assisted-by: Claude Code:claude-opus-5-5 * Expect withheld vlt pins in the capture VEX test The capture VEX test still expected every hosted pin of every captured lock to be attested, but discovery now withholds the pins of a lock some vlt release discards (the 0.0.0-1 and 0.0.0-16 captures have no lockfileVersion). It now copies each capture's vlt.json beside the lock and expects those locks to keep their refs unpinned with one patched_ref_unattributable warning. Assisted-by: Claude Code:claude-opus-5-5 * Harden vlt reads, redact grant tokens, fix heal A FIFO or device at vlt-lock.json could block `rollback` forever: it read the lock with a plain read before any revert. `repair`'s wiring snapshot, the vendored takeover and `setup`'s vlt member check did the same. All of them now use the FIFO-safe regular-file reader. New tests cover the rollback and the repair snapshot. The `redirect_vlt_artifact_unverifiable` detail quoted the full hosted artifact URL, including the org's grant token, on stderr and in --json. The token level (the path segment before the patch uuid) is now spelled `<redacted>`; host, uuid and leaf stay. The production e2e gets the URL to probe from the public reference endpoint instead of parsing it out of the warning. After an unscoped hosted rollback, removing the stale vlt store copies waited for every replay group to succeed. Now it follows the vlt group alone, so a drifted package-lock.json no longer leaves copies behind that the restored vlt-lock.json no longer names. Smaller fixes: - The artifact preflight moves verified bodies instead of copying them, so each body is held once. - A git failure during the vendored ignore check now warns `vendor_artifact_gitignore_unchecked` instead of passing silently. - Two test messages no longer print patch uuids (CodeQL cleartext-logging). Assisted-by: Claude Code:claude-opus-5-5
1 parent 0b4e645 commit b32711f

900 files changed

Lines changed: 85727 additions & 638 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.gitattributes‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ crates/socket-patch-core/tests/fixtures/pdm-native/*.lock -text
1111
# derive their CRLF variants from the LF bytes themselves.
1212
crates/socket-patch-core/tests/fixtures/pnpm-hosted/** -text
1313

14+
# Captured vlt locks are byte-real; CRLF variants are derived in the tests.
15+
crates/socket-patch-core/tests/fixtures/vlt-locks/** -text
16+
17+
# The vendored vlt fixtures pin locks real vlt wrote, byte for byte.
18+
crates/socket-patch-core/tests/fixtures/vendor/** -text
19+
1420
# The legacy vendor ledgers are what the base binary wrote, byte for byte:
1521
# vendor_ledger_schema_e2e replays them through `vendor --revert` and
1622
# compares the result byte for byte, so a CRLF checkout would change both

‎.github/workflows/ci.yml‎

Lines changed: 153 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,7 @@ jobs:
580580
nuget) EXTRA="--test docker_e2e_vendor_nuget" ;;
581581
pypi) EXTRA="--test docker_e2e_vendor_pypi_pm" ;;
582582
esac
583+
# shellcheck disable=SC2086 # EXTRA is intentionally word-split
583584
cargo llvm-cov \
584585
--features docker-e2e \
585586
--no-report \
@@ -922,6 +923,55 @@ jobs:
922923
- {os: ubuntu-latest, suite: mode_migration_bun, bun: '1.2.23', test_filter: --include-ignored}
923924
- {os: ubuntu-latest, suite: e2e_bun_lockb, bun: '1.0.36', test_filter: --include-ignored}
924925
- {os: ubuntu-latest, suite: e2e_bun_lockb, bun: '1.1.45', test_filter: --include-ignored}
926+
# Real-vlt capstones (DESIGN §8.4): wiremock patch service and a local
927+
# npm registry fed from npmjs, driven by the pinned vlt release
928+
# (`node vlt.js`, installed below from a sha512-checked `npm pack`).
929+
# Every test is `#[ignore]`d and named `vlt_pinned_matrix_*`, so the
930+
# filter must be `--include-ignored vlt_pinned_matrix` (the job
931+
# default `--ignored` selects nothing). The run pipes through
932+
# scripts/check-vlt-legs.py, which fails on `0 passed` or any leg
933+
# line the manifest does not predict. The eras: A0 0.0.0-16, A
934+
# 0.0.0-32, B rc.12/rc.14 (rc.14 legs reach public npm), C rc.32,
935+
# D 1.0.4/1.0.7, E 1.1.1, F 1.2.0.
936+
- {os: ubuntu-latest, suite: e2e_redirect_vlt_build, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
937+
- {os: macos-latest, suite: e2e_redirect_vlt_build, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
938+
- {os: windows-latest, suite: e2e_redirect_vlt_build, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
939+
- {os: ubuntu-latest, suite: e2e_redirect_vlt_build, vlt: '0.0.0-16', test_filter: --include-ignored vlt_pinned_matrix}
940+
- {os: ubuntu-latest, suite: e2e_redirect_vlt_build, vlt: '0.0.0-32', test_filter: --include-ignored vlt_pinned_matrix}
941+
- {os: ubuntu-latest, suite: e2e_redirect_vlt_build, vlt: '1.0.0-rc.14', test_filter: --include-ignored vlt_pinned_matrix}
942+
- {os: ubuntu-latest, suite: e2e_redirect_vlt_build, vlt: '1.0.0-rc.32', test_filter: --include-ignored vlt_pinned_matrix}
943+
- {os: ubuntu-latest, suite: e2e_redirect_vlt_build, vlt: '1.0.4', test_filter: --include-ignored vlt_pinned_matrix}
944+
- {os: ubuntu-latest, suite: e2e_redirect_vlt_build, vlt: '1.1.1', test_filter: --include-ignored vlt_pinned_matrix}
945+
- {os: ubuntu-latest, suite: e2e_vendor_vlt_build, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
946+
- {os: macos-latest, suite: e2e_vendor_vlt_build, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
947+
- {os: windows-latest, suite: e2e_vendor_vlt_build, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
948+
- {os: ubuntu-latest, suite: e2e_vendor_vlt_build, vlt: '0.0.0-32', test_filter: --include-ignored vlt_pinned_matrix}
949+
- {os: ubuntu-latest, suite: e2e_vendor_vlt_build, vlt: '1.0.0-rc.14', test_filter: --include-ignored vlt_pinned_matrix}
950+
- {os: ubuntu-latest, suite: e2e_vendor_vlt_build, vlt: '1.0.0-rc.32', test_filter: --include-ignored vlt_pinned_matrix}
951+
- {os: ubuntu-latest, suite: e2e_vendor_vlt_build, vlt: '1.0.4', test_filter: --include-ignored vlt_pinned_matrix}
952+
- {os: windows-latest, suite: e2e_vendor_vlt_build, vlt: '1.0.0-rc.14', test_filter: --include-ignored vlt_pinned_matrix}
953+
- {os: ubuntu-latest, suite: mode_migration_vlt, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
954+
- {os: macos-latest, suite: mode_migration_vlt, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
955+
- {os: windows-latest, suite: mode_migration_vlt, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
956+
- {os: ubuntu-latest, suite: mode_migration_vlt, vlt: '0.0.0-32', test_filter: --include-ignored vlt_pinned_matrix}
957+
- {os: ubuntu-latest, suite: mode_migration_vlt, vlt: '1.0.0-rc.14', test_filter: --include-ignored vlt_pinned_matrix, vlt_upgrade: '1.2.0'}
958+
- {os: windows-latest, suite: mode_migration_vlt, vlt: '1.0.0-rc.14', test_filter: --include-ignored vlt_pinned_matrix}
959+
# Linux `auto` hardlinks from the global store; every OS gets the
960+
# explicit hardlink linker.
961+
- {os: ubuntu-latest, suite: e2e_safety_vlt, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
962+
- {os: ubuntu-latest, suite: e2e_safety_vlt, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix, vlt_store_linker: 'hardlink'}
963+
- {os: macos-latest, suite: e2e_safety_vlt, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix, vlt_store_linker: 'hardlink'}
964+
- {os: windows-latest, suite: e2e_safety_vlt, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix, vlt_store_linker: 'hardlink'}
965+
# rc.12 gets the definite no-hook advisory; windows rc.14 runs the
966+
# legacy DepIDs on NTFS with pre-junction symlinks.
967+
- {os: ubuntu-latest, suite: e2e_vlt, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
968+
- {os: macos-latest, suite: e2e_vlt, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
969+
- {os: windows-latest, suite: e2e_vlt, vlt: '1.2.0', test_filter: --include-ignored vlt_pinned_matrix}
970+
- {os: ubuntu-latest, suite: e2e_vlt, vlt: '0.0.0-32', test_filter: --include-ignored vlt_pinned_matrix}
971+
- {os: ubuntu-latest, suite: e2e_vlt, vlt: '1.0.0-rc.12', test_filter: --include-ignored vlt_pinned_matrix}
972+
- {os: ubuntu-latest, suite: e2e_vlt, vlt: '1.0.0-rc.32', test_filter: --include-ignored vlt_pinned_matrix}
973+
- {os: ubuntu-latest, suite: e2e_vlt, vlt: '1.0.7', test_filter: --include-ignored vlt_pinned_matrix}
974+
- {os: windows-latest, suite: e2e_vlt, vlt: '1.0.0-rc.14', test_filter: --include-ignored vlt_pinned_matrix}
925975
# The named corepack pnpm hosted legs (pnpm 7-11, get-uuid,
926976
# zero-touch, --trust-lockfile). `#[ignore]`d and previously run in
927977
# no job; the pinned matrix inside the same suite runs in
@@ -1067,8 +1117,9 @@ jobs:
10671117
# same-OS legs wins the cache reserve and the rest fail to save.
10681118
# Several suites run one leg per pinned toolchain release (bun, uv,
10691119
# poetry, pdm, hatch, pipenv, pip, bundler, composer, maven, dotnet,
1070-
# deno), so the release is part of the key too.
1071-
key: ${{ matrix.suite }}-${{ matrix.bun || matrix.uv || matrix.poetry || matrix.pdm || matrix.hatch || matrix.pipenv || matrix.pip || matrix.bundler || matrix.composer || matrix.maven || matrix.dotnet || matrix.deno || 'default' }}
1120+
# deno, vlt), so the release is part of the key too, plus the vlt
1121+
# store linker of the two ubuntu e2e_safety_vlt legs.
1122+
key: ${{ matrix.suite }}-${{ matrix.vlt || matrix.bun || matrix.uv || matrix.poetry || matrix.pdm || matrix.hatch || matrix.pipenv || matrix.pip || matrix.bundler || matrix.composer || matrix.maven || matrix.dotnet || matrix.deno || 'default' }}${{ matrix.vlt_store_linker && format('-{0}', matrix.vlt_store_linker) || '' }}
10721123
save-if: ${{ github.ref == 'refs/heads/main' }}
10731124

10741125
- name: Setup Node.js
@@ -1242,7 +1293,45 @@ jobs:
12421293
with:
12431294
bun-version: ${{ matrix.bun }}
12441295

1296+
- name: Setup Node.js 24 (vlt legs)
1297+
if: matrix.vlt != ''
1298+
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
1299+
with:
1300+
node-version: '24.21.0'
1301+
1302+
- name: Setup vlt
1303+
if: matrix.vlt != ''
1304+
# The pinned release (and, for the upgrade legs, the second vlt):
1305+
# `npm pack`, sha512 against the registry and the committed pin, then
1306+
# a prefix install run as `node vlt.js`. The store-linker knob is a
1307+
# harness variable because the harness scrubs ambient VLT_*.
1308+
shell: bash
1309+
env:
1310+
VLT_TEST_VERSION: ${{ matrix.vlt }}
1311+
VLT_TEST_UPGRADE: ${{ matrix.vlt_upgrade }}
1312+
VLT_TEST_STORE_LINKER: ${{ matrix.vlt_store_linker }}
1313+
run: |
1314+
set -euo pipefail
1315+
js=$(scripts/install-vlt.sh "$VLT_TEST_VERSION" "$RUNNER_TEMP/vlt-tool")
1316+
{
1317+
echo "SOCKET_PATCH_VLT_E2E_JS=$js"
1318+
echo "SOCKET_PATCH_VLT_E2E_VERSION=$VLT_TEST_VERSION"
1319+
echo "SOCKET_PATCH_VLT_E2E_REQUIRED=1"
1320+
echo "LANG=C"
1321+
echo "LC_ALL=C"
1322+
} >> "$GITHUB_ENV"
1323+
if [ -n "$VLT_TEST_STORE_LINKER" ]; then
1324+
echo "SOCKET_PATCH_VLT_E2E_STORE_LINKER=$VLT_TEST_STORE_LINKER" >> "$GITHUB_ENV"
1325+
fi
1326+
if [ -n "$VLT_TEST_UPGRADE" ]; then
1327+
up=$(scripts/install-vlt.sh "$VLT_TEST_UPGRADE" "$RUNNER_TEMP/vlt-upgrade")
1328+
echo "SOCKET_PATCH_VLT_E2E_UPGRADE_JS=$up" >> "$GITHUB_ENV"
1329+
echo "SOCKET_PATCH_VLT_E2E_UPGRADE_VERSION=$VLT_TEST_UPGRADE" >> "$GITHUB_ENV"
1330+
fi
1331+
node --version
1332+
12451333
- name: Run e2e tests
1334+
if: matrix.vlt == ''
12461335
# Suites are `#[ignore]`-gated out of the unpinned `test` job by
12471336
# default, hence `--ignored`; an entry that sets `test_filter`
12481337
# overrides the selector for itself only.
@@ -1289,6 +1378,25 @@ jobs:
12891378
SOCKET_PATCH_DENO_E2E_VERSION: ${{ matrix.deno }}
12901379
run: cargo test -p socket-patch-cli --all-features --test ${{ matrix.suite }} -- ${{ matrix.test_filter || '--ignored' }}
12911380

1381+
- name: Run vlt e2e tests
1382+
if: matrix.vlt != ''
1383+
# One capstone binary per row, through the leg checker: it fails on
1384+
# `0 passed`, a crashed binary, a missing `ran`, an unexpected skip or
1385+
# an unknown leg (crates/socket-patch-cli/tests/vlt-leg-manifest.json).
1386+
shell: bash
1387+
env:
1388+
SOCKET_PATCH_VLT_E2E_REQUIRED: ${{ matrix.vlt != '' && '1' || '' }}
1389+
VLT_SUITE: ${{ matrix.suite }}
1390+
VLT_TEST_FILTER: ${{ matrix.test_filter }}
1391+
run: |
1392+
set -uo pipefail
1393+
status=0
1394+
# shellcheck disable=SC2086 # the filter is several libtest arguments
1395+
cargo test -p socket-patch-cli --all-features --test "$VLT_SUITE" -- $VLT_TEST_FILTER 2>&1 | tee vlt-leg.log || status=1
1396+
py=$(command -v python3 || command -v python)
1397+
"$py" scripts/check-vlt-legs.py --manifest crates/socket-patch-cli/tests/vlt-leg-manifest.json vlt-leg.log || status=1
1398+
exit "$status"
1399+
12921400
# ----------------------------------------------------------------------
12931401
# Docker-driven real-package e2e suite.
12941402
#
@@ -1726,10 +1834,19 @@ jobs:
17261834
corepack prepare yarn@1.22.22 --activate
17271835
corepack prepare yarn@4.6.0 --activate
17281836
npm install -g bun@1
1837+
# vlt: the same sha512-checked pack-and-install as the e2e rows.
1838+
js=$(scripts/install-vlt.sh 1.2.0 "$RUNNER_TEMP/vlt-tool")
1839+
{
1840+
echo "SOCKET_PATCH_VLT_E2E_JS=$js"
1841+
echo "SOCKET_PATCH_VLT_E2E_VERSION=1.2.0"
1842+
echo "SOCKET_PATCH_VLT_E2E_REQUIRED=1"
1843+
echo "SOCKET_PATCH_HOSTED_E2E_STRICT=1"
1844+
} >> "$GITHUB_ENV"
17291845
node --version
17301846
npm --version
17311847
pnpm --version
17321848
bun --version
1849+
node --no-warnings "$js" --version
17331850
17341851
- name: Setup Python + uv
17351852
if: steps.gate.outputs.run == 'true'
@@ -1773,18 +1890,48 @@ jobs:
17731890
# suites were pulled from the PR matrix (see the `e2e` job). Retry the
17741891
# whole suite a couple of times before calling it a real failure, so a
17751892
# transient 503 does not block merges through a required check.
1893+
set -o pipefail
17761894
for attempt in 1 2 3; do
17771895
echo "::group::hosted-e2e attempt $attempt"
1896+
# The step shell runs with -e: keep a failed attempt from ending it.
1897+
status=0
17781898
cargo test -p socket-patch-cli --test e2e_hosted_production -- \
1779-
--ignored --nocapture --test-threads=4
1780-
status=$?
1899+
--ignored --nocapture --test-threads=4 2>&1 | tee hosted-e2e.log || status=$?
17811900
echo "::endgroup::"
17821901
if [ "$status" -eq 0 ]; then
1783-
exit 0
1902+
# The vlt leg (probe-driven: the clean refusal while the artifact
1903+
# is content-encoded, the full install proof once it is not).
1904+
python3 scripts/check-vlt-legs.py \
1905+
--manifest crates/socket-patch-cli/tests/vlt-leg-manifest.json hosted-e2e.log
1906+
exit $?
17841907
fi
17851908
echo "::warning title=hosted-e2e attempt $attempt failed::retrying"
17861909
sleep $((attempt * 20))
17871910
done
17881911
echo "::error title=hosted-e2e::suite failed on all 3 attempts"
17891912
exit 1
1790-
if-no-files-found: warn
1913+
1914+
- name: Run vendored-mode production e2e (vlt)
1915+
if: steps.gate.outputs.run == 'true'
1916+
# The vendored vlt install proof against production: the service's
1917+
# directory artifact in the D19 layout, then a fresh `vlt ci`.
1918+
env:
1919+
SOCKET_PATCH_VENDORED_E2E_STRICT: '1'
1920+
run: |
1921+
set -uo pipefail
1922+
for attempt in 1 2 3; do
1923+
echo "::group::vendored vlt production attempt $attempt"
1924+
status=0
1925+
cargo test -p socket-patch-cli --test e2e_vendored_production -- \
1926+
--include-ignored vlt_pinned_matrix --nocapture 2>&1 | tee vlt-vendored-production.log || status=$?
1927+
echo "::endgroup::"
1928+
if [ "$status" -eq 0 ]; then
1929+
python3 scripts/check-vlt-legs.py \
1930+
--manifest crates/socket-patch-cli/tests/vlt-leg-manifest.json vlt-vendored-production.log
1931+
exit $?
1932+
fi
1933+
echo "::warning title=vendored vlt production attempt $attempt failed::retrying"
1934+
sleep $((attempt * 20))
1935+
done
1936+
echo "::error title=hosted-e2e::the vendored vlt production proof failed on all 3 attempts"
1937+
exit 1

0 commit comments

Comments
 (0)