@sysid/sandbox-runtime-improved 0.0.61-sysid.1 → 0.0.64-sysid.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/README.md +76 -15
  2. package/dist/cli.js +12 -18
  3. package/dist/cli.js.map +1 -1
  4. package/dist/index.d.ts +4 -4
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +2 -2
  7. package/dist/index.js.map +1 -1
  8. package/dist/sandbox/credential-mask-files.d.ts +100 -15
  9. package/dist/sandbox/credential-mask-files.d.ts.map +1 -1
  10. package/dist/sandbox/credential-mask-files.js +172 -20
  11. package/dist/sandbox/credential-mask-files.js.map +1 -1
  12. package/dist/sandbox/http-proxy.d.ts +1 -1
  13. package/dist/sandbox/http-proxy.d.ts.map +1 -1
  14. package/dist/sandbox/http-proxy.js +20 -0
  15. package/dist/sandbox/http-proxy.js.map +1 -1
  16. package/dist/sandbox/linux-sandbox-utils.d.ts +5 -0
  17. package/dist/sandbox/linux-sandbox-utils.d.ts.map +1 -1
  18. package/dist/sandbox/linux-sandbox-utils.js +29 -19
  19. package/dist/sandbox/linux-sandbox-utils.js.map +1 -1
  20. package/dist/sandbox/linux-violation-monitor.d.ts +48 -0
  21. package/dist/sandbox/linux-violation-monitor.d.ts.map +1 -0
  22. package/dist/sandbox/linux-violation-monitor.js +156 -0
  23. package/dist/sandbox/linux-violation-monitor.js.map +1 -0
  24. package/dist/sandbox/macos-sandbox-utils.js +3 -3
  25. package/dist/sandbox/macos-sandbox-utils.js.map +1 -1
  26. package/dist/sandbox/mitm-ca.d.ts +52 -1
  27. package/dist/sandbox/mitm-ca.d.ts.map +1 -1
  28. package/dist/sandbox/mitm-ca.js +143 -11
  29. package/dist/sandbox/mitm-ca.js.map +1 -1
  30. package/dist/sandbox/mitm-leaf.d.ts +1 -1
  31. package/dist/sandbox/mitm-leaf.d.ts.map +1 -1
  32. package/dist/sandbox/mitm-leaf.js +21 -32
  33. package/dist/sandbox/mitm-leaf.js.map +1 -1
  34. package/dist/sandbox/sandbox-config.d.ts +231 -40
  35. package/dist/sandbox/sandbox-config.d.ts.map +1 -1
  36. package/dist/sandbox/sandbox-config.js +161 -32
  37. package/dist/sandbox/sandbox-config.js.map +1 -1
  38. package/dist/sandbox/sandbox-manager.d.ts +1 -1
  39. package/dist/sandbox/sandbox-manager.d.ts.map +1 -1
  40. package/dist/sandbox/sandbox-manager.js +331 -252
  41. package/dist/sandbox/sandbox-manager.js.map +1 -1
  42. package/dist/sandbox/sandbox-utils.d.ts +13 -0
  43. package/dist/sandbox/sandbox-utils.d.ts.map +1 -1
  44. package/dist/sandbox/sandbox-utils.js +32 -7
  45. package/dist/sandbox/sandbox-utils.js.map +1 -1
  46. package/dist/sandbox/windows-sandbox-utils.d.ts +353 -297
  47. package/dist/sandbox/windows-sandbox-utils.d.ts.map +1 -1
  48. package/dist/sandbox/windows-sandbox-utils.js +516 -396
  49. package/dist/sandbox/windows-sandbox-utils.js.map +1 -1
  50. package/dist/utils/shell-quote.d.ts +27 -0
  51. package/dist/utils/shell-quote.d.ts.map +1 -0
  52. package/dist/utils/shell-quote.js +47 -0
  53. package/dist/utils/shell-quote.js.map +1 -0
  54. package/package.json +1 -3
  55. package/vendor/seccomp/arm64/apply-seccomp +0 -0
  56. package/vendor/seccomp/x64/apply-seccomp +0 -0
@@ -1,67 +1,67 @@
1
1
  export { containsGlobCharsWin, stripExtendedPathPrefix, } from './sandbox-utils.js';
2
2
  import type { SandboxDependencyCheck } from './linux-sandbox-utils.js';
3
+ import type { SrtWinConfig } from './sandbox-config.js';
3
4
  /**
4
5
  * Windows sandbox backend.
5
6
  *
6
7
  * Network isolation is enforced by `srt-win.exe` — a Rust helper that
7
- * manages a local discriminator group, a machine-wide WFP filter set
8
- * keyed on that group's SID, and an `exec` subcommand that spawns the
9
- * target under a restricted token (group flipped deny-only) inside a
10
- * hardened job. The sandboxed child reaches the host only via the JS
11
- * http/socks proxies, which `srt-win exec` points at via env vars.
8
+ * provisions a dedicated `srt-sandbox` local user account, installs a
9
+ * machine-wide WFP filter set keyed on that account's SID, and
10
+ * provides an `exec` subcommand that spawns the target via a two-hop
11
+ * launch (broker `CreateProcessWithLogonW(runner)` runner
12
+ * restricted-token child) under `srt-sandbox`. The sandboxed child
13
+ * reaches the host only via the JS mux proxy, which the caller
14
+ * passes in via `--env`.
15
+ *
16
+ * The separate-user account structurally closes the surrogate-spawn
17
+ * class (schtasks, `PROC_THREAD_ATTRIBUTE_PARENT_PROCESS`, BITS,
18
+ * RunAs="Interactive User" COM): the child's token carries a
19
+ * different user SID, so it cannot reach real-user processes, tasks
20
+ * register under `srt-sandbox`, and the user-SID WFP filter fences
21
+ * `srt-sandbox` egress regardless of how the child was spawned.
12
22
  *
13
23
  * This module is a thin wrapper around the `srt-win` CLI; all status
14
- * comes from live enumeration (group via `LookupAccountNameW` +
15
- * token-membership check; WFP via providerData-tag enumeration under
16
- * the configured sublayer). There is no marker file.
24
+ * comes from live enumeration. There is no marker file.
17
25
  *
18
- * Filesystem deny (`denyRead`/`denyWrite`) is enforced via
19
- * `srt-win acl stamp` at session start: a broker-only DACL is
20
- * applied to each listed file plus a `Modify`-minus-`FILE_DELETE_CHILD`
21
- * allow-list on its immediate parent directory, with restore state
22
- * sealed by an inert hash-ACE marker so the on-disk SD is
23
- * self-authenticating. See {@link stampWindowsAcl}.
26
+ * Filesystem rules (`denyRead`/`denyWrite`/`allowRead`/`allowWrite`)
27
+ * are enforced via additive explicit ACEs for `<sb-SID>` see
28
+ * {@link grantWindowsAcl} / {@link stampWindowsAcl}.
24
29
  */
25
- export declare const DEFAULT_WINDOWS_GROUP_NAME = "sandbox-runtime-net";
26
30
  export declare const DEFAULT_WINDOWS_PROXY_PORT_RANGE: readonly [number, number];
27
- /** Identifies the discriminator group either by name or by SID. */
28
- export interface WindowsGroupRef {
29
- /** Local or domain group name. Default: `sandbox-runtime-net`. */
30
- groupName?: string;
31
- /**
32
- * Group SID in `S-1-…` form. Takes precedence over `groupName` —
33
- * use for domain groups or where name resolution is unreliable.
34
- */
35
- groupSid?: string;
36
- }
37
- export type WindowsGroupStatus = 'absent' | 'created-not-on-token' | 'ready';
38
- export interface WindowsGroupStatusResult {
39
- state: WindowsGroupStatus;
40
- sid?: string;
41
- warning?: string;
42
- error?: string;
43
- }
44
- export type WindowsWfpStatus = 'absent' | 'installed';
31
+ /**
32
+ * `cannot-read` is the graceful-degrade state when BFE enumeration
33
+ * is access-denied (it is admin-gated). The non-elevated readiness
34
+ * check is {@link verifyWindowsWfpEgress}, not this enum.
35
+ */
36
+ export type WindowsWfpStatus = 'absent' | 'installed' | 'cannot-read';
45
37
  export interface WindowsWfpStatusResult {
46
38
  state: WindowsWfpStatus;
39
+ /** Live filter count from BFE enum; `0` on `cannot-read`. */
47
40
  filters: number;
48
- /** `[low, high]` from the `permit-loopback` filter's tag, when present. */
41
+ /** `[low, high]` for the loopback PERMIT, when known. */
49
42
  portRange?: [number, number];
50
- /**
51
- * Number of user-SID-keyed filters present (subset of `filters`).
52
- * Zero on installs that predate the sandbox-user provisioning
53
- * step, or when only `wfp install` (group set) was run.
54
- */
55
- userFilters: number;
56
43
  /** Sandbox-user SID read from the first user-keyed filter tag. */
57
44
  userSid?: string;
45
+ /**
46
+ * Populated only on `cannot-read` (BFE enumeration is admin-gated;
47
+ * a non-elevated caller can't read it). The non-elevated readiness
48
+ * check is {@link verifyWindowsWfpEgress}, not this enum.
49
+ */
50
+ hint?: string;
51
+ }
52
+ /**
53
+ * Result of `srt-win wfp verify` on success (exit 0, `blocked`) —
54
+ * see {@link verifyWindowsWfpEgress}. Any other outcome throws, so
55
+ * the tri-state is unobservable on the return path.
56
+ */
57
+ export interface WindowsWfpVerifyResult {
58
+ target: string;
59
+ /** Runner's stderr (carries the `BLOCKED (…)` diagnostic line). */
60
+ stderr: string;
58
61
  }
59
62
  /**
60
63
  * State of the `srt-sandbox` local account that `srt-win install`
61
- * provisions. The sandboxed child eventually runs **as** this
62
- * account; for now it is reported alongside the group/WFP status
63
- * so callers can surface a "re-run install" diagnostic when the
64
- * account is missing.
64
+ * provisions. The sandboxed child runs **as** this account.
65
65
  */
66
66
  export interface WindowsSandboxUserStatus {
67
67
  /** The `srt-sandbox` local account exists. */
@@ -85,6 +85,12 @@ export interface WindowsSandboxUserStatus {
85
85
  credPresent: boolean;
86
86
  /** Setup marker schema version, when the marker row exists. */
87
87
  markerVersion?: number;
88
+ /**
89
+ * The calling (real) user's SID — the broker's identity, surfaced
90
+ * for diagnostics. The DENY-ACE trustee is `srt-sandbox`'s SID
91
+ * ({@link sid}), not this. Always present.
92
+ */
93
+ realUserSid: string;
88
94
  /**
89
95
  * SHA-1 thumbprint of the install-time CA, when one was
90
96
  * installed via `srt-win user trust-ca`. Uppercase hex.
@@ -94,18 +100,17 @@ export interface WindowsSandboxUserStatus {
94
100
  caCertPem?: string;
95
101
  }
96
102
  /**
97
- * Inner shell to run `command` under, inside the restricted-token
98
- * sandbox. The discriminant picks both the executable and the flag
99
- * shape (`/c` vs `-Command` vs `-c`); see
100
- * {@link wrapCommandWithSandboxWindows}.
103
+ * Inner shell to run `command` under, inside the sandbox. The
104
+ * discriminant picks both the executable and the flag shape (`/c`
105
+ * vs `-Command` vs `-c`); see {@link wrapCommandWithSandboxWindows}.
101
106
  *
102
107
  * For `kind: 'bash'`, `path` is the absolute Git Bash executable
103
108
  * (no fixed install location). It MUST originate from trusted host
104
109
  * configuration (user settings / install detection), NEVER from
105
110
  * workspace or repository content — the inner shell runs INSIDE the
106
- * restricted-token sandbox so an unexpected path is not a
107
- * sandbox-escape vector, but it would still be an arbitrary-exec
108
- * footgun if sourced from untrusted input.
111
+ * sandbox so an unexpected path is not a sandbox-escape vector, but
112
+ * it would still be an arbitrary-exec footgun if sourced from
113
+ * untrusted input.
109
114
  */
110
115
  export type WindowsBinShell = {
111
116
  kind: 'cmd';
@@ -129,94 +134,95 @@ export type WindowsBinShell = {
129
134
  export declare function parseWindowsBinShell(raw?: string): WindowsBinShell;
130
135
  export interface WindowsSandboxParams {
131
136
  command: string;
132
- group: WindowsGroupRef;
133
137
  /**
134
- * Sublayer GUID under which the WFP filters were installed.
135
- * `srt-win exec` checks `wfp status` against it and refuses to
136
- * launch when no filter set is present (fail-closed network
137
- * fence). When omitted, srt-win uses its compile-time default
138
- * GUID — same as `srt-win install` with no `--sublayer-guid`.
138
+ * JS HTTP proxy port fed to `generateProxyEnvVars` for the env
139
+ * overlay. With the in-process proxy this is the mux front-end
140
+ * port (same as `socksProxyPort`).
139
141
  */
140
- sublayerGuid?: string;
141
- /** JS HTTP proxy port — fed to `generateProxyEnvVars` for the returned env. */
142
142
  httpProxyPort?: number;
143
- /** JS SOCKS proxy port — fed to `generateProxyEnvVars` for the returned env. */
143
+ /**
144
+ * JS SOCKS proxy port — fed to `generateProxyEnvVars` for the env
145
+ * overlay. With the in-process proxy this is the mux front-end
146
+ * port (same as `httpProxyPort`).
147
+ */
144
148
  socksProxyPort?: number;
145
149
  /** Per-session proxy auth token; embedded in proxy env URLs. */
146
150
  proxyAuthToken?: string;
147
151
  /**
148
- * Credential env vars to drop from the inherited environment
149
- * (`mode: 'deny'`). Applied BEFORE the proxy assignments so the
150
- * sandbox's own proxy plumbing survives even if a caller lists
151
- * one of those names here same precedence as the macOS/Linux
152
- * `env -u VAR=… sandbox-exec` order.
153
- */
154
- unsetEnvVars?: readonly string[];
155
- /**
156
- * Credential env vars to overwrite with a sentinel
157
- * (`mode: 'mask'`). Applied BEFORE the proxy assignments for the
158
- * same precedence reason as {@link unsetEnvVars}.
152
+ * `mode: 'mask'` credential env vars sentinel values the
153
+ * sandboxed child should see in place of the real credentials.
154
+ * Threaded through the `--env` overlay so the runner forwards
155
+ * them into the child's fresh profile env (the broker's own
156
+ * environment never reaches the child, so an `env -u`-style
157
+ * scrub is structurally moot — there is no `unsetEnvVars`).
158
+ * Applied BEFORE the proxy assignments so the sandbox's own
159
+ * proxy plumbing survives even if a caller masks one of those
160
+ * names same precedence as macOS/Linux.
159
161
  */
160
162
  setEnvVars?: Readonly<Record<string, string>>;
161
163
  /**
162
- * PID of the long-lived host whose `srt-win acl stamp` holds
163
- * this exec should run under. When set, `srt-win exec` opens a
164
- * no-`FILE_SHARE_DELETE` handle on each of that holder's stamped
165
- * directories and fenced files before spawning the child — the
166
- * OS then refuses delete/rename of those, which the file's DACL
167
- * alone cannot prevent. Omit for an exec with no file-deny
168
- * session active.
169
- */
170
- holderPid?: number;
171
- /**
172
- * Per-exec read-deny paths, stamped under the `srt-win exec`
173
- * process's own PID and restored after the child exits. Same
164
+ * Per-exec read-deny paths, applied via an additive
165
+ * `(D;OICI;FA;;;<sb-SID>)` ACE under the `srt-win exec`
166
+ * process's own PID and released after the child exits. Same
174
167
  * disk-first chokepoint as the session-level
175
168
  * {@link stampWindowsAcl}; same fail-closed semantics (exec
176
169
  * fails if any path cannot be stamped).
177
170
  *
178
- * Pass RAW normalized paths. Do NOT pre-filter or pre-expand
179
- * via {@link expandWindowsFsDenyPaths} `srt-win exec`'s
180
- * `canonicalize_deny_targets` is the sole authority for
181
- * glob/dir/nonexistent rejection (hard-fail). A missing path
182
- * is a caller error, not a skip; pre-filtering would silently
183
- * drop it and run the child with the file readable.
171
+ * Normalized concrete paths globs expanded by the caller via
172
+ * {@link expandWindowsFsPaths}, the same as session-level.
173
+ * `srt-win exec`'s `canonicalize_ace_targets` hard-fails on a
174
+ * glob (it never expands), so a `*`/`?` reaching this field is
175
+ * a caller bug.
184
176
  */
185
177
  denyRead?: readonly string[];
186
178
  /** Per-exec write-deny paths — see {@link denyRead}. */
187
179
  denyWrite?: readonly string[];
188
180
  /**
189
- * Run the child as the dedicated `srt-sandbox` user via the
190
- * two-hop launch (broker `CreateProcessWithLogonW(runner)`
191
- * runner restricted-token child). Requires `srt-win install` to
192
- * have provisioned the sandbox user. Opt-in — when `false` or
193
- * omitted the same-user deny-only-group path is used. The
194
- * separate-user path structurally closes the surrogate-spawn
195
- * class (schtasks, `PROC_THREAD_ATTRIBUTE_PARENT_PROCESS`, BITS,
196
- * RunAs="Interactive User" COM): the child's token carries a
197
- * different user SID, so it cannot reach real-user processes,
198
- * tasks register under `srt-sandbox`, and the user-SID WFP filter
199
- * fences `srt-sandbox` egress regardless of how the child was
200
- * spawned.
181
+ * Working directory the child starts in. Fed to
182
+ * {@link buildGitConfigEnv} as a `safe.directory` entry so git
183
+ * inside the sandbox accepts the real-user-owned working tree.
184
+ * Default: `process.cwd()`.
185
+ *
186
+ * `srt-win exec` has no `--cwd` flag — the child's working
187
+ * directory is whatever the caller passes as the spawn `{cwd:}`
188
+ * option (broker `current_dir()` runner `lpCurrentDirectory`
189
+ * child inherits). This field must match that spawn option so
190
+ * `safe.directory` covers where git actually runs.
201
191
  */
202
- asSandboxUser?: boolean;
192
+ cwd?: string;
203
193
  /**
204
- * PEM-encoded CA certificate file. Same parameter macOS/Linux
205
- * thread to {@link generateProxyEnvVars} for the env-var trust
206
- * layer (`NODE_EXTRA_CA_CERTS` etc.). NOT passed to `srt-win
207
- * exec` — schannel-level trust under the sandbox user is set
208
- * separately via `srt-win user trust-ca` /
209
- * {@link windowsTrustCa}; per-exec only sets the env-var layer.
194
+ * Session-level write-granted paths (the resolved
195
+ * `filesystem.allowWrite` set). Each becomes a `safe.directory`
196
+ * entry see {@link buildGitConfigEnv}.
197
+ */
198
+ allowWrite?: readonly string[];
199
+ /**
200
+ * Path to the TLS-termination trust bundle (the MITM CA + system
201
+ * roots) — fed to {@link generateProxyEnvVars} so the child's
202
+ * `NODE_EXTRA_CA_CERTS` / `CURL_CA_BUNDLE` / `SSL_CERT_FILE` /
203
+ * etc. point at it. Backslashes are normalised to forward slashes
204
+ * before emission so the value survives msys2 env conversion AND
205
+ * is accepted by native tools.
206
+ *
207
+ * The env-var layer covers OpenSSL-backed clients (msys2 curl,
208
+ * openssl-backed git, node, python, cargo). Schannel/.NET clients
209
+ * that read the Windows certificate store exclusively (System32
210
+ * `curl.exe`, `Invoke-WebRequest`, Go-built tools) trust via the
211
+ * separate `srt-win user trust-ca` / {@link windowsTrustCa}
212
+ * install-time write into the sandbox user's `CurrentUser\Root`.
210
213
  *
211
- * **Under {@link asSandboxUser}**, this is currently NOT
212
- * forwarded to the child: the bundle file lives in the broker's
213
- * `%TEMP%`, which the `srt-sandbox` user cannot read, so OpenSSL
214
- * clients (msys2 curl, openssl-backed git, node, python) would
215
- * fail with `ACCESS_DENIED` on the bundle. The schannel-level
216
- * trust set via {@link windowsTrustCa} is the only CA-trust path
217
- * for the two-hop launch until working-tree/profile grants land.
214
+ * The caller is responsible for the sandbox user having read
215
+ * access to this path `sandbox-manager.ts`'s `initialize()`
216
+ * pushes it into the session's `acl grant` read-set alongside the
217
+ * working-tree grants.
218
218
  */
219
219
  caCertPath?: string;
220
+ /**
221
+ * Resolved `srt-win` spawn descriptor — from
222
+ * {@link resolveSrtWin}. Omit to resolve the packaged vendor
223
+ * binary at call time.
224
+ */
225
+ srtWin?: SrtWinSpawn;
220
226
  /**
221
227
  * Inner shell. Defaults to `{ kind: 'cmd' }`. The child's post-`/c`
222
228
  * (or `-Command` / `-c`) content is **passthrough** — `&` chains,
@@ -229,19 +235,21 @@ export interface WindowsSandboxParams {
229
235
  binShell?: WindowsBinShell;
230
236
  }
231
237
  /**
232
- * Locate `srt-win.exe`. Resolution order:
233
- * 1. `SRT_WIN_PATH` env var (CI sets this to the freshly-built binary).
234
- * 2. `<root>/vendor/srt-win/{arch}/srt-win.exe` (prebuilt — published npm
238
+ * Locate the packaged `srt-win.exe`. Resolution order:
239
+ * 1. `<root>/vendor/srt-win/{arch}/srt-win.exe` (prebuilt published npm
235
240
  * package, or after `npm run build:srt-win` locally).
236
- * 3. `<root>/vendor/srt-win-src/target/release/srt-win.exe` (local
241
+ * 2. `<root>/vendor/srt-win-src/target/release/srt-win.exe` (local
237
242
  * `cargo build --release` fallback for development).
238
- * 4. `<root>/vendor/srt-win/target/release/srt-win.exe` (transitional:
239
- * stale local build from before the srt-win-src rename).
240
243
  *
241
244
  * `<root>` is {@link repoRoot} — `__dirname/../..`, which resolves to the
242
245
  * repo root from `src/sandbox/` and `dist/sandbox/` alike, and to the
243
246
  * package root when installed under `node_modules`.
244
247
  *
248
+ * Callers that ship their own binary (or a multicall binary that
249
+ * routes on `argv[1] == `{@link SRT_WIN_DISPATCH_ARG1}) pass
250
+ * `windows.srtWin` instead of relying on this lookup — see
251
+ * {@link resolveSrtWin}.
252
+ *
245
253
  * Resolution via the optional `@anthropic-ai/sandbox-runtime-win32-*`
246
254
  * platform packages is added separately.
247
255
  *
@@ -249,46 +257,105 @@ export interface WindowsSandboxParams {
249
257
  */
250
258
  export declare function getSrtWinPath(): string;
251
259
  /**
252
- * Query the discriminator group's state in SAM and in the current
253
- * process's `TokenGroups`. `ready` means the group exists AND is
254
- * enabled in the caller's token (i.e. the logout/login dance has
255
- * happened). `created-not-on-token` means the install step ran but
256
- * a fresh logon is needed before {@link initialize} can succeed.
260
+ * `argv[1]` sentinel a multicall embedder's dispatcher matches
261
+ * against to route into `srt_win::run_from_args`. Mirrors the Rust
262
+ * `srt_win::SRT_WIN_DISPATCH_ARG1`; the two MUST stay in sync.
263
+ * `run_from_args` strips it before clap, so the standalone binary
264
+ * accepts it harmlessly.
265
+ */
266
+ export declare const SRT_WIN_DISPATCH_ARG1 = "--srt-win";
267
+ /**
268
+ * Resolved `srt-win` spawn descriptor — the executable to load plus
269
+ * the leading arguments that carry the dispatch sentinel. Threaded
270
+ * to every spawn site so {@link resolveSrtWin} runs once (at
271
+ * `initialize()`) instead of re-`stat`ing on every helper call.
272
+ */
273
+ export type SrtWinSpawn = Readonly<{
274
+ exe: string;
275
+ prependArgs: readonly string[];
276
+ }>;
277
+ /**
278
+ * Resolve the `srt-win` spawn target from config. When `cfg.path` is
279
+ * set it is used verbatim (no fallback to the packaged binary — an
280
+ * explicit override is a directive, not a hint) and
281
+ * {@link SRT_WIN_DISPATCH_ARG1} is prepended so a multicall
282
+ * dispatcher routes on `argv[1]`. When unset, falls back to
283
+ * {@link getSrtWinPath} with no sentinel (the packaged binary
284
+ * doesn't need it; `run_from_args` would strip it anyway).
257
285
  */
258
- export declare function getWindowsGroupStatus(ref: WindowsGroupRef): WindowsGroupStatusResult;
286
+ export declare function resolveSrtWin(cfg?: SrtWinConfig): SrtWinSpawn;
259
287
  /**
260
- * Query the WFP filter set under the given sublayer. `installed` means
261
- * srt-win-tagged `permit-group` AND `block` filters are both present
262
- * under that sublayer. Detection is **tag-based** (providerData JSON);
263
- * filters installed by other tooling without the tag are not counted.
288
+ * Query the WFP filter set under the given sublayer via live BFE
289
+ * enumeration. `installed` means at least one srt-win-tagged
290
+ * `block-user` filter is present. Detection is **tag-based**
291
+ * (providerData JSON); filters installed by other tooling without the
292
+ * tag are not counted.
293
+ *
294
+ * BFE enumeration is admin-gated — a non-elevated caller gets
295
+ * `state:"cannot-read"` with a `hint` (not an error). The
296
+ * non-elevated readiness check is {@link verifyWindowsWfpEgress}.
264
297
  */
265
298
  export declare function getWindowsWfpStatus(opts?: {
266
299
  sublayerGuid?: string;
300
+ srtWin?: SrtWinSpawn;
267
301
  }): WindowsWfpStatusResult;
302
+ /**
303
+ * Behavioral proof that the WFP egress fence is active for the
304
+ * sandbox user. Binds a local listener on an ephemeral loopback port
305
+ * outside the WFP loopback-permit range, then spawns `srt-win
306
+ * runner` as the sandbox user (via `CreateProcessWithLogonW`) to
307
+ * attempt a direct TCP connect to it. The WFP block-user filter
308
+ * fires at `ALE_AUTH_CONNECT` — before any packet leaves — so an
309
+ * active fence yields WSAEACCES immediately and a missing fence lets
310
+ * the connect through (the kernel completes the handshake against
311
+ * the listening socket's backlog; no event-loop tick required, so
312
+ * the synchronous `runSrtWin` is safe). Does not require elevation
313
+ * and does not depend on any external host.
314
+ *
315
+ * `initialize()` calls this once per session, so a stale install
316
+ * (sandbox user provisioned but filters since removed) fails closed
317
+ * at session start instead of running every exec with full egress.
318
+ *
319
+ * @param opts.target overrides the probe target (skips the local
320
+ * listener bind).
321
+ * @param opts.proxyPortRange the WFP loopback-permit range the
322
+ * listener must avoid. Default
323
+ * {@link DEFAULT_WINDOWS_PROXY_PORT_RANGE}.
324
+ * @throws on any outcome other than `blocked` (exit 0).
325
+ */
326
+ export declare function verifyWindowsWfpEgress(opts?: {
327
+ target?: string;
328
+ proxyPortRange?: readonly [number, number];
329
+ srtWin?: SrtWinSpawn;
330
+ }): Promise<WindowsWfpVerifyResult>;
268
331
  /**
269
332
  * Query the sandbox user account's provisioning state. Each field
270
333
  * is independently observed so a half-provisioned install (e.g.
271
334
  * user exists but credential file missing) is distinguishable.
272
335
  * Does not require elevation.
273
336
  */
274
- export declare function getWindowsSandboxUserStatus(): WindowsSandboxUserStatus;
337
+ export declare function getWindowsSandboxUserStatus(opts?: {
338
+ srtWin?: SrtWinSpawn;
339
+ }): WindowsSandboxUserStatus;
275
340
  /**
276
341
  * Read back the persistent MITM CA the sandbox was installed with
277
342
  * (via `srt-win user trust-ca` / {@link windowsTrustCa}).
278
343
  * Returns `null` when no CA was installed. The PEM is what `srt-win
279
344
  * user status` reconstructs from the DER stored in `state.db`.
280
345
  *
281
- * On Windows with `windows.asSandboxUser`, `tlsTerminate` requires
282
- * this CA to be present in the sandbox user's `CurrentUser\Root`
283
- * (schannel-level trust is an install-time concern, not
284
- * per-session); the host calls this from `initialize()` to fail
285
- * early with an actionable message when it isn't.
346
+ * On Windows, `tlsTerminate` requires this CA to be present in the
347
+ * sandbox user's `CurrentUser\Root` (schannel-level trust is an
348
+ * install-time concern, not per-session); the host calls this from
349
+ * `initialize()` to fail early with an actionable message when it
350
+ * isn't.
286
351
  *
287
352
  * @param status pass an already-fetched
288
353
  * {@link getWindowsSandboxUserStatus} result to avoid a second
289
354
  * `srt-win user status` spawn.
290
355
  */
291
- export declare function getWindowsSandboxCaCert(status?: WindowsSandboxUserStatus): {
356
+ export declare function getWindowsSandboxCaCert(status?: WindowsSandboxUserStatus, opts?: {
357
+ srtWin?: SrtWinSpawn;
358
+ }): {
292
359
  pem: string;
293
360
  thumb: string;
294
361
  } | null;
@@ -302,17 +369,16 @@ export declare function getWindowsSandboxCaCert(status?: WindowsSandboxUserStatu
302
369
  *
303
370
  * The CA has a separate lifecycle from {@link installWindowsSandbox}
304
371
  * — install provisions the account/filters and never touches the CA;
305
- * call this AFTER install when `tlsTerminate` will be used with
306
- * `windows.asSandboxUser`.
372
+ * call this AFTER install when `tlsTerminate` will be used.
307
373
  *
308
374
  * @throws when the sandbox user is not provisioned, the file is not a
309
375
  * parseable X.509 certificate, or the registry write into the
310
376
  * sandbox user's hive fails.
311
377
  */
312
- export declare function windowsTrustCa(caCertPath: string): void;
313
- export interface WindowsInstallOptions extends WindowsGroupRef {
314
- /** Add this user (instead of the current user) to the group. */
315
- userSid?: string;
378
+ export declare function windowsTrustCa(caCertPath: string, opts?: {
379
+ srtWin?: SrtWinSpawn;
380
+ }): void;
381
+ export interface WindowsInstallOptions {
316
382
  /** WFP sublayer GUID. Omit for srt-win's compile-time default. */
317
383
  sublayerGuid?: string;
318
384
  /**
@@ -321,17 +387,23 @@ export interface WindowsInstallOptions extends WindowsGroupRef {
321
387
  * Default {@link DEFAULT_WINDOWS_PROXY_PORT_RANGE}.
322
388
  */
323
389
  proxyPortRange?: readonly [number, number];
390
+ /**
391
+ * Name for the sandbox user account (created if absent, adopted
392
+ * if it already exists as a local user). Default `srt-sandbox`.
393
+ */
394
+ sandboxUser?: string;
324
395
  /**
325
396
  * Replace an existing install whose configuration differs
326
- * (different group SID or port range under the same sublayer).
327
- * Without this, install refuses with "already installed with
328
- * different config" rather than silently overwriting.
397
+ * (different port range or sandbox-user name under the same
398
+ * sublayer). Without this, install refuses with "already
399
+ * installed with different config" rather than silently
400
+ * overwriting.
329
401
  */
330
402
  force?: boolean;
403
+ /** Resolved `srt-win` spawn descriptor — from {@link resolveSrtWin}. */
404
+ srtWin?: SrtWinSpawn;
331
405
  }
332
406
  export interface WindowsInstallResult {
333
- /** Post-install group state. */
334
- group: WindowsGroupStatusResult;
335
407
  /** Post-install WFP state. */
336
408
  wfp: WindowsWfpStatusResult;
337
409
  /** Post-install sandbox-user state. */
@@ -344,187 +416,169 @@ export interface WindowsInstallResult {
344
416
  cancelled?: true;
345
417
  }
346
418
  /**
347
- * One-shot install: creates the discriminator group, adds the
348
- * current user (or `userSid`), and installs the machine-wide WFP
349
- * filter set — all in a single self-elevating process (one UAC
350
- * prompt). Idempotent.
419
+ * One-shot install: provisions the `srt-sandbox` user account and
420
+ * installs the user-SID-keyed WFP filter set all in a single
421
+ * self-elevating process (one UAC prompt). Idempotent; re-running
422
+ * rotates the sandbox user's password.
351
423
  *
352
- * Network for the calling user is **not disrupted** before the
353
- * required logout: while the group is absent from the token, WFP
354
- * filter-0 (PERMIT non-members) matches and traffic flows normally.
355
- * After log-out/log-in, the group is enabled in the token and
356
- * filter-1 (PERMIT group-enabled) takes over for the broker; only
357
- * `srt-win exec` children (group flipped deny-only) fall through to
358
- * the loopback/BLOCK filters.
424
+ * Network for the calling user is **not disrupted**: the filters key
425
+ * on the `srt-sandbox` user's SID, so the broker, services, and
426
+ * every other principal fall through to default-permit. No logout
427
+ * is required.
359
428
  *
360
- * Returns the post-call group + WFP state. If the user cancels the
361
- * UAC prompt this returns `{cancelled: true, …}` rather than
362
- * throwing — cancellation is a user choice, not an error.
429
+ * Returns the post-call WFP + sandbox-user state. If the user
430
+ * cancels the UAC prompt this returns `{cancelled: true, …}` rather
431
+ * than throwing — cancellation is a user choice, not an error.
363
432
  *
364
- * @throws on group/WFP creation failure, or if filters already
365
- * exist under `sublayerGuid` with different configuration and
366
- * `force` is not set.
433
+ * @throws on user/WFP creation failure, or if filters already exist
434
+ * under `sublayerGuid` with a different port range and `force` is
435
+ * not set.
367
436
  */
368
437
  export declare function installWindowsSandbox(opts?: WindowsInstallOptions): WindowsInstallResult;
369
438
  /**
370
- * Remove the WFP filter set under `sublayerGuid` (one UAC prompt).
371
- * Idempotent.
372
- *
373
- * **Does NOT delete the discriminator group** — group membership is
374
- * persistent user state and removing it would force every user to
375
- * re-do the logout dance on the next install. Call
376
- * {@link deleteWindowsGroup} explicitly if you want full teardown.
377
- *
378
- * **Does** remove the `srt-sandbox` account, its credential file,
379
- * and the setup marker, unless `keepUser` is set — the credential
380
- * is useless without the account and vice versa, so they're
381
- * treated as one unit.
439
+ * Remove the WFP filter set under `sublayerGuid` and the
440
+ * `srt-sandbox` account, its credential file, and the setup marker
441
+ * (one UAC prompt). Idempotent.
382
442
  *
383
443
  * @returns `{cancelled: true}` if the user dismissed UAC.
384
444
  */
385
445
  export declare function uninstallWindowsSandbox(opts?: {
386
446
  sublayerGuid?: string;
387
447
  keepUser?: boolean;
448
+ srtWin?: SrtWinSpawn;
388
449
  }): {
389
450
  cancelled?: true;
390
451
  };
391
452
  /**
392
- * Delete the discriminator group. Separate from
393
- * {@link uninstallWindowsSandbox} so that uninstall→reinstall
394
- * doesn't force a fresh logout for every member. **Requires
395
- * elevation.** Idempotent (no-op if the group doesn't exist).
396
- */
397
- export declare function deleteWindowsGroup(ref: WindowsGroupRef): void;
398
- /**
399
- * Granular primitive: create the discriminator group and add the
400
- * current user (or `userSid`). Most callers should use
401
- * {@link installWindowsSandbox} instead; this exists for
402
- * enterprise/CI flows that manage group and WFP separately.
403
- * **Requires elevation.** Idempotent.
404
- */
405
- export declare function createWindowsGroup(ref: WindowsGroupRef & {
406
- userSid?: string;
407
- }): void;
408
- /**
409
- * Granular primitive: install the machine-wide WFP filter set
410
- * under `sublayerGuid` keyed on the group SID. Most callers should
411
- * use {@link installWindowsSandbox} instead; this exists for
412
- * enterprise/CI flows that manage group and WFP separately.
413
- * **Requires elevation.** Idempotent — re-running replaces any
414
- * existing srt-win-tagged filters under that sublayer.
415
- */
416
- export declare function createWindowsWfp(ref: WindowsGroupRef & {
417
- sublayerGuid?: string;
418
- proxyPortRange?: readonly [number, number];
419
- }): void;
420
- /**
421
- * Per-file outcome from `srt-win acl restore --json`. `status:
422
- * "restored"` covers both `Restored` and `AlreadyOriginal` on the
423
- * Rust side (the host doesn't need to distinguish them); every
424
- * other status keeps the snapshot row (fail-closed) and is
425
- * surfaced to the user as an anomaly to investigate. Mirrors
426
- * `restore_entry()` in `vendor/srt-win-src/src/main.rs`.
427
- */
428
- export interface WindowsAclPathOutcome {
429
- path: string;
430
- status: 'restored' | 'relocated' | 'missing' | 'leftChanged' | 'leftUnreadable' | 'originalSdTampered' | 'originalSdLost' | 'stampedUnrecognized';
431
- /** Hex `FILE_ID_INFO` recorded at stamp time. Present when `status ≠ "restored"`. */
432
- expectedFileId?: string;
433
- /** Where the protected file was found by `file_id`. Only on `relocated`. */
434
- movedTo?: string;
435
- /** `true` whenever `status ≠ "restored"` — the snapshot row was kept (restore not confirmed). */
436
- leftStamped?: boolean;
437
- }
438
- /**
439
- * Per-parent-directory outcome from `srt-win acl restore --json`.
440
- * `stillHeld` is normal (another active session still references
441
- * a file under this directory). Mirrors `parent_entries_from()` +
442
- * `ParentRestoreOutcome::as_str()` in `vendor/srt-win-src/src/`.
453
+ * Resolve any Windows filesystem-config path list — `allowRead`/
454
+ * `allowWrite` grants and `denyRead`/`denyWrite` stamps — to
455
+ * concrete existing paths via the single platform-aware
456
+ * {@link normalizePathForSandbox} chokepoint (Linux/macOS parity:
457
+ * point-in-time expansion at session initialize, not per-exec).
458
+ * Glob patterns are expanded; non-glob paths are normalized and
459
+ * returned 1:1. Missing paths are dropped (statSync probe).
460
+ * Directory targets are accepted the additive sandbox-user ACE
461
+ * carries `(OI)(CI)` so it covers the subtree.
443
462
  */
444
- export interface WindowsAclParentOutcome {
445
- path: string;
446
- status: 'restored' | 'alreadyOriginal' | 'stillHeld' | 'leftChanged' | 'missing' | 'leftStamped';
447
- /** Underlying error for `leftStamped`. */
448
- error?: string;
449
- }
450
- /** Top-level shape of `srt-win acl restore --json`. */
451
- export interface WindowsAclRestoreResult {
452
- paths: WindowsAclPathOutcome[];
453
- parents: WindowsAclParentOutcome[];
454
- }
455
- /**
456
- * Expand the `denyRead`/`denyWrite` input set to a flat list of
457
- * existing FILE paths for `srt-win acl stamp`.
458
- *
459
- * Every input goes through {@link normalizePathForSandbox} (the
460
- * single Windows-aware chokepoint: `\\?\`/UNC-strip, drive-letter
461
- * case-fold, ~-expand, realpath). Globs (`*`/`?` only — `[`/`]`
462
- * are legal Win32 filename chars) expand via the shared walker
463
- * with case-insensitive matching (point-in-time: a file appearing
464
- * after this returns is NOT covered). Each candidate is checked
465
- * with one `statSync({throwIfNoEntry:false})`: missing → drop
466
- * (the protection model covers files present at session start);
467
- * directory → reject (the file stamp applies a per-file DACL plus
468
- * a per-parent-directory allow-list; stamping a directory itself
469
- * would touch every child); file → keep.
470
- */
471
- export declare function expandWindowsFsDenyPaths(patterns: readonly string[]): string[];
463
+ export declare function expandWindowsFsPaths(patterns: readonly string[]): string[];
472
464
  export interface WindowsAclStampOptions {
473
- group: WindowsGroupRef;
474
- /** Files the sandboxed child must not read. */
465
+ /** Paths the sandboxed child must not read. */
475
466
  denyRead: readonly string[];
476
- /** Files the sandboxed child must not write (read stays allowed). */
467
+ /** Paths the sandboxed child must not write (read stays allowed). */
477
468
  denyWrite: readonly string[];
469
+ /** SID of the dedicated sandbox user — {@link WindowsSandboxUserStatus.sid}. */
470
+ sandboxUserSid: string;
478
471
  /** Long-lived host PID the holds are tied to. Default: this process. */
479
472
  holderPid?: number;
473
+ /** Resolved `srt-win` spawn descriptor — from {@link resolveSrtWin}. */
474
+ srtWin?: SrtWinSpawn;
480
475
  }
481
476
  /**
482
- * Apply the file-deny stamp set for one host session. Idempotent
483
- * via `srt-win`'s disk-first `ensure_stamped` chokepoint calling
484
- * this again with overlapping paths re-verifies the on-disk DACL
485
- * against the hash-ACE marker rather than trusting state-DB rows.
477
+ * Apply the file-deny ACE set for one host session: an additive
478
+ * `(D;OICI;mask;;;<sb-SID>)` on the target plus a
479
+ * `(D;OICI;FILE_DELETE_CHILD;;;<sb-SID>)` on the parent no
480
+ * PROTECTED rewrite, no SD snapshot. Idempotent and refcounted via
481
+ * srt-win's `working_aces` table.
486
482
  *
487
- * Inputs are passed verbatim to `srt-win` (which canonicalizes,
488
- * rejects directories and globs, and stamps each file plus its
489
- * immediate parent directory). Callers that accept globs should
490
- * pre-expand via {@link expandWindowsFsDenyPaths}.
483
+ * Inputs are passed verbatim to `srt-win` (which canonicalizes and
484
+ * rejects globs). Callers that accept globs should pre-expand via
485
+ * {@link expandWindowsFsPaths}.
491
486
  *
492
487
  * @throws on exit ≠ 0 — including exit 2 (one or more inputs
493
488
  * skipped). srt-win stamps the resolvable inputs before exiting
494
489
  * 2, so on throw the caller should call {@link restoreWindowsAcl}
495
- * to release whatever WAS stamped (fail-closed at session start
496
- * means tearing down a partial setup).
490
+ * to release whatever WAS stamped.
497
491
  */
498
492
  export declare function stampWindowsAcl(opts: WindowsAclStampOptions): void;
499
- export interface WindowsAclRestoreOptions {
500
- group: WindowsGroupRef;
501
- /** Long-lived host PID whose holds to release. Default: this process. */
493
+ /**
494
+ * Per-path outcome from `srt-win acl restore --json` /
495
+ * `revoke --json`. The status set is intentionally loose: the
496
+ * pre-/post- same-user-removal `srt-win` builds emit different
497
+ * vocabularies for `restore` (`restored`/`leftChanged`/… vs
498
+ * `revoked`/`stillHeld`/…). Callers (`reset()`) only log these,
499
+ * so the union is whatever the binary on PATH says.
500
+ */
501
+ export interface WindowsAclAceOutcome {
502
+ path: string;
503
+ status: string;
504
+ }
505
+ /**
506
+ * Release this holder's deny ACEs and remove the sandbox-user ACE
507
+ * on any path whose refcount falls to zero. Best-effort (does not
508
+ * throw on per-path anomalies); returns per-path outcomes for the
509
+ * caller to surface. Returns `undefined` only when `srt-win`
510
+ * itself failed (no JSON to parse).
511
+ */
512
+ export declare function restoreWindowsAcl(opts: {
513
+ sandboxUserSid: string;
514
+ holderPid?: number;
515
+ srtWin?: SrtWinSpawn;
516
+ }): WindowsAclAceOutcome[] | undefined;
517
+ export interface WindowsAclGrantOptions {
518
+ /** Paths to grant `MODIFY_NO_FDC` on (the working tree, `allowWrite`). */
519
+ write: readonly string[];
520
+ /** Paths to grant `FILE_GENERIC_READ|EXECUTE` on (`allowRead`). */
521
+ read: readonly string[];
522
+ /** SID of the dedicated sandbox user — {@link WindowsSandboxUserStatus.sid}. */
523
+ sandboxUserSid: string;
524
+ /** Long-lived host PID the holds are tied to. Default: this process. */
502
525
  holderPid?: number;
526
+ /** Resolved `srt-win` spawn descriptor — from {@link resolveSrtWin}. */
527
+ srtWin?: SrtWinSpawn;
503
528
  }
504
529
  /**
505
- * Release this holder's file-deny stamps and return per-path /
506
- * per-parent outcomes. Best-effort: a non-`restored` entry means
507
- * the file's stamp was LEFT in place (fail-closed) see
508
- * {@link WindowsAclPathOutcome} for the cases. Does not throw on
509
- * anomalies; the caller decides whether to surface them.
530
+ * Apply per-session additive `(OI)(CI)` ALLOW ACEs for the sandbox
531
+ * user on each path. The sandbox user has no inherent rights on
532
+ * real-user-owned files; this is what makes the working tree (and
533
+ * explicit `allowRead`/`allowWrite` paths) reachable from the
534
+ * child. Idempotent and refcounted via srt-win's `working_aces`
535
+ * table.
510
536
  *
511
- * Returns `undefined` when `srt-win acl restore` itself failed
512
- * (no JSON to parse) the caller should log and move on rather
513
- * than block teardown.
537
+ * @throws on exit 0. On throw the caller should call
538
+ * {@link revokeWindowsAcl} to release whatever WAS granted.
514
539
  */
515
- export declare function restoreWindowsAcl(opts: WindowsAclRestoreOptions): WindowsAclRestoreResult | undefined;
540
+ export declare function grantWindowsAcl(opts: WindowsAclGrantOptions): void;
516
541
  /**
517
- * Per-path outcomes that mean the file's DACL was returned to its
518
- * pre-stamp state (or was already there). Anything else left the
519
- * stamp in place and should be surfaced to the user.
542
+ * Release this holder's grants and remove the sandbox-user ACE on
543
+ * any path whose refcount falls to zero. Best-effort (does not
544
+ * throw); logs anomalies.
520
545
  */
521
- export declare const WINDOWS_ACL_PATH_OK: Set<"restored" | "relocated" | "missing" | "leftChanged" | "leftUnreadable" | "originalSdTampered" | "originalSdLost" | "stampedUnrecognized">;
546
+ export declare function revokeWindowsAcl(opts: {
547
+ sandboxUserSid: string;
548
+ holderPid?: number;
549
+ srtWin?: SrtWinSpawn;
550
+ }): WindowsAclAceOutcome[] | undefined;
522
551
  /**
523
- * Per-parent-directory outcomes that are expected during normal
524
- * teardown. `stillHeld` is normal when another active session
525
- * still references a file under this directory.
552
+ * Build the `GIT_CONFIG_COUNT` / `GIT_CONFIG_KEY_<n>` /
553
+ * `GIT_CONFIG_VALUE_<n>` env-var set for the sandboxed child.
554
+ *
555
+ * Emits:
556
+ * - `safe.directory=<dir>` for each entry in `safeDirs` (or one
557
+ * `safe.directory=*` when the list is long) — the working tree
558
+ * is owned by the real user, so git running as `srt-sandbox`
559
+ * refuses with "detected dubious ownership" without it.
560
+ * - `http.schannelUseSSLCAInfo=true` and
561
+ * `http.schannelCheckRevoke=false` when `schannelCa` — makes
562
+ * git's default (schannel) backend honor `GIT_SSL_CAINFO`
563
+ * without `-c http.sslBackend=openssl`. Revocation is disabled
564
+ * because CryptoAPI CRL/OCSP fetches ignore proxy env and would
565
+ * be WFP-fenced.
566
+ *
567
+ * Composes with an existing `GIT_CONFIG_COUNT` in `baseEnv` by
568
+ * continuing its numbering; the returned `GIT_CONFIG_COUNT` is the
569
+ * new total. Under the two-hop launch the broker's own environment
570
+ * never reaches the child, so `baseEnv` is the caller-supplied
571
+ * overlay ({@link WindowsSandboxParams.setEnvVars}), not
572
+ * `process.env`.
573
+ *
574
+ * Paths are emitted with forward slashes so the value survives
575
+ * msys2's env conversion untouched and native git accepts it.
526
576
  */
527
- export declare const WINDOWS_ACL_PARENT_OK: Set<"restored" | "missing" | "leftChanged" | "alreadyOriginal" | "stillHeld" | "leftStamped">;
577
+ export declare function buildGitConfigEnv(opts: {
578
+ safeDirs: readonly string[];
579
+ schannelCa: boolean;
580
+ baseEnv?: Readonly<Record<string, string | undefined>>;
581
+ }): Record<string, string>;
528
582
  /**
529
583
  * Build the spawn descriptor for running `command` inside the Windows
530
584
  * sandbox: an `argv` array plus the `env` to spawn it with.
@@ -538,9 +592,10 @@ export declare const WINDOWS_ACL_PARENT_OK: Set<"restored" | "missing" | "leftCh
538
592
  * Proxy configuration is single-sourced by {@link generateProxyEnvVars}
539
593
  * (the same canonical builder used on macOS/Linux). `srt-win exec`
540
594
  * takes no `--http-proxy` / `--socks-proxy` flags and synthesizes no
541
- * proxy env; it forwards its own environment to the sandboxed child
542
- * verbatim. So the full proxy set is merged over the broker's
543
- * environment here and the child inherits it through the spawn.
595
+ * proxy env. The two-hop runner starts with the SANDBOX user's
596
+ * profile env (`USERPROFILE`/`TEMP` isolated) and overlays exactly
597
+ * what we pass as `--env` built here from the broker's `PATH` plus
598
+ * the generated proxy set.
544
599
  */
545
600
  export declare function wrapCommandWithSandboxWindows(p: WindowsSandboxParams): {
546
601
  argv: string[];
@@ -548,13 +603,14 @@ export declare function wrapCommandWithSandboxWindows(p: WindowsSandboxParams):
548
603
  };
549
604
  /**
550
605
  * Install instructions, surfaced verbatim in error messages.
551
- * Tailored to the observed group state: if the install already
552
- * ran (`created-not-on-token`), only the logout is missing.
553
606
  */
554
- export declare function windowsInstallInstructions(ref: WindowsGroupRef, sublayerGuid: string | undefined, groupState: WindowsGroupStatus): string;
607
+ export declare function windowsInstallInstructions(sublayerGuid: string | undefined): string;
555
608
  /**
556
609
  * Check the Windows backend is ready to sandbox. Errors block
557
610
  * `initialize()`; warnings are informational.
558
611
  */
559
- export declare function checkWindowsDependencies(ref: WindowsGroupRef, sublayerGuid?: string): SandboxDependencyCheck;
612
+ export declare function checkWindowsDependencies(opts?: {
613
+ sublayerGuid?: string;
614
+ srtWin?: SrtWinSpawn;
615
+ }): SandboxDependencyCheck;
560
616
  //# sourceMappingURL=windows-sandbox-utils.d.ts.map