@descryy/runtime-controller 0.4.0 → 0.4.2

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 (85) hide show
  1. package/dist/attach-discovery.d.ts +26 -0
  2. package/dist/attach-discovery.d.ts.map +1 -1
  3. package/dist/attach-discovery.js +181 -10
  4. package/dist/attach-discovery.js.map +1 -1
  5. package/dist/attach-fencing.d.ts +11 -1
  6. package/dist/attach-fencing.d.ts.map +1 -1
  7. package/dist/attach-fencing.js +52 -23
  8. package/dist/attach-fencing.js.map +1 -1
  9. package/dist/attach-log-file.d.ts +23 -0
  10. package/dist/attach-log-file.d.ts.map +1 -0
  11. package/dist/attach-log-file.js +90 -0
  12. package/dist/attach-log-file.js.map +1 -0
  13. package/dist/bounded-file.d.ts +11 -0
  14. package/dist/bounded-file.d.ts.map +1 -0
  15. package/dist/bounded-file.js +41 -0
  16. package/dist/bounded-file.js.map +1 -0
  17. package/dist/bounded-output.d.ts +25 -0
  18. package/dist/bounded-output.d.ts.map +1 -0
  19. package/dist/bounded-output.js +95 -0
  20. package/dist/bounded-output.js.map +1 -0
  21. package/dist/container-sandbox.d.ts +7 -20
  22. package/dist/container-sandbox.d.ts.map +1 -1
  23. package/dist/container-sandbox.js +140 -8
  24. package/dist/container-sandbox.js.map +1 -1
  25. package/dist/controller.d.ts +10 -2
  26. package/dist/controller.d.ts.map +1 -1
  27. package/dist/controller.js +245 -84
  28. package/dist/controller.js.map +1 -1
  29. package/dist/dependency-version-check.d.ts +1 -0
  30. package/dist/dependency-version-check.d.ts.map +1 -1
  31. package/dist/dependency-version-check.js +43 -24
  32. package/dist/dependency-version-check.js.map +1 -1
  33. package/dist/environment-metadata.d.ts +13 -0
  34. package/dist/environment-metadata.d.ts.map +1 -1
  35. package/dist/environment-metadata.js +138 -24
  36. package/dist/environment-metadata.js.map +1 -1
  37. package/dist/environment-version-check.d.ts +1 -0
  38. package/dist/environment-version-check.d.ts.map +1 -1
  39. package/dist/environment-version-check.js +13 -7
  40. package/dist/environment-version-check.js.map +1 -1
  41. package/dist/execution-safety.d.ts +2 -0
  42. package/dist/execution-safety.d.ts.map +1 -1
  43. package/dist/execution-safety.js +36 -0
  44. package/dist/execution-safety.js.map +1 -1
  45. package/dist/index.d.ts +16 -7
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +9 -4
  48. package/dist/index.js.map +1 -1
  49. package/dist/node-options.d.ts +3 -0
  50. package/dist/node-options.d.ts.map +1 -0
  51. package/dist/node-options.js +34 -0
  52. package/dist/node-options.js.map +1 -0
  53. package/dist/orphan-reaper-process.d.ts +2 -0
  54. package/dist/orphan-reaper-process.d.ts.map +1 -0
  55. package/dist/orphan-reaper-process.js +98 -0
  56. package/dist/orphan-reaper-process.js.map +1 -0
  57. package/dist/orphan-reaper.d.ts +25 -0
  58. package/dist/orphan-reaper.d.ts.map +1 -0
  59. package/dist/orphan-reaper.js +161 -0
  60. package/dist/orphan-reaper.js.map +1 -0
  61. package/dist/process-identity.d.ts +1 -0
  62. package/dist/process-identity.d.ts.map +1 -1
  63. package/dist/process-identity.js +18 -4
  64. package/dist/process-identity.js.map +1 -1
  65. package/dist/process-manager.d.ts +13 -9
  66. package/dist/process-manager.d.ts.map +1 -1
  67. package/dist/process-manager.js +309 -133
  68. package/dist/process-manager.js.map +1 -1
  69. package/dist/readiness.d.ts +1 -0
  70. package/dist/readiness.d.ts.map +1 -1
  71. package/dist/readiness.js +77 -11
  72. package/dist/readiness.js.map +1 -1
  73. package/dist/sandbox.d.ts +22 -8
  74. package/dist/sandbox.d.ts.map +1 -1
  75. package/dist/sandbox.js +366 -51
  76. package/dist/sandbox.js.map +1 -1
  77. package/dist/spawn-environment.d.ts +16 -0
  78. package/dist/spawn-environment.d.ts.map +1 -0
  79. package/dist/spawn-environment.js +35 -0
  80. package/dist/spawn-environment.js.map +1 -0
  81. package/dist/target-pid.d.ts +6 -0
  82. package/dist/target-pid.d.ts.map +1 -0
  83. package/dist/target-pid.js +18 -0
  84. package/dist/target-pid.js.map +1 -0
  85. package/package.json +2 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded-file.d.ts","sourceRoot":"","sources":["../src/bounded-file.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAC5B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAI1D,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CA6BtF"}
@@ -0,0 +1,41 @@
1
+ import { closeSync, constants as fsConstants, fstatSync, openSync, readSync } from "node:fs";
2
+ const READ_CHUNK_BYTES = 64 * 1024;
3
+ export function readBoundedRegularFile(path, maxBytes) {
4
+ let descriptor;
5
+ try {
6
+ descriptor = openSync(path, fsConstants.O_RDONLY | fsConstants.O_NONBLOCK);
7
+ }
8
+ catch (error) {
9
+ const code = error.code;
10
+ if (code === "ENOENT" || code === "ENOTDIR")
11
+ return { kind: "missing" };
12
+ return { kind: "skipped", reason: `${path} could not be opened: ${error instanceof Error ? error.message : String(error)}` };
13
+ }
14
+ try {
15
+ const stats = fstatSync(descriptor);
16
+ if (!stats.isFile())
17
+ return { kind: "skipped", reason: `${path} is not a regular file, so it was not read` };
18
+ if (stats.size > maxBytes)
19
+ return { kind: "skipped", reason: `${path} is ${String(stats.size)} bytes, over the ${String(maxBytes)} byte limit, so it was not read` };
20
+ const chunks = [];
21
+ let total = 0;
22
+ for (;;) {
23
+ const chunk = Buffer.allocUnsafe(Math.min(READ_CHUNK_BYTES, maxBytes - total + 1));
24
+ const read = readSync(descriptor, chunk, 0, chunk.length, null);
25
+ if (read === 0)
26
+ break;
27
+ total += read;
28
+ if (total > maxBytes)
29
+ return { kind: "skipped", reason: `${path} grew past the ${String(maxBytes)} byte limit while being read, so it was not used` };
30
+ chunks.push(chunk.subarray(0, read));
31
+ }
32
+ return { kind: "read", text: Buffer.concat(chunks).toString("utf8") };
33
+ }
34
+ catch (error) {
35
+ return { kind: "skipped", reason: `${path} could not be read: ${error instanceof Error ? error.message : String(error)}` };
36
+ }
37
+ finally {
38
+ closeSync(descriptor);
39
+ }
40
+ }
41
+ //# sourceMappingURL=bounded-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded-file.js","sourceRoot":"","sources":["../src/bounded-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,SAAS,IAAI,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAO7F,MAAM,gBAAgB,GAAG,EAAE,GAAG,IAAI,CAAC;AAEnC,MAAM,UAAU,sBAAsB,CAAC,IAAY,EAAE,QAAgB;IACnE,IAAI,UAAkB,CAAC;IACvB,IAAI,CAAC;QACH,UAAU,GAAG,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,QAAQ,GAAG,WAAW,CAAC,UAAU,CAAC,CAAC;IAC7E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,GAAI,KAA+B,CAAC,IAAI,CAAC;QACnD,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACxE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,yBAAyB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;IAC/H,CAAC;IACD,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,4CAA4C,EAAE,CAAC;QAC7G,IAAI,KAAK,CAAC,IAAI,GAAG,QAAQ;YAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,oBAAoB,MAAM,CAAC,QAAQ,CAAC,iCAAiC,EAAE,CAAC;QACrK,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,SAAS,CAAC;YACR,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,QAAQ,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;YACnF,MAAM,IAAI,GAAG,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAChE,IAAI,IAAI,KAAK,CAAC;gBAAE,MAAM;YACtB,KAAK,IAAI,IAAI,CAAC;YACd,IAAI,KAAK,GAAG,QAAQ;gBAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,kBAAkB,MAAM,CAAC,QAAQ,CAAC,kDAAkD,EAAE,CAAC;YACtJ,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;QACvC,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;IACxE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,IAAI,uBAAuB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;IAC7H,CAAC;YAAS,CAAC;QACT,SAAS,CAAC,UAAU,CAAC,CAAC;IACxB,CAAC;AACH,CAAC"}
@@ -0,0 +1,25 @@
1
+ export declare const OUTPUT_HEAD_BYTES: number;
2
+ export declare const OUTPUT_TAIL_BYTES: number;
3
+ export interface ProcessOutputInfo {
4
+ /** Every byte this process has written to stdout+stderr, whether kept or dropped. */
5
+ readonly totalBytesSeen: number;
6
+ /** True once `totalBytesSeen` exceeds what head+tail can hold -- `readOutput()` is a bounded view, not the whole thing. */
7
+ readonly truncated: boolean;
8
+ }
9
+ export interface ProcessOutputRead {
10
+ readonly text: string;
11
+ readonly cursor: number;
12
+ readonly droppedChars: number;
13
+ }
14
+ export declare function assertCursor(cursor: number, end: number): void;
15
+ export declare class BoundedOutput {
16
+ #private;
17
+ skipLeadingBytes(bytes: number): void;
18
+ appendText(text: string): void;
19
+ countBytes(bytes: number): void;
20
+ startNewEpoch(): void;
21
+ read(): string;
22
+ info(): ProcessOutputInfo;
23
+ readFrom(cursor: number): ProcessOutputRead;
24
+ }
25
+ //# sourceMappingURL=bounded-output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded-output.d.ts","sourceRoot":"","sources":["../src/bounded-output.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAC3C,eAAO,MAAM,iBAAiB,QAAc,CAAC;AAE7C,MAAM,WAAW,iBAAiB;IAChC,qFAAqF;IACrF,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,2HAA2H;IAC3H,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAUD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAO9D;AAED,qBAAa,aAAa;;IASxB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIrC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAW9B,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI/B,aAAa,IAAI,IAAI;IAYrB,IAAI,IAAI,MAAM;IAYd,IAAI,IAAI,iBAAiB;IAIzB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB;CAyB5C"}
@@ -0,0 +1,95 @@
1
+ export const OUTPUT_HEAD_BYTES = 64 * 1024;
2
+ export const OUTPUT_TAIL_BYTES = 1024 * 1024;
3
+ function truncationMarker(droppedChars, totalChars, totalBytes) {
4
+ return `\n\n...[Descry truncated ${String(droppedChars)} of ${String(totalChars)} characters (${String(totalBytes)} bytes) of output here -- head/tail kept, middle dropped]...\n\n`;
5
+ }
6
+ function leadingSkipMarker(skippedBytes) {
7
+ return `...[Descry skipped the first ${String(skippedBytes)} bytes of the existing log: only the newest bytes up to the backlog cap are read, so the first line below may be cut]...\n`;
8
+ }
9
+ export function assertCursor(cursor, end) {
10
+ if (!Number.isSafeInteger(cursor) || cursor < 0) {
11
+ throw new RangeError(`output cursor must be a non-negative integer, got ${String(cursor)}`);
12
+ }
13
+ if (cursor > end) {
14
+ throw new RangeError(`output cursor ${String(cursor)} is past the ${String(end)} characters of output that exist`);
15
+ }
16
+ }
17
+ export class BoundedOutput {
18
+ #head = "";
19
+ #tail = "";
20
+ #chars = 0;
21
+ #bytes = 0;
22
+ #epochStart = 0;
23
+ #skippedLeadingBytes = 0;
24
+ #skippedLeadingReported = false;
25
+ skipLeadingBytes(bytes) {
26
+ this.#skippedLeadingBytes += bytes;
27
+ }
28
+ appendText(text) {
29
+ if (text === "")
30
+ return;
31
+ this.#chars += text.length;
32
+ if (this.#head.length < OUTPUT_HEAD_BYTES) {
33
+ this.#head += text;
34
+ if (this.#head.length > OUTPUT_HEAD_BYTES)
35
+ this.#head = this.#head.slice(0, OUTPUT_HEAD_BYTES);
36
+ }
37
+ this.#tail += text;
38
+ if (this.#tail.length > OUTPUT_TAIL_BYTES)
39
+ this.#tail = this.#tail.slice(this.#tail.length - OUTPUT_TAIL_BYTES);
40
+ }
41
+ countBytes(bytes) {
42
+ this.#bytes += bytes;
43
+ }
44
+ startNewEpoch() {
45
+ this.#epochStart += this.#chars;
46
+ this.#chars = 0;
47
+ this.#bytes = 0;
48
+ this.#head = "";
49
+ this.#tail = "";
50
+ }
51
+ #droppedMiddleChars() {
52
+ return Math.max(0, this.#chars - this.#head.length - this.#tail.length);
53
+ }
54
+ read() {
55
+ const text = this.#readKept();
56
+ return this.#skippedLeadingBytes === 0 ? text : leadingSkipMarker(this.#skippedLeadingBytes) + text;
57
+ }
58
+ #readKept() {
59
+ const tailStart = this.#chars - this.#tail.length;
60
+ if (tailStart <= 0)
61
+ return this.#tail;
62
+ if (this.#head.length >= tailStart)
63
+ return this.#head.slice(0, tailStart) + this.#tail;
64
+ return this.#head + truncationMarker(this.#droppedMiddleChars(), this.#chars, this.#bytes) + this.#tail;
65
+ }
66
+ info() {
67
+ return { totalBytesSeen: this.#bytes, truncated: this.#droppedMiddleChars() > 0 || this.#skippedLeadingBytes > 0 };
68
+ }
69
+ readFrom(cursor) {
70
+ const end = this.#epochStart + this.#chars;
71
+ assertCursor(cursor, end);
72
+ let droppedChars = 0;
73
+ if (!this.#skippedLeadingReported && this.#skippedLeadingBytes > 0 && cursor === 0) {
74
+ this.#skippedLeadingReported = true;
75
+ droppedChars += this.#skippedLeadingBytes;
76
+ }
77
+ let relative = cursor - this.#epochStart;
78
+ if (relative < 0) {
79
+ droppedChars += -relative;
80
+ relative = 0;
81
+ }
82
+ const tailStart = this.#chars - this.#tail.length;
83
+ if (relative >= tailStart) {
84
+ return { text: this.#tail.slice(relative - tailStart), cursor: end, droppedChars };
85
+ }
86
+ if (relative < this.#head.length) {
87
+ if (this.#head.length >= tailStart) {
88
+ return { text: this.#head.slice(relative, tailStart) + this.#tail, cursor: end, droppedChars };
89
+ }
90
+ return { text: this.#head.slice(relative), cursor: this.#epochStart + this.#head.length, droppedChars };
91
+ }
92
+ return { text: this.#tail, cursor: end, droppedChars: droppedChars + (tailStart - relative) };
93
+ }
94
+ }
95
+ //# sourceMappingURL=bounded-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded-output.js","sourceRoot":"","sources":["../src/bounded-output.ts"],"names":[],"mappings":"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"}
@@ -49,7 +49,7 @@
49
49
  * interception + IP filtering) -- `unsupportedContainerNetworkPolicyReason` reports
50
50
  * it the same way, matching posture rather than overclaiming.
51
51
  */
52
- import type { CapabilityStatus, FilesystemPolicy, NetworkPolicy } from "@descryy/runtime-contracts";
52
+ import type { CapabilityStatus, FilesystemPolicy, NetworkPolicy, ResourceLimits } from "@descryy/runtime-contracts";
53
53
  /** Real check: working Docker CLI + reachable daemon, not just a `docker` binary on PATH. `docker version` talks to the daemon, so a CLI with no daemon running fails the same way a missing binary does -- both mean "cannot enforce." */
54
54
  export declare function containerRuntimeCapability(env?: NodeJS.ProcessEnv): CapabilityStatus;
55
55
  export declare function containerFilesystemIsolationCapability(env?: NodeJS.ProcessEnv): CapabilityStatus;
@@ -68,37 +68,24 @@ export interface ContainerSandboxOptions {
68
68
  readonly filesystemPolicy?: FilesystemPolicy;
69
69
  readonly networkPolicy?: NetworkPolicy;
70
70
  /**
71
- * Env vars the containerized process needs, forwarded via `-e KEY=VALUE`. `PATH` is
71
+ * Env vars the containerized process needs. `PATH` is
72
72
  * never forwarded: the container must resolve `command` against its own image
73
73
  * layout (`/usr/local/bin/node`, not the host's), and the host's PATH would break
74
- * that or run the wrong binary. Everything else forwards unfiltered, matching
75
- * bwrap's own unfiltered-inheritance precedent (no `--clearenv`).
74
+ * that or run the wrong binary.
76
75
  */
77
76
  readonly processEnv?: Readonly<Record<string, string | undefined>>;
78
77
  /** Env for running the `docker` CLI itself (PATH, `DOCKER_HOST`). Defaults to `process.env`. */
79
78
  readonly env?: NodeJS.ProcessEnv;
80
79
  /** Explicit override, bypasses `resolveContainerImage`'s name-based guess. */
81
80
  readonly containerImage?: string;
81
+ readonly resourceLimits?: ResourceLimits;
82
82
  }
83
- /**
84
- * Wraps `command`/`args` with `docker run` so a container boundary enforces
85
- * `filesystemPolicy`/`networkPolicy`. Neither declared returns them unchanged and
86
- * never invokes docker -- same non-regression contract as `sandbox.ts`'s
87
- * `applySandbox`.
88
- *
89
- * **Throws rather than silently spawning unconstrained** when a policy can't
90
- * actually be backed (no working Docker, unimplemented `networkPolicy` shape).
91
- *
92
- * **Returns a real, unique `containerName` whenever it wraps.** Found via real
93
- * escape testing: `process-manager.ts`'s group-kill targets the local `docker` CLI
94
- * process's group, which is right for bwrap but not Docker -- the container runs
95
- * under `dockerd`, not as the CLI's child, so killing the CLI's group left an
96
- * orphaned `node:22-slim` container running in testing. `containerName` lets the
97
- * caller issue an explicit `docker stop <name>` against the container itself.
98
- */
83
+ export declare const CONTAINER_HOST_ENV_PASSTHROUGH: readonly string[];
84
+ export declare function containerProcessEnv(declared: Readonly<Record<string, string | undefined>> | undefined, host?: NodeJS.ProcessEnv): Record<string, string | undefined>;
99
85
  export declare function applyContainerSandbox(options: ContainerSandboxOptions): {
100
86
  readonly command: string;
101
87
  readonly args: readonly string[];
102
88
  readonly containerName?: string;
89
+ readonly env?: Readonly<Record<string, string>>;
103
90
  };
104
91
  //# sourceMappingURL=container-sandbox.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"container-sandbox.d.ts","sourceRoot":"","sources":["../src/container-sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAKH,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEpG,2OAA2O;AAC3O,wBAAgB,0BAA0B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,gBAAgB,CAUjG;AAKD,wBAAgB,sCAAsC,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,gBAAgB,CAE7G;AAED,wBAAgB,mCAAmC,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,gBAAgB,CAE1G;AAED,+NAA+N;AAC/N,wBAAgB,uCAAuC,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAO5F;AAYD,wBAAgB,qBAAqB,CAAC,kBAAkB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE/E;AAED,MAAM,WAAW,uBAAuB;IACtC,oGAAoG;IACpG,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,qGAAqG;IACrG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,mHAAmH;IACnH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAC7C,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC;;;;;;OAMG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IACnE,gGAAgG;IAChG,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,8EAA8E;IAC9E,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,uBAAuB,GAC/B;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,CAkDjG"}
1
+ {"version":3,"file":"container-sandbox.d.ts","sourceRoot":"","sources":["../src/container-sandbox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAOH,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGpH,2OAA2O;AAC3O,wBAAgB,0BAA0B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,gBAAgB,CAUjG;AAmCD,wBAAgB,sCAAsC,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,gBAAgB,CAE7G;AAED,wBAAgB,mCAAmC,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,gBAAgB,CAE1G;AAED,+NAA+N;AAC/N,wBAAgB,uCAAuC,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAO5F;AAYD,wBAAgB,qBAAqB,CAAC,kBAAkB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE/E;AAED,MAAM,WAAW,uBAAuB;IACtC,oGAAoG;IACpG,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,qGAAqG;IACrG,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,mHAAmH;IACnH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAC7C,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IACnE,gGAAgG;IAChG,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,8EAA8E;IAC9E,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;CAC1C;AA0ED,eAAO,MAAM,8BAA8B,EAAE,SAAS,MAAM,EAAqD,CAAC;AAElH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,SAAS,EAClE,IAAI,GAAE,MAAM,CAAC,UAAwB,GACpC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAMpC;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,uBAAuB,GAC/B;IACD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACjD,CAqFA"}
@@ -51,7 +51,10 @@
51
51
  */
52
52
  import { execFileSync } from "node:child_process";
53
53
  import { randomUUID } from "node:crypto";
54
- import { basename } from "node:path";
54
+ import { existsSync } from "node:fs";
55
+ import { basename, dirname, isAbsolute, join, relative } from "node:path";
56
+ import { fileURLToPath } from "node:url";
57
+ import { sandboxPathRefusalReason, writableAllowedRoots } from "./sandbox.js";
55
58
  /** Real check: working Docker CLI + reachable daemon, not just a `docker` binary on PATH. `docker version` talks to the daemon, so a CLI with no daemon running fails the same way a missing binary does -- both mean "cannot enforce." */
56
59
  export function containerRuntimeCapability(env = process.env) {
57
60
  try {
@@ -63,8 +66,32 @@ export function containerRuntimeCapability(env = process.env) {
63
66
  reason: "docker is not on PATH, or no Docker daemon is reachable -- container-based isolation cannot be enforced without a real, running Docker",
64
67
  };
65
68
  }
69
+ return hardenedLaunchStatus(env);
70
+ }
71
+ const HARDENED_PROBE_IMAGE = "alpine:latest";
72
+ const HARDENED_PROBE_TIMEOUT_MS = 60_000;
73
+ let defaultEnvHardenedStatus;
74
+ function probeHardenedLaunch(env) {
75
+ try {
76
+ execFileSync("docker", ["run", "--rm", "--pull", "never", "--cap-drop", "ALL", "--security-opt", "no-new-privileges", HARDENED_PROBE_IMAGE, "true"], { env, stdio: ["ignore", "ignore", "pipe"], timeout: HARDENED_PROBE_TIMEOUT_MS });
77
+ }
78
+ catch (error) {
79
+ const stderr = String(error.stderr ?? "");
80
+ if (/operation not permitted/i.test(stderr)) {
81
+ return {
82
+ availability: "unavailable",
83
+ reason: "docker is reachable but cannot start a container with --security-opt no-new-privileges here (exec: operation not permitted -- typically a snap-confined Docker); the container sandbox launches every process that way, so it cannot be enforced on this host",
84
+ };
85
+ }
86
+ }
66
87
  return { availability: "available", reason: null };
67
88
  }
89
+ function hardenedLaunchStatus(env) {
90
+ if (env !== process.env)
91
+ return probeHardenedLaunch(env);
92
+ defaultEnvHardenedStatus ??= probeHardenedLaunch(env);
93
+ return defaultEnvHardenedStatus;
94
+ }
68
95
  // Mirrors sandbox.ts's filesystem/network capability split: one real mechanism
69
96
  // (container boundary), two named capabilities since the policies are declared
70
97
  // and reasoned about independently.
@@ -110,6 +137,73 @@ export function resolveContainerImage(interpreterCommand) {
110
137
  * orphaned `node:22-slim` container running in testing. `containerName` lets the
111
138
  * caller issue an explicit `docker stop <name>` against the container itself.
112
139
  */
140
+ const DEFAULT_CONTAINER_PIDS_LIMIT = 4096;
141
+ function isWithin(root, target) {
142
+ const offset = relative(root, target);
143
+ return offset === "" || (!offset.startsWith("..") && !isAbsolute(offset));
144
+ }
145
+ function hostUserSpecifier() {
146
+ const uid = process.getuid?.();
147
+ const gid = process.getgid?.();
148
+ if (uid === undefined || gid === undefined || uid === 0)
149
+ return null;
150
+ return `${String(uid)}:${String(gid)}`;
151
+ }
152
+ const NODE_OPTIONS_MODULE_FLAGS = new Set(["--import", "--require", "-r", "--experimental-loader", "--loader"]);
153
+ function nearestPackageRoot(file) {
154
+ let directory = dirname(file);
155
+ for (let hops = 0; hops < 4; hops += 1) {
156
+ if (existsSync(join(directory, "package.json")))
157
+ return directory;
158
+ const parent = dirname(directory);
159
+ if (parent === directory)
160
+ break;
161
+ directory = parent;
162
+ }
163
+ return dirname(file);
164
+ }
165
+ function fileUrlToPathOrNull(value) {
166
+ try {
167
+ return fileURLToPath(value);
168
+ }
169
+ catch {
170
+ return null;
171
+ }
172
+ }
173
+ function instrumentationRoots(nodeOptions) {
174
+ if (nodeOptions === undefined)
175
+ return [];
176
+ const tokens = nodeOptions.match(/"(?:[^"\\]|\\.)*"|\S+/g) ?? [];
177
+ const roots = new Set();
178
+ for (let index = 0; index < tokens.length; index += 1) {
179
+ const flag = tokens[index];
180
+ const equals = flag.indexOf("=");
181
+ const [name, inlineValue] = equals > 0 ? [flag.slice(0, equals), flag.slice(equals + 1)] : [flag, undefined];
182
+ if (!NODE_OPTIONS_MODULE_FLAGS.has(name))
183
+ continue;
184
+ let value = inlineValue ?? tokens[index + 1];
185
+ if (inlineValue === undefined)
186
+ index += 1;
187
+ if (value === undefined)
188
+ continue;
189
+ if (value.startsWith('"'))
190
+ value = value.slice(1, -1).replace(/\\(.)/g, "$1");
191
+ const path = value.startsWith("file://") ? fileUrlToPathOrNull(value) : value;
192
+ if (path !== null && isAbsolute(path) && existsSync(path))
193
+ roots.add(nearestPackageRoot(path));
194
+ }
195
+ return [...roots];
196
+ }
197
+ const FORWARDABLE_ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;
198
+ export const CONTAINER_HOST_ENV_PASSTHROUGH = ["LANG", "LANGUAGE", "LC_ALL", "LC_CTYPE", "TZ"];
199
+ export function containerProcessEnv(declared, host = process.env) {
200
+ const env = {};
201
+ for (const name of CONTAINER_HOST_ENV_PASSTHROUGH) {
202
+ if (host[name] !== undefined)
203
+ env[name] = host[name];
204
+ }
205
+ return { ...env, ...declared };
206
+ }
113
207
  export function applyContainerSandbox(options) {
114
208
  const { filesystemPolicy, networkPolicy } = options;
115
209
  if (filesystemPolicy === undefined && networkPolicy === undefined) {
@@ -131,22 +225,60 @@ export function applyContainerSandbox(options) {
131
225
  throw new Error(`container sandbox was requested but no base image is known for interpreter "${options.interpreterCommand}" -- pass containerImage explicitly`);
132
226
  }
133
227
  const containerName = `descry-sandbox-${randomUUID()}`;
134
- const dockerArgs = ["run", "--rm", "--name", containerName];
228
+ const dockerArgs = ["run", "--rm", "--init", "--name", containerName, "--cap-drop", "ALL", "--security-opt", "no-new-privileges"];
229
+ dockerArgs.push("--pids-limit", String(options.resourceLimits?.maxProcesses ?? DEFAULT_CONTAINER_PIDS_LIMIT));
230
+ if (options.resourceLimits?.maxMemoryBytes !== undefined)
231
+ dockerArgs.push("--memory", String(options.resourceLimits.maxMemoryBytes));
232
+ if (options.resourceLimits?.maxCpuSeconds !== undefined)
233
+ dockerArgs.push("--ulimit", `cpu=${String(options.resourceLimits.maxCpuSeconds)}`);
234
+ const hostUser = hostUserSpecifier();
235
+ if (hostUser !== null)
236
+ dockerArgs.push("--user", hostUser);
135
237
  if (networkPolicy !== undefined) {
136
238
  dockerArgs.push("--network", "none");
137
239
  }
138
- dockerArgs.push("-v", `${options.cwd}:${options.cwd}`, "-w", options.cwd);
139
- if (filesystemPolicy !== undefined) {
140
- for (const root of filesystemPolicy.allowedRoots) {
141
- dockerArgs.push("-v", `${root}:${root}`);
240
+ const allowedWritableRoots = writableAllowedRoots(filesystemPolicy);
241
+ const writableRoots = [options.cwd, ...allowedWritableRoots];
242
+ const mounts = [
243
+ { role: "working directory", path: options.cwd, readOnly: false },
244
+ ];
245
+ for (const path of allowedWritableRoots) {
246
+ if (mounts.some((mount) => mount.path === path))
247
+ continue;
248
+ mounts.push({ role: "allowed root", path, readOnly: false });
249
+ }
250
+ for (const root of filesystemPolicy?.readOnlyRoots ?? []) {
251
+ if (writableRoots.some((bound) => isWithin(bound, root)) || !existsSync(root))
252
+ continue;
253
+ mounts.push({ role: "read-only root", path: root, readOnly: true });
254
+ }
255
+ for (const preloadRoot of instrumentationRoots(options.processEnv?.NODE_OPTIONS)) {
256
+ if (mounts.some((mount) => isWithin(mount.path, preloadRoot)))
257
+ continue;
258
+ mounts.push({ role: "instrumentation directory", path: preloadRoot, readOnly: true });
259
+ }
260
+ for (const mount of mounts) {
261
+ const refusal = sandboxPathRefusalReason(mount.path, mount.role);
262
+ if (refusal !== null)
263
+ throw new Error(`sandbox refused: ${refusal}`);
264
+ if (/[,"\n\r\0]/.test(mount.path)) {
265
+ throw new Error(`sandbox refused: ${mount.role} ${JSON.stringify(mount.path)} contains a character (comma, quote or line break) that cannot be passed to docker --mount`);
142
266
  }
267
+ dockerArgs.push("--mount", `type=bind,source=${mount.path},target=${mount.path}${mount.readOnly ? ",readonly" : ""}`);
143
268
  }
269
+ dockerArgs.push("-w", options.cwd);
270
+ const forwarded = {};
144
271
  for (const [key, value] of Object.entries(options.processEnv ?? {})) {
145
272
  if (key === "PATH" || value === undefined)
146
273
  continue;
147
- dockerArgs.push("-e", `${key}=${value}`);
274
+ if (!FORWARDABLE_ENV_NAME.test(key)) {
275
+ throw new Error(`environment variable ${JSON.stringify(key)} cannot be forwarded into the container: a name must be letters, digits ` +
276
+ "and underscores, not starting with a digit");
277
+ }
278
+ forwarded[key] = value;
279
+ dockerArgs.push("-e", key);
148
280
  }
149
281
  dockerArgs.push(image, options.command, ...options.args);
150
- return { command: "docker", args: dockerArgs, containerName };
282
+ return { command: "docker", args: dockerArgs, containerName, env: forwarded };
151
283
  }
152
284
  //# sourceMappingURL=container-sandbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"container-sandbox.js","sourceRoot":"","sources":["../src/container-sandbox.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"container-sandbox.js","sourceRoot":"","sources":["../src/container-sandbox.ts"],"names":[],"mappings":"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"}
@@ -5,8 +5,10 @@
5
5
  * specific language or framework (principle 8).
6
6
  */
7
7
  import { type Execution, type ProcessHandle } from "@descryy/runtime-contracts";
8
+ import { type ProcessOutputRead } from "./process-manager.ts";
8
9
  import type { AttachFence } from "./attach-fencing.ts";
9
10
  import { type ProcessOutputReader, type ReadinessCheck, type ReadinessResult } from "./readiness.ts";
11
+ import { type OrphanProtectionStatus } from "./orphan-reaper.ts";
10
12
  import type { ExecutionConfiguration } from "@descryy/runtime-contracts";
11
13
  export interface CreateExecutionInput {
12
14
  readonly application: string;
@@ -39,6 +41,7 @@ export interface RunOptions {
39
41
  * swallow its own failure" discipline `Collector` imposes on every callback here.
40
42
  */
41
43
  readonly onProcessLifecycleEvent?: (event: ProcessLifecycleEvent) => void;
44
+ readonly signal?: AbortSignal;
42
45
  }
43
46
  export interface ServiceStartResult {
44
47
  readonly serviceName: string;
@@ -96,8 +99,13 @@ export declare class ExecutionController {
96
99
  get serviceStartResults(): readonly ServiceStartResult[];
97
100
  /** Non-null only when `run()` refused before spawning anything. */
98
101
  get validationError(): string | null;
102
+ get timeoutNote(): string | null;
103
+ get orphanProtection(): OrphanProtectionStatus;
104
+ get lifecycleObserverErrors(): readonly string[];
105
+ get teardownErrors(): readonly string[];
99
106
  /** Combined stdout+stderr of the named service's process so far, or "" if it was never spawned. */
100
107
  readProcessOutput(serviceName: string): string;
108
+ readProcessOutputFrom(serviceName: string, cursor: number): ProcessOutputRead;
101
109
  /**
102
110
  * RT-N3's fence for the named service's process, or `null` for a spawned
103
111
  * service (nothing predates observation) or one this controller never
@@ -132,11 +140,11 @@ export declare class ExecutionController {
132
140
  run(options: RunOptions): Promise<Execution>;
133
141
  stop(): Promise<Execution>;
134
142
  /**
135
- * Stop everything and record `TIMED_OUT` -- same transition `#onTimeout` makes,
143
+ * Stop everything and record `TIMED_OUT` -- same transition the internal timer makes,
136
144
  * for a caller that knows the budget expired before the internal timer noticed.
137
145
  *
138
146
  * **Why not `stop()`:** the orchestrator clamps its observation window to
139
- * whatever's left of `timeoutMs`, making `TIMED_OUT` a race between `#onTimeout`
147
+ * whatever's left of `timeoutMs`, making `TIMED_OUT` a race between the internal timer
140
148
  * and `stop()` at the deadline -- measured: the same case reported `TIMED_OUT` at
141
149
  * 1534ms and `COMPLETED` at 1515ms. `execution.state` is what `observe_runtime`
142
150
  * reads to choose `ok` vs `timed_out`, so losing that race silently hides a real
@@ -1 +1 @@
1
- {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"controller.d.ts","sourceRoot":"","sources":["../src/controller.ts"],"names":[],"mappings":"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"}