@hydraharness/harness-pwsh-sandbox 0.1.1-rc.6

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 DeepSeek
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # @hydraharness/harness-pwsh-sandbox
2
+
3
+ Sandbox-consuming PowerShell implementation of the [`ctx.shell` executor seam](../shell/): every command runs as `pwsh -NoLogo -NoProfile -NonInteractive -Command <command>` **confined through `ctx.sandbox`**, with the selected mode, enforcement, and denial facts stamped on each settled result. The pwsh twin of [`@hydraharness/harness-bash-sandbox`](../bash-sandbox/), a call-for-call mirror per the [pwsh executor and tool decision](../../../.agents/notes/implemented/feature/2026-08-01-pwsh-tool-and-executor.md) — the confinement substance is platform-neutral: on Windows the sandbox seam resolves to the ACL restricted-token runner chain ([`@hydraharness/harness-sandbox-windows-acl`](../../sandbox/sandbox-windows-acl/)), on Linux/macOS to bwrap/Landlock/Seatbelt.
4
+
5
+ The executor inherits [`@hydraharness/harness-pwsh-local`](../pwsh-local/)'s process mechanics and consumes its argv-level seam (`argv()` / `runArgv()` / `startArgv()` / `onProcessDone()`) to wrap the exact pwsh invocation through the provider. The sandbox policy (mode + workspace root) is NOT this package's config: it rides each call from `ctx.sandboxPolicy` (tool calls pass the calling session's resolved policy; direct calls fall back to deployment policy).
6
+
7
+ ## Behavior
8
+
9
+ - `danger-full-access`: commands run through the local executor unchanged; results carry `sandbox: { mode, denied: false }`.
10
+ - Confined modes (`read-only`, `workspace-write`): the pwsh argv is wrapped by `ctx.sandbox.confine()`; runner-launch refusal fails closed with `SANDBOX_UNAVAILABLE` (foreground throw, background `runnerFailed` fact), and a denied write classifies against the selected backend's `denialSignatures` into `sandbox.denied`.
11
+
12
+ ## Model Experience
13
+
14
+ ### Confinement works, denial surfaces as command failure
15
+
16
+ #### What the model sees
17
+
18
+ The confined command's own stderr (e.g. `Access to the path '...' is denied.` under the Windows ACL runner); the tool layer converts classified denials into the standard permission-denied surface exactly as it does for the bash tool.
19
+
20
+ #### Token effect
21
+
22
+ No model-visible text beyond the command's stderr and the tool layer's standard denial surface.
23
+
24
+ #### KV Cache effect
25
+
26
+ None directly; the denial surface belongs to the tool layer.
27
+
28
+ ## Known Limitations and Deferred Work
29
+
30
+ - **Reads are unrestricted** on Windows (the ACL runner restricts writes only); the read boundary is documented in `@hydraharness/harness-sandbox-windows-acl`.
31
+ - **Windows workspace-write temp authority is private** per live session/workspace pair; agentless calls receive a fresh private directory per invocation. The ambient temp root is never granted, and the runner rewrites TMP/TEMP to the private directory before spawning.
32
+ - **Windows read-only grants no explicit writable root but remains partial** because the restricted token must retain Everyone. Objects whose DACL grants Everyone write access — including compatible opens of the NUL device — remain ambient authority; PowerShell's `> $null` redirection still works without opening NUL.
package/lib/index.js ADDED
@@ -0,0 +1,241 @@
1
+ import { SandboxUnavailableError } from "@hydraharness/harness-sandbox";
2
+ import { PwshLocalExecutor } from "@hydraharness/harness-pwsh-local";
3
+ import { accessSync, constants, statSync } from "node:fs";
4
+ //#region lib/types/helpers.js
5
+ /**
6
+ * Internal sandbox-result classification helpers — deliberate call-for-call
7
+ * mirror of `@hydraharness/harness-bash-sandbox/src/helpers.ts` (the pwsh twin of
8
+ * the bash consumer shares the identical classification dialect).
9
+ *
10
+ * @module @hydraharness/harness-pwsh-sandbox/helpers
11
+ */
12
+ /** Node-local spawn codes proven to identify executable resolution or permission failure. */
13
+ const EXECUTABLE_SPAWN_CODES = new Set(["EACCES", "ENOENT"]);
14
+ /** Whether the caller-owned spawn cwd can be entered. */
15
+ function isUsableWorkdir(path) {
16
+ try {
17
+ if (!statSync(path).isDirectory()) return false;
18
+ accessSync(path, constants.X_OK);
19
+ return true;
20
+ } catch {
21
+ return false;
22
+ }
23
+ }
24
+ /**
25
+ * Attribute only Node ENOENT/EACCES failures with positive argv[0] provenance
26
+ * after independently ruling out the caller-owned cwd. A supplied error path
27
+ * must exactly identify the runner; without one, the syscall must. With a
28
+ * usable cwd, these codes describe resolution or execute permission for that
29
+ * argv[0] or its shebang interpreter.
30
+ * The workdir is checked at classification time, not atomically with spawn;
31
+ * concurrent path replacement may change attribution but cannot permit an
32
+ * unconfined execution.
33
+ * @param error - the original spawn rejection.
34
+ * @param runnerProgram - provider argv[0], the executable that establishes confinement.
35
+ * @param workdir - the caller-owned spawn cwd, checked independently for usability.
36
+ * @returns whether the rejection has executable-specific runner evidence.
37
+ */
38
+ function isRunnerSpawnFailure(error, runnerProgram, workdir) {
39
+ if (runnerProgram === void 0 || !isUsableWorkdir(workdir)) return false;
40
+ if (typeof error !== "object" || error === null) return false;
41
+ const { code, path, syscall } = error;
42
+ if (typeof code !== "string" || !EXECUTABLE_SPAWN_CODES.has(code)) return false;
43
+ if (typeof syscall !== "string") return false;
44
+ const exactSyscall = `spawn ${runnerProgram}`;
45
+ if (path === void 0) return syscall === exactSyscall;
46
+ if (typeof path !== "string" || path.length === 0 || path !== runnerProgram) return false;
47
+ return syscall === "spawn" || syscall === exactSyscall;
48
+ }
49
+ /**
50
+ * Classify a failed run against the selected backend's denial dialect.
51
+ * @param result - settled foreground run.
52
+ * @param signatures - case-insensitive denial substrings from the active wrap.
53
+ * @returns whether the failed run matches that denial dialect.
54
+ */
55
+ function classifyDenial(result, signatures) {
56
+ return matchesSignature(result.exitCode, result.stderr.text, signatures);
57
+ }
58
+ /**
59
+ * Classify one settled process against the selected backend's structured
60
+ * runner-failure rules. Each rule requires a nonzero exit, its optional
61
+ * exit-code gate, and a fatal signature on one stderr line after exact
62
+ * informational lines are excluded.
63
+ * @param exitCode - process exit code; null means signal termination.
64
+ * @param stderr - collected stderr text, left unchanged.
65
+ * @param rules - structured runner-failure rules from the active wrap.
66
+ * @returns the first matching fatal line, or undefined when evidence is insufficient.
67
+ */
68
+ function classifyRunnerFailure(exitCode, stderr, rules) {
69
+ if (exitCode === null || exitCode === 0) return void 0;
70
+ const lines = stderr.split(/\r?\n/);
71
+ for (const rule of rules) {
72
+ if (rule.allowedExitCodes !== void 0 && !rule.allowedExitCodes.includes(exitCode)) continue;
73
+ const informationalLines = new Set((rule.informationalLines ?? []).map((line) => line.toLowerCase()));
74
+ const fatalSignatures = rule.fatalSignatures.filter((signature) => signature.trim().length > 0).map((signature) => signature.toLowerCase());
75
+ for (const line of lines) {
76
+ const lowered = line.toLowerCase();
77
+ if (informationalLines.has(lowered)) continue;
78
+ if (fatalSignatures.some((signature) => lowered.includes(signature))) return { detail: line };
79
+ }
80
+ }
81
+ }
82
+ /**
83
+ * Match a non-zero exit against case-insensitive stderr signatures.
84
+ * @param exitCode - process exit code; null means signal termination.
85
+ * @param stderr - collected stderr text.
86
+ * @param signatures - substrings identifying the selected backend's dialect.
87
+ * @returns whether this is a non-zero exit whose stderr matches a signature.
88
+ */
89
+ function matchesSignature(exitCode, stderr, signatures) {
90
+ if (exitCode === null || exitCode === 0) return false;
91
+ const lowered = stderr.toLowerCase();
92
+ return signatures.some((signature) => lowered.includes(signature.toLowerCase()));
93
+ }
94
+ //#endregion
95
+ //#region lib/types/index.js
96
+ /**
97
+ * Sandbox-consuming PowerShell executor — the pwsh twin of
98
+ * `@hydraharness/harness-bash-sandbox`. It wraps the exact local pwsh argv through
99
+ * `ctx.sandbox` (which on Windows resolves to the ACL restricted-token runner
100
+ * chain), inherits local process mechanics, and reports the selected mode,
101
+ * enforcement, and denial facts. Positive runner-launch evidence means the
102
+ * command never ran: foreground calls throw `SANDBOX_UNAVAILABLE`, while
103
+ * background processes carry `runnerFailed`; other spawn rejections retain
104
+ * local-executor semantics. The tool layer owns the escalation approval flow
105
+ * through `ctx.approval`; this executor reports the sandbox facts the tool
106
+ * renders.
107
+ * @module @hydraharness/harness-pwsh-sandbox
108
+ */
109
+ /**
110
+ * Registers as `ctx.shell` in place of the local pwsh executor and requires a
111
+ * `ctx.sandbox` provider plus `ctx.sandboxPolicy`; the tool layer carries the
112
+ * sandbox denial rendering and escalation surface (see the
113
+ * pwsh-tool-and-executor Agent Note). Tool calls pass the calling session's
114
+ * resolved policy; direct calls fall back to deployment policy.
115
+ * `result.sandbox` reports the mode, enforcement, and denial facts the tool
116
+ * renders.
117
+ */
118
+ var SandboxPwshExecutor = class extends PwshLocalExecutor {
119
+ static inject = [
120
+ "subprocess",
121
+ "sandbox",
122
+ "sandboxPolicy"
123
+ ];
124
+ mode;
125
+ /**
126
+ * Per-process confinement facts retained until settlement. Providers may
127
+ * vary enforcement and diagnostic dialect between overlapping calls, so a
128
+ * shared latest-wrap value would classify a process against the wrong facts.
129
+ * Unconfined processes have no entry.
130
+ */
131
+ processFacts = /* @__PURE__ */ new Map();
132
+ constructor(ctx, config) {
133
+ super(ctx, config);
134
+ this.mode = ctx.sandboxPolicy.defaultMode;
135
+ }
136
+ /** The configured default mode — the capability fact the tool layer reads. */
137
+ get sandboxMode() {
138
+ return this.mode;
139
+ }
140
+ /**
141
+ * Stamp a complete per-call policy onto the spec. Tool calls supply the
142
+ * calling session's resolved mode and root; lower-level callers fall back to
143
+ * the deployment policy.
144
+ */
145
+ resolve(request) {
146
+ return {
147
+ ...super.resolve(request),
148
+ sandboxPolicy: request.sandboxPolicy ?? this.ctx.sandboxPolicy.resolve()
149
+ };
150
+ }
151
+ async run(spec) {
152
+ const policy = spec.sandboxPolicy;
153
+ const { mode } = policy;
154
+ if (mode === "danger-full-access") return {
155
+ ...await super.run(spec),
156
+ sandbox: {
157
+ mode,
158
+ denied: false
159
+ }
160
+ };
161
+ const confined = this.confine(spec, {
162
+ ...policy,
163
+ mode
164
+ });
165
+ let result;
166
+ try {
167
+ result = await this.runArgv(spec, confined.argv);
168
+ } catch (error) {
169
+ if (spec.signal?.aborted === true) spec.signal.throwIfAborted();
170
+ if (isRunnerSpawnFailure(error, confined.argv[0], spec.workdir)) throw new SandboxUnavailableError(mode, String(error));
171
+ throw error;
172
+ }
173
+ const runnerFailure = classifyRunnerFailure(result.exitCode, result.stderr.text, confined.runnerFailureRules);
174
+ if (runnerFailure !== void 0) throw new SandboxUnavailableError(mode, runnerFailure.detail);
175
+ return {
176
+ ...result,
177
+ sandbox: {
178
+ mode,
179
+ denied: classifyDenial(result, confined.denialSignatures),
180
+ enforcement: confined.enforcement
181
+ }
182
+ };
183
+ }
184
+ start(spec) {
185
+ const policy = spec.sandboxPolicy;
186
+ const { mode } = policy;
187
+ if (mode === "danger-full-access") return super.start(spec);
188
+ const confined = this.confine(spec, {
189
+ ...policy,
190
+ mode
191
+ });
192
+ let proc;
193
+ try {
194
+ proc = this.startArgv(spec, confined.argv);
195
+ } catch (error) {
196
+ if (isRunnerSpawnFailure(error, confined.argv[0], spec.workdir)) throw new SandboxUnavailableError(mode, String(error));
197
+ throw error;
198
+ }
199
+ const { enforcement, denialSignatures, runnerFailureRules } = confined;
200
+ this.processFacts.set(proc, {
201
+ mode,
202
+ enforcement,
203
+ denialSignatures,
204
+ runnerFailureRules,
205
+ runnerProgram: confined.argv[0],
206
+ workdir: spec.workdir
207
+ });
208
+ return proc;
209
+ }
210
+ /**
211
+ * Stamp per-process sandbox facts before `done` settles. Full-access
212
+ * processes have no facts; signal deaths are not denials.
213
+ */
214
+ onProcessDone(proc, stderr, spawnFailed, spawnError) {
215
+ const facts = this.processFacts.get(proc);
216
+ if (facts !== void 0) {
217
+ this.processFacts.delete(proc);
218
+ const runnerFailed = spawnFailed ? isRunnerSpawnFailure(spawnError, facts.runnerProgram, facts.workdir) : classifyRunnerFailure(proc.exitCode, stderr, facts.runnerFailureRules) !== void 0;
219
+ proc.sandbox = {
220
+ mode: facts.mode,
221
+ denied: !runnerFailed && matchesSignature(proc.exitCode, stderr, facts.denialSignatures),
222
+ enforcement: facts.enforcement,
223
+ ...runnerFailed ? { runnerFailed } : {}
224
+ };
225
+ }
226
+ super.onProcessDone(proc, stderr, spawnFailed, spawnError);
227
+ }
228
+ /**
229
+ * Wrap one pwsh invocation via the `ctx.sandbox` provider. Provider errors
230
+ * propagate unchanged; the returned argv is handed directly to the local
231
+ * executor's subprocess path.
232
+ * @param spec - resolved execution spec whose pwsh argv is confined.
233
+ * @param policy - resolved confined execution policy.
234
+ * @returns the provider's exact argv and settlement-classification facts.
235
+ */
236
+ confine(spec, policy) {
237
+ return this.ctx.sandbox.confine(this.argv(spec), policy);
238
+ }
239
+ };
240
+ //#endregion
241
+ export { SandboxPwshExecutor, SandboxPwshExecutor as default };
@@ -0,0 +1,23 @@
1
+ //#region lib/types/invariant.js
2
+ /**
3
+ * Package-owned invariant companion for `@hydraharness/harness-pwsh-sandbox`.
4
+ * @module @hydraharness/harness-pwsh-sandbox/invariant
5
+ */
6
+ const PACKAGE_NAME = "@hydraharness/harness-pwsh-sandbox";
7
+ /** Cordis companion plugin name. */
8
+ const name = "pwsh-sandbox-invariant";
9
+ /** Service required before the companion can reserve package ownership. */
10
+ const inject = ["invariants"];
11
+ /**
12
+ * No runtime invariant: this package exposes no independent event sequence or
13
+ * mutable data relation beyond contracts enforced at its owning seams.
14
+ */
15
+ const install = () => {};
16
+ /**
17
+ * Register this package's invariant companion.
18
+ * @param ctx - Cordis context carrying the invariant service.
19
+ * @returns the installed registration's disposer after setup succeeds.
20
+ */
21
+ const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
22
+ //#endregion
23
+ export { apply, inject, name };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Internal sandbox-result classification helpers — deliberate call-for-call
3
+ * mirror of `@hydraharness/harness-bash-sandbox/src/helpers.ts` (the pwsh twin of
4
+ * the bash consumer shares the identical classification dialect).
5
+ *
6
+ * @module @hydraharness/harness-pwsh-sandbox/helpers
7
+ */
8
+ import type { ShellRunResult } from '@hydraharness/harness-shell';
9
+ import type { RunnerFailureRule } from '@hydraharness/harness-sandbox';
10
+ /**
11
+ * Attribute only Node ENOENT/EACCES failures with positive argv[0] provenance
12
+ * after independently ruling out the caller-owned cwd. A supplied error path
13
+ * must exactly identify the runner; without one, the syscall must. With a
14
+ * usable cwd, these codes describe resolution or execute permission for that
15
+ * argv[0] or its shebang interpreter.
16
+ * The workdir is checked at classification time, not atomically with spawn;
17
+ * concurrent path replacement may change attribution but cannot permit an
18
+ * unconfined execution.
19
+ * @param error - the original spawn rejection.
20
+ * @param runnerProgram - provider argv[0], the executable that establishes confinement.
21
+ * @param workdir - the caller-owned spawn cwd, checked independently for usability.
22
+ * @returns whether the rejection has executable-specific runner evidence.
23
+ */
24
+ export declare function isRunnerSpawnFailure(error: unknown, runnerProgram: string | undefined, workdir: string): boolean;
25
+ /** Fatal runner evidence retained for infrastructure-error detail. */
26
+ interface RunnerFailureMatch {
27
+ /** The original stderr line that matched a fatal signature. */
28
+ detail: string;
29
+ }
30
+ /**
31
+ * Classify a failed run against the selected backend's denial dialect.
32
+ * @param result - settled foreground run.
33
+ * @param signatures - case-insensitive denial substrings from the active wrap.
34
+ * @returns whether the failed run matches that denial dialect.
35
+ */
36
+ export declare function classifyDenial(result: ShellRunResult, signatures: readonly string[]): boolean;
37
+ /**
38
+ * Classify one settled process against the selected backend's structured
39
+ * runner-failure rules. Each rule requires a nonzero exit, its optional
40
+ * exit-code gate, and a fatal signature on one stderr line after exact
41
+ * informational lines are excluded.
42
+ * @param exitCode - process exit code; null means signal termination.
43
+ * @param stderr - collected stderr text, left unchanged.
44
+ * @param rules - structured runner-failure rules from the active wrap.
45
+ * @returns the first matching fatal line, or undefined when evidence is insufficient.
46
+ */
47
+ export declare function classifyRunnerFailure(exitCode: number | null, stderr: string, rules: readonly RunnerFailureRule[]): RunnerFailureMatch | undefined;
48
+ /**
49
+ * Match a non-zero exit against case-insensitive stderr signatures.
50
+ * @param exitCode - process exit code; null means signal termination.
51
+ * @param stderr - collected stderr text.
52
+ * @param signatures - substrings identifying the selected backend's dialect.
53
+ * @returns whether this is a non-zero exit whose stderr matches a signature.
54
+ */
55
+ export declare function matchesSignature(exitCode: number | null, stderr: string, signatures: readonly string[]): boolean;
56
+ export {};
57
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Sandbox-consuming PowerShell executor — the pwsh twin of
3
+ * `@hydraharness/harness-bash-sandbox`. It wraps the exact local pwsh argv through
4
+ * `ctx.sandbox` (which on Windows resolves to the ACL restricted-token runner
5
+ * chain), inherits local process mechanics, and reports the selected mode,
6
+ * enforcement, and denial facts. Positive runner-launch evidence means the
7
+ * command never ran: foreground calls throw `SANDBOX_UNAVAILABLE`, while
8
+ * background processes carry `runnerFailed`; other spawn rejections retain
9
+ * local-executor semantics. The tool layer owns the escalation approval flow
10
+ * through `ctx.approval`; this executor reports the sandbox facts the tool
11
+ * renders.
12
+ * @module @hydraharness/harness-pwsh-sandbox
13
+ */
14
+ import { Context } from '@hydraharness/cordis';
15
+ import type { ShellExecRequest, ShellExecSpec, ShellProcess, ShellRunResult } from '@hydraharness/harness-shell';
16
+ import type { SandboxMode } from '@hydraharness/harness-sandbox';
17
+ import { PwshLocalExecutor } from '@hydraharness/harness-pwsh-local';
18
+ import type { Config as LocalConfig } from '@hydraharness/harness-pwsh-local';
19
+ /**
20
+ * Plugin config: the local executor's knobs, verbatim. The sandbox policy —
21
+ * the default mode and fallback `workspace-write` root — is NOT here: it lives
22
+ * on `ctx.sandboxPolicy` (`@hydraharness/harness-sandbox-policy`), which resolves
23
+ * each calling session's mode and cwd for every enforcing capability. The
24
+ * runner choice is likewise the `ctx.sandbox` provider's config, not this
25
+ * executor's.
26
+ */
27
+ export type Config = LocalConfig;
28
+ /**
29
+ * Registers as `ctx.shell` in place of the local pwsh executor and requires a
30
+ * `ctx.sandbox` provider plus `ctx.sandboxPolicy`; the tool layer carries the
31
+ * sandbox denial rendering and escalation surface (see the
32
+ * pwsh-tool-and-executor Agent Note). Tool calls pass the calling session's
33
+ * resolved policy; direct calls fall back to deployment policy.
34
+ * `result.sandbox` reports the mode, enforcement, and denial facts the tool
35
+ * renders.
36
+ */
37
+ export declare class SandboxPwshExecutor extends PwshLocalExecutor {
38
+ static inject: string[];
39
+ private readonly mode;
40
+ /**
41
+ * Per-process confinement facts retained until settlement. Providers may
42
+ * vary enforcement and diagnostic dialect between overlapping calls, so a
43
+ * shared latest-wrap value would classify a process against the wrong facts.
44
+ * Unconfined processes have no entry.
45
+ */
46
+ private readonly processFacts;
47
+ constructor(ctx: Context, config: Config);
48
+ /** The configured default mode — the capability fact the tool layer reads. */
49
+ get sandboxMode(): SandboxMode;
50
+ /**
51
+ * Stamp a complete per-call policy onto the spec. Tool calls supply the
52
+ * calling session's resolved mode and root; lower-level callers fall back to
53
+ * the deployment policy.
54
+ */
55
+ resolve(request: ShellExecRequest): ShellExecSpec;
56
+ run(spec: ShellExecSpec): Promise<ShellRunResult>;
57
+ start(spec: ShellExecSpec): ShellProcess;
58
+ /**
59
+ * Stamp per-process sandbox facts before `done` settles. Full-access
60
+ * processes have no facts; signal deaths are not denials.
61
+ */
62
+ protected onProcessDone(proc: ShellProcess, stderr: string, spawnFailed: boolean, spawnError?: unknown): void;
63
+ /**
64
+ * Wrap one pwsh invocation via the `ctx.sandbox` provider. Provider errors
65
+ * propagate unchanged; the returned argv is handed directly to the local
66
+ * executor's subprocess path.
67
+ * @param spec - resolved execution spec whose pwsh argv is confined.
68
+ * @param policy - resolved confined execution policy.
69
+ * @returns the provider's exact argv and settlement-classification facts.
70
+ */
71
+ private confine;
72
+ }
73
+ export default SandboxPwshExecutor;
74
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Package-owned invariant companion for `@hydraharness/harness-pwsh-sandbox`.
3
+ * @module @hydraharness/harness-pwsh-sandbox/invariant
4
+ */
5
+ import type { Context } from '@hydraharness/cordis';
6
+ /** Cordis companion plugin name. */
7
+ export declare const name = "pwsh-sandbox-invariant";
8
+ /** Service required before the companion can reserve package ownership. */
9
+ export declare const inject: string[];
10
+ /**
11
+ * Register this package's invariant companion.
12
+ * @param ctx - Cordis context carrying the invariant service.
13
+ * @returns the installed registration's disposer after setup succeeds.
14
+ */
15
+ export declare const apply: (ctx: Context) => Promise<() => void>;
16
+ //# sourceMappingURL=invariant.d.ts.map
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@hydraharness/harness-pwsh-sandbox",
3
+ "description": "Sandbox-consuming implementation of the Hydra harness PowerShell executor seam (confines every command via ctx.sandbox, reports denial/enforcement result facts)",
4
+ "hydra": {
5
+ "plugin": {
6
+ "application": "Run PowerShell commands under the session's configured sandbox restrictions."
7
+ }
8
+ },
9
+ "version": "0.1.1-rc.6",
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/MaiHongPhong1902/Hydra-Harness.git",
16
+ "directory": "packages/shell/pwsh-sandbox"
17
+ },
18
+ "type": "module",
19
+ "main": "lib/index.js",
20
+ "types": "lib/types/index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./lib/types/index.d.ts",
24
+ "default": "./lib/index.js"
25
+ },
26
+ "./invariant": {
27
+ "types": "./lib/types/invariant.d.ts",
28
+ "default": "./lib/invariant.js"
29
+ },
30
+ "./src/*": "./src/*",
31
+ "./package.json": "./package.json"
32
+ },
33
+ "files": [
34
+ "lib/index.js",
35
+ "lib/invariant.js",
36
+ "lib/types/**/*.d.ts"
37
+ ],
38
+ "license": "MIT",
39
+ "peerDependencies": {
40
+ "@hydraharness/harness-shell": "^0.1.1-rc.6",
41
+ "@hydraharness/harness-pwsh-local": "^0.1.1-rc.6",
42
+ "@hydraharness/harness-sandbox": "^0.1.1-rc.6",
43
+ "@hydraharness/harness-invariants": "^0.1.1-rc.6",
44
+ "@hydraharness/cordis": "^4.0.2",
45
+ "@hydraharness/harness-sandbox-policy": "^0.1.1-rc.6"
46
+ },
47
+ "devDependencies": {
48
+ "@hydraharness/harness-shell": "^0.1.1-rc.6",
49
+ "@hydraharness/harness-pwsh-local": "^0.1.1-rc.6",
50
+ "@hydraharness/harness-sandbox": "^0.1.1-rc.6",
51
+ "@hydraharness/harness-invariants": "^0.1.1-rc.6",
52
+ "@hydraharness/harness-sandbox-local": "^0.1.1-rc.6",
53
+ "@hydraharness/harness-sandbox-policy": "^0.1.1-rc.6",
54
+ "@hydraharness/harness-subprocess-local": "^0.1.1-rc.6",
55
+ "@hydraharness/cordis": "^4.0.2"
56
+ }
57
+ }