Skip to content
2 changes: 1 addition & 1 deletion crates/socket-patch-cli/CLI_CONTRACT.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ Beyond the globals above, each subcommand defines a small set of local arguments
| `vendor` | `--revert` | `SOCKET_VENDOR_REVERT` | Undo vendoring: restore recorded original lockfile fragments + remove `.socket/vendor/` artifacts. Works without a manifest |
| `apply`, `scan`, `vendor` | `--vex` | `SOCKET_VEX` | Generate an OpenVEX 0.2.0 document at this path on a successful run; see "embedded VEX" below |
| `apply`, `scan`, `vendor` | `--vex-product`, `--vex-no-verify`, `--vex-doc-id`, `--vex-compact` | `SOCKET_VEX_PRODUCT`, `SOCKET_VEX_NO_VERIFY`, `SOCKET_VEX_DOC_ID`, `SOCKET_VEX_COMPACT` | Passthrough to the embedded VEX builder; mirror the standalone `vex` knobs. Inert unless `--vex` is set |
| `scan` | `--mode <hosted\|vendored\|agent>` | — | The documented selector for the three patch-application modes. Each value is equivalent to one legacy boolean spelling: `hosted` == `--redirect`, `vendored` == `--vendor`, `agent` == `--apply` (`--sync` counts as an agent spelling). Combining `--mode` with a boolean of a DIFFERENT mode is a usage error (exit 2, enforced in `resolve_mode_flags` — clap's `conflicts_with` is value-independent); the same mode spelled both ways is accepted. `--prune` is an orthogonal GC knob and never conflicts |
| `scan` | `--mode <hosted\|vendored\|agent>` | — | The documented selector for the three patch-application modes. Each value is equivalent to one legacy boolean spelling: `hosted` == `--redirect`, `vendored` == `--vendor`, `agent` == `--apply` (`--sync` counts as an agent spelling). Combining `--mode` with a boolean of a DIFFERENT mode is a usage error (exit 2, enforced in `resolve_mode_flags` — clap's `conflicts_with` is value-independent); the same mode spelled both ways is accepted. `--prune` is an orthogonal GC knob and never conflicts — but hosted mode runs no GC, so `--mode hosted --prune` emits an explicit `redirect_prune_ignored` warning (JSON `redirect.warnings[]` + stderr) instead of silently dropping the flag |
| `scan` | `--redirect` | — | Hosted mode's legacy boolean spelling (**hidden from `--help`** and **deprecated** — `--mode hosted` is the documented spelling; this alias is scheduled for removal in v4): rewrite lockfiles / registry configs so ONLY the patched dependencies resolve to Socket's hosted patch server; no artifact bytes land in the repo. Conflicts with `--apply`/`--sync`/`--vendor` |
| `scan` | `--apply` / `--prune` / `--sync` | — | Mode selectors (sync = apply + prune); `--apply` == `--mode agent` |
| `scan` | `--vendor` / `--detached` | — | Vendor every patched dependency instead of applying in place (`--vendor` == `--mode vendored`; conflicts with `--apply`/`--sync`, combines with `--prune`); `--detached` additionally skips all manifest writes — the vendor ledger embeds the patch records (requires vendored mode in either spelling) |
Expand Down
16 changes: 15 additions & 1 deletion crates/socket-patch-cli/src/commands/scan/hosted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ pub(super) async fn run_redirect(
// may still claim package(s) this project also has a hosted redirect ledger
// for — their tarballs would then be orphaned and that ledger stale. But the
// overlap alone does NOT prove hosted won: only warn for the package(s) the
// LIVE lockfile actually routes to `patch.socket.dev` (see
// LIVE lockfile actually routes to the hosted patch server (see
// `classify_overlap_takeover`), so a dry-run / no-op over a lock that still
// points at the vendored files stays silent instead of pointing cleanup at
// the live vendored ledger. Warn (JSON `warnings[]` and stderr) WITHOUT
Expand All @@ -628,6 +628,19 @@ pub(super) async fn run_redirect(
}));
}

// `--prune` is a no-op in hosted mode (both hosted terminals return
// before the GC blocks): make that explicit in the JSON `warnings[]`
// rather than silently dropping the flag — a bot migrating from
// `--mode agent --prune` must see WHY it stopped pruning. The human
// path warns once up front in `run` (before this flow is entered).
let mut prune_warnings: Vec<serde_json::Value> = Vec::new();
if args.prune || args.sync {
prune_warnings.push(serde_json::json!({
"code": super::REDIRECT_PRUNE_IGNORED,
"detail": super::REDIRECT_PRUNE_IGNORED_DETAIL,
}));
}

// Emit an OpenVEX attestation when `--vex` was requested. The redirected
// bytes are fetched from the hosted patch server at install time, so the
// PURLs CONFIRMED REDIRECTED BY THIS RUN are attested from the ledger
Expand Down Expand Up @@ -670,6 +683,7 @@ pub(super) async fn run_redirect(
warnings.extend(rush_warnings.iter().cloned());
warnings.extend(pnpm_warnings.iter().cloned());
warnings.extend(takeover_warnings.iter().cloned());
warnings.extend(prune_warnings.iter().cloned());
// Nest the redirect result under `redirect` inside the classic scan
// object (built by `run`, threaded in via `scan_result`), mirroring
// vendored mode's nested `vendor` block. This keeps the hosted `--json`
Expand Down
Loading
Loading