[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: register comment.
Kind: refactor (test structure). Source: review Part 8.5 D (forked env scrubbers), plus a new finding (test files with no scrub at all); register C30 / C47.
Problem
The CLI test tree already has a hermetic spawner: common::run_bin_with_env seeds and scrubs the high-risk vars, prefix-sweeps the remaining SOCKET_* (keeping the telemetry opt-outs, SOCKET_NO_CONFIG and SOCKET_NO_UPDATE_CHECK), and forces SOCKET_NO_CONFIG=1 / SOCKET_NO_UPDATE_CHECK=1. But it only returns (code, stdout, stderr), so tests that need a Command (stdin, PTY, extra env removal, output() bytes) hand-roll their own:
- 15 private
scrub_socket_env copies with 14 different bodies. Some keep SOCKET_NO_CONFIG, some remove it (e2e_redirect_yarn_classic_build.rs#L98`` strips every SOCKET_*, including the `.cargo/config.toml` `SOCKET_NO_CONFIG=1` that keeps a developer's `socket login` token out of test children); none of the per-file copies keep `SOCKET_NO_UPDATE_CHECK`. Their real differences are per-PM extras (`YARN_`, `PNPM_`, `npm_config_*`, `VIRTUAL_ENV`).
- 10 files that spawn the binary with no scrub at all (only
SOCKET_TELEMETRY_DISABLED or a token removal): repair/repair_vendor_e2e.rs (L201-L212),`` scan/scan_invariants.rs (L53), `scan/scan_sync_e2e.rs`, `cli/api_client_errors_e2e.rs`, `cli_parse_remove.rs`, `apply/in_process_npm_multicopy.rs`, `self_update_e2e.rs`, `self_update_failures_e2e.rs`, `update/covgap_update_swap.rs`, `update/covgap_update_download.rs`. (Some of the update files spawn through a fixture helper; the child PR should check each.)
Proof (on 045d7ec, debug build, run twice, as root in a cloud container):
| ambient var |
repair_vendor_e2e (unscrubbed, 19 tests) |
the other 97 tests in the repair target (scrubbed) |
| none |
19 pass |
95 pass, 2 fail* |
SOCKET_DRY_RUN=true |
1 pass, 18 fail ("setup must vendor the tarball") |
95 pass, 2 fail* |
SOCKET_OFFLINE=true |
1 pass, 18 fail |
95 pass, 2 fail* |
*The two baseline failures are the "lock file unremovable" tests, which can't simulate an unremovable file as root; they are unrelated.
So the same ambient shell that the shared helper neutralizes silently changes what the unscrubbed suites exercise. Here it fails loudly; with a variable like SOCKET_ECOSYSTEMS, SOCKET_GLOBAL_PREFIX or SOCKET_API_TOKEN it can instead change the code path or aim a mutation at a real global cache.
Symptoms
None filed; contributors hit this as "passes in CI, fails locally".
Impact
Test hermeticity and maintenance: each new SOCKET_* variable has to be remembered in up to 16 places. Size: test-only, no production change.
Proposed change
- Split
run_bin_with_env into pub fn hermetic_command(bin: &Path) -> Command (seed, scrub, force the two opt-outs) and the existing runner, which becomes hermetic_command(bin) + args + caller env + output().
- Give it the per-PM extras as an explicit opt-in, e.g.
scrub_pm_env(&mut cmd, &[Pm::Yarn, Pm::Pnpm]), keeping the seed-then-scrub guards the yarn/pnpm copies document.
- Route the 10 unscrubbed files and the 15
scrub_socket_env copies through it, and delete the 15 copies.
Size and scope
~25 test files, net negative (~−250 lines). Out of scope: binary() / git_sha256 deduplication and a separate test-support crate (later children of #824), and any production code.
Acceptance criteria
Dependencies
Blocked by nothing. First child of tracking issue #824. Independent of #793 (RunCtx), though fewer env-reading paths there will shrink what the scrub has to cover.
[agent] Filed by the scheduled architecture audit routine (CLI and core). Register: register comment.
Kind: refactor (test structure). Source: review Part 8.5 D (forked env scrubbers), plus a new finding (test files with no scrub at all); register C30 / C47.
Problem
The CLI test tree already has a hermetic spawner:
common::run_bin_with_envseeds and scrubs the high-risk vars, prefix-sweeps the remainingSOCKET_*(keeping the telemetry opt-outs,SOCKET_NO_CONFIGandSOCKET_NO_UPDATE_CHECK), and forcesSOCKET_NO_CONFIG=1/SOCKET_NO_UPDATE_CHECK=1. But it only returns(code, stdout, stderr), so tests that need aCommand(stdin, PTY, extra env removal,output()bytes) hand-roll their own:scrub_socket_envcopies with 14 different bodies. Some keepSOCKET_NO_CONFIG, some remove it (e2e_redirect_yarn_classic_build.rs#L98`` strips everySOCKET_*, including the `.cargo/config.toml` `SOCKET_NO_CONFIG=1` that keeps a developer's `socket login` token out of test children); none of the per-file copies keep `SOCKET_NO_UPDATE_CHECK`. Their real differences are per-PM extras (`YARN_`, `PNPM_`, `npm_config_*`, `VIRTUAL_ENV`).SOCKET_TELEMETRY_DISABLEDor a token removal):repair/repair_vendor_e2e.rs(L201-L212),``scan/scan_invariants.rs(L53), `scan/scan_sync_e2e.rs`, `cli/api_client_errors_e2e.rs`, `cli_parse_remove.rs`, `apply/in_process_npm_multicopy.rs`, `self_update_e2e.rs`, `self_update_failures_e2e.rs`, `update/covgap_update_swap.rs`, `update/covgap_update_download.rs`. (Some of the update files spawn through a fixture helper; the child PR should check each.)Proof (on
045d7ec, debug build, run twice, as root in a cloud container):repair_vendor_e2e(unscrubbed, 19 tests)repairtarget (scrubbed)SOCKET_DRY_RUN=trueSOCKET_OFFLINE=true*The two baseline failures are the "lock file unremovable" tests, which can't simulate an unremovable file as root; they are unrelated.
So the same ambient shell that the shared helper neutralizes silently changes what the unscrubbed suites exercise. Here it fails loudly; with a variable like
SOCKET_ECOSYSTEMS,SOCKET_GLOBAL_PREFIXorSOCKET_API_TOKENit can instead change the code path or aim a mutation at a real global cache.Symptoms
None filed; contributors hit this as "passes in CI, fails locally".
Impact
Test hermeticity and maintenance: each new
SOCKET_*variable has to be remembered in up to 16 places. Size: test-only, no production change.Proposed change
run_bin_with_envintopub fn hermetic_command(bin: &Path) -> Command(seed, scrub, force the two opt-outs) and the existing runner, which becomeshermetic_command(bin)+ args + caller env +output().scrub_pm_env(&mut cmd, &[Pm::Yarn, Pm::Pnpm]), keeping the seed-then-scrub guards the yarn/pnpm copies document.scrub_socket_envcopies through it, and delete the 15 copies.Size and scope
~25 test files, net negative (~−250 lines). Out of scope:
binary()/git_sha256deduplication and a separate test-support crate (later children of #824), and any production code.Acceptance criteria
common::hermetic_commandexists, andrun_bin_with_envis built on it.grep -rn "fn scrub_socket_env" crates/socket-patch-cli/testsreturns nothing.CARGO_BIN_EXE_socket-patch(or a staged copy of it) does so throughhermetic_commandor therun*helpers; a guard test (or a grep in an existing lint test) keeps it that way.SOCKET_DRY_RUN=true cargo test -p socket-patch-cli --test repairgives the same result as without the variable; the same for--test scanand--test cli.Dependencies
Blocked by nothing. First child of tracking issue #824. Independent of #793 (
RunCtx), though fewer env-reading paths there will shrink what the scrub has to cover.