diff --git a/README.md b/README.md index b10152567..814e12560 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ vulnerabilities without waiting for an upstream release or upgrading the depende The default workflow is **scan → install → vex**: -- `socket-patch scan` finds available patches and updates your dependency files to - use Socket-hosted patched packages. +- `socket-patch scan` finds available patches from project dependency files and + updates them to use Socket-hosted patched packages. - Your package manager installs those packages using the updated references and integrity pins. Commit the files that `scan` reports. - `socket-patch vex` produces an OpenVEX document describing the vulnerabilities @@ -53,13 +53,18 @@ installs, use that package manager's update command. The ## Quick start -From the root of a project with dependency files: +From the root of a project with a supported lockfile, including a fresh checkout +before dependencies are installed: ```sh socket-patch scan --dry-run # preview available patches and edits socket-patch scan # apply hosted references; never prompts ``` +Agent mode needs installed packages. Some ecosystems need build-tool resolution +records first, such as sbt and scala-cli; see the +[ecosystem notes](docs/ecosystems.md). + Without an API token, the CLI uses Socket's public proxy for free patches. To use your organization's patch tier, set `SOCKET_API_TOKEN`, or sign in with the separate Socket CLI using `socket login`. See [configuration](docs/configuration.md). @@ -119,6 +124,7 @@ socket-patch scan --max-new-patches 5 # introduce at most five new patche socket-patch scan 'apps/*' # scan project directories in a monorepo socket-patch get CVE-2024-12345 # target an advisory; hosted by default socket-patch vendor # eject an existing hosted patch set +socket-patch repair # restore agent or vendored patch artifacts socket-patch rollback # restore upstream dependencies ``` diff --git a/crates/socket-patch-cli/src/args.rs b/crates/socket-patch-cli/src/args.rs index 62dc7b5f2..23cf8925a 100644 --- a/crates/socket-patch-cli/src/args.rs +++ b/crates/socket-patch-cli/src/args.rs @@ -57,8 +57,8 @@ fn unsupported_ecosystem_message(token: &str, supported: &str) -> String { /// clap value-parser for `--vendor-source` / `SOCKET_VENDOR_SOURCE`. /// -/// Validates the token against [`VendorSource`] (`auto` | `service` | `build`, -/// case-insensitive) at parse time so a typo fails the command immediately +/// Validates the token against [`VendorSource`] (`service` or its `auto` alias, +/// case-insensitive; `build` is rejected) at parse time so a typo fails immediately /// rather than at vendor time, and normalizes it to the canonical lowercase /// tag. Mirrors [`parse_supported_ecosystem`]'s fail-loud-on-typo posture. fn parse_vendor_source(s: &str) -> Result { diff --git a/crates/socket-patch-cli/src/lib.rs b/crates/socket-patch-cli/src/lib.rs index 5f6336f21..4e9420c26 100644 --- a/crates/socket-patch-cli/src/lib.rs +++ b/crates/socket-patch-cli/src/lib.rs @@ -32,18 +32,21 @@ use socket_patch_core::utils::target::is_uuid_shaped; version, propagate_version = true, after_help = "Patch a project:\n \ - socket-patch scan Patch every dependency with a patch (hosted: rewrites lockfiles)\n \ - socket-patch get Patch one package, CVE, GHSA or patch UUID\n \ - socket-patch list Show the patches in this project\n\n\ + socket-patch scan --dry-run Preview hosted changes from dependency files\n \ + socket-patch scan Write hosted references for dependencies with patches\n \ + socket-patch get Patch one package, CVE, GHSA or patch UUID\n \ + socket-patch list Show the patches in this project\n\n\ + Supported lockfiles work from a fresh checkout; install dependencies after scanning.\n\n\ Undo:\n \ - socket-patch remove Unwind one patch (by PURL or UUID)\n \ - socket-patch rollback Unwind every patch\n\n\ + socket-patch remove Unwind one patch (by PURL or UUID)\n \ + socket-patch rollback Unwind every patch\n\n\ Ship:\n \ - socket-patch vex Emit an OpenVEX document for your vulnerability scanner\n \ - socket-patch vendor Eject the patches into .socket/vendor/ for offline installs\n\n\ + socket-patch vex Emit an OpenVEX document for your vulnerability scanner\n \ + socket-patch vendor Eject the patches into .socket/vendor/ for offline installs\n\n\ + Repair artifacts (agent and vendored):\n \ + socket-patch repair Restore missing or corrupt artifacts; clean unused ones\n\n\ Agent mode (`scan --mode agent` edits installed files in place):\n \ - socket-patch apply Re-apply .socket/manifest.json after each install (e.g. in CI)\n \ - socket-patch repair Restore missing patch artifacts" + socket-patch apply Re-apply .socket/manifest.json after each install (e.g. in CI)" )] pub struct Cli { #[command(subcommand)] @@ -68,8 +71,17 @@ pub struct Cli { #[derive(Subcommand)] pub enum Commands { - /// Find patches for installed packages and apply them by rewriting - /// lockfiles to Socket-hosted patched packages + /// Find patches from project dependency files; write hosted lockfile + /// references by default (preview with --dry-run) + /// + /// Rewrites lockfiles and related dependency files to use Socket-hosted + /// patched packages without prompting. Use `scan --dry-run` to preview + /// changes without writing them. + /// + /// Supported lockfiles can be scanned from a fresh checkout before + /// installing dependencies. Some workflows require installed packages or + /// build-tool resolution records first: agent mode patches installed + /// files, and sbt / scala-cli need their build tool's resolution records. Scan(commands::scan::ScanArgs), /// Patch one package, CVE, GHSA or patch UUID (hosted mode by default) @@ -102,11 +114,12 @@ pub enum Commands { /// Agent mode: apply the patches in `.socket/manifest.json` in place Apply(commands::apply::ApplyArgs), - /// Agent mode: download missing patch artifacts and clean up unused ones + /// Restore agent or vendored patch artifacts and clean up unused ones /// - /// Restores missing blobs and diff/package archives, rebuilds missing - /// or corrupt vendored artifacts, then deletes the artifacts nothing - /// references. + /// Downloads missing agent patch data and redownloads missing or corrupt + /// vendored artifacts using the existing vendor ledger, then deletes + /// unreferenced artifacts. A lost `.socket/vendor/state.json` cannot be + /// reconstructed; restore it from version control. Repair(commands::repair::RepairArgs), // Internal parse target of the root `--update` flag (see the rewrite diff --git a/crates/socket-patch-cli/tests/help_text_hygiene.rs b/crates/socket-patch-cli/tests/help_text_hygiene.rs index 369297994..294010dbb 100644 --- a/crates/socket-patch-cli/tests/help_text_hygiene.rs +++ b/crates/socket-patch-cli/tests/help_text_hygiene.rs @@ -202,15 +202,17 @@ fn vendor_and_repair_summaries_read_as_one_line() { ); assert!( text.lines().any(|l| l - == " repair Agent mode: download missing patch artifacts and clean up unused ones"), + == " repair Restore agent or vendored patch artifacts and clean up unused ones"), "{text}" ); let repair = long_help(&["repair"]); assert!( repair.starts_with( - "Agent mode: download missing patch artifacts and clean up unused ones\n\n\ - Restores missing blobs and diff/package archives, rebuilds missing or corrupt \ - vendored artifacts, then deletes the artifacts nothing references.\n" + "Restore agent or vendored patch artifacts and clean up unused ones\n\n\ + Downloads missing agent patch data and redownloads missing or corrupt \ + vendored artifacts using the existing vendor ledger, then deletes \ + unreferenced artifacts. A lost `.socket/vendor/state.json` cannot be \ + reconstructed; restore it from version control.\n" ), "{repair}" ); diff --git a/docs/migrating-to-v5.md b/docs/migrating-to-v5.md index a423eda09..19898097c 100644 --- a/docs/migrating-to-v5.md +++ b/docs/migrating-to-v5.md @@ -8,7 +8,12 @@ existing scripts against the new CLI; the [changelog](../CHANGELOG.md) and - Bare `scan` and `get` now patch in hosted mode when the project has no patch state yet. `scan` never prompts; hosted and vendored `get` do not prompt either. - Use `scan --dry-run` for a preview or `--mode agent` to retain in-place patching. + `scan` discovers patches from project dependency files and writes hosted + references. Supported lockfiles work from a fresh checkout before installing + dependencies; install or resolve first where the selected + [mode or ecosystem](ecosystems.md) requires it, such as agent mode or + sbt / scala-cli. Use `scan --dry-run` for a preview or `--mode agent` to retain + in-place patching. - A bare `scan` or `get` keeps the mode a project already uses: a project with a vendor ledger (`.socket/vendor/state.json`) stays vendored, and one whose `.socket/manifest.json` holds patches stays in agent mode. Switching modes needs an @@ -25,8 +30,10 @@ existing scripts against the new CLI; the [changelog](../CHANGELOG.md) and - `rollback` now removes patch records and unused artifacts as well as restoring dependencies. Pass `--preserve-state` to retain local state for reuse. - `scan` / `get --mode vendored` need no agent manifest. Commit - `.socket/vendor/state.json` with the artifacts. `repair` no longer reconstructs - a missing ledger from lockfiles. + `.socket/vendor/state.json` with the artifacts. `repair` restores missing agent + patch data or missing/corrupt vendored artifacts using existing records. It no + longer reconstructs a missing vendor ledger from lockfiles; restore the ledger + from version control. - Vendored Cargo patches move into workspace-root `Cargo.toml` and use `+socket.` versions. Re-running vendoring or repair migrates older wiring. The tag is visible in `CARGO_PKG_VERSION`; see @@ -42,6 +49,26 @@ existing scripts against the new CLI; the [changelog](../CHANGELOG.md) and `SOCKET_ORG_SLUG` to get org patches. The org is resolved once per run, so an embedded `--vex` no longer resolves it again. +## Service-only vendoring + +v4 could build patched artifacts locally, with `auto` as the default acquisition +policy. v5 downloads new artifacts only from the patch service: + +- `--vendor-source build` and `SOCKET_VENDOR_SOURCE=build` are rejected as usage + errors (exit 2). Remove that configuration or change it to `service`. +- `service` is the new default. `--vendor-source auto` and + `SOCKET_VENDOR_SOURCE=auto` remain compatibility aliases for `service`; they no + longer select a local build fallback. +- Missing or pending service artifacts, network errors, and integrity mismatches + do not trigger a local build fallback, even when the original package is installed. + +Healthy committed artifacts can still be reused offline. Commit `.socket/vendor/`, +including `state.json`, and the dependency-file changes the CLI reports. Installing +those patched packages needs neither Socket API access nor the Socket Patch CLI; +unpatched dependencies still need their normal registry, mirror, or cache. +Fetching a new artifact or redownloading a missing or corrupt one requires service +access. See [vendoring and offline installs](usage.md#vendoring-and-offline-installs). + ## JSON output Every `--json` failure now reports its top-level `error` as an object, @@ -181,6 +208,7 @@ whole root, not a `vendor_jvm_degraded` warning on mixed Maven + Gradle roots. | `scan --apply` | `scan --mode agent` | | `scan --vendor` | `scan --mode vendored` | | `get --no-apply` | `get --save-only` (`SOCKET_SAVE_ONLY` is unchanged) | +| `--vendor-source build`, `SOCKET_VENDOR_SOURCE=build` | Remove the setting or use `service`; `auto` is now a service-only alias | | `socket-patch download` | `socket-patch get` | | `socket-patch gc` | `socket-patch repair` | | `--download-mode`, `SOCKET_DOWNLOAD_MODE` | No replacement; patch content is always fetched as per-file blobs | diff --git a/docs/usage.md b/docs/usage.md index 3751c84f1..23f0cf4da 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -7,10 +7,15 @@ flags, response fields, and diagnostic codes live in the ## Select patches -A bare `scan` applies patches without prompting, in the mode the project already -uses: hosted for a new project, vendored or agent if `.socket/` already holds patches -in that mode. Pass `--mode` to choose or switch modes. Use `--dry-run` to inspect -what it would change, and `--json` for a machine-readable result: +A bare `scan` discovers patches from project dependency files and applies them +without prompting, in the mode the project already uses: hosted (writing hosted +references) for a new project, vendored or agent if `.socket/` already holds +patches in that mode. Pass `--mode` to choose or switch modes. Supported lockfiles +work from a fresh checkout before installing dependencies. Agent mode needs +installed packages, and some ecosystems need resolution records first (see +[sbt and scala-cli](#sbt-and-scala-cli) and the [ecosystem notes](ecosystems.md)). +Use `--dry-run` to inspect what would change, and `--json` for a machine-readable +result: ```sh socket-patch scan --dry-run --json @@ -103,8 +108,8 @@ owns archive construction, including Yarn Berry cache checksums. Python vendoring accepts both wheels and source distributions supplied by the service. `--vendor-source service` is the default. `auto` remains an alias for the same -behavior; `build` is rejected. A missing artifact, pending build, network error, -or integrity mismatch fails without a local build fallback. Healthy committed +behavior; `build` is rejected. Missing or pending service artifacts, network errors, +and integrity mismatches do not trigger a local build fallback. Healthy committed artifacts can be reused offline. `repair` redownloads missing or corrupt artifacts and checks them against the @@ -226,7 +231,7 @@ The removed `setup` command is covered in the [migration guide](migrating-to-v5. | `rollback [PURL\|UUID\|PATH]...` | Restore selected patches, or all patches when no target is given, and remove their local state | | `remove ` | Restore and remove one patch | | `vendor --revert` | Undo vendoring from its recorded edits and remove the vendored artifacts | -| `repair` | Restore missing patch data or damaged vendored artifacts and clean unused data | +| `repair` | Restore missing agent patch data or missing/corrupt vendored artifacts using existing records, and clean unused data | | `scan --mode agent --prune` | Patch discovered packages and remove records for dependencies that left the project | Use `--dry-run` to preview. `rollback --preserve-state` and