@melra/terminal-runtime 0.3.0-alpha.11 → 0.3.0-alpha.13

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/README.md CHANGED
@@ -1,7 +1,9 @@
1
1
  # @melra/terminal-runtime
2
2
 
3
3
  Bounded process execution for [MELRA](https://github.com/XAGI-Lab/melra):
4
- one-shot `run`, plus `start`/`status`/`output`/`stop` for longer-lived processes.
4
+ one-shot `run`, plus `start`/`status`/`output`/`stop` for longer-lived processes
5
+ and `send` to answer a job started with `interactive: true` (stdin is a pipe,
6
+ not a pseudo-terminal).
5
7
 
6
8
  ```bash
7
9
  npm install @melra/terminal-runtime
@@ -33,8 +35,10 @@ Output is captured up to the operation's `maxOutputChars` and flagged
33
35
  budget actually stops work rather than just reporting a timeout.
34
36
 
35
37
  `redactTerminalOutput` strips credential-shaped values from captured output
36
- before it is persisted — tokens, `Authorization` headers, and connection strings
37
- show up in stdout more often than anyone expects.
38
+ before it is persisted — keys, tokens, and `Authorization` headers show up in
39
+ stdout more often than anyone expects. It applies the same `SECRET_PATTERNS`
40
+ list as receipts and memory, from
41
+ [`@melra/receipt-schema`](https://www.npmjs.com/package/@melra/receipt-schema).
38
42
 
39
43
  Allowlisting decides which commands may run at all, and that lives in
40
44
  [`@melra/policy-core`](https://www.npmjs.com/package/@melra/policy-core), not
package/dist/index.d.ts CHANGED
@@ -1,20 +1,56 @@
1
- import type { TerminalOperation } from "@melra/protocol";
1
+ import { type TerminalOperation } from "@melra/protocol";
2
2
  export { quoteForCmd, resolveCommand } from "./resolve-command.js";
3
3
  export type { ResolvedCommand } from "./resolve-command.js";
4
4
  export interface TerminalRuntimeOptions {
5
5
  root: string;
6
6
  allowedEnvironment?: string[];
7
7
  baseEnvironment?: NodeJS.ProcessEnv;
8
+ /** Whether a path is, or is inside, one of MELRA's own files, which no argument may reach in any mode. Absent, nothing is. */
9
+ reserved?: (path: string) => Promise<boolean>;
10
+ /** Whether a path is a directory holding one of them, which a recursive reader given it reaches unnamed. Absent, none is. */
11
+ holdsReserved?: (path: string) => Promise<boolean>;
12
+ /** Refuse an argument spelled inside the root that leads out: policy asked approval only for ones spelled outside. */
13
+ confineArguments?: boolean;
8
14
  }
9
15
  export declare function redactTerminalOutput(value: string): string;
16
+ /**
17
+ * Policy classifies several `git` subcommands (diff, show, log, status, ...) as
18
+ * approval-free reads, but git runs programs the repository's own config and
19
+ * attributes name while serving one. Those live in the git directory, not in
20
+ * the terminal arguments, so `checkArguments` never sees them, and policy
21
+ * cannot either.
22
+ *
23
+ * The guarantee is that nothing MELRA writes lands in a git directory: the
24
+ * file runtime refuses it (`path_git_metadata`), so only a person approving a
25
+ * command that does so can change what git's config makes it run. This is
26
+ * defence in depth on top: a read-shaped call (subcommand first, as policy
27
+ * requires for a read) spawns with system and global config nulled, the
28
+ * switches above, and external diff and textconv off on the subcommands that
29
+ * emit diffs (the only ones that accept the flags). Mutations — commit, push,
30
+ * or a global option before the subcommand — are left untouched, so a
31
+ * committer's identity and credentials from global config still apply.
32
+ *
33
+ * Pure and exported for unit testing. The caller's `operation.args` are never
34
+ * touched, only the spawned argv, so receipts still quote what was asked.
35
+ */
36
+ export declare function hardenGitRead(command: string, args: readonly string[]): {
37
+ args: string[];
38
+ env: Record<string, string>;
39
+ } | undefined;
10
40
  export declare class TerminalRuntime {
11
41
  readonly root: string;
12
42
  readonly allowedEnvironment: Set<string>;
13
43
  readonly baseEnvironment: NodeJS.ProcessEnv;
44
+ /** The root as policy spelled it, which is what "spelled inside" is measured against. */
45
+ private readonly lexicalRoot;
46
+ private readonly reserved;
47
+ private readonly holdsReserved;
48
+ private readonly confineArguments;
14
49
  private readonly jobs;
15
50
  private constructor();
16
51
  static create(options: TerminalRuntimeOptions): Promise<TerminalRuntime>;
17
52
  private resolveCwd;
53
+ private checkArguments;
18
54
  private prepare;
19
55
  private runForeground;
20
56
  private startBackground;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAGzD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACrC;AAcD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK1D;AAkDD,qBAAa,eAAe;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC,UAAU,CAAC;IAC5C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoC;IAEzD,OAAO;WAWM,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,eAAe,CAAC;YAIhE,UAAU;YAQV,OAAO;YA8CP,aAAa;YA+Db,eAAe;IAgF7B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,SAAS;IA0BjB,OAAO,CAAC,GAAG;IASX,OAAO,CAAC,SAAS;IAuBX,OAAO,CACX,SAAS,EAAE,iBAAiB,EAC5B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAoBnC;;;;;OAKG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAgB7B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAyC,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAIhG,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACnE,YAAY,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACpC,8HAA8H;IAC9H,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,6HAA6H;IAC7H,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACnD,sHAAsH;IACtH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAgBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AA+CD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAAG,SAAS,CAW7D;AAuGD,qBAAa,eAAe;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,kBAAkB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC,UAAU,CAAC;IAC5C,yFAAyF;IACzF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAC9D,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqC;IACnE,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAU;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoC;IAEzD,OAAO;WAeM,MAAM,CAAC,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,eAAe,CAAC;YAIhE,UAAU;YAQV,cAAc;YAwBd,OAAO;YAwDP,aAAa;YA8Fb,eAAe;IA6F7B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,SAAS;IA2BjB,OAAO,CAAC,GAAG;IASX,OAAO,CAAC,SAAS;IAuBX,OAAO,CACX,SAAS,EAAE,iBAAiB,EAC5B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAoBnC;;;;;OAKG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAc7B"}
package/dist/index.js CHANGED
@@ -3,21 +3,96 @@
3
3
  import { spawn } from "node:child_process";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import { realpath } from "node:fs/promises";
6
- import { isAbsolute, relative, resolve, sep } from "node:path";
6
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
7
+ import { outcomeUnknown, terminalArgumentPaths } from "@melra/protocol";
8
+ import { redactSecrets } from "@melra/receipt-schema";
7
9
  import { resolveCommand } from "./resolve-command.js";
8
10
  export { quoteForCmd, resolveCommand } from "./resolve-command.js";
9
- const SECRET_PATTERNS = [
10
- /\bgh[opurs]_[A-Za-z0-9]{20,}\b/g,
11
- /\b(?:sk|pk|api)[-_][a-z0-9_-]{16,}\b/gi,
12
- /\bBearer\s+[A-Za-z0-9._~+/-]+=*\b/gi,
13
- /\b(password|passwd|secret)\s*[:=]\s*\S+/gi,
14
- ];
11
+ /**
12
+ * Programs that print names, never contents, so a directory holding MELRA's
13
+ * files is safe to give them: `ls ..` from a project under home keeps working.
14
+ * Naming the files themselves is still refused.
15
+ */
16
+ const NAME_LISTERS = new Set(["ls", "pwd", "where"]);
15
17
  function inside(root, candidate) {
16
18
  const rel = relative(root, candidate);
17
19
  return rel === "" || (!rel.startsWith(`..${sep}`) && rel !== ".." && !isAbsolute(rel));
18
20
  }
21
+ // The shared list, so terminal output is redacted for exactly the shapes a
22
+ // receipt or a memory value would be.
19
23
  export function redactTerminalOutput(value) {
20
- return SECRET_PATTERNS.reduce((current, pattern) => current.replace(pattern, "[REDACTED]"), value);
24
+ return redactSecrets(value).value;
25
+ }
26
+ /** Where a path leads: through every link, or for one not there yet, through its directory's. */
27
+ async function leadsTo(spelled) {
28
+ return await realpath(spelled).catch(async () => join(await realpath(dirname(spelled)).catch(() => resolve(dirname(spelled))), basename(spelled)));
29
+ }
30
+ /** The null device, so git's system/global config files resolve to nothing. */
31
+ const GIT_NULL_CONFIG = process.platform === "win32" ? "NUL" : "/dev/null";
32
+ /**
33
+ * git subcommands policy classifies as approval-free reads (the same set as
34
+ * `READ_ONLY_GIT_ACTIONS` in policy-core). Kept here, not imported, because this
35
+ * is the spawn boundary and it has to decide for itself what git it is about to
36
+ * run — policy cannot see what the .git/config of the repo will do.
37
+ */
38
+ const GIT_READ_SUBCOMMANDS = new Set(["branch", "diff", "log", "rev-parse", "show", "status", "tag"]);
39
+ /** The read subcommands that emit diffs — the only ones that accept the diff flags below. */
40
+ const GIT_DIFF_SUBCOMMANDS = new Set(["diff", "log", "show"]);
41
+ /** Whether a command, path-qualified or not, is the git program by name. */
42
+ function isGitCommand(command) {
43
+ return (basename(command.replaceAll("\\", "/")).toLowerCase().replace(/\.(exe|cmd|bat|com|ps1)$/, "") ===
44
+ "git");
45
+ }
46
+ /**
47
+ * Settings that each turn off a whole family of programs git can run while
48
+ * serving a read: hooks (every hook, through one hooks path), signature
49
+ * verifiers (every format's program), and fetching objects a partial clone is
50
+ * missing (every transport, proxy and credential program behind it). Each is a
51
+ * `-c` or an environment variable, so it also reaches any git a read starts in
52
+ * turn, such as a submodule's.
53
+ *
54
+ * ponytail: GIT_NO_LAZY_FETCH needs git 2.45; an older git ignores it.
55
+ */
56
+ const GIT_READ_SWITCHES = [
57
+ "-c", "core.fsmonitor=false",
58
+ "-c", `core.hooksPath=${GIT_NULL_CONFIG}`,
59
+ "-c", `gpg.program=${GIT_NULL_CONFIG}`,
60
+ "-c", `gpg.ssh.program=${GIT_NULL_CONFIG}`,
61
+ "-c", `gpg.x509.program=${GIT_NULL_CONFIG}`,
62
+ ];
63
+ /**
64
+ * Policy classifies several `git` subcommands (diff, show, log, status, ...) as
65
+ * approval-free reads, but git runs programs the repository's own config and
66
+ * attributes name while serving one. Those live in the git directory, not in
67
+ * the terminal arguments, so `checkArguments` never sees them, and policy
68
+ * cannot either.
69
+ *
70
+ * The guarantee is that nothing MELRA writes lands in a git directory: the
71
+ * file runtime refuses it (`path_git_metadata`), so only a person approving a
72
+ * command that does so can change what git's config makes it run. This is
73
+ * defence in depth on top: a read-shaped call (subcommand first, as policy
74
+ * requires for a read) spawns with system and global config nulled, the
75
+ * switches above, and external diff and textconv off on the subcommands that
76
+ * emit diffs (the only ones that accept the flags). Mutations — commit, push,
77
+ * or a global option before the subcommand — are left untouched, so a
78
+ * committer's identity and credentials from global config still apply.
79
+ *
80
+ * Pure and exported for unit testing. The caller's `operation.args` are never
81
+ * touched, only the spawned argv, so receipts still quote what was asked.
82
+ */
83
+ export function hardenGitRead(command, args) {
84
+ if (!isGitCommand(command))
85
+ return undefined;
86
+ const first = args[0];
87
+ if (first === undefined || !GIT_READ_SUBCOMMANDS.has(first.toLowerCase()))
88
+ return undefined;
89
+ const diffFlags = GIT_DIFF_SUBCOMMANDS.has(first.toLowerCase())
90
+ ? ["--no-ext-diff", "--no-textconv"]
91
+ : [];
92
+ return {
93
+ args: [...GIT_READ_SWITCHES, first, ...diffFlags, ...args.slice(1)],
94
+ env: { GIT_CONFIG_SYSTEM: GIT_NULL_CONFIG, GIT_CONFIG_GLOBAL: GIT_NULL_CONFIG, GIT_NO_LAZY_FETCH: "1" },
95
+ };
21
96
  }
22
97
  /**
23
98
  * `spawn` reports a missing program as a bare `ENOENT` naming only the syscall,
@@ -33,15 +108,73 @@ function describeSpawnError(error, command) {
33
108
  }
34
109
  /** How long a signalled child gets to exit on its own before SIGKILL. */
35
110
  const CLOSE_GRACE_MS = 2_000;
111
+ /** How long a SIGTERM gets before SIGKILL when a run times out or is cancelled. */
112
+ const KILL_GRACE_MS = 1_000;
113
+ /**
114
+ * How long after the command exits its output pipes may stay open. A process
115
+ * it started can inherit them and keep them open for as long as it lives,
116
+ * which held a run, its timeout and its cancel, until that process ended.
117
+ */
118
+ const EXIT_DRAIN_MS = 250;
119
+ /** Jobs kept at once, running or finished; the oldest finished one makes room. */
120
+ const MAX_JOBS = 64;
121
+ /**
122
+ * Each command leads its own process group on POSIX, so a timeout, a cancel
123
+ * or `stop` reaches what it started too, not only the program itself. Windows
124
+ * has no process groups to signal; `taskkill /T` walks the tree instead.
125
+ */
126
+ const OWN_GROUP = process.platform !== "win32";
127
+ function signalTree(child, signal) {
128
+ if (child.pid === undefined)
129
+ return;
130
+ if (!OWN_GROUP) {
131
+ // `/F` because Windows has no SIGTERM to trap: TerminateProcess is all
132
+ // `child.kill` did there too.
133
+ spawn("taskkill", ["/pid", String(child.pid), "/T", "/F"], { stdio: "ignore", windowsHide: true })
134
+ .on("error", () => child.kill(signal));
135
+ return;
136
+ }
137
+ try {
138
+ process.kill(-child.pid, signal);
139
+ }
140
+ catch {
141
+ // The group is already gone.
142
+ }
143
+ }
144
+ /** SIGTERM to the tree now and SIGKILL shortly after, unless it has all exited. */
145
+ function stopTree(child, graceMs) {
146
+ signalTree(child, "SIGTERM");
147
+ const escalation = setTimeout(() => signalTree(child, "SIGKILL"), graceMs);
148
+ escalation.unref();
149
+ return escalation;
150
+ }
151
+ /** Once the command exits, its pipes get a moment to drain and are then closed. */
152
+ function closePipesAfterExit(child) {
153
+ child.once("exit", () => {
154
+ setTimeout(() => {
155
+ child.stdout?.destroy();
156
+ child.stderr?.destroy();
157
+ }, EXIT_DRAIN_MS).unref();
158
+ });
159
+ }
36
160
  export class TerminalRuntime {
37
161
  root;
38
162
  allowedEnvironment;
39
163
  baseEnvironment;
164
+ /** The root as policy spelled it, which is what "spelled inside" is measured against. */
165
+ lexicalRoot;
166
+ reserved;
167
+ holdsReserved;
168
+ confineArguments;
40
169
  jobs = new Map();
41
170
  constructor(options, root) {
42
171
  this.root = root;
43
172
  this.allowedEnvironment = new Set(options.allowedEnvironment ?? ["CI", "LANG", "LC_ALL", "NO_COLOR", "TERM"]);
44
173
  this.baseEnvironment = options.baseEnvironment ?? process.env;
174
+ this.lexicalRoot = resolve(options.root);
175
+ this.reserved = options.reserved ?? (async () => false);
176
+ this.holdsReserved = options.holdsReserved ?? (async () => false);
177
+ this.confineArguments = options.confineArguments ?? false;
45
178
  }
46
179
  static async create(options) {
47
180
  return new TerminalRuntime(options, await realpath(options.root));
@@ -55,6 +188,28 @@ export class TerminalRuntime {
55
188
  throw new Error("cwd_outside_workspace");
56
189
  return actual;
57
190
  }
191
+ async checkArguments(operation, cwd) {
192
+ const lexicalCwd = resolve(this.lexicalRoot, operation.cwd ?? ".");
193
+ // A path-qualified program is whatever file sits at that path, so only a
194
+ // bare name is taken at its word.
195
+ const command = operation.command ?? "";
196
+ const listsNames = !/[\\/]/.test(command) &&
197
+ NAME_LISTERS.has(command.toLowerCase().replace(/\.(exe|cmd|bat|com|ps1)$/, ""));
198
+ for (const path of [".", ...terminalArgumentPaths(operation.args)]) {
199
+ // Unnormalised: the program resolves `link/..` through the link.
200
+ const real = await leadsTo(isAbsolute(path) ? path : `${cwd}${sep}${path}`);
201
+ // findstr and where expand their own wildcards, reading the directory.
202
+ for (const probe of /[*?]/.test(path) ? [real, dirname(real)] : [real]) {
203
+ if ((await this.reserved(probe)) || (!listsNames && (await this.holdsReserved(probe)))) {
204
+ throw new Error("terminal_path_reserved");
205
+ }
206
+ }
207
+ const spelledInside = inside(this.lexicalRoot, resolve(lexicalCwd, path));
208
+ if (this.confineArguments && spelledInside && !inside(this.root, real)) {
209
+ throw new Error("terminal_path_outside_workspace");
210
+ }
211
+ }
212
+ }
58
213
  async prepare(operation) {
59
214
  if (operation.command === undefined) {
60
215
  throw new Error(`terminal_${operation.action}_requires_command`);
@@ -63,6 +218,9 @@ export class TerminalRuntime {
63
218
  throw new Error("terminal_input_contains_null");
64
219
  }
65
220
  const cwd = await this.resolveCwd(operation.cwd);
221
+ // Before the program is looked up, so a refusal never depends on whether
222
+ // it is installed.
223
+ await this.checkArguments(operation, cwd);
66
224
  const environment = {};
67
225
  for (const name of ["PATH", "PATHEXT", "SYSTEMROOT", "WINDIR", "COMSPEC"]) {
68
226
  if (this.baseEnvironment[name] !== undefined) {
@@ -86,37 +244,50 @@ export class TerminalRuntime {
86
244
  pathExt: environment["PATHEXT"],
87
245
  comspec: this.baseEnvironment["COMSPEC"],
88
246
  });
247
+ // Disable git's config-defined program channels on a read at the spawn
248
+ // boundary, since policy cannot see .git/config (see hardenGitRead).
249
+ // Skipped when resolveCommand wrapped the call in cmd.exe, where `args` is an
250
+ // already-quoted command line rather than git's own arguments.
251
+ const hardened = resolved.windowsVerbatimArguments
252
+ ? undefined
253
+ : hardenGitRead(resolved.executable, resolved.args);
89
254
  return {
90
255
  command: operation.command,
91
256
  args: operation.args,
92
257
  file: resolved.file,
93
- spawnArgs: resolved.args,
258
+ spawnArgs: hardened?.args ?? resolved.args,
94
259
  windowsVerbatimArguments: resolved.windowsVerbatimArguments,
95
260
  executable: resolved.executable,
96
261
  cwd,
97
- environment,
262
+ environment: hardened === undefined ? environment : { ...environment, ...hardened.env },
98
263
  timeoutMs: operation.timeoutMs,
99
264
  maxOutputChars: operation.maxOutputChars,
100
265
  interactive: operation.interactive,
101
266
  };
102
267
  }
103
268
  async runForeground(prepared, signal) {
269
+ if (signal?.aborted === true)
270
+ throw new Error("task_cancelled");
104
271
  return await new Promise((resolvePromise, reject) => {
105
272
  const child = spawn(prepared.file, prepared.spawnArgs, {
106
273
  cwd: prepared.cwd,
107
274
  env: prepared.environment,
108
275
  shell: false,
276
+ detached: OWN_GROUP,
109
277
  windowsHide: true,
110
278
  windowsVerbatimArguments: prepared.windowsVerbatimArguments,
111
279
  stdio: ["ignore", "pipe", "pipe"],
112
- signal,
113
280
  });
114
281
  let stdout = "";
115
282
  let stderr = "";
116
283
  let truncated = false;
117
284
  let timedOut = false;
285
+ let settled = false;
286
+ // Decoded across chunks, so a character split between two reads stays one.
287
+ child.stdout.setEncoding("utf8");
288
+ child.stderr.setEncoding("utf8");
118
289
  const append = (current, chunk) => {
119
- const next = current + chunk.toString("utf8");
290
+ const next = current + chunk;
120
291
  if (next.length > prepared.maxOutputChars) {
121
292
  truncated = true;
122
293
  return next.slice(0, prepared.maxOutputChars);
@@ -131,16 +302,45 @@ export class TerminalRuntime {
131
302
  });
132
303
  const timer = setTimeout(() => {
133
304
  timedOut = true;
134
- child.kill("SIGTERM");
135
- setTimeout(() => child.kill("SIGKILL"), 1_000).unref();
305
+ stopTree(child, KILL_GRACE_MS);
136
306
  }, prepared.timeoutMs);
137
307
  timer.unref();
308
+ // Not spawn's own `signal` option: that sends SIGTERM to the program
309
+ // alone, and its listener is gone once the program exits, so a program
310
+ // that traps SIGTERM, or anything it started, outlived the cancel.
311
+ const onAbort = () => {
312
+ if (settled)
313
+ return;
314
+ settled = true;
315
+ clearTimeout(timer);
316
+ stopTree(child, KILL_GRACE_MS);
317
+ // It may well have done its work (written the file, pushed the
318
+ // branch) before it was stopped, so this is not "it did not happen".
319
+ const reason = signal?.reason instanceof Error ? signal.reason.message : "task_cancelled";
320
+ reject(outcomeUnknown(reason));
321
+ };
322
+ signal?.addEventListener("abort", onAbort, { once: true });
323
+ closePipesAfterExit(child);
324
+ // A foreground run is over when its program is; whatever it left behind
325
+ // in its group goes with it.
326
+ child.once("exit", () => {
327
+ if (OWN_GROUP)
328
+ signalTree(child, "SIGTERM");
329
+ });
138
330
  child.once("error", (error) => {
139
331
  clearTimeout(timer);
332
+ signal?.removeEventListener("abort", onAbort);
333
+ if (settled)
334
+ return;
335
+ settled = true;
140
336
  reject(describeSpawnError(error, prepared.command));
141
337
  });
142
338
  child.once("close", (code, terminationSignal) => {
143
339
  clearTimeout(timer);
340
+ signal?.removeEventListener("abort", onAbort);
341
+ if (settled)
342
+ return;
343
+ settled = true;
144
344
  resolvePromise({
145
345
  command: prepared.command,
146
346
  args: prepared.args,
@@ -157,19 +357,25 @@ export class TerminalRuntime {
157
357
  });
158
358
  }
159
359
  async startBackground(prepared) {
360
+ // Jobs are kept for their output after they end, so a caller looping
361
+ // `start` grew memory and processes for the life of the server.
362
+ if (this.jobs.size >= MAX_JOBS) {
363
+ const finished = [...this.jobs.values()].find((candidate) => candidate.endedAt !== undefined);
364
+ if (finished === undefined)
365
+ throw new Error("terminal_too_many_jobs");
366
+ this.jobs.delete(finished.id);
367
+ }
160
368
  const id = randomUUID();
161
369
  const child = spawn(prepared.file, prepared.spawnArgs, {
162
370
  cwd: prepared.cwd,
163
371
  env: prepared.environment,
164
372
  shell: false,
373
+ detached: OWN_GROUP,
165
374
  windowsHide: true,
166
375
  windowsVerbatimArguments: prepared.windowsVerbatimArguments,
167
376
  stdio: [prepared.interactive ? "pipe" : "ignore", "pipe", "pipe"],
168
377
  });
169
- const timer = setTimeout(() => {
170
- child.kill("SIGTERM");
171
- setTimeout(() => child.kill("SIGKILL"), 1_000).unref();
172
- }, prepared.timeoutMs);
378
+ const timer = setTimeout(() => stopTree(child, KILL_GRACE_MS), prepared.timeoutMs);
173
379
  timer.unref();
174
380
  const job = {
175
381
  id,
@@ -184,19 +390,27 @@ export class TerminalRuntime {
184
390
  timer,
185
391
  };
186
392
  const append = (current, chunk) => {
187
- const next = current + chunk.toString("utf8");
393
+ const next = current + chunk;
188
394
  if (next.length > prepared.maxOutputChars) {
189
395
  job.truncated = true;
190
396
  return next.slice(0, prepared.maxOutputChars);
191
397
  }
192
398
  return next;
193
399
  };
400
+ child.stdout?.setEncoding("utf8");
401
+ child.stderr?.setEncoding("utf8");
194
402
  child.stdout?.on("data", (chunk) => {
195
403
  job.stdout = append(job.stdout, chunk);
196
404
  });
197
405
  child.stderr?.on("data", (chunk) => {
198
406
  job.stderr = append(job.stderr, chunk);
199
407
  });
408
+ // A write to a reader that has gone fails later, as an error event on the
409
+ // pipe. Unheard, that event took the whole server down.
410
+ child.stdin?.on("error", (error) => {
411
+ job.stdinError = error.message;
412
+ });
413
+ closePipesAfterExit(child);
200
414
  child.once("error", (error) => {
201
415
  job.error = error.message;
202
416
  job.endedAt = new Date().toISOString();
@@ -259,6 +473,8 @@ export class TerminalRuntime {
259
473
  if (stdin === null || stdin.destroyed || !stdin.writable) {
260
474
  throw new Error("terminal_job_not_interactive");
261
475
  }
476
+ if (job.stdinError !== undefined)
477
+ throw new Error("terminal_job_stdin_closed");
262
478
  const payload = operation.appendNewline && !operation.input.endsWith("\n")
263
479
  ? `${operation.input}\n`
264
480
  : operation.input;
@@ -316,7 +532,7 @@ export class TerminalRuntime {
316
532
  case "stop": {
317
533
  const job = this.job(operation);
318
534
  if (job.endedAt === undefined)
319
- job.child.kill("SIGTERM");
535
+ stopTree(job.child, CLOSE_GRACE_MS);
320
536
  return { stopped: true, ...this.jobResult(job, true) };
321
537
  }
322
538
  }
@@ -333,11 +549,9 @@ export class TerminalRuntime {
333
549
  if (job.endedAt !== undefined)
334
550
  return;
335
551
  const exited = new Promise((done) => job.child.once("close", () => done()));
336
- job.child.kill("SIGTERM");
337
552
  // A child is free to trap SIGTERM, and shutdown blocking forever on one
338
553
  // that does is worse than the race this replaced.
339
- const escalation = setTimeout(() => job.child.kill("SIGKILL"), CLOSE_GRACE_MS);
340
- escalation.unref();
554
+ const escalation = stopTree(job.child, CLOSE_GRACE_MS);
341
555
  await exited;
342
556
  clearTimeout(escalation);
343
557
  });
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -30,6 +30,12 @@ export interface ResolveCommandOptions {
30
30
  * the allowlist would otherwise be bypassable by `npm install "%FOO%"`.
31
31
  * Newlines are refused for the same reason: a command line cannot carry one.
32
32
  *
33
+ * So is `"`. `CommandLineToArgvW` reads `\"` as a literal quote, but `cmd.exe`
34
+ * does not: to it every `"` toggles quoting, so `a" & calc & "` closed the
35
+ * quotes and ran `calc` as cmd syntax (BatBadBut). There is no escape both
36
+ * layers agree on, and a quote inside an argument to a batch shim is rare
37
+ * enough that refusing it costs little.
38
+ *
33
39
  * Written as a scan rather than `/(\\*)"/g` + `/(\\*)$/`: both of those
34
40
  * backtrack quadratically, and an argument of 40k backslashes took 11s to quote
35
41
  * before this. An attacker-supplied argument is exactly the input this sees.
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-command.d.ts","sourceRoot":"","sources":["../src/resolve-command.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,kEAAkE;IAClE,wBAAwB,EAAE,OAAO,CAAC;IAClC,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,2EAA2E;IAC3E,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAClD;AAoBD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqBjD;AAgDD;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAiC1B"}
1
+ {"version":3,"file":"resolve-command.d.ts","sourceRoot":"","sources":["../src/resolve-command.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,kEAAkE;IAClE,wBAAwB,EAAE,OAAO,CAAC;IAClC,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,2EAA2E;IAC3E,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAClD;AAoBD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqBjD;AAgDD;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAiC1B"}
@@ -33,12 +33,18 @@ async function isFile(candidate) {
33
33
  * the allowlist would otherwise be bypassable by `npm install "%FOO%"`.
34
34
  * Newlines are refused for the same reason: a command line cannot carry one.
35
35
  *
36
+ * So is `"`. `CommandLineToArgvW` reads `\"` as a literal quote, but `cmd.exe`
37
+ * does not: to it every `"` toggles quoting, so `a" & calc & "` closed the
38
+ * quotes and ran `calc` as cmd syntax (BatBadBut). There is no escape both
39
+ * layers agree on, and a quote inside an argument to a batch shim is rare
40
+ * enough that refusing it costs little.
41
+ *
36
42
  * Written as a scan rather than `/(\\*)"/g` + `/(\\*)$/`: both of those
37
43
  * backtrack quadratically, and an argument of 40k backslashes took 11s to quote
38
44
  * before this. An attacker-supplied argument is exactly the input this sees.
39
45
  */
40
46
  export function quoteForCmd(value) {
41
- if (/[%!\r\n]/.test(value)) {
47
+ if (/[%!"\r\n]/.test(value)) {
42
48
  throw new Error("terminal_windows_argument_not_quotable");
43
49
  }
44
50
  let escaped = "";
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-command.js","sourceRoot":"","sources":["../src/resolve-command.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolve-command.js","sourceRoot":"","sources":["../src/resolve-command.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@melra/terminal-runtime",
3
- "version": "0.3.0-alpha.11",
3
+ "version": "0.3.0-alpha.13",
4
4
  "description": "Shell-free supervised terminal reference effect adapter for the MELRA kernel.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -21,12 +21,13 @@
21
21
  "dist"
22
22
  ],
23
23
  "dependencies": {
24
- "@melra/protocol": "0.3.0-alpha.11"
24
+ "@melra/protocol": "0.3.0-alpha.13",
25
+ "@melra/receipt-schema": "0.3.0-alpha.13"
25
26
  },
26
27
  "scripts": {
27
28
  "build": "tsc -p tsconfig.json",
28
29
  "clean": "rm -rf dist",
29
30
  "test": "vitest run",
30
- "typecheck": "tsc -p tsconfig.json --noEmit"
31
+ "typecheck": "tsc -p tsconfig.test.json"
31
32
  }
32
33
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=index.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":""}
@@ -1,168 +0,0 @@
1
- // Copyright 2026 XAGI Labs Private Limited
2
- // SPDX-License-Identifier: Apache-2.0
3
- import { mkdtemp, rm } from "node:fs/promises";
4
- import { tmpdir } from "node:os";
5
- import { join } from "node:path";
6
- import { afterEach, describe, expect, it } from "vitest";
7
- import { TerminalOperationSchema } from "@melra/protocol";
8
- import { TerminalRuntime, redactTerminalOutput } from "./index.js";
9
- const roots = [];
10
- afterEach(async () => {
11
- await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })));
12
- });
13
- describe("TerminalRuntime", () => {
14
- it("runs executable and argument arrays without a shell", async () => {
15
- const root = await mkdtemp(join(tmpdir(), "melra-terminal-"));
16
- roots.push(root);
17
- const runtime = await TerminalRuntime.create({ root });
18
- const result = await runtime.execute(TerminalOperationSchema.parse({
19
- kind: "terminal",
20
- action: "run",
21
- command: process.execPath,
22
- args: ["-e", "process.stdout.write(process.argv[1])", "hello; touch nope"],
23
- }));
24
- expect(result.success).toBe(true);
25
- expect(result.stdout).toBe("hello; touch nope");
26
- });
27
- it("redacts secret-shaped output", () => {
28
- expect(redactTerminalOutput("password=hunter2 ghp_123456789012345678901234")).not.toContain("hunter2");
29
- });
30
- it("stops commands at the configured timeout", async () => {
31
- const root = await mkdtemp(join(tmpdir(), "melra-terminal-"));
32
- roots.push(root);
33
- const runtime = await TerminalRuntime.create({ root });
34
- const result = await runtime.execute(TerminalOperationSchema.parse({
35
- kind: "terminal",
36
- action: "run",
37
- command: process.execPath,
38
- args: ["-e", "setTimeout(() => {}, 10_000)"],
39
- timeoutMs: 150,
40
- }));
41
- expect(result.timedOut).toBe(true);
42
- expect(result.success).toBe(false);
43
- });
44
- it("supervises bounded background jobs and output", async () => {
45
- const root = await mkdtemp(join(tmpdir(), "melra-terminal-"));
46
- roots.push(root);
47
- const runtime = await TerminalRuntime.create({ root });
48
- const started = await runtime.execute(TerminalOperationSchema.parse({
49
- kind: "terminal",
50
- action: "start",
51
- command: process.execPath,
52
- args: [
53
- "-e",
54
- "process.stdout.write('background-ready'); setTimeout(() => {}, 150)",
55
- ],
56
- timeoutMs: 2_000,
57
- }));
58
- expect(started.started).toBe(true);
59
- // The child writes its output and then exits on its own. How long that
60
- // takes depends on process startup under CI load, so poll for completion
61
- // rather than assuming it finishes within a fixed wall-clock delay.
62
- const deadline = Date.now() + 10_000;
63
- const readOutput = async () => runtime.execute(TerminalOperationSchema.parse({
64
- kind: "terminal",
65
- action: "output",
66
- jobId: started.jobId,
67
- }));
68
- let output = await readOutput();
69
- while (output.running === true && Date.now() < deadline) {
70
- await new Promise((resolvePromise) => setTimeout(resolvePromise, 25));
71
- output = await readOutput();
72
- }
73
- expect(output.stdout).toContain("background-ready");
74
- expect(output.running).toBe(false);
75
- await runtime.close();
76
- }, 30_000);
77
- it("answers a running job's prompt and refuses one that cannot be answered", async () => {
78
- const root = await mkdtemp(join(tmpdir(), "melra-terminal-"));
79
- roots.push(root);
80
- const runtime = await TerminalRuntime.create({ root });
81
- const script = "process.stdout.write('name? ');" +
82
- "process.stdin.once('data', (d) => { process.stdout.write('hello ' + String(d).trim()); process.exit(0); })";
83
- const start = (interactive) => runtime.execute(TerminalOperationSchema.parse({
84
- kind: "terminal",
85
- action: "start",
86
- command: process.execPath,
87
- args: ["-e", script],
88
- interactive,
89
- timeoutMs: 5_000,
90
- }));
91
- const interactive = await start(true);
92
- const sent = await runtime.execute(TerminalOperationSchema.parse({
93
- kind: "terminal",
94
- action: "send",
95
- jobId: interactive.jobId,
96
- input: "melra",
97
- }));
98
- expect(sent.sent).toBe(true);
99
- const deadline = Date.now() + 10_000;
100
- const readOutput = async (jobId) => runtime.execute(TerminalOperationSchema.parse({
101
- kind: "terminal",
102
- action: "output",
103
- jobId,
104
- }));
105
- let output = await readOutput(interactive.jobId);
106
- while (output.running === true && Date.now() < deadline) {
107
- await new Promise((done) => setTimeout(done, 25));
108
- output = await readOutput(interactive.jobId);
109
- }
110
- expect(output.stdout).toContain("hello melra");
111
- // Without `interactive`, stdin is ignored rather than piped. Writing to it
112
- // would throw EPIPE asynchronously and surface as an unhandled error, so
113
- // the refusal has to come first and name the reason.
114
- const plain = await start(false);
115
- await expect(runtime.execute(TerminalOperationSchema.parse({
116
- kind: "terminal",
117
- action: "send",
118
- jobId: plain.jobId,
119
- input: "melra",
120
- }))).rejects.toThrow("terminal_job_not_interactive");
121
- await runtime.close();
122
- }, 30_000);
123
- it("names a missing program instead of surfacing a bare ENOENT", async () => {
124
- const root = await mkdtemp(join(tmpdir(), "melra-terminal-"));
125
- roots.push(root);
126
- const runtime = await TerminalRuntime.create({ root });
127
- await expect(runtime.execute(TerminalOperationSchema.parse({
128
- kind: "terminal",
129
- action: "run",
130
- command: "melra-program-that-does-not-exist",
131
- }))).rejects.toThrow("terminal_command_not_found");
132
- await runtime.close();
133
- });
134
- it("does not report a background job that never started", async () => {
135
- // `spawn` reports a failed start asynchronously, so this used to resolve
136
- // with `started: true` and a job id for a process that never existed.
137
- const root = await mkdtemp(join(tmpdir(), "melra-terminal-"));
138
- roots.push(root);
139
- const runtime = await TerminalRuntime.create({ root });
140
- await expect(runtime.execute(TerminalOperationSchema.parse({
141
- kind: "terminal",
142
- action: "start",
143
- command: "melra-program-that-does-not-exist",
144
- }))).rejects.toThrow("terminal_command_not_found");
145
- await runtime.close();
146
- });
147
- it("does not resolve close until its children have actually exited", async () => {
148
- // A signalled-but-live child holds its cwd open on Windows, so a caller
149
- // deleting the workspace right after close raced rmdir and got EBUSY.
150
- // Signalling is not exiting; this asserts the difference.
151
- const root = await mkdtemp(join(tmpdir(), "melra-terminal-"));
152
- roots.push(root);
153
- const runtime = await TerminalRuntime.create({ root });
154
- const started = await runtime.execute(TerminalOperationSchema.parse({
155
- kind: "terminal",
156
- action: "start",
157
- command: process.execPath,
158
- args: ["-e", "setTimeout(() => {}, 30_000)"],
159
- timeoutMs: 30_000,
160
- }));
161
- const pid = started.pid;
162
- await runtime.close();
163
- // Signal 0 tests for the process rather than signalling it: ESRCH means it
164
- // is gone, and no throw means close resolved while it was still running.
165
- expect(() => process.kill(pid, 0)).toThrow(/ESRCH/);
166
- }, 30_000);
167
- });
168
- //# sourceMappingURL=index.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,sCAAsC;AAEtC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,KAAK,GAAa,EAAE,CAAC;AAE3B,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/F,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC9D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAClC,uBAAuB,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,OAAO,CAAC,QAAQ;YACzB,IAAI,EAAE,CAAC,IAAI,EAAE,uCAAuC,EAAE,mBAAmB,CAAC;SAC3E,CAAC,CACH,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,CACJ,oBAAoB,CAAC,+CAA+C,CAAC,CACtE,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC9D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAClC,uBAAuB,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,OAAO,CAAC,QAAQ;YACzB,IAAI,EAAE,CAAC,IAAI,EAAE,8BAA8B,CAAC;YAC5C,SAAS,EAAE,GAAG;SACf,CAAC,CACH,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC9D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CACnC,uBAAuB,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,OAAO,CAAC,QAAQ;YACzB,IAAI,EAAE;gBACJ,IAAI;gBACJ,qEAAqE;aACtE;YACD,SAAS,EAAE,KAAK;SACjB,CAAC,CACH,CAAC;QACF,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnC,uEAAuE;QACvE,yEAAyE;QACzE,oEAAoE;QACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC;QACrC,MAAM,UAAU,GAAG,KAAK,IAAI,EAAE,CAC5B,OAAO,CAAC,OAAO,CACb,uBAAuB,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,QAAQ;YAChB,KAAK,EAAE,OAAO,CAAC,KAAK;SACrB,CAAC,CACH,CAAC;QACJ,IAAI,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YACxD,MAAM,IAAI,OAAO,CAAC,CAAC,cAAc,EAAE,EAAE,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAC;YACtE,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAC9B,CAAC;QACD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;QACpD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC,EAAE,MAAM,CAAC,CAAC;IAEX,EAAE,CAAC,wEAAwE,EAAE,KAAK,IAAI,EAAE;QACtF,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC9D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,MAAM,GACV,iCAAiC;YACjC,4GAA4G,CAAC;QAC/G,MAAM,KAAK,GAAG,CAAC,WAAoB,EAAE,EAAE,CACrC,OAAO,CAAC,OAAO,CACb,uBAAuB,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,OAAO,CAAC,QAAQ;YACzB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC;YACpB,WAAW;YACX,SAAS,EAAE,KAAK;SACjB,CAAC,CACH,CAAC;QAEJ,MAAM,WAAW,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAChC,uBAAuB,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,MAAM;YACd,KAAK,EAAE,WAAW,CAAC,KAAK;YACxB,KAAK,EAAE,OAAO;SACf,CAAC,CACH,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC;QACrC,MAAM,UAAU,GAAG,KAAK,EAAE,KAAc,EAAE,EAAE,CAC1C,OAAO,CAAC,OAAO,CACb,uBAAuB,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,QAAQ;YAChB,KAAK;SACN,CAAC,CACH,CAAC;QACJ,IAAI,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACjD,OAAO,MAAM,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YACxD,MAAM,IAAI,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;YAClD,MAAM,GAAG,MAAM,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC/C,CAAC;QACD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QAE/C,2EAA2E;QAC3E,yEAAyE;QACzE,qDAAqD;QACrD,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,MAAM,CACV,OAAO,CAAC,OAAO,CACb,uBAAuB,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,MAAM;YACd,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,OAAO;SACf,CAAC,CACH,CACF,CAAC,OAAO,CAAC,OAAO,CAAC,8BAA8B,CAAC,CAAC;QAClD,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC,EAAE,MAAM,CAAC,CAAC;IAEX,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC9D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,MAAM,CACV,OAAO,CAAC,OAAO,CACb,uBAAuB,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,KAAK;YACb,OAAO,EAAE,mCAAmC;SAC7C,CAAC,CACH,CACF,CAAC,OAAO,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;QAChD,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,yEAAyE;QACzE,sEAAsE;QACtE,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC9D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,MAAM,CACV,OAAO,CAAC,OAAO,CACb,uBAAuB,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,mCAAmC;SAC7C,CAAC,CACH,CACF,CAAC,OAAO,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;QAChD,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;QAC9E,wEAAwE;QACxE,sEAAsE;QACtE,0DAA0D;QAC1D,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC;QAC9D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CACnC,uBAAuB,CAAC,KAAK,CAAC;YAC5B,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,OAAO,CAAC,QAAQ;YACzB,IAAI,EAAE,CAAC,IAAI,EAAE,8BAA8B,CAAC;YAC5C,SAAS,EAAE,MAAM;SAClB,CAAC,CACH,CAAC;QACF,MAAM,GAAG,GAAG,OAAO,CAAC,GAAa,CAAC;QAClC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,2EAA2E;QAC3E,yEAAyE;QACzE,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,CAAC,EAAE,MAAM,CAAC,CAAC;AACb,CAAC,CAAC,CAAC"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=resolve-command.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"resolve-command.test.d.ts","sourceRoot":"","sources":["../src/resolve-command.test.ts"],"names":[],"mappings":""}
@@ -1,108 +0,0 @@
1
- // Copyright 2026 XAGI Labs Private Limited
2
- // SPDX-License-Identifier: Apache-2.0
3
- import { describe, expect, it } from "vitest";
4
- import { quoteForCmd, resolveCommand } from "./resolve-command.js";
5
- /**
6
- * These run the Windows branch on every host. The Windows breakage shipped green
7
- * through a CI matrix that *includes* `windows-latest` precisely because nothing
8
- * exercised the win32 path, so platform and filesystem are injected rather than
9
- * detected.
10
- */
11
- const WINDOWS_FILES = new Set([
12
- "C:\\Program Files\\nodejs\\npm.cmd",
13
- "C:\\Program Files\\nodejs\\node.exe",
14
- "C:\\Windows\\System32\\where.exe",
15
- // npm also ships a POSIX shell script with no extension, right next to the
16
- // shim. It is not runnable on Windows.
17
- "C:\\Program Files\\nodejs\\npm",
18
- ].map((item) => item.toLowerCase()));
19
- const windows = {
20
- cwd: "C:\\workspace",
21
- platform: "win32",
22
- path: "C:\\Program Files\\nodejs;C:\\Windows\\System32",
23
- pathExt: ".COM;.EXE;.BAT;.CMD",
24
- comspec: "C:\\Windows\\System32\\cmd.exe",
25
- exists: async (candidate) => WINDOWS_FILES.has(candidate.toLowerCase()),
26
- };
27
- describe("resolveCommand", () => {
28
- it("leaves POSIX commands untouched", async () => {
29
- await expect(resolveCommand("git", ["status"], {
30
- cwd: "/workspace",
31
- platform: "linux",
32
- })).resolves.toEqual({
33
- file: "git",
34
- args: ["status"],
35
- windowsVerbatimArguments: false,
36
- executable: "git",
37
- });
38
- });
39
- it("resolves a bare Windows name to its .exe", async () => {
40
- const resolved = await resolveCommand("node", ["-v"], windows);
41
- expect(resolved.file.toLowerCase()).toBe("c:\\program files\\nodejs\\node.exe");
42
- expect(resolved.args).toEqual(["-v"]);
43
- expect(resolved.windowsVerbatimArguments).toBe(false);
44
- });
45
- it("prefers the .cmd shim over the extension-less POSIX script", async () => {
46
- // The deadlock in miniature: `npm` is what policy allowlists, `npm.cmd` is
47
- // what Windows can actually start, and `npm` (the sh script) is a trap.
48
- const resolved = await resolveCommand("npm", ["install"], windows);
49
- expect(resolved.executable.toLowerCase()).toBe("c:\\program files\\nodejs\\npm.cmd");
50
- });
51
- it("runs a batch shim through cmd.exe with the payload quoted", async () => {
52
- const resolved = await resolveCommand("npm", ["run", "build"], windows);
53
- expect(resolved.file).toBe("C:\\Windows\\System32\\cmd.exe");
54
- expect(resolved.windowsVerbatimArguments).toBe(true);
55
- expect(resolved.args.slice(0, 3)).toEqual(["/d", "/s", "/c"]);
56
- expect(resolved.args[3]).toBe('""C:\\Program Files\\nodejs\\npm.cmd" "run" "build""');
57
- });
58
- it("keeps shell metacharacters inside the quoted argument", async () => {
59
- // Without quoting, cmd.exe would treat `&&` as a separator and run a second
60
- // program that policy never allowlisted.
61
- const resolved = await resolveCommand("npm", ["install", "x && calc.exe"], windows);
62
- expect(resolved.args[3]).toContain('"install" "x && calc.exe"');
63
- });
64
- it("refuses arguments cmd.exe would expand rather than quoting them wrongly", async () => {
65
- await expect(resolveCommand("npm", ["install", "%USERPROFILE%"], windows)).rejects.toThrow("terminal_windows_argument_not_quotable");
66
- });
67
- it("reports a missing program by name instead of a bare ENOENT", async () => {
68
- await expect(resolveCommand("rg", [], windows)).rejects.toThrow("terminal_command_not_found:rg");
69
- });
70
- it("does not search the working directory for a bare command", async () => {
71
- // A `git.cmd` dropped in the workspace must not shadow the allowlisted git.
72
- await expect(resolveCommand("git", [], {
73
- ...windows,
74
- exists: async (candidate) => candidate.toLowerCase() === "c:\\workspace\\git.cmd",
75
- })).rejects.toThrow("terminal_command_not_found:git");
76
- });
77
- it("still honours an explicitly directory-qualified command", async () => {
78
- const resolved = await resolveCommand(".\\tool", [], {
79
- ...windows,
80
- exists: async (candidate) => candidate.toLowerCase() === "c:\\workspace\\tool.exe",
81
- });
82
- expect(resolved.file.toLowerCase()).toBe("c:\\workspace\\tool.exe");
83
- });
84
- });
85
- describe("quoteForCmd", () => {
86
- it("escapes embedded quotes so the program sees them literally", () => {
87
- expect(quoteForCmd('say "hi"')).toBe('"say \\"hi\\""');
88
- });
89
- it("doubles a trailing backslash run before the closing quote", () => {
90
- expect(quoteForCmd("C:\\path\\")).toBe('"C:\\path\\\\"');
91
- });
92
- it("refuses a newline, which a command line cannot carry", () => {
93
- expect(() => quoteForCmd("a\nb")).toThrow("terminal_windows_argument_not_quotable");
94
- });
95
- it("doubles a backslash run only where a quote consumes it", () => {
96
- // Mid-string backslashes are literal to CommandLineToArgvW; only the run
97
- // that a quote (or the closing quote) eats is doubled.
98
- expect(quoteForCmd('a\\\\b"c')).toBe('"a\\\\b\\"c"');
99
- });
100
- it("quotes a pathological backslash run without backtracking", () => {
101
- // The previous regex pair was quadratic: 40k backslashes took ~11s, which
102
- // an allowlisted `npm install <arg>` could reach from outside.
103
- const started = process.hrtime.bigint();
104
- expect(quoteForCmd("\\".repeat(40_000) + "x")).toHaveLength(40_003);
105
- expect(Number(process.hrtime.bigint() - started) / 1e6).toBeLessThan(500);
106
- });
107
- });
108
- //# sourceMappingURL=resolve-command.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"resolve-command.test.js","sourceRoot":"","sources":["../src/resolve-command.test.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,sCAAsC;AAEtC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEnE;;;;;GAKG;AACH,MAAM,aAAa,GAAG,IAAI,GAAG,CAC3B;IACE,oCAAoC;IACpC,qCAAqC;IACrC,kCAAkC;IAClC,2EAA2E;IAC3E,uCAAuC;IACvC,gCAAgC;CACjC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CACpC,CAAC;AAEF,MAAM,OAAO,GAAG;IACd,GAAG,EAAE,eAAe;IACpB,QAAQ,EAAE,OAAgB;IAC1B,IAAI,EAAE,iDAAiD;IACvD,OAAO,EAAE,qBAAqB;IAC9B,OAAO,EAAE,gCAAgC;IACzC,MAAM,EAAE,KAAK,EAAE,SAAiB,EAAE,EAAE,CAClC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;CAC7C,CAAC;AAEF,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,MAAM,CACV,cAAc,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,EAAE;YAChC,GAAG,EAAE,YAAY;YACjB,QAAQ,EAAE,OAAO;SAClB,CAAC,CACH,CAAC,QAAQ,CAAC,OAAO,CAAC;YACjB,IAAI,EAAE,KAAK;YACX,IAAI,EAAE,CAAC,QAAQ,CAAC;YAChB,wBAAwB,EAAE,KAAK;YAC/B,UAAU,EAAE,KAAK;SAClB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QAC/D,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CACtC,qCAAqC,CACtC,CAAC;QACF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,2EAA2E;QAC3E,wEAAwE;QACxE,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,KAAK,EAAE,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;QACnE,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAC5C,oCAAoC,CACrC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;QACxE,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;QAC7D,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9D,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC3B,sDAAsD,CACvD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,4EAA4E;QAC5E,yCAAyC;QACzC,MAAM,QAAQ,GAAG,MAAM,cAAc,CACnC,KAAK,EACL,CAAC,SAAS,EAAE,eAAe,CAAC,EAC5B,OAAO,CACR,CAAC;QACF,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,MAAM,CACV,cAAc,CAAC,KAAK,EAAE,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE,OAAO,CAAC,CAC7D,CAAC,OAAO,CAAC,OAAO,CAAC,wCAAwC,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAC1E,MAAM,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAC7D,+BAA+B,CAChC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,4EAA4E;QAC5E,MAAM,MAAM,CACV,cAAc,CAAC,KAAK,EAAE,EAAE,EAAE;YACxB,GAAG,OAAO;YACV,MAAM,EAAE,KAAK,EAAE,SAAiB,EAAE,EAAE,CAClC,SAAS,CAAC,WAAW,EAAE,KAAK,wBAAwB;SACvD,CAAC,CACH,CAAC,OAAO,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;QACvE,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,EAAE,EAAE;YACnD,GAAG,OAAO;YACV,MAAM,EAAE,KAAK,EAAE,SAAiB,EAAE,EAAE,CAClC,SAAS,CAAC,WAAW,EAAE,KAAK,yBAAyB;SACxD,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,aAAa,EAAE,GAAG,EAAE;IAC3B,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sDAAsD,EAAE,GAAG,EAAE;QAC9D,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CACvC,wCAAwC,CACzC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,yEAAyE;QACzE,uDAAuD;QACvD,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,0EAA0E;QAC1E,+DAA+D;QAC/D,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACxC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACpE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}