Skip to content

Commit fc9514a

Browse files
committed
Merge release/v5-prerelease (#285, #288, #289, #290) into v5/one-hosted-engine
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KHZ8uzdXfkG2zH8ZYDG8ju
2 parents 907de9c + 0f2de18 commit fc9514a

25 files changed

Lines changed: 5207 additions & 31 deletions

‎.github/workflows/bun-compatibility.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,11 @@ on:
9595
permissions:
9696
contents: read
9797

98-
# Supersede stale PR runs. The `main` guard is load-bearing: main runs are the
99-
# ONLY rust-cache writers (save-if), so they must never be cancelled mid-save.
98+
# Supersede stale PR runs only: main runs are the ONLY rust-cache writers
99+
# (save-if), so push, dispatch and schedule runs are never cancelled mid-save.
100100
concurrency:
101101
group: bun-patch-${{ github.event.pull_request.number || github.ref }}
102-
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
102+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
103103

104104
env:
105105
CARGO_PROFILE_DEV_DEBUG: '0'

‎.github/workflows/ci.yml‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ on:
1717
permissions:
1818
contents: read
1919

20-
# Supersede stale runs on force-push / rapid PR updates. The `main` guard is
21-
# load-bearing: main runs are the ONLY rust-cache writers (save-if), so they
22-
# must never be cancelled mid-save.
20+
# A newer push to the same PR supersedes its older run; nothing else is
21+
# cancelled. Push, dispatch and schedule runs always finish: main runs are
22+
# the ONLY rust-cache writers (save-if) and must not die mid-save, and a
23+
# dispatched base-branch run is the base's only CI verdict.
2324
concurrency:
24-
group: ci-${{ github.ref }}
25-
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
25+
group: ci-${{ github.event.pull_request.number || github.ref }}
26+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
2627

2728
jobs:
2829
clippy:

‎.github/workflows/go-compatibility.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ permissions:
3030

3131
concurrency:
3232
group: go-compat-${{ github.event.pull_request.number || github.ref }}
33-
cancel-in-progress: true
33+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
3434

3535
env:
3636
SOCKET_NO_CONFIG: '1'

‎.github/workflows/pdm-compatibility.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ permissions:
4848

4949
concurrency:
5050
group: pdm-compat-${{ github.event.pull_request.number || github.ref }}
51-
cancel-in-progress: true
51+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
5252

5353
env:
5454
SOCKET_NO_CONFIG: '1'

‎.github/workflows/poetry-compatibility.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ permissions:
4040

4141
concurrency:
4242
group: poetry-compat-${{ github.event.pull_request.number || github.ref }}
43-
cancel-in-progress: true
43+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
4444

4545
env:
4646
SOCKET_NO_CONFIG: '1'

‎.github/workflows/vlt-compatibility.yml‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,11 @@ on:
117117
permissions:
118118
contents: read
119119

120-
# Supersede stale PR runs; main runs are the only rust-cache writers, so they
121-
# are never cancelled mid-save.
120+
# Supersede stale PR runs only: main runs are the only rust-cache writers, so
121+
# push, dispatch and schedule runs are never cancelled mid-save.
122122
concurrency:
123123
group: vlt-compat-${{ github.event.pull_request.number || github.ref }}
124-
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
124+
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
125125

126126
env:
127127
CARGO_PROFILE_DEV_DEBUG: '0'

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,8 +1484,9 @@ async fn scan_hosted_paths_run_once_per_project_directory() {
14841484

14851485
let (code, stdout, stderr) = run_scan_human(tmp.path(), &mock.uri(), &["apps/*"]);
14861486
assert_eq!(code, 0, "stdout={stdout}; stderr={stderr}");
1487-
for app in ["apps/a", "apps/b"] {
1488-
let header = format!("== {} ==", std::path::Path::new(app).display());
1487+
// glob rebuilds matches with the native separator (`apps\a` on Windows).
1488+
for app in ["a", "b"] {
1489+
let header = format!("== {} ==", Path::new("apps").join(app).display());
14891490
assert!(stdout.contains(&header), "missing {header:?}: {stdout}");
14901491
}
14911492
assert_eq!(stdout.matches("Redirected 0 packages").count(), 2, "{stdout}");

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,10 @@ fn fresh_checkout(from: &Path, to: &Path) {
306306
for f in ["app.csproj", "nuget.config", "packages.lock.json"] {
307307
std::fs::copy(from.join(f), to.join(f)).unwrap_or_else(|e| panic!("copy {f}: {e}"));
308308
}
309-
copy_tree(&from.join(".socket"), &to.join(".socket"));
309+
// v5 hosted mode writes no `.socket/`: the lock pins are its whole state.
310+
if from.join(".socket").is_dir() {
311+
copy_tree(&from.join(".socket"), &to.join(".socket"));
312+
}
310313
strip_manifest(to);
311314
let blobs = to.join(".socket/blobs");
312315
if blobs.exists() {

‎docs/design/configuration.md‎

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# Configuration design: env vars, the socket-cli config file, and what we deliberately don't read
22

3-
Status: **implemented** (v3.5). This document records the settled design so
4-
future configuration surface grows inside it instead of inventing new
5-
mechanisms.
3+
Status: **implemented** (v3.5); section 4 (`socket.yml` patch policy) is
4+
**planned** for v5.0 (see `staged-rollout.md`). This document records the
5+
settled design so future configuration surface grows inside it instead of
6+
inventing new mechanisms.
67

78
## Problem
89

@@ -69,35 +70,71 @@ UX policy and are ignored.
6970
- The python `socketsecurity` CLI already accepts `SOCKET_API_TOKEN`, so
7071
the canonical names are the cross-tool bridge; no `SOCKET_SECURITY_*`
7172
aliases were added.
72-
- `socket.yml` stays a scanning-product surface (projectIgnorePaths /
73-
issueRules / githubApp); socket-patch does not read it.
73+
- `socket.yml` is shared with the scanning product (projectIgnorePaths /
74+
triggerPaths / issueRules / githubApp). As of v5.0 socket-patch reads
75+
exactly two of its keys, `projectIgnorePaths` and a new `patches` block,
76+
and nothing else (section 4).
7477
- `SOCKET_PROXY_URL` (the public patch **endpoint**) must never be
7578
conflated with socket-cli's `apiProxy` (an HTTP **forward proxy**).
7679
Forward-proxy behavior comes from the standard
7780
`HTTP_PROXY`/`HTTPS_PROXY`/`NO_PROXY` vars, which reqwest honors.
7881

82+
### 4. `socket.yml` carries patch selection policy, never settings (v5.0)
83+
84+
Revisits the v3.5 position that socket-patch does not read `socket.yml`.
85+
Staged rollout needs a repo-owned, reviewable place to say which projects,
86+
ecosystems and packages may be patched, a severity floor and a per-run cap
87+
on new patches (`staged-rollout.md`). `socket.yml` is where Socket users
88+
already express repo policy, it lives at the repo root, and a new
89+
top-level `patches:` key is stripped or ignored by every existing parser.
90+
91+
The trust boundary is unchanged and gains its positive half:
92+
93+
- A repository file may **narrow or pace** what `scan` patches. It may
94+
never widen it, name an endpoint or credential, choose a mode or download
95+
format, or disable a safety interlock. The parser has no fields for any
96+
of those; such keys are unknown keys and fail validation.
97+
- Because the file only narrows, an unreadable file or an invalid
98+
`patches` block fails closed (exit 1, `socket_yml_invalid`, nothing
99+
written) instead of being treated as absent. (A repo with no `patches`
100+
block and a malformed `projectIgnorePaths` gets a warning, so repos that
101+
never opted in do not start failing.) This is the opposite of the socket-cli `config.json` rule above
102+
(corrupt → warn and ignore), and deliberately so: ignoring a broken
103+
user-level login file loses a convenience; ignoring a broken repo policy
104+
widens the rollout.
105+
- Lookup is bounded to the repository (nearest `.git` ancestor of
106+
`--cwd` owned by the user, honoring `GIT_CEILING_DIRECTORIES`, else
107+
`--cwd`), root files only, regular files only.
108+
- Flags and env vars still win over the file for scalars (CLI > env >
109+
file > default) and intersect with it for list filters;
110+
`--no-socket-yml` / `SOCKET_NO_SOCKET_YML` ignores the file.
111+
- Only `scan` (every mode) and the in-memory engine honor it. Commands
112+
that report, attest or undo existing state (`list`, `vex`, `rollback`,
113+
`remove`, `repair`, `apply`, `vendor`) ignore it; `get` bypasses it with
114+
a warning.
115+
79116
## Explicitly rejected
80117

81118
| Idea | Why not |
82119
|---|---|
83120
| Auto-loading `.env` / `.env.local` | Trust boundary: the tool mutates installed packages while holding an API token; a file in a *cloned repo* must never redirect endpoints, disable interlocks, or spend the token. Also the wrong convention class — npm/cargo/pip/git read no `.env`; dotenv is an app-runtime convention. Users who want it have direnv/mise/dotenvx. |
84121
| A new socket-patch config file (`.socket/config.toml`, …) | Duplicates socket-cli's persisted config; one more file format to trust, document, and migrate. |
85122
| Writing to socket-cli's `config.json` | No login flow here; shared mutable state and format drift for zero benefit. |
86-
| Honoring endpoints/credentials from repo-level files (manifest, socket.yml) | Same trust boundary as `.env`. Stated as a contract property in `CLI_CONTRACT.md`. |
123+
| Honoring endpoints/credentials/interlock switches from repo-level files (manifest, socket.yml) | Same trust boundary as `.env`. Stated as a contract property in `CLI_CONTRACT.md`. Selection policy that only narrows is the one exception (section 4). |
124+
| A `version: 3` socket.yml for the `patches` block | socket-cli rejects any version but 2; older ajv parsers would treat 3 as 2 anyway. The block is additive under `version: 2`. |
125+
| Per-directory `socket.yml` files | No existing consumer supports them; one root file with `includePaths` covers monorepos. |
87126
| `SOCKET_CLI_CONFIG` (ephemeral full-JSON config override) | Imports socket-cli's whole config vocabulary as a permanent compat contract. |
88127
| Mapping `apiProxy` → anything | Forward-proxy vs patch-endpoint semantic trap; `HTTP_PROXY` et al. already work. |
89128
| `enforcedOrgs` / `skipAskToPersistDefaultOrg` | Interactive socket-cli UX policy with no socket-patch analog. |
90129

91130
## Deferred (designated homes, no implementation yet)
92131

93-
- **Project-level behavioral defaults** (`ecosystems`, `downloadMode`,
94-
`vendorSource`): if demand materializes, they go in the manifest `setup`
95-
block (`setup.defaults`, camelCase) — the manifest already controls what
96-
gets patched, so behavioral defaults there grant no new capability, and
97-
the serde struct simply has no fields for URLs/credentials/interlocks.
98-
Requires teaching the TS zod twin
99-
(`npm/socket-patch/src/schema/manifest-schema.ts`) to model `setup`.
100-
Precedence would be flag > env > `setup.defaults` > default.
132+
- **Project-level behavioral defaults** (`downloadMode`, `vendorSource`,
133+
mode): not planned. The v3.5 idea of a manifest `setup.defaults` block is
134+
obsolete in v5 (hosted and vendored projects have no manifest and `setup`
135+
is removed). Selection policy (ecosystems, packages, paths, severity,
136+
per-run cap) went to `socket.yml` `patches` instead (section 4). Anything
137+
that is not pure narrowing stays out of repo files.
101138
- **Env cleanup sweep**: core's direct env readers (`SOCKET_OFFLINE` in
102139
`utils/env_compat.rs`, `SOCKET_TELEMETRY_DISABLED` in `telemetry.rs`)
103140
still match only `1|true`, unlike `parse_bool_flag`'s vocabulary (the CLI

0 commit comments

Comments
 (0)