@descryy/runtime-controller 0.2.0 → 0.3.0

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 (61) hide show
  1. package/LICENSE +6 -0
  2. package/dist/capability-registry.d.ts +0 -15
  3. package/dist/capability-registry.d.ts.map +1 -1
  4. package/dist/capability-registry.js +9 -19
  5. package/dist/capability-registry.js.map +1 -1
  6. package/dist/collector-version.d.ts +1 -8
  7. package/dist/collector-version.d.ts.map +1 -1
  8. package/dist/collector-version.js +1 -8
  9. package/dist/collector-version.js.map +1 -1
  10. package/dist/container-sandbox.d.ts +66 -150
  11. package/dist/container-sandbox.d.ts.map +1 -1
  12. package/dist/container-sandbox.js +62 -143
  13. package/dist/container-sandbox.js.map +1 -1
  14. package/dist/controller.d.ts +54 -87
  15. package/dist/controller.d.ts.map +1 -1
  16. package/dist/controller.js +77 -104
  17. package/dist/controller.js.map +1 -1
  18. package/dist/dependency-version-check.d.ts +19 -73
  19. package/dist/dependency-version-check.d.ts.map +1 -1
  20. package/dist/dependency-version-check.js +18 -67
  21. package/dist/dependency-version-check.js.map +1 -1
  22. package/dist/env.d.ts +4 -10
  23. package/dist/env.d.ts.map +1 -1
  24. package/dist/env.js +4 -10
  25. package/dist/env.js.map +1 -1
  26. package/dist/environment-metadata.d.ts +9 -17
  27. package/dist/environment-metadata.d.ts.map +1 -1
  28. package/dist/environment-metadata.js +12 -29
  29. package/dist/environment-metadata.js.map +1 -1
  30. package/dist/environment-version-check.d.ts +22 -65
  31. package/dist/environment-version-check.d.ts.map +1 -1
  32. package/dist/environment-version-check.js +24 -66
  33. package/dist/environment-version-check.js.map +1 -1
  34. package/dist/execution-safety.d.ts +54 -112
  35. package/dist/execution-safety.d.ts.map +1 -1
  36. package/dist/execution-safety.js +48 -102
  37. package/dist/execution-safety.js.map +1 -1
  38. package/dist/index.d.ts +0 -10
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js.map +1 -1
  41. package/dist/orchestration.d.ts +24 -39
  42. package/dist/orchestration.d.ts.map +1 -1
  43. package/dist/orchestration.js +39 -75
  44. package/dist/orchestration.js.map +1 -1
  45. package/dist/process-collector.d.ts +8 -22
  46. package/dist/process-collector.d.ts.map +1 -1
  47. package/dist/process-collector.js +23 -55
  48. package/dist/process-collector.js.map +1 -1
  49. package/dist/process-manager.d.ts +45 -80
  50. package/dist/process-manager.d.ts.map +1 -1
  51. package/dist/process-manager.js +51 -101
  52. package/dist/process-manager.js.map +1 -1
  53. package/dist/readiness.d.ts +28 -70
  54. package/dist/readiness.d.ts.map +1 -1
  55. package/dist/readiness.js +73 -95
  56. package/dist/readiness.js.map +1 -1
  57. package/dist/sandbox.d.ts +60 -105
  58. package/dist/sandbox.d.ts.map +1 -1
  59. package/dist/sandbox.js +78 -121
  60. package/dist/sandbox.js.map +1 -1
  61. package/package.json +7 -2
package/dist/readiness.js CHANGED
@@ -1,65 +1,30 @@
1
1
  /**
2
- * Readiness (plan §6): "Readiness must not equal 'process exists.'" —
3
- * supported strategies are HTTP health check, TCP/port check, a known log
4
- * pattern, a real subprocess command, or a caller-supplied hook (which
5
- * covers the plan's "framework readiness hook" and "user-defined readiness"
6
- * — two names for the same shape, a caller-provided async predicate,
7
- * consolidated into one mechanism rather than two near-identical ones).
2
+ * Readiness (§6): "readiness must not equal 'process exists.'" Mechanisms: HTTP
3
+ * check, TCP/port check, log pattern, subprocess command, or a caller hook
4
+ * (consolidates the plan's "framework readiness hook" and "user-defined readiness"
5
+ * into one predicate shape).
8
6
  *
9
- * **`command` is not `custom-hook` (RT-193).** An earlier version of this
10
- * comment folded the plan's "command check" into `custom-hook` too, on the
11
- * reasoning that both are "a caller-provided check." That collapsed a real
12
- * distinction: `custom-hook` runs a caller's own in-process predicate,
13
- * while `command` runs an actual subprocess and reads its actual exit
14
- * code — the same "declared, not inferred" shape `ServiceConfiguration`'s
15
- * own `command` field already uses, one layer over. A caller with a real
16
- * CLI health check (`pg_isready`, a framework's own readiness script) had
17
- * no way to express that without either wrapping it in a hand-written
18
- * `custom-hook` predicate that shells out itself, or reimplementing the
19
- * subprocess plumbing per caller — `command` is that plumbing, built once.
7
+ * **`command` is not `custom-hook` (RT-193).** `custom-hook` runs a caller's
8
+ * in-process predicate; `command` runs a real subprocess and reads its exit code --
9
+ * built once so a caller with a real CLI health check (`pg_isready`) doesn't have to
10
+ * shell out from inside a hand-written hook.
20
11
  *
21
- * The plan requires recording which mechanism succeeded — `ReadinessResult`
22
- * makes that a field, not something inferred after the fact.
12
+ * **What `ready: true` does not claim (RT-024).** All mechanisms answer "is
13
+ * something listening/responding," none confirm it's the process *this* spawn
14
+ * produced -- a stale listener from an already-dead run satisfies `http`/`tcp-port`
15
+ * identically. `log-pattern` only carries the stronger this-run guarantee if `read`
16
+ * is wired to this execution's own `readOutput()` (caller discipline, not enforced
17
+ * by the type). An ephemeral port closes this gap by construction; a fixed,
18
+ * guessable port doesn't. Found via a real 30s collector timeout that looked like a
19
+ * Playwright bug and was actually a wait on an orphaned process from a dead session
20
+ * (RT-024).
23
21
  *
24
- * **What `ready: true` does and does not claim (RT-024).** All four
25
- * mechanisms answer one question — is something listening / responding
26
- * where expected — and none answer whether it is the process *this*
27
- * `spawnProcess` call produced. A stale listener from an unrelated, already-
28
- * dead run satisfies `http`/`tcp-port` identically to a correct one; nothing
29
- * here can tell them apart. `log-pattern` only carries the stronger,
30
- * this-run-specific guarantee when its `read` is wired to *this* execution's
31
- * own `ManagedProcess.readOutput()` — the type does not enforce that wiring,
32
- * it is a caller discipline. `custom-hook` inherits whatever the caller's
33
- * predicate actually checks.
34
- *
35
- * Callers that bind a fixed, guessable host:port are exposed to this gap;
36
- * an ephemeral port closes it by construction (nothing else can already be
37
- * bound there) rather than by detection, and is the default recommendation
38
- * over a startup-nonce scheme, which only earns its extra machinery when a
39
- * fixed port is genuinely unavoidable (a contract with an external tool).
40
- * See `descry-runtime`'s `DECISIONS.md` RT-024 for how this was found —
41
- * a real 30-second collector timeout that looked like a Playwright/DOM bug
42
- * and was actually a correct wait against an orphaned process from a
43
- * different, already-dead session.
44
- *
45
- * **A single probe attempt cannot outlive `timeoutMs` (RT-030).** `http`
46
- * and `tcp-port` each bind their I/O to the *remaining* time until
47
- * `deadline`, not a fresh per-attempt budget — a target that accepts a
48
- * connection and never responds no longer lets one probe attempt run past
49
- * the caller's own deadline. Measured, not theoretical: an unbound `fetch`
50
- * here let `awaitReadiness` run past its own `timeoutMs` (>8s observed
51
- * against a 3s budget). `command` honors the same discipline, the same
52
- * way: `execFile`'s own `timeout` option is set to the remaining time until
53
- * `deadline`, so a command that hangs instead of exiting is killed rather
54
- * than left to run past the caller's own budget — it owns a real OS
55
- * resource (a child process) exactly like the http/tcp-port sockets do, so
56
- * it gets the same treatment. `custom-hook` is not wrapped the same way — a
57
- * caller-supplied predicate owns its own timeout behavior, same as every
58
- * other `Collector`-shaped callback contract in this repo (`collector.ts`'s
59
- * own docs put "must resolve, not hang" on the implementer); imposing a
60
- * surprise external cancellation on arbitrary caller code would be a
61
- * different, larger decision than fixing the mechanisms that own a real OS
62
- * resource this module can actually clean up.
22
+ * **A single probe attempt cannot outlive `timeoutMs` (RT-030).** `http`/`tcp-port`
23
+ * bind I/O to the remaining time until `deadline`, not a fresh per-attempt budget --
24
+ * measured: an unbound `fetch` here let `awaitReadiness` run 8s+ past a 3s budget.
25
+ * `command` gets the same treatment via `execFile`'s `timeout`. `custom-hook` is not
26
+ * wrapped this way -- a caller predicate owns its own timeout, same as every other
27
+ * `Collector` callback contract here.
63
28
  */
64
29
  import { createConnection } from "node:net";
65
30
  import { execFile } from "node:child_process";
@@ -72,35 +37,34 @@ export async function awaitReadiness(checks, options) {
72
37
  if (checks.length === 0) {
73
38
  return { ready: false, mechanism: null, elapsedMs: 0, reason: "no readiness checks configured" };
74
39
  }
40
+ // C-F4: last real diagnostic any probe captured before giving up (chiefly
41
+ // `command`'s stderr/exit code -- http/tcp-port have nothing richer than
42
+ // "connection refused"). Kept as "last seen", most likely to explain the timeout.
43
+ let lastDetail = null;
75
44
  do {
76
45
  for (const check of checks) {
77
- if (await probe(check, deadline)) {
46
+ const result = await probe(check, deadline);
47
+ if (result.ok) {
78
48
  return { ready: true, mechanism: check.kind, elapsedMs: Date.now() - startedAt, reason: null };
79
49
  }
50
+ if (result.detail !== null)
51
+ lastDetail = `${check.kind}: ${result.detail}`;
80
52
  }
81
53
  await sleep(pollIntervalMs);
82
54
  } while (Date.now() < deadline);
83
- // Names what was actually probed, not just that nothing answered.
84
- //
85
- // This is the only cheap thing available against the ephemeral-port race
86
- // in `allocateEphemeralPort` (bind 0, read, close, spawn): if another
87
- // process takes the port in the window between release and the child's
88
- // own bind, the child never comes up and the *only* symptom is this
89
- // result. "No readiness mechanism succeeded" sends the reader to look at
90
- // the application; "nothing answered http://127.0.0.1:41237/health"
91
- // sends them to look at the port, which is where the problem is. The race
92
- // itself cannot be closed without binding the real service directly to
93
- // the probe socket, which the child-process model does not support — so
94
- // making its one symptom legible is the honest remainder.
55
+ // Names what was actually probed, not just that nothing answered -- the only
56
+ // cheap mitigation for the ephemeral-port race in `allocateEphemeralPort`
57
+ // (bind 0, read, close, spawn): if another process grabs the port first, the
58
+ // child never comes up and this message is the only symptom. Naming the exact
59
+ // address probed sends the reader to the port, not the application.
95
60
  return {
96
61
  ready: false,
97
62
  mechanism: null,
98
63
  elapsedMs: Date.now() - startedAt,
99
- // "timeout" stays in the wording deliberately: the first draft of this
100
- // message replaced it with "within 1500ms", which reads fine and drops
101
- // the one word a caller can match on. §41's hung-process test does
102
- // exactly that, and caught it.
103
- reason: `no readiness mechanism succeeded within the ${options.timeoutMs}ms timeout — probed ${checks.map(describeCheck).join(", ")}`,
64
+ // "timeout" stays in the wording deliberately -- §41's hung-process test
65
+ // matches on that word.
66
+ reason: `no readiness mechanism succeeded within the ${options.timeoutMs}ms timeout — probed ${checks.map(describeCheck).join(", ")}` +
67
+ (lastDetail !== null ? `; last observed failure — ${lastDetail}` : ""),
104
68
  };
105
69
  }
106
70
  function describeCheck(check) {
@@ -117,6 +81,12 @@ function describeCheck(check) {
117
81
  return "custom hook";
118
82
  }
119
83
  }
84
+ function ok() {
85
+ return { ok: true, detail: null };
86
+ }
87
+ function notReady(detail = null) {
88
+ return { ok: false, detail };
89
+ }
120
90
  async function probe(check, deadline) {
121
91
  switch (check.kind) {
122
92
  case "http":
@@ -124,52 +94,60 @@ async function probe(check, deadline) {
124
94
  case "tcp-port":
125
95
  return probeTcpPort(check, deadline);
126
96
  case "log-pattern":
127
- return check.pattern.test(check.read());
97
+ return check.pattern.test(check.read()) ? ok() : notReady();
128
98
  case "command":
129
99
  return probeCommand(check, deadline);
130
100
  case "custom-hook":
131
- return check.check();
101
+ return (await check.check()) ? ok() : notReady();
132
102
  }
133
103
  }
134
104
  async function probeHttp(check, deadline) {
135
105
  try {
136
106
  const response = await fetch(check.url, { signal: AbortSignal.timeout(Math.max(0, deadline - Date.now())) });
137
- return response.status === (check.expectedStatus ?? 200);
107
+ if (response.status === (check.expectedStatus ?? 200))
108
+ return ok();
109
+ return notReady(`responded with status ${String(response.status)}, expected ${String(check.expectedStatus ?? 200)}`);
138
110
  }
139
- catch {
140
- return false;
111
+ catch (error) {
112
+ return notReady(error instanceof Error ? error.message : String(error));
141
113
  }
142
114
  }
143
115
  function probeTcpPort(check, deadline) {
144
116
  return new Promise((resolve) => {
145
117
  const socket = createConnection({ host: check.host, port: check.port });
146
118
  socket.setTimeout(Math.max(0, deadline - Date.now()));
147
- const finish = (ok) => {
119
+ const finish = (result) => {
148
120
  socket.destroy();
149
- resolve(ok);
121
+ resolve(result);
150
122
  };
151
- socket.once("connect", () => finish(true));
152
- socket.once("error", () => finish(false));
153
- socket.once("timeout", () => finish(false));
123
+ socket.once("connect", () => finish(ok()));
124
+ socket.once("error", (error) => finish(notReady(error.message)));
125
+ socket.once("timeout", () => finish(notReady("connection attempt timed out")));
154
126
  });
155
127
  }
156
128
  /**
157
- * Ready when `check.command` exits 0 within the remaining time until
158
- * `deadline` (RT-030 — see this module's own header). A non-zero exit, a
159
- * spawn failure (e.g. command not found), and a timeout kill are all "not
160
- * ready yet" here — `awaitReadiness`'s polling loop retries on the next
161
- * `pollIntervalMs` tick regardless of which one happened, the same as every
162
- * other mechanism's `false`.
129
+ * Ready when `check.command` exits 0 within the remaining time until `deadline`
130
+ * (RT-030). Non-zero exit, spawn failure, and timeout kill are all "not ready yet" --
131
+ * same as every other mechanism's `false`.
132
+ *
133
+ * C-F4: stdout/stderr are the actual health-check output, the richest diagnostic
134
+ * available here. Preferring stderr, then stdout, then the bare error message
135
+ * mirrors `runAttacher`'s ordering in `attach-to-running-jvm-process.ts`.
163
136
  */
164
137
  function probeCommand(check, deadline) {
165
138
  return new Promise((resolve) => {
166
139
  const remainingMs = Math.max(0, deadline - Date.now());
167
140
  if (remainingMs === 0) {
168
- resolve(false);
141
+ resolve(notReady("no time remaining before the readiness deadline"));
169
142
  return;
170
143
  }
171
- execFile(check.command, check.args ?? [], { cwd: check.cwd, timeout: remainingMs }, (error) => {
172
- resolve(error === null);
144
+ execFile(check.command, check.args ?? [], { cwd: check.cwd, timeout: remainingMs }, (error, stdout, stderr) => {
145
+ if (error === null) {
146
+ resolve(ok());
147
+ return;
148
+ }
149
+ const detail = stderr.trim() || stdout.trim() || error.message;
150
+ resolve(notReady(detail));
173
151
  });
174
152
  });
175
153
  }
@@ -1 +1 @@
1
- {"version":3,"file":"readiness.js","sourceRoot":"","sources":["../src/readiness.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"readiness.js","sourceRoot":"","sources":["../src/readiness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,CAAU,CAAC;AA8D3G,MAAM,wBAAwB,GAAG,GAAG,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAiC,EACjC,OAA8B;IAE9B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAC/C,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,wBAAwB,CAAC;IAE1E,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,EAAE,gCAAgC,EAAE,CAAC;IACnG,CAAC;IAED,0EAA0E;IAC1E,yEAAyE;IACzE,kFAAkF;IAClF,IAAI,UAAU,GAAkB,IAAI,CAAC;IAErC,GAAG,CAAC;QACF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAC5C,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;gBACd,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YACjG,CAAC;YACD,IAAI,MAAM,CAAC,MAAM,KAAK,IAAI;gBAAE,UAAU,GAAG,GAAG,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QAC7E,CAAC;QACD,MAAM,KAAK,CAAC,cAAc,CAAC,CAAC;IAC9B,CAAC,QAAQ,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE;IAEhC,6EAA6E;IAC7E,0EAA0E;IAC1E,6EAA6E;IAC7E,8EAA8E;IAC9E,oEAAoE;IACpE,OAAO;QACL,KAAK,EAAE,KAAK;QACZ,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;QACjC,yEAAyE;QACzE,wBAAwB;QACxB,MAAM,EACJ,+CAA+C,OAAO,CAAC,SAAS,uBAAuB,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;YAC7H,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,6BAA6B,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACzE,CAAC;AACJ,CAAC;AAED,SAAS,aAAa,CAAC,KAAqB;IAC1C,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,MAAM;YACT,OAAO,KAAK,CAAC,GAAG,CAAC;QACnB,KAAK,UAAU;YACb,OAAO,OAAO,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC3C,KAAK,aAAa;YAChB,OAAO,eAAe,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAChD,KAAK,SAAS;YACZ,OAAO,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACvE,KAAK,aAAa;YAChB,OAAO,aAAa,CAAC;IACzB,CAAC;AACH,CAAC;AAQD,SAAS,EAAE;IACT,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACpC,CAAC;AACD,SAAS,QAAQ,CAAC,SAAwB,IAAI;IAC5C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAC/B,CAAC;AAED,KAAK,UAAU,KAAK,CAAC,KAAqB,EAAE,QAAgB;IAC1D,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,MAAM;YACT,OAAO,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACpC,KAAK,UAAU;YACb,OAAO,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACvC,KAAK,aAAa;YAChB,OAAO,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC9D,KAAK,SAAS;YACZ,OAAO,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QACvC,KAAK,aAAa;YAChB,OAAO,CAAC,MAAM,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACrD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,KAAyB,EAAE,QAAgB;IAClE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7G,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,KAAK,CAAC,cAAc,IAAI,GAAG,CAAC;YAAE,OAAO,EAAE,EAAE,CAAC;QACnE,OAAO,QAAQ,CAAC,yBAAyB,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,cAAc,MAAM,CAAC,KAAK,CAAC,cAAc,IAAI,GAAG,CAAC,EAAE,CAAC,CAAC;IACvH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,QAAQ,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,KAA4B,EAAE,QAAgB;IAClE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACxE,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,CAAC,MAAmB,EAAQ,EAAE;YAC3C,MAAM,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,MAAM,CAAC,CAAC;QAClB,CAAC,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,8BAA8B,CAAC,CAAC,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,YAAY,CAAC,KAA4B,EAAE,QAAgB;IAClE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACvD,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,CAAC,QAAQ,CAAC,iDAAiD,CAAC,CAAC,CAAC;YACrE,OAAO;QACT,CAAC;QACD,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YAC5G,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;gBACnB,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;gBACd,OAAO;YACT,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,IAAI,MAAM,CAAC,IAAI,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC;YAC/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
package/dist/sandbox.d.ts CHANGED
@@ -1,110 +1,70 @@
1
1
  /**
2
- * §21's execution boundary, real isolation half (the sandbox-isolation
3
- * lane, superseding the "sandbox platform is a separate architectural
4
- * decision, not built here" deferral). RT-070 and RT-193 gave this runtime
5
- * a *named* boundary (trusted-local, resource limits, privilege reporting)
6
- * but not an *isolating* one -- nothing stopped a spawned process from
7
- * reading any file the invoking user could read, or reaching any host the
8
- * invoking user's network could reach. This module closes that gap for
9
- * real, on Linux, for processes this runtime SPAWNS.
2
+ * §21's execution boundary, real isolation half. RT-070/RT-193 gave this runtime a
3
+ * *named* boundary (trusted-local, resource limits, privilege reporting) but not an
4
+ * *isolating* one -- nothing stopped a spawned process from reading any file, or
5
+ * reaching any host, the invoking user could. This module closes that gap for real,
6
+ * on Linux, for processes this runtime SPAWNS.
10
7
  *
11
- * **The architectural constraint this module does not try to solve
12
- * around:** isolation can only wrap a process Descry itself launches.
13
- * Attach-mode (`attach-to-running-process.ts`, `attach-to-running-node-
14
- * process.ts`, `attach-to-running-jvm-process.ts`) reaches a process that
15
- * was already running, unconfined, before Descry touched it -- there is no
16
- * honest way to retroactively contain it (ptrace-based interception was
17
- * investigated and rejected elsewhere in this repo as "not honestly
18
- * generalizable"). Spawn-mode gets real isolation via this module.
19
- * Attach-mode stays permanently and explicitly unsandboxed --
20
- * `SANDBOX_BOUNDARY_DISCLOSURE` in `execution-safety.ts` says so in-product,
21
- * and this module does not (and structurally cannot) change that.
8
+ * **Architectural constraint this module cannot solve around:** isolation can only
9
+ * wrap a process Descry itself launches. Attach-mode reaches a process already
10
+ * running, unconfined, before Descry touched it -- there is no honest way to
11
+ * retroactively contain it (ptrace-based interception was investigated and rejected
12
+ * elsewhere as not honestly generalizable). Attach-mode stays permanently and
13
+ * explicitly unsandboxed -- `SANDBOX_BOUNDARY_DISCLOSURE` in `execution-safety.ts`
14
+ * discloses this in-product; this module does not and structurally cannot change it.
22
15
  *
23
- * **Mechanism: bubblewrap (bwrap), not raw `unshare`/`clone`.** bwrap is
24
- * the unprivileged sandboxing helper behind Flatpak and used by many
25
- * developer tools directly -- a small (tens of KB), auditable, actively
26
- * maintained binary, not a bespoke native module this repo would need to
27
- * build and ship per-platform. It runs setuid-free on any kernel with
28
- * unprivileged user namespaces enabled (checked below, not assumed) and
29
- * gives one process a new mount namespace (real filesystem visibility
30
- * control) and network namespace (real network denial) in one exec,
31
- * composing cleanly with `applyResourceLimits`'s `prlimit` wrap and with
32
- * this package's existing process-group kill mechanism (`detached: true` +
33
- * `process.kill(-pid, …)`) -- verified directly: bwrap does not create a
34
- * new process group unless asked to, so the group-kill in
35
- * `process-manager.ts` reaches it and everything it started, unchanged.
36
- * The one dependency this buys: `bwrap` must be on `PATH`. Reported as a
37
- * capability, exactly like `prlimit` -- refused, never silently
38
- * unconstrained, when requested and absent.
16
+ * **Mechanism: bubblewrap (bwrap), not raw `unshare`/`clone`.** bwrap is the
17
+ * unprivileged sandboxing helper behind Flatpak -- small, auditable, actively
18
+ * maintained, not a bespoke native module this repo builds per-platform. Runs
19
+ * setuid-free on any kernel with unprivileged user namespaces enabled (checked
20
+ * below, never assumed) and gives one process a new mount namespace (real
21
+ * filesystem visibility control) and network namespace (real network denial) in one
22
+ * exec. Composes with `applyResourceLimits`'s `prlimit` wrap and with
23
+ * `process-manager.ts`'s process-group kill -- verified directly: bwrap does not
24
+ * create a new process group unless asked, so the existing group-kill reaches it
25
+ * unchanged. The one dependency this buys: `bwrap` must be on PATH, reported as a
26
+ * capability exactly like `prlimit` -- refused, never silently unconstrained, when
27
+ * requested and absent.
39
28
  *
40
- * **What this module does NOT attempt, and where that gap actually closes:**
41
- * a *native* macOS or Windows sandbox for this mechanism (`sandbox-exec`/
42
- * Seatbelt -- deprecated public API; the Endpoint Security Framework --
43
- * needs a special Apple entitlement this project does not have; Windows Job
44
- * Objects + restricted tokens/AppContainer + WFP network enforcement -- a
45
- * second and third bespoke native sandbox to build and maintain). That is
46
- * not "researched but not built here, someday" -- it is an explicit
47
- * architecture decision NOT to build native sandboxes for those two
48
- * platforms at all. `../container-sandbox.ts` closes the gap instead, by
49
- * routing macOS and Windows through a real Docker container that reuses
50
- * THIS module's own proven Linux mechanism underneath (Docker Desktop's
51
- * Linux VM on macOS, WSL2/Docker Desktop's Windows backend on Windows) --
52
- * see that module's own doc comment for exactly what is real-tested there
53
- * versus unverified on real macOS/Windows hardware. `filesystemIsolationCapability`/
54
- * `networkIsolationCapability` below still report `unavailable` with a
55
- * reason on non-Linux platforms -- this module never silently claims to
56
- * cover them; `container-sandbox.ts` is the module a non-Linux caller
57
- * actually wants.
29
+ * **NOT attempted, deliberately: a native macOS or Windows sandbox.** `sandbox-exec`/
30
+ * Seatbelt is deprecated with no public API replacement; the Endpoint Security
31
+ * Framework needs an Apple entitlement this project doesn't have; Windows Job
32
+ * Objects + AppContainer + WFP would be a second and third bespoke native sandbox.
33
+ * This is an explicit decision not to build native sandboxes for those platforms at
34
+ * all -- `../container-sandbox.ts` closes the gap instead, routing macOS/Windows
35
+ * through a real Docker container that reuses this module's proven Linux mechanism
36
+ * (see that module's doc for what's real-tested there vs unverified on real
37
+ * hardware). `filesystemIsolationCapability`/`networkIsolationCapability` below
38
+ * still report `unavailable` with a reason on non-Linux -- never silently claimed
39
+ * as covered.
58
40
  */
59
41
  import type { CapabilityStatus, FilesystemPolicy, NetworkPolicy } from "@descryy/runtime-contracts";
60
- /**
61
- * Real capability check, matching `resourceLimitCapability`'s own shape and
62
- * precedent exactly: existence on `PATH` first (fast, matches
63
- * `prlimit --version`'s pattern), then the one Linux-specific precondition
64
- * that existence alone doesn't prove -- unprivileged user namespaces
65
- * actually being usable, not just bwrap being installed.
66
- */
42
+ /** Real capability check, same shape as `resourceLimitCapability`: PATH existence first, then the Linux-specific precondition existence alone doesn't prove -- unprivileged user namespaces actually usable, not just bwrap installed. */
67
43
  export declare function filesystemIsolationCapability(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): CapabilityStatus;
68
- /**
69
- * The same underlying mechanism as `filesystemIsolationCapability` --
70
- * bwrap building one namespace set covers both a restricted mount view and
71
- * a network namespace in the same exec -- so this delegates rather than
72
- * duplicating the check. Kept as its own named function because the two
73
- * policies are declared, refused, and reasoned about independently
74
- * (`NetworkPolicy` only supports one shape; see `unsupportedNetworkPolicyReason`),
75
- * even though today they share one mechanism underneath.
76
- */
44
+ /** Same underlying mechanism as `filesystemIsolationCapability` (one bwrap namespace set covers both) -- delegates rather than duplicating. Kept as its own function because the two policies are declared and reasoned about independently. */
77
45
  export declare function networkIsolationCapability(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): CapabilityStatus;
78
46
  /**
79
- * `NetworkPolicy`'s general shape (arbitrary allow/deny host lists) is not
80
- * what this iteration's mechanism enforces -- only full denial. Returns the
81
- * reason a given policy cannot be applied, or `null` if it is the one
82
- * shape that can. Checked independently of `networkIsolationCapability`:
83
- * a policy can be shape-unsupported on a platform where the mechanism
84
- * itself is otherwise available, and the two refusals are different
85
- * claims ("nothing here can enforce any network policy" vs. "this specific
86
- * policy asks for something the real mechanism doesn't do yet").
47
+ * `NetworkPolicy`'s general shape (arbitrary allow/deny host lists) is not what
48
+ * this mechanism enforces -- only full denial. Returns the reason a policy can't be
49
+ * applied, or `null` if it's the one shape that can. Checked independently of
50
+ * `networkIsolationCapability`: "nothing here can enforce any policy" and "this
51
+ * specific policy asks for something not built yet" are different claims.
87
52
  */
88
53
  export declare function unsupportedNetworkPolicyReason(policy: NetworkPolicy): string | null;
89
54
  /**
90
55
  * Resolves the real, symlink-followed directory containing the executable
91
- * `command` would run as -- the one piece of host filesystem a sandboxed
92
- * process needs beyond the standard OS directories and whatever the caller
93
- * declared, and the one this function computes generically rather than by
94
- * naming a language: an interpreter installed outside `/usr` (nvm, rbenv,
95
- * pyenv, sdkman -- all common, all under a user's home directory) would
96
- * otherwise be invisible inside the sandbox no matter which language it
97
- * is, which is exactly the kind of per-language special case §IR-boundary
98
- * rules out. Returns `null` when `command` cannot be resolved (already
99
- * absolute-looking and missing, or not found on `PATH`) -- the caller
100
- * proceeds without an extra bind in that case; the exec itself will fail
101
- * inside the sandbox the same honest way it would outside one.
56
+ * `command` would run as -- the one extra host path a sandboxed process needs
57
+ * beyond standard OS dirs and whatever the caller declared. Computed generically,
58
+ * not per-language: an interpreter installed outside `/usr` (nvm, rbenv, pyenv,
59
+ * sdkman) would otherwise be invisible inside the sandbox regardless of language.
60
+ * Returns `null` when unresolvable -- the caller proceeds without an extra bind;
61
+ * the exec fails inside the sandbox the same honest way it would outside one.
102
62
  */
103
63
  export declare function resolveExecutableDirectory(command: string, cwd: string, env: NodeJS.ProcessEnv): string | null;
104
64
  export interface SandboxOptions {
105
- /** The original, un-resource-limit-wrapped command (e.g. `"node"`) -- used only to resolve which extra directory the interpreter itself needs bound in. */
65
+ /** Original, un-resource-limit-wrapped command (e.g. "node") -- used only to resolve which extra directory the interpreter needs bound in. */
106
66
  readonly interpreterCommand: string;
107
- /** The command to actually exec inside the sandbox -- already passed through `applyResourceLimits`, so this may be `"prlimit"` with the real command in `args`. */
67
+ /** Command to actually exec inside the sandbox -- already passed through `applyResourceLimits`, so may be "prlimit" with the real command in `args`. */
108
68
  readonly command: string;
109
69
  readonly args: readonly string[];
110
70
  readonly cwd: string;
@@ -114,23 +74,18 @@ export interface SandboxOptions {
114
74
  readonly platform?: NodeJS.Platform;
115
75
  }
116
76
  /**
117
- * Wraps `command`/`args` with `bwrap` so the OS enforces `filesystemPolicy`
118
- * and/or `networkPolicy`. Neither declared returns `command`/`args`
119
- * unchanged -- every execution before this lane keeps behaving exactly as
120
- * before unless it opts in, the same non-regression contract
121
- * `applyResourceLimits` already established for resource limits.
77
+ * Wraps `command`/`args` with `bwrap` so the OS enforces `filesystemPolicy`/
78
+ * `networkPolicy`. Neither declared returns them unchanged -- same non-regression
79
+ * contract as `applyResourceLimits`.
122
80
  *
123
- * **Throws rather than silently spawning unconstrained** -- same
124
- * `tokenizeCommand`/`applyResourceLimits` precedent -- when a policy is
125
- * requested and the real mechanism cannot back it, whether because the
126
- * platform has no mechanism at all or because the declared shape is one
127
- * this mechanism doesn't implement (`unsupportedNetworkPolicyReason`).
81
+ * **Throws rather than silently spawning unconstrained** when a policy is
82
+ * requested and the real mechanism can't back it -- no mechanism on this platform,
83
+ * or a declared shape this mechanism doesn't implement.
128
84
  *
129
- * Composes with `applyResourceLimits`: this function wraps *outside* it
130
- * (`bwrap … -- prlimit … -- realCommand`), because the mount namespace must
131
- * exist before `prlimit` or the real command run inside it, and `prlimit`
132
- * itself (in `/usr/bin`) is reachable through the same base OS binding
133
- * every sandboxed process gets.
85
+ * Composes with `applyResourceLimits` by wrapping *outside* it (`bwrap … --
86
+ * prlimit … -- realCommand`) -- the mount namespace must exist before `prlimit` or
87
+ * the real command run inside it; `prlimit` (in `/usr/bin`) is reachable through
88
+ * the same base OS binding every sandboxed process gets.
134
89
  */
135
90
  export declare function applySandbox(options: SandboxOptions): {
136
91
  readonly command: string;
@@ -1 +1 @@
1
- {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyDG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AA+BpG;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,gBAAgB,CAoBlJ;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,gBAAgB,CAE/I;AAED;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAOnF;AAOD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,IAAI,CAwB9G;AAED,MAAM,WAAW,cAAc;IAC7B,2JAA2J;IAC3J,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,mKAAmK;IACnK,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAC7C,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAmFpH"}
1
+ {"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../src/sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAkCpG,0OAA0O;AAC1O,wBAAgB,6BAA6B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,gBAAgB,CAoBlJ;AAED,gPAAgP;AAChP,wBAAgB,0BAA0B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAAG,gBAAgB,CAE/I;AAED;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAOnF;AAOD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,IAAI,CAwB9G;AAED,MAAM,WAAW,cAAc;IAC7B,8IAA8I;IAC9I,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,wJAAwJ;IACxJ,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAC7C,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;CACrC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAkFpH"}