@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
@@ -1,153 +1,95 @@
1
1
  /**
2
- * §21's execution boundary (RT-070): resource limits and privilege
3
- * reporting for a runtime whose declared mode is trusted-local (see
4
- * DECISIONS.md RT-070) -- every spawned process runs with the invoking
5
- * user's own OS privileges, no filesystem or network restriction. That
6
- * declaration does not make unrestricted execution safe; it names the
7
- * boundary instead of leaving it absent, which is what §38's "arbitrary
8
- * application code runs without a defined safety boundary" actually bans.
9
- * Real isolation (containers/namespaces) is a separate architectural
10
- * decision this module does not invent (plan §29's own instruction).
2
+ * §21/RT-070's execution boundary: resource limits and privilege reporting for a
3
+ * runtime declared trusted-local -- every spawned process runs with the invoking
4
+ * user's own OS privileges, no filesystem/network restriction. Names the boundary
5
+ * rather than leaving it absent (§38); real isolation (containers/namespaces) is a
6
+ * separate decision this module does not invent (§29).
11
7
  *
12
- * What this module DOES enforce, for real, via the OS: CPU time, virtual
13
- * memory, and process count, through `prlimit` -- an exec wrapper, never a
14
- * shell. Reintroducing `sh -c 'ulimit ...; exec ...'` to get these would
15
- * undo RT-036's `tokenizeCommand` refusal of shell metacharacters. `prlimit`
16
- * is util-linux and absent on macOS, so it is reported as a capability,
17
- * never assumed.
8
+ * Enforces for real, via the OS: CPU time, virtual memory, process count, through
9
+ * `prlimit` -- an exec wrapper, never a shell (a shell would undo RT-036's
10
+ * `tokenizeCommand` refusal of shell metacharacters). `prlimit` is util-linux, absent
11
+ * on macOS, so it's reported as a capability, never assumed.
18
12
  */
19
13
  import type { CapabilityStatus, ResourceLimits } from "@descryy/runtime-contracts";
20
- /**
21
- * Whether `prlimit` is reachable on this platform's `PATH`. Takes `env` as
22
- * a parameter (defaulting to `process.env`) rather than reading it
23
- * internally so the "unavailable" branch is directly testable without
24
- * mutating this process's own real environment or depending on running on
25
- * a platform that genuinely lacks it.
26
- */
14
+ /** Whether `prlimit` is reachable on PATH. `env` is a parameter (default `process.env`) so the "unavailable" branch is testable without mutating the real environment. */
27
15
  export declare function resourceLimitCapability(env?: NodeJS.ProcessEnv): CapabilityStatus;
28
16
  /**
29
- * RT-193 originally made this always `unavailable` -- no platform had any
30
- * enforcement mechanism wired up. The sandbox-isolation lane changes that
31
- * on Linux: `networkIsolationCapability()` (`./sandbox.ts`) is real, backed
32
- * by a bwrap network namespace. This function is kept as the stable name
33
- * every existing caller (`ExecutionController.run()`, this package's own
34
- * tests) already imports, delegating rather than duplicating the check --
35
- * exactly the seam RT-193's own comment anticipated ("if a real mechanism
36
- * is ever built, this one function changes and every caller keeps working
37
- * unmodified"). Still unconditionally `unavailable` on macOS/Windows, where
38
- * nothing enforces it yet.
17
+ * RT-193 originally made this always `unavailable`. Now delegates to
18
+ * `networkIsolationCapability()` (`./sandbox.ts`), real on Linux via a bwrap network
19
+ * namespace -- kept as the stable name every caller already imports (the seam
20
+ * RT-193 anticipated). Still unconditionally `unavailable` on macOS/Windows.
39
21
  */
40
22
  export declare function networkPolicyCapability(env?: NodeJS.ProcessEnv): CapabilityStatus;
41
23
  /**
42
- * Wraps `command`/`args` so the OS enforces `limits`, via `prlimit`.
43
- * `undefined` or an empty `limits` returns `command`/`args` unchanged --
44
- * every execution before RT-070 keeps behaving exactly as before unless it
45
- * opts in.
24
+ * Wraps `command`/`args` so the OS enforces `limits`, via `prlimit`. `undefined` or
25
+ * empty `limits` returns them unchanged -- opt-in only.
46
26
  *
47
- * **Throws rather than silently spawning unconstrained** when a limit was
48
- * requested and `prlimit` is unavailable. `tokenizeCommand`'s own precedent
49
- * (RT-036) is refuse rather than guess; the equivalent failure here would
50
- * be a caller asking for a memory cap and getting a process that can
51
- * allocate without bound, silently -- exactly the "sandbox that doesn't
52
- * sandbox" shape §38 bans, one row up from this one.
27
+ * **Throws rather than silently spawning unconstrained** when a limit was requested
28
+ * and `prlimit` is unavailable (refuse-not-guess, per RT-036) -- the alternative is a
29
+ * caller asking for a memory cap and silently getting an unbounded process, the
30
+ * "sandbox that doesn't sandbox" shape §38 bans.
53
31
  */
54
32
  export declare function applyResourceLimits(command: string, args: readonly string[], limits: ResourceLimits | undefined, env?: NodeJS.ProcessEnv): {
55
33
  readonly command: string;
56
34
  readonly args: readonly string[];
57
35
  };
58
36
  /**
59
- * DEC-272's disclosure requirement: the sandbox boundary (RT-070) must be
60
- * stated to the user directly in-product, not left as a silent gap in a
61
- * doc. Fixed, not derived from `runningAsRoot` -- the boundary is the same
62
- * regardless of which privilege level was found; only the observed fact
63
- * changes.
37
+ * DEC-272: the sandbox boundary (RT-070) must be stated to the user directly, not
38
+ * left as a silent doc gap. Fixed, not derived from `runningAsRoot` -- the boundary
39
+ * is the same regardless of privilege level found.
64
40
  *
65
- * **Scope, corrected by the attach-mode-mitigations lane: this is the
66
- * unconditional-unisolated text, not a universal one.** Written when
67
- * RT-193/RT-070 landed, before `sandbox.ts` existed -- at that point it was
68
- * accurate for every execution, because nothing anywhere in this runtime
69
- * could isolate anything. That stopped being true the moment the
70
- * sandbox-isolation lane gave spawn-mode real, bwrap-backed filesystem/
71
- * network isolation (`applySandbox`, this same package): a spawned process
72
- * that actually got a `FilesystemPolicy`/`NetworkPolicy` applied to it is
73
- * genuinely more contained than "the same as if you started it yourself"
74
- * says. Using this constant unconditionally for that process would be a
75
- * real disclosure-accuracy bug -- understating a boundary is not the safe
76
- * direction to be wrong in, it just happens to be a less alarming one.
77
- * `sandboxBoundaryDisclosureFor()` below is the mode-aware replacement: it
78
- * returns this exact string when no policy was applied (attach-mode always,
79
- * and any spawn that declared none -- unchanged from before this lane), and
80
- * a real, specific description of what is and is not contained when a
81
- * policy genuinely was. This constant is kept, unchanged, as that function's
82
- * own no-policy-applied return value and as attach-mode's own disclosure,
83
- * not deprecated -- attach-mode never has anything more accurate to say.
41
+ * **Scope: this is the unconditional-unisolated text, not a universal one.** Accurate
42
+ * for every execution before `sandbox.ts` existed; no longer true once spawn-mode got
43
+ * real bwrap-backed isolation (`applySandbox`) -- using this unconditionally for an
44
+ * isolated process would understate its boundary, which is not the safe direction to
45
+ * be wrong in. `sandboxBoundaryDisclosureFor()` below is the mode-aware replacement;
46
+ * this constant remains its no-policy-applied return value and attach-mode's own
47
+ * disclosure (attach-mode never has anything more accurate to say).
84
48
  */
85
49
  export declare const SANDBOX_BOUNDARY_DISCLOSURE: string;
86
50
  /**
87
- * Whether a real `FilesystemPolicy`/`NetworkPolicy` was actually enforced on
88
- * the process this disclosure describes -- not merely requested.
89
- * `applySandbox` already refuses to spawn (throws) rather than proceed
90
- * unconstrained when a declared policy cannot be enforced (see its own
91
- * comment), so by the time a caller can observe a successfully spawned
92
- * process, "declared" and "applied" are the same fact; this type exists so
93
- * a caller states that fact explicitly rather than this function silently
94
- * assuming it.
51
+ * Whether a real policy was actually enforced, not merely requested. `applySandbox`
52
+ * already throws rather than proceed unconstrained when a declared policy can't be
53
+ * enforced, so by the time a process is observed running, "declared" and "applied"
54
+ * are the same fact -- this type makes the caller state it explicitly.
95
55
  */
96
56
  export interface AppliedIsolationPolicies {
97
57
  readonly filesystemPolicyApplied: boolean;
98
58
  readonly networkPolicyApplied: boolean;
99
59
  }
100
60
  /**
101
- * The mode-aware replacement for reading `SANDBOX_BOUNDARY_DISCLOSURE`
102
- * unconditionally. Defaults to reporting no policy applied -- so calling
103
- * this with no argument at all is identical to the pre-existing constant,
104
- * the same non-regression contract every other opt-in in this file
105
- * (`applyResourceLimits`, `applySandbox`) already keeps.
61
+ * Mode-aware replacement for reading `SANDBOX_BOUNDARY_DISCLOSURE` unconditionally.
62
+ * Defaults to no-policy-applied, so a no-arg call matches the old constant exactly.
106
63
  *
107
- * **Still only ever true for spawn-mode.** Attach-mode has no code path
108
- * that can produce `filesystemPolicyApplied: true` or
109
- * `networkPolicyApplied: true` for any process it did not itself spawn --
110
- * see `sandbox.ts`'s own module doc for why that is structural, not a gap
111
- * in this function. A caller in attach-mode should simply never pass
112
- * anything but the default here, and the default's return value is this
113
- * disclosure's original, unconditional "not isolated" text, unchanged.
64
+ * **Only ever true for spawn-mode.** Attach-mode has no path to produce
65
+ * `filesystemPolicyApplied`/`networkPolicyApplied: true` for a process it didn't
66
+ * spawn (structural, see `sandbox.ts`) -- attach-mode callers should never pass
67
+ * anything but the default.
114
68
  */
115
69
  export declare function sandboxBoundaryDisclosureFor(policies?: AppliedIsolationPolicies): string;
116
70
  /**
117
- * Attach mode's own contractual scope guarantee -- distinct from the
118
- * sandbox-*boundary* disclosure above (what is or isn't contained) because
119
- * this is a claim about what an attach-mode `Collector` is even permitted
120
- * to *do*, not about what OS boundary wraps it. See `Collector` in
121
- * `@descryy/runtime-contracts` for the interface-level statement this
122
- * mirrors, and `sandbox.ts`'s own module doc for why attach-mode can never
123
- * acquire the isolation `sandboxBoundaryDisclosureFor` describes for
124
- * spawn-mode. Stated once, here, so every attach-mode caller surfaces the
125
- * identical sentence rather than each writing its own paraphrase.
71
+ * Attach mode's contractual scope guarantee -- distinct from the sandbox-boundary
72
+ * disclosure above: this is what an attach-mode `Collector` is permitted to *do*, not
73
+ * what OS boundary wraps it. Mirrors `Collector` in `@descryy/runtime-contracts`.
74
+ * Stated once so every attach-mode caller surfaces the identical sentence.
126
75
  */
127
76
  export declare const ATTACH_MODE_SCOPE_DISCLOSURE: string;
128
77
  export interface PrivilegeReport {
129
- /** Null when this platform has no uid concept at all (`process.getuid` is undefined on Windows) -- distinct from `false`, which is a real answer, not an absent one. */
78
+ /** Null when the platform has no uid concept (`process.getuid` undefined on Windows) -- distinct from `false`, a real answer. */
130
79
  readonly runningAsRoot: boolean | null;
131
- /** DEC-272: plain-language statement of the sandbox boundary, carried on the same result the privilege level already travels on rather than a new return path. Always populated -- the disclosure is unconditional, not dependent on `runningAsRoot`. */
80
+ /** DEC-272: plain-language sandbox boundary statement, carried on this result rather than a new return path. Always populated, independent of `runningAsRoot`. */
132
81
  readonly disclosure: string;
133
82
  }
134
83
  /**
135
- * Reports, never enforces. §21's privilege policy for a runtime declared
136
- * trusted-local (RT-070) is not "refuse to run as root" -- CI containers
137
- * commonly run as root by default, and a hard refusal there would turn a
138
- * documented boundary into an undocumented outage. The policy is: the real
139
- * privilege level becomes an observable fact instead of an invisible one,
140
- * which is what nothing before RT-070 made it.
84
+ * Reports, never enforces. §21's policy for trusted-local (RT-070) is not "refuse to
85
+ * run as root" -- CI containers commonly do, and a hard refusal would turn a
86
+ * documented boundary into an undocumented outage. The privilege level just becomes
87
+ * observable instead of invisible.
141
88
  *
142
- * A required parameter, not a defaulted one: `undefined` is the real,
143
- * meaningful value a platform with no uid concept produces
144
- * (`process.getuid` is itself `undefined` on Windows), and a *default*
145
- * parameter cannot tell "caller explicitly passed undefined" apart from
146
- * "caller omitted the argument" -- both look identical to the function.
147
- * `currentPrivilegeReport()` below is the zero-argument convenience wrapper
148
- * real callers use; this is what makes both branches -- root, and no uid
149
- * concept at all -- directly testable without this process actually
150
- * needing to run as root or on Windows.
89
+ * A required parameter, not defaulted: `undefined` is the real value a no-uid-concept
90
+ * platform produces, and a default can't distinguish "explicitly undefined" from
91
+ * "omitted." `currentPrivilegeReport()` below is the convenience wrapper; this makes
92
+ * both branches testable without actually running as root or on Windows.
151
93
  */
152
94
  export declare function privilegeReportFor(getuid: (() => number) | undefined): PrivilegeReport;
153
95
  export declare function currentPrivilegeReport(): PrivilegeReport;
@@ -1 +1 @@
1
- {"version":3,"file":"execution-safety.d.ts","sourceRoot":"","sources":["../src/execution-safety.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGnF;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,gBAAgB,CAU9F;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,gBAAgB,CAE9F;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAchE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,2BAA2B,QAGT,CAAC;AAEhC;;;;;;;;;GASG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,uBAAuB,EAAE,OAAO,CAAC;IAC1C,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;CACxC;AAID;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,GAAE,wBAA8C,GAAG,MAAM,CAwB7G;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,QAKoC,CAAC;AAE9E,MAAM,WAAW,eAAe;IAC9B,wKAAwK;IACxK,QAAQ,CAAC,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;IACvC,yPAAyP;IACzP,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,GAAG,eAAe,CAGtF;AAED,wBAAgB,sBAAsB,IAAI,eAAe,CAExD"}
1
+ {"version":3,"file":"execution-safety.d.ts","sourceRoot":"","sources":["../src/execution-safety.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGnF,0KAA0K;AAC1K,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,gBAAgB,CAU9F;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,gBAAgB,CAE9F;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,MAAM,EAAE,cAAc,GAAG,SAAS,EAClC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAchE;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,2BAA2B,QAGT,CAAC;AAEhC;;;;;GAKG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,uBAAuB,EAAE,OAAO,CAAC;IAC1C,QAAQ,CAAC,oBAAoB,EAAE,OAAO,CAAC;CACxC;AAID;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,GAAE,wBAA8C,GAAG,MAAM,CAwB7G;AAED;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,QAKoC,CAAC;AAE9E,MAAM,WAAW,eAAe;IAC9B,iIAAiI;IACjI,QAAQ,CAAC,aAAa,EAAE,OAAO,GAAG,IAAI,CAAC;IACvC,kKAAkK;IAClK,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,CAAC,MAAM,MAAM,CAAC,GAAG,SAAS,GAAG,eAAe,CAGtF;AAED,wBAAgB,sBAAsB,IAAI,eAAe,CAExD"}
@@ -1,30 +1,18 @@
1
1
  /**
2
- * §21's execution boundary (RT-070): resource limits and privilege
3
- * reporting for a runtime whose declared mode is trusted-local (see
4
- * DECISIONS.md RT-070) -- every spawned process runs with the invoking
5
- * user's own OS privileges, no filesystem or network restriction. That
6
- * declaration does not make unrestricted execution safe; it names the
7
- * boundary instead of leaving it absent, which is what §38's "arbitrary
8
- * application code runs without a defined safety boundary" actually bans.
9
- * Real isolation (containers/namespaces) is a separate architectural
10
- * decision this module does not invent (plan §29's own instruction).
2
+ * §21/RT-070's execution boundary: resource limits and privilege reporting for a
3
+ * runtime declared trusted-local -- every spawned process runs with the invoking
4
+ * user's own OS privileges, no filesystem/network restriction. Names the boundary
5
+ * rather than leaving it absent (§38); real isolation (containers/namespaces) is a
6
+ * separate decision this module does not invent (§29).
11
7
  *
12
- * What this module DOES enforce, for real, via the OS: CPU time, virtual
13
- * memory, and process count, through `prlimit` -- an exec wrapper, never a
14
- * shell. Reintroducing `sh -c 'ulimit ...; exec ...'` to get these would
15
- * undo RT-036's `tokenizeCommand` refusal of shell metacharacters. `prlimit`
16
- * is util-linux and absent on macOS, so it is reported as a capability,
17
- * never assumed.
8
+ * Enforces for real, via the OS: CPU time, virtual memory, process count, through
9
+ * `prlimit` -- an exec wrapper, never a shell (a shell would undo RT-036's
10
+ * `tokenizeCommand` refusal of shell metacharacters). `prlimit` is util-linux, absent
11
+ * on macOS, so it's reported as a capability, never assumed.
18
12
  */
19
13
  import { execFileSync } from "node:child_process";
20
14
  import { networkIsolationCapability } from "./sandbox.js";
21
- /**
22
- * Whether `prlimit` is reachable on this platform's `PATH`. Takes `env` as
23
- * a parameter (defaulting to `process.env`) rather than reading it
24
- * internally so the "unavailable" branch is directly testable without
25
- * mutating this process's own real environment or depending on running on
26
- * a platform that genuinely lacks it.
27
- */
15
+ /** Whether `prlimit` is reachable on PATH. `env` is a parameter (default `process.env`) so the "unavailable" branch is testable without mutating the real environment. */
28
16
  export function resourceLimitCapability(env = process.env) {
29
17
  try {
30
18
  execFileSync("prlimit", ["--version"], { env, stdio: "ignore" });
@@ -38,32 +26,22 @@ export function resourceLimitCapability(env = process.env) {
38
26
  }
39
27
  }
40
28
  /**
41
- * RT-193 originally made this always `unavailable` -- no platform had any
42
- * enforcement mechanism wired up. The sandbox-isolation lane changes that
43
- * on Linux: `networkIsolationCapability()` (`./sandbox.ts`) is real, backed
44
- * by a bwrap network namespace. This function is kept as the stable name
45
- * every existing caller (`ExecutionController.run()`, this package's own
46
- * tests) already imports, delegating rather than duplicating the check --
47
- * exactly the seam RT-193's own comment anticipated ("if a real mechanism
48
- * is ever built, this one function changes and every caller keeps working
49
- * unmodified"). Still unconditionally `unavailable` on macOS/Windows, where
50
- * nothing enforces it yet.
29
+ * RT-193 originally made this always `unavailable`. Now delegates to
30
+ * `networkIsolationCapability()` (`./sandbox.ts`), real on Linux via a bwrap network
31
+ * namespace -- kept as the stable name every caller already imports (the seam
32
+ * RT-193 anticipated). Still unconditionally `unavailable` on macOS/Windows.
51
33
  */
52
34
  export function networkPolicyCapability(env = process.env) {
53
35
  return networkIsolationCapability(env);
54
36
  }
55
37
  /**
56
- * Wraps `command`/`args` so the OS enforces `limits`, via `prlimit`.
57
- * `undefined` or an empty `limits` returns `command`/`args` unchanged --
58
- * every execution before RT-070 keeps behaving exactly as before unless it
59
- * opts in.
38
+ * Wraps `command`/`args` so the OS enforces `limits`, via `prlimit`. `undefined` or
39
+ * empty `limits` returns them unchanged -- opt-in only.
60
40
  *
61
- * **Throws rather than silently spawning unconstrained** when a limit was
62
- * requested and `prlimit` is unavailable. `tokenizeCommand`'s own precedent
63
- * (RT-036) is refuse rather than guess; the equivalent failure here would
64
- * be a caller asking for a memory cap and getting a process that can
65
- * allocate without bound, silently -- exactly the "sandbox that doesn't
66
- * sandbox" shape §38 bans, one row up from this one.
41
+ * **Throws rather than silently spawning unconstrained** when a limit was requested
42
+ * and `prlimit` is unavailable (refuse-not-guess, per RT-036) -- the alternative is a
43
+ * caller asking for a memory cap and silently getting an unbounded process, the
44
+ * "sandbox that doesn't sandbox" shape §38 bans.
67
45
  */
68
46
  export function applyResourceLimits(command, args, limits, env = process.env) {
69
47
  if (limits === undefined)
@@ -84,50 +62,30 @@ export function applyResourceLimits(command, args, limits, env = process.env) {
84
62
  return { command: "prlimit", args: [...flags, "--", command, ...args] };
85
63
  }
86
64
  /**
87
- * DEC-272's disclosure requirement: the sandbox boundary (RT-070) must be
88
- * stated to the user directly in-product, not left as a silent gap in a
89
- * doc. Fixed, not derived from `runningAsRoot` -- the boundary is the same
90
- * regardless of which privilege level was found; only the observed fact
91
- * changes.
65
+ * DEC-272: the sandbox boundary (RT-070) must be stated to the user directly, not
66
+ * left as a silent doc gap. Fixed, not derived from `runningAsRoot` -- the boundary
67
+ * is the same regardless of privilege level found.
92
68
  *
93
- * **Scope, corrected by the attach-mode-mitigations lane: this is the
94
- * unconditional-unisolated text, not a universal one.** Written when
95
- * RT-193/RT-070 landed, before `sandbox.ts` existed -- at that point it was
96
- * accurate for every execution, because nothing anywhere in this runtime
97
- * could isolate anything. That stopped being true the moment the
98
- * sandbox-isolation lane gave spawn-mode real, bwrap-backed filesystem/
99
- * network isolation (`applySandbox`, this same package): a spawned process
100
- * that actually got a `FilesystemPolicy`/`NetworkPolicy` applied to it is
101
- * genuinely more contained than "the same as if you started it yourself"
102
- * says. Using this constant unconditionally for that process would be a
103
- * real disclosure-accuracy bug -- understating a boundary is not the safe
104
- * direction to be wrong in, it just happens to be a less alarming one.
105
- * `sandboxBoundaryDisclosureFor()` below is the mode-aware replacement: it
106
- * returns this exact string when no policy was applied (attach-mode always,
107
- * and any spawn that declared none -- unchanged from before this lane), and
108
- * a real, specific description of what is and is not contained when a
109
- * policy genuinely was. This constant is kept, unchanged, as that function's
110
- * own no-policy-applied return value and as attach-mode's own disclosure,
111
- * not deprecated -- attach-mode never has anything more accurate to say.
69
+ * **Scope: this is the unconditional-unisolated text, not a universal one.** Accurate
70
+ * for every execution before `sandbox.ts` existed; no longer true once spawn-mode got
71
+ * real bwrap-backed isolation (`applySandbox`) -- using this unconditionally for an
72
+ * isolated process would understate its boundary, which is not the safe direction to
73
+ * be wrong in. `sandboxBoundaryDisclosureFor()` below is the mode-aware replacement;
74
+ * this constant remains its no-policy-applied return value and attach-mode's own
75
+ * disclosure (attach-mode never has anything more accurate to say).
112
76
  */
113
77
  export const SANDBOX_BOUNDARY_DISCLOSURE = "This app runs with your own user permissions, the same as if you started it yourself. " +
114
78
  "The filesystem and network are not isolated -- anything your own account could read, write, " +
115
79
  "or reach, this run can too.";
116
80
  const NO_POLICIES_APPLIED = { filesystemPolicyApplied: false, networkPolicyApplied: false };
117
81
  /**
118
- * The mode-aware replacement for reading `SANDBOX_BOUNDARY_DISCLOSURE`
119
- * unconditionally. Defaults to reporting no policy applied -- so calling
120
- * this with no argument at all is identical to the pre-existing constant,
121
- * the same non-regression contract every other opt-in in this file
122
- * (`applyResourceLimits`, `applySandbox`) already keeps.
82
+ * Mode-aware replacement for reading `SANDBOX_BOUNDARY_DISCLOSURE` unconditionally.
83
+ * Defaults to no-policy-applied, so a no-arg call matches the old constant exactly.
123
84
  *
124
- * **Still only ever true for spawn-mode.** Attach-mode has no code path
125
- * that can produce `filesystemPolicyApplied: true` or
126
- * `networkPolicyApplied: true` for any process it did not itself spawn --
127
- * see `sandbox.ts`'s own module doc for why that is structural, not a gap
128
- * in this function. A caller in attach-mode should simply never pass
129
- * anything but the default here, and the default's return value is this
130
- * disclosure's original, unconditional "not isolated" text, unchanged.
85
+ * **Only ever true for spawn-mode.** Attach-mode has no path to produce
86
+ * `filesystemPolicyApplied`/`networkPolicyApplied: true` for a process it didn't
87
+ * spawn (structural, see `sandbox.ts`) -- attach-mode callers should never pass
88
+ * anything but the default.
131
89
  */
132
90
  export function sandboxBoundaryDisclosureFor(policies = NO_POLICIES_APPLIED) {
133
91
  const { filesystemPolicyApplied, networkPolicyApplied } = policies;
@@ -150,15 +108,10 @@ export function sandboxBoundaryDisclosureFor(policies = NO_POLICIES_APPLIED) {
150
108
  "it can read, write, or reach anything your own account's filesystem could.");
151
109
  }
152
110
  /**
153
- * Attach mode's own contractual scope guarantee -- distinct from the
154
- * sandbox-*boundary* disclosure above (what is or isn't contained) because
155
- * this is a claim about what an attach-mode `Collector` is even permitted
156
- * to *do*, not about what OS boundary wraps it. See `Collector` in
157
- * `@descryy/runtime-contracts` for the interface-level statement this
158
- * mirrors, and `sandbox.ts`'s own module doc for why attach-mode can never
159
- * acquire the isolation `sandboxBoundaryDisclosureFor` describes for
160
- * spawn-mode. Stated once, here, so every attach-mode caller surfaces the
161
- * identical sentence rather than each writing its own paraphrase.
111
+ * Attach mode's contractual scope guarantee -- distinct from the sandbox-boundary
112
+ * disclosure above: this is what an attach-mode `Collector` is permitted to *do*, not
113
+ * what OS boundary wraps it. Mirrors `Collector` in `@descryy/runtime-contracts`.
114
+ * Stated once so every attach-mode caller surfaces the identical sentence.
162
115
  */
163
116
  export const ATTACH_MODE_SCOPE_DISCLOSURE = "Attach mode observes an already-running process; it never executes code in it or applies changes to it. " +
164
117
  "This is a permanent, documented architectural limitation, not a temporary gap -- there is no honest way to " +
@@ -166,22 +119,15 @@ export const ATTACH_MODE_SCOPE_DISCLOSURE = "Attach mode observes an already-run
166
119
  "Respawn-and-supervise and the cgroup resource-limit move are real alternatives next to attach mode, not " +
167
120
  "fixes to it; see their own documentation for what each actually gets you.";
168
121
  /**
169
- * Reports, never enforces. §21's privilege policy for a runtime declared
170
- * trusted-local (RT-070) is not "refuse to run as root" -- CI containers
171
- * commonly run as root by default, and a hard refusal there would turn a
172
- * documented boundary into an undocumented outage. The policy is: the real
173
- * privilege level becomes an observable fact instead of an invisible one,
174
- * which is what nothing before RT-070 made it.
122
+ * Reports, never enforces. §21's policy for trusted-local (RT-070) is not "refuse to
123
+ * run as root" -- CI containers commonly do, and a hard refusal would turn a
124
+ * documented boundary into an undocumented outage. The privilege level just becomes
125
+ * observable instead of invisible.
175
126
  *
176
- * A required parameter, not a defaulted one: `undefined` is the real,
177
- * meaningful value a platform with no uid concept produces
178
- * (`process.getuid` is itself `undefined` on Windows), and a *default*
179
- * parameter cannot tell "caller explicitly passed undefined" apart from
180
- * "caller omitted the argument" -- both look identical to the function.
181
- * `currentPrivilegeReport()` below is the zero-argument convenience wrapper
182
- * real callers use; this is what makes both branches -- root, and no uid
183
- * concept at all -- directly testable without this process actually
184
- * needing to run as root or on Windows.
127
+ * A required parameter, not defaulted: `undefined` is the real value a no-uid-concept
128
+ * platform produces, and a default can't distinguish "explicitly undefined" from
129
+ * "omitted." `currentPrivilegeReport()` below is the convenience wrapper; this makes
130
+ * both branches testable without actually running as root or on Windows.
185
131
  */
186
132
  export function privilegeReportFor(getuid) {
187
133
  if (getuid === undefined)
@@ -1 +1 @@
1
- {"version":3,"file":"execution-safety.js","sourceRoot":"","sources":["../src/execution-safety.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"execution-safety.js","sourceRoot":"","sources":["../src/execution-safety.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -20,16 +20,6 @@ export type { DependencyVersionMismatch, DependencyVersionCheckResult } from "./
20
20
  export { checkDependencyVersions } from "./dependency-version-check.ts";
21
21
  export type { DeclaredVersionSource, EnvironmentVersionCheckResult } from "./environment-version-check.ts";
22
22
  export { DECLARED_VERSION_SOURCES, checkEnvironmentVersion, satisfiesDeclaredNodeVersion } from "./environment-version-check.ts";
23
- /**
24
- * RT-073: promoted from internal-only. `tokenizeCommand`'s POSIX-style
25
- * "refuse rather than guess" tokenizer is exactly what `packages/test-runner`
26
- * needs to validate a declared runner command before spawning it -- the
27
- * same job it already does for `ServiceConfiguration.command` here.
28
- * Re-implementing a second copy for one more caller would be the "two
29
- * shapes that could drift" mistake this codebase has already named and
30
- * avoided elsewhere (RT-068's `BrowserConfiguration`, RT-070's
31
- * `ResourceLimits`).
32
- */
33
23
  export type { CommandTokenization, ServicesValidation } from "./orchestration.ts";
34
24
  export { tokenizeCommand, validateServicesConfiguration, substitutePortPlaceholders } from "./orchestration.ts";
35
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEjD,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACvH,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE1F,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,wBAAwB,EACxB,cAAc,EACd,eAAe,EACf,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEtE,YAAY,EAAE,oBAAoB,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,YAAY,EAAE,+BAA+B,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACxG,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAE5F,YAAY,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,2BAA2B,EAC3B,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC1B,8BAA8B,EAC9B,0BAA0B,EAC1B,YAAY,GACb,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EACL,0BAA0B,EAC1B,sCAAsC,EACtC,mCAAmC,EACnC,uCAAuC,EACvC,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAEvE,YAAY,EAAE,yBAAyB,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7G,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAExE,YAAY,EAAE,qBAAqB,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC3G,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAEjI;;;;;;;;;GASG;AACH,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAEjD,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACvH,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE1F,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,qBAAqB,EACrB,wBAAwB,EACxB,cAAc,EACd,eAAe,EACf,qBAAqB,GACtB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEtE,YAAY,EAAE,oBAAoB,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,YAAY,EAAE,+BAA+B,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACxG,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAE5F,YAAY,EAAE,eAAe,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,2BAA2B,EAC3B,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC1B,8BAA8B,EAC9B,0BAA0B,EAC1B,YAAY,GACb,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EACL,0BAA0B,EAC1B,sCAAsC,EACtC,mCAAmC,EACnC,uCAAuC,EACvC,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAEvE,YAAY,EAAE,yBAAyB,EAAE,4BAA4B,EAAE,MAAM,+BAA+B,CAAC;AAC7G,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAExE,YAAY,EAAE,qBAAqB,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAC;AAC3G,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAKjI,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,eAAe,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGjD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAa1F,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAGtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAG5F,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,2BAA2B,EAC3B,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC1B,8BAA8B,EAC9B,0BAA0B,EAC1B,YAAY,GACb,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,0BAA0B,EAC1B,sCAAsC,EACtC,mCAAmC,EACnC,uCAAuC,EACvC,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAGvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAGxE,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAajI,OAAO,EAAE,eAAe,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAGjD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAa1F,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAGtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAG5F,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,sBAAsB,EACtB,2BAA2B,EAC3B,4BAA4B,EAC5B,4BAA4B,GAC7B,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,6BAA6B,EAC7B,0BAA0B,EAC1B,8BAA8B,EAC9B,0BAA0B,EAC1B,YAAY,GACb,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,0BAA0B,EAC1B,sCAAsC,EACtC,mCAAmC,EACnC,uCAAuC,EACvC,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAAE,0BAA0B,EAAE,MAAM,2BAA2B,CAAC;AAGvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAGxE,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAMjI,OAAO,EAAE,eAAe,EAAE,6BAA6B,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC"}
@@ -1,15 +1,12 @@
1
1
  /**
2
- * Turns a declarative `services` map (plan §6, RT-028) into a concrete
3
- * spawn order for `ExecutionController.run()` (RT-032). Everything here is
4
- * pure and side-effect-free — validated and ordered before anything is
5
- * spawned, so a bad reference is refused atomically rather than discovered
6
- * mid-sequence with some services already running.
2
+ * Turns a declarative `services` map (§6, RT-028) into a concrete spawn order for
3
+ * `ExecutionController.run()` (RT-032). Pure and side-effect-free -- validated and
4
+ * ordered before anything is spawned, so a bad reference is refused atomically
5
+ * rather than discovered mid-sequence.
7
6
  *
8
- * Start order and port injection are **declared in configuration, never
9
- * inferred** — the same "ask, don't guess" discipline RT-023 already
10
- * applied to browser script-URL roots. A `${name.port}` reference alone
11
- * does not create an ordering guarantee; `name` must also appear in the
12
- * referencing service's own `dependsOn`, or validation refuses.
7
+ * Start order and port injection are declared, never inferred (RT-023's "ask, don't
8
+ * guess"): a `${name.port}` reference alone doesn't create an ordering guarantee --
9
+ * `name` must also appear in the referencing service's `dependsOn`, or validation refuses.
13
10
  */
14
11
  import type { ServiceConfiguration } from "@descryy/runtime-contracts";
15
12
  export type ServicesValidation = {
@@ -20,23 +17,17 @@ export type ServicesValidation = {
20
17
  readonly reason: string;
21
18
  };
22
19
  /**
23
- * Validates a `services` map and returns a valid topological spawn order.
24
- * Three checks, all before anything is spawned:
25
- * 1. every `dependsOn` entry names a real key in `services`;
26
- * 2. the `dependsOn` graph has no cycle (a start order must exist);
27
- * 3. every `${name}.port` placeholder referenced in a service's own `env`
28
- * has `name` in that same service's `dependsOn` — the placeholder does
29
- * not itself create the ordering guarantee it depends on.
20
+ * Validates a `services` map and returns a topological spawn order. Checks, all
21
+ * before anything is spawned: every `dependsOn` names a real key; the `dependsOn`
22
+ * graph has no cycle; every `${name}.port` placeholder in a service's `env` has
23
+ * `name` in that service's own `dependsOn`.
30
24
  */
31
25
  export declare function validateServicesConfiguration(services: Readonly<Record<string, ServiceConfiguration>>): ServicesValidation;
32
26
  /**
33
- * Replaces every `${name}.port` in `env`'s values with the resolved port
34
- * for `name`. Assumes `validateServicesConfiguration` already confirmed
35
- * every referenced name is a declared dependency that the caller resolves
36
- * earlier in the same spawn order — a reference this function can't
37
- * resolve is left untouched rather than silently dropped, so a caller that
38
- * skipped validation sees an obviously-wrong literal `${...}` instead of a
39
- * silently empty substitution.
27
+ * Replaces every `${name}.port` in `env`'s values with the resolved port for `name`.
28
+ * Assumes `validateServicesConfiguration` already confirmed the reference. An
29
+ * unresolvable reference is left untouched, not dropped -- a caller that skipped
30
+ * validation sees an obviously-wrong literal instead of a silent empty substitution.
40
31
  */
41
32
  export declare function substitutePortPlaceholders(env: Readonly<Record<string, string>> | undefined, resolvedPorts: ReadonlyMap<string, number>): Record<string, string>;
42
33
  export type CommandTokenization = {
@@ -48,23 +39,17 @@ export type CommandTokenization = {
48
39
  readonly reason: string;
49
40
  };
50
41
  /**
51
- * POSIX-style tokenizer for `ServiceConfiguration.command`: single quotes
52
- * (literal throughout), double quotes (with `\` escaping `"` and `\`), and
53
- * backslash escapes outside quotes. `spawnProcess` takes `command`/`args`
54
- * separately while configuration carries one string (plan §6's YAML shape),
55
- * so something has to split it, and doing that by whitespace alone breaks
56
- * every path with a space in it — `"C:\Program Files\node.exe"` and
57
- * `python3 -c "import app; app.main()"` both tokenized wrong before.
42
+ * POSIX-style tokenizer for `ServiceConfiguration.command`: single quotes (literal),
43
+ * double quotes (`\` escapes `"` and `\`), backslash escapes outside quotes. Needed
44
+ * because config carries one string (§6) but `spawnProcess` wants `command`/`args`
45
+ * separately, and plain whitespace-split breaks paths with spaces.
58
46
  *
59
- * **Refuses rather than guesses** on an unterminated quote, a trailing
60
- * backslash, or an unquoted shell operator. Each of those has no correct
61
- * interpretation without a shell, and returning a plausible tokenization
62
- * for input that cannot mean what it says is how a configuration error
63
- * arrives disguised as an application failure.
47
+ * Refuses rather than guesses on an unterminated quote, trailing backslash, or
48
+ * unquoted shell operator -- a plausible-but-wrong tokenization would disguise a
49
+ * config error as an application failure.
64
50
  *
65
- * Globs and `~` are *not* refused: they pass through literally, which is
66
- * exactly what happens with no shell, and unlike the operators above they
67
- * are frequently intended literally.
51
+ * Globs and `~` pass through literally, unrefused -- exactly what happens with no
52
+ * shell, and frequently intended literally.
68
53
  */
69
54
  export declare function tokenizeCommand(raw: string): CommandTokenization;
70
55
  //# sourceMappingURL=orchestration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"orchestration.d.ts","sourceRoot":"","sources":["../src/orchestration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAiBvE,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,GACvD,kBAAkB,CA+DpB;AAkCD;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,EACjD,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACzC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACjF;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAkBpD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CA8EhE"}
1
+ {"version":3,"file":"orchestration.d.ts","sourceRoot":"","sources":["../src/orchestration.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAUvE,MAAM,MAAM,kBAAkB,GAC1B;IAAE,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAC3D;IAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,GACvD,kBAAkB,CAyDpB;AAkCD;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,EACjD,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACzC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACjF;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAWpD;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,mBAAmB,CA6EhE"}