Skip to content

Commit bdb826f

Browse files
committed
docs(v5): consolidate guides and remove stale research
1 parent 31c0ae4 commit bdb826f

56 files changed

Lines changed: 1067 additions & 146469 deletions

Some content is hidden

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

‎CHANGELOG.md‎

Lines changed: 113 additions & 2191 deletions
Large diffs are not rendered by default.

‎README.md‎

Lines changed: 97 additions & 1509 deletions
Large diffs are not rendered by default.

‎crates/socket-patch-cli/CLI_CONTRACT.md‎

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
# socket-patch CLI contract
22

3-
This document defines the **public surface** of the `socket-patch` binary. Anything listed here is part of the user-visible contract: third-party scripts, CI pipelines, and the npm/pypi/cargo wrappers depend on it. Changes are governed by the semver policy at the bottom of this file.
3+
This document defines the **public surface** of the `socket-patch` binary. Third-party scripts, CI pipelines, and the npm distribution depend on this contract. Changes are governed by the semver policy at the bottom of this file.
44

55
> **Why this exists.** A flag rename, a default-value change, or a JSON key rename can land green and break every shipped wrapper silently. The contract below is backed by the unit tests under `crates/socket-patch-cli/src/**` (`#[cfg(test)] mod tests`) and the parser tests under `crates/socket-patch-cli/tests/cli_parse_*.rs`. Changes that violate the contract must update those tests in lock-step with a major version bump.
66
7+
For task-oriented guidance, start with [usage](../../docs/usage.md),
8+
[configuration](../../docs/configuration.md), or [v5 migration](../../docs/migrating-to-v5.md).
9+
10+
**Reference:** [Commands](#subcommands) · [Arguments](#global-arguments) ·
11+
[Policy](#socketyml-patch-policy-v50) · [VEX](#manifest-less-vex-lockfile-discovery) ·
12+
[Vendoring](#vendor-command-contract) · [Rollback](#rollback-command-contract-v50) ·
13+
[Environment](#environment-variables) · [JSON](#json-output-shapes) · [Exit codes](#exit-codes)
14+
715
## Subcommands
816

917
| Name | Visible alias(es) | Notes |
@@ -12,11 +20,11 @@ This document defines the **public surface** of the `socket-patch` binary. Anyth
1220
| `vex` | — | Emit an OpenVEX 0.2.0 attestation derived from the local manifest, the vendor ledger, and the hosted / vendored patch references the project's lockfiles wire (no manifest required; hosted records come from the API) |
1321
| `vendor` | — | Eject patched dependencies into committable `.socket/vendor/` and rewire lockfiles |
1422
| `list` | — | Print patches in the local manifest, plus the vendor ledger's records (v5.0) and the hosted pins the lockfiles wire (labeled; see the action matrix; an empty project exits 0) |
15-
| `get` | `download` | Agent mode by default (`--mode` selects hosted/vendored): fetch + apply a patch; requires positional `identifier` |
23+
| `get` | `download` | Fetch a selected patch in hosted mode by default; `--mode agent` selects in-place application, also the default with `--save-only` or global targeting. Requires positional `identifier`. |
1624
| `apply` | — | Agent mode: apply patches from the local manifest |
1725
| `rollback` | — | **Full-state rollback (v5.0, MAJOR)**: restore original files AND unwind vendored lockfile wiring / restore hosted pins to their upstream registry entries, remove the rolled-back entries from the manifest, and GC their blobs/archives; takes optional variadic positional `targets` (PURL \| UUID \| path glob). See [Rollback command contract](#rollback-command-contract-v50) |
18-
| `remove` | — | Agent mode: remove a patch from manifest (rolls back first); requires positional `identifier` |
19-
| `repair` | `gc` | Agent mode: download missing blobs, re-vendor missing/corrupt vendored artifacts (never re-synthesizing a lost ledger), and clean up unused ones (refuses with `lock_held` when a live process holds the lock; see "Lock lifecycle" below) |
26+
| `remove` | — | Restore and remove one patch across hosted, vendored, and agent state; requires positional `identifier`. |
27+
| `repair` | `gc` | Download missing agent blobs, re-vendor missing/corrupt vendored artifacts (never re-synthesizing a lost ledger), and clean up unused ones (refuses with `lock_held` when a live process holds the lock; see "Lock lifecycle" below) |
2028

2129
Rows are in `--help` order (v5.0): the hosted/vendored workflow (`scan` → `vex` → `vendor`, with `list` to inspect), then the agent-mode (in-place patching) commands.
2230

@@ -34,7 +42,7 @@ Rows are in `--help` order (v5.0): the hosted/vendored workflow (`scan` → `vex
3442

3543
## Global arguments
3644

37-
In v3.0 every subcommand accepts the same set of "global" flags via a single shared `GlobalArgs` struct that's `#[command(flatten)]`-ed into each per-command struct (`crates/socket-patch-cli/src/args.rs`). Subcommands that don't actually consume a given flag accept it silently — e.g. `list --global` parses fine and is a no-op. Every flag also has an environment-variable binding; precedence is **CLI arg > env var > default** — and for exactly three keys (`--api-token`, `--org`, `--api-url`) the JS socket-cli's persisted login sits between env var and default: **CLI arg > env var (canonical, then `SOCKET_CLI_*` alias) > socket-cli `config.json` > default**. See "Persisted configuration" under Environment variables.
45+
Every subcommand accepts the same set of "global" flags via a single shared `GlobalArgs` struct that's `#[command(flatten)]`-ed into each per-command struct (`crates/socket-patch-cli/src/args.rs`). Subcommands that don't actually consume a given flag accept it silently — e.g. `list --global` parses fine and is a no-op. Every flag also has an environment-variable binding; precedence is **CLI arg > env var > default** — and for exactly three keys (`--api-token`, `--org`, `--api-url`) the JS socket-cli's persisted login sits between env var and default: **CLI arg > env var (canonical, then `SOCKET_CLI_*` alias) > socket-cli `config.json` > default**. See "Persisted configuration" under Environment variables.
3846

3947
| Long | Short | Env var | Default | Type | Semantic |
4048
|---|---|---|---|---|---|
@@ -180,7 +188,7 @@ The hidden alias `--no-apply` on `get --save-only` is **part of the contract**
180188

181189
### socket.yml patch policy (v5.0)
182190

183-
A repository can **narrow** what `scan` patches with a `patches` block in its root `socket.yml` (the Socket scanner's config file; `version: 2` keeps every other consumer working — they strip or ignore the block). Design record: `docs/design/staged-rollout.md`.
191+
A repository can **narrow** what `scan` patches with a `patches` block in its root `socket.yml` (the Socket scanner's config file; `version: 2` keeps every other consumer working — they strip or ignore the block). Usage guide: [repository patch policy](../../docs/configuration.md#repository-patch-policy).
184192

185193
**Grammar.** Every key is optional; camelCase, like the rest of socket.yml.
186194

@@ -261,9 +269,9 @@ patches:
261269

262270
### Per-run limit on new patches (`scan --max-new-patches`, v5.0)
263271

264-
`scan --max-new-patches <N|none>` (env `SOCKET_MAX_NEW_PATCHES`; socket.yml `patches.maxNewPatches`) paces a rollout: each run adds at most N patches to packages that had none, the most critical first, and defers the rest to the next run. It applies to `scan` in hosted, vendored and agent mode, wet and `--dry-run`, and to the in-memory engine (napi `maxNewPatches`, `hosted-bundle`); `get` is explicit intent and ignores it. Design: `docs/design/staged-rollout.md` §5.
272+
`scan --max-new-patches <N|none>` (env `SOCKET_MAX_NEW_PATCHES`; socket.yml `patches.maxNewPatches`) paces a rollout: each run adds at most N patches to packages that had none, the most critical first, and defers the rest to the next run. It applies to `scan` in hosted, vendored and agent mode, wet and `--dry-run`, and to the in-memory engine (napi `maxNewPatches`, `hosted-bundle`); `get` is explicit intent and ignores it. Usage guide: [gradual rollout](../../docs/configuration.md#gradual-rollout).
265273

266-
**Classification.** After per-package selection, each selected `(project, purl)` row is compared with the project's **recorded view** — the merged manifest > hosted lockfile pins > vendor ledger that `updates[]` reads (§5.1):
274+
**Classification.** After per-package selection, each selected `(project, purl)` row is compared with the project's **recorded view** — the merged manifest > hosted lockfile pins > vendor ledger that `updates[]` reads:
267275

268276
| Class | Rule | Capped | The writer gets |
269277
|---|---|---|---|
@@ -422,7 +430,7 @@ hand (the `postinstall`/`dependencies` entries, the `socket-patch[hook]` depende
422430
`socket-patch-bundler` gem are no longer published.
423431

424432
Prefer hosted or vendored mode: their lockfile (and `.socket/vendor/`) edits are the persistence, so
425-
no install step exists. Agent mode (`scan --mode agent`, `get`, `apply`) patches the installed tree
433+
no Socket Patch install hook is needed. Agent mode (`scan --mode agent`, `get --mode agent`, `apply`) patches the installed tree
426434
in place, which the next package-manager install reverts; wire it into CI yourself:
427435

428436
```sh
@@ -1023,7 +1031,7 @@ State lives at `$XDG_CACHE_HOME`|`~/.cache` (Unix/macOS) or `%LOCALAPPDATA%` (Wi
10231031

10241032
## Environment variables
10251033

1026-
All v3.0 env vars use the `SOCKET_*` prefix. Three legacy `SOCKET_PATCH_*` names are still honored at runtime for compatibility: on first read of any of the three the binary emits a one-shot deprecation warning to stderr (the warning fires unconditionally — even under `--silent` / `--json` — because it's a transition signal users need to see). The legacy names will be removed in a future major release.
1034+
Public configuration uses the `SOCKET_*` names below. The three deprecated v3/v4 environment aliases were removed in v5; see [Removed env vars](#removed-env-vars).
10271035

10281036
Four `SOCKET_CLI_*` names from the sibling JS Socket CLI are additionally accepted as **peer aliases** (supported, not deprecated — no warning): `SOCKET_CLI_API_TOKEN` → `SOCKET_API_TOKEN`, `SOCKET_CLI_ORG_SLUG` → `SOCKET_ORG_SLUG`, `SOCKET_CLI_API_BASE_URL` → `SOCKET_API_URL`, `SOCKET_CLI_NO_API_TOKEN` → `SOCKET_NO_API_TOKEN`. The canonical `SOCKET_*` name always wins when both are set; promotion is silent and happens in-process before clap parses. Other socket-cli names (`SOCKET_CLI_CONFIG`, `SOCKET_CLI_API_PROXY`, `SOCKET_CLI_DEBUG`) are deliberately **not** honored.
10291037

@@ -1058,7 +1066,7 @@ Empty string means unset at every layer: exported-but-empty flag-bound vars are
10581066
| `SOCKET_NO_NPM_ALLOW_REMOTE_CONFIG` | `--no-npm-allow-remote-config` | `false` | Hosted mode: skip the `allow-remote=all` write to the project `.npmrc`. |
10591067
| `SOCKET_NO_VLT_INSTALL_CLEANUP` | `--no-vlt-install-cleanup` | `false` | Hosted mode, `rollback`, `remove`: keep stale vlt installed copies. |
10601068
| `SOCKET_FORCE` | `apply --force` / `-f`, `vendor --force` / `-f`, `--update --force` | `false` | Local to `apply`, `vendor` and `--update`. |
1061-
| `SOCKET_PATCH_VERSION` | `--update <VERSION>` | (latest) | Local to `--update`; the same pin `install.sh` and the gem launcher honor. |
1069+
| `SOCKET_PATCH_VERSION` | `--update <VERSION>` | (latest) | Local to `--update`; the same pin `install.sh` honors. |
10621070
| `SOCKET_BATCH_SIZE` | `scan --batch-size` | `500` authenticated / `100` proxy | Local to `scan`. |
10631071
| `SOCKET_MAX_NEW_PATCHES` | `scan --max-new-patches` | (unlimited) | Local to `scan` (v5.0): a count or `none`; empty is unset, malformed exits 2. |
10641072
| `SOCKET_SCAN_PACKAGES` | `scan --package` | (none) | Local to `scan` (v5.0); comma-separated names or purls. |

‎crates/socket-patch-cli/src/commands/scan/rollout.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//! Scan's side of the rollout stage (`docs/design/staged-rollout.md` §5,
2-
//! §9.2): `updates[]`, the hosted gate and the human lines. The stage
1+
//! Scan's side of the rollout stage (`docs/configuration.md#gradual-rollout`):
2+
//! `updates[]`, the hosted gate and the human lines. The stage
33
//! itself is [`socket_patch_core::rollout::stage`].
44
55
use std::collections::{BTreeMap, BTreeSet, HashSet};

‎crates/socket-patch-cli/src/commands/scan/rollout_args.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//! `scan --max-new-patches` (work item B of the staged-rollout design,
2-
//! `docs/design/staged-rollout.md` §5).
1+
//! `scan --max-new-patches` (see the rollout guide,
2+
//! `docs/configuration.md#gradual-rollout`).
33
44

55
use clap::Args;

‎crates/socket-patch-cli/tests/e2e_golang_hosted_build.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//! machinery still has teeth against a tampered pin.
77
//!
88
//! The three properties this pins (each validated empirically before the
9-
//! feature was built — see `docs/design/golang-hosted.md`):
9+
//! feature was built — see `docs/ecosystems.md#go-directory-replaces-and-gosum`):
1010
//!
1111
//! 1. **No sumdb consultation**: `GOSUMDB` is set to a bogus database name
1212
//! for every day-2 command. go parses `GOSUMDB` lazily and consults it only

‎crates/socket-patch-cli/tests/e2e_hosted_production.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
//! cargo tier emptied on 2026-08-28, so the leg was demoted to the canary
5252
//! (`docs/testing/hosted-production-e2e.md` says how to re-promote it).
5353
//! * **golang** — hosted mode is supported for free-tier references carrying
54-
//! a `goproxy` override (`docs/design/golang-hosted.md`), but production
54+
//! a `goproxy` override (`docs/ecosystems.md#go-directory-replaces-and-gosum`), but production
5555
//! publishes no golang hosted modules yet. Covered as a shape guard that
5656
//! holds in both worlds.
5757
//! * **deno** — hosted mode is not supported. Covered as a negative assertion.
@@ -2427,7 +2427,7 @@ fn statements_for_opt(doc: Option<&serde_json::Value>, purl: &str) -> usize {
24272427
// ===========================================================================
24282428

24292429
/// Go hosted mode: supported for free-tier references that carry a `goproxy`
2430-
/// override (`docs/design/golang-hosted.md`); refused with
2430+
/// override (`docs/ecosystems.md#go-directory-replaces-and-gosum`); refused with
24312431
/// `redirect_golang_unsupported` otherwise (`golang-hosted-no-go.md`, the
24322432
/// paid-tier analysis).
24332433
///

‎crates/socket-patch-cli/tests/e2e_redirect_gem_build.rs‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
//! `/api/v1/dependencies` fallback returned a zero-byte body); the 2026-08-18
77
//! gem catalog republish fixed the served index, and this hermetic suite pins
88
//! the contract from both sides regardless of production's current state —
9-
//! see the history section of `docs/testing/hosted-production-e2e.md`.
9+
//! see `docs/testing/hosted-production-e2e.md` for the live-service counterpart.
1010
//!
1111
//! Unlike the npm/cargo siblings, this suite is FULLY hermetic: the fixture
1212
//! gems are authored here and built with the real `gem build`, and ONE
@@ -1390,8 +1390,8 @@ async fn gem_hosted_gems_rb_spelling_redirects_and_installs() {
13901390

13911391
/// The compact-index DEPENDENCY contract, pinned from the red side: a patch
13921392
/// registry whose `/info` omits the gem's runtime deps (production's
1393-
/// HISTORICAL behavior until the 2026-08-18 republish fixed the served index
1394-
/// — see docs/testing/hosted-production-e2e.md's history section) BREAKS the
1393+
/// HISTORICAL behavior until the 2026-08-18 republish fixed the served index)
1394+
/// BREAKS the
13951395
/// prescribed install with bundler's `APIResponseMismatchError`. If the CLI
13961396
/// or fixture ever starts tolerating that silently, this turns red.
13971397
#[tokio::test(flavor = "multi_thread")]

‎crates/socket-patch-core/README.md‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ Core library for [socket-patch](https://github.com/SocketDev/socket-patch) — a
44

55
## What this crate provides
66

7-
- **Manifest management** — read, write, and validate `.socket/manifest.json` patch manifests
8-
- **Patch engine** — apply and rollback file-level patches using git SHA-256 content hashes
9-
- **Crawlers** — discover installed packages across npm, PyPI, Ruby gems, Cargo, Go, Maven, Composer, NuGet, and Deno
10-
- **API client** — fetch patches from the Socket API
11-
- **Utilities** — PURL parsing, blob storage, hash verification, fuzzy matching
7+
- Dependency discovery from installed packages and lockfiles.
8+
- Hosted dependency rewriting, including the in-memory engine used by the Node bindings.
9+
- Selection policy and gradual rollout shared across disk and in-memory scans.
10+
- Vendored artifact acquisition, verification, wiring, and reversal.
11+
- Agent patch manifests and file-level apply/rollback with content-hash checks.
12+
- Socket API access and OpenVEX generation from patch records and live references.
13+
14+
See the repository's [development guide](../../docs/development.md) for the code map
15+
and [ecosystem matrix](../../docs/ecosystems.md) for supported formats and limits.
1216

1317
## Usage
1418

‎crates/socket-patch-core/src/patch/redirect/mod.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5868,7 +5868,7 @@ fn go_token_safe(s: &str) -> bool {
58685868
!s.is_empty() && !s.chars().any(|c| c.is_whitespace() || c.is_control())
58695869
}
58705870

5871-
// The committable shape (validated empirically — `docs/design/golang-hosted.md`):
5871+
// The committable shape (validated empirically — `docs/ecosystems.md#go-directory-replaces-and-gosum`):
58725872
//
58735873
// go.mod: replace <orig> <ver> => patch.socket.dev/gopatch/<uuid> <sver>
58745874
// go.sum: patch.socket.dev/gopatch/<uuid> <sver> h1:… (zip dirhash)

0 commit comments

Comments
 (0)