@descryy/runtime-controller 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +6 -0
- package/dist/attach-fencing.d.ts +109 -0
- package/dist/attach-fencing.d.ts.map +1 -0
- package/dist/attach-fencing.js +215 -0
- package/dist/attach-fencing.js.map +1 -0
- package/dist/capability-registry.d.ts +0 -15
- package/dist/capability-registry.d.ts.map +1 -1
- package/dist/capability-registry.js +9 -19
- package/dist/capability-registry.js.map +1 -1
- package/dist/collector-version.d.ts +1 -8
- package/dist/collector-version.d.ts.map +1 -1
- package/dist/collector-version.js +1 -8
- package/dist/collector-version.js.map +1 -1
- package/dist/container-sandbox.d.ts +66 -150
- package/dist/container-sandbox.d.ts.map +1 -1
- package/dist/container-sandbox.js +62 -143
- package/dist/container-sandbox.js.map +1 -1
- package/dist/controller.d.ts +49 -106
- package/dist/controller.d.ts.map +1 -1
- package/dist/controller.js +65 -123
- package/dist/controller.js.map +1 -1
- package/dist/dependency-version-check.d.ts +19 -73
- package/dist/dependency-version-check.d.ts.map +1 -1
- package/dist/dependency-version-check.js +18 -67
- package/dist/dependency-version-check.js.map +1 -1
- package/dist/env.d.ts +4 -10
- package/dist/env.d.ts.map +1 -1
- package/dist/env.js +4 -10
- package/dist/env.js.map +1 -1
- package/dist/environment-metadata.d.ts +9 -17
- package/dist/environment-metadata.d.ts.map +1 -1
- package/dist/environment-metadata.js +12 -29
- package/dist/environment-metadata.js.map +1 -1
- package/dist/environment-version-check.d.ts +22 -65
- package/dist/environment-version-check.d.ts.map +1 -1
- package/dist/environment-version-check.js +24 -66
- package/dist/environment-version-check.js.map +1 -1
- package/dist/execution-safety.d.ts +54 -112
- package/dist/execution-safety.d.ts.map +1 -1
- package/dist/execution-safety.js +48 -102
- package/dist/execution-safety.js.map +1 -1
- package/dist/index.d.ts +2 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/orchestration.d.ts +24 -39
- package/dist/orchestration.d.ts.map +1 -1
- package/dist/orchestration.js +39 -75
- package/dist/orchestration.js.map +1 -1
- package/dist/process-collector.d.ts +8 -22
- package/dist/process-collector.d.ts.map +1 -1
- package/dist/process-collector.js +23 -55
- package/dist/process-collector.js.map +1 -1
- package/dist/process-manager.d.ts +65 -80
- package/dist/process-manager.d.ts.map +1 -1
- package/dist/process-manager.js +80 -103
- package/dist/process-manager.js.map +1 -1
- package/dist/readiness.d.ts +28 -70
- package/dist/readiness.d.ts.map +1 -1
- package/dist/readiness.js +73 -95
- package/dist/readiness.js.map +1 -1
- package/dist/sandbox.d.ts +60 -105
- package/dist/sandbox.d.ts.map +1 -1
- package/dist/sandbox.js +78 -121
- package/dist/sandbox.js.map +1 -1
- package/package.json +8 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { withDefaultProcessEnv } from "./env.ts";
|
|
2
2
|
export type { SpawnProcessOptions, ProcessExitInfo, ManagedProcess, AttachProcessOptions } from "./process-manager.ts";
|
|
3
3
|
export { spawnProcess, attachManagedProcess, isProcessAlive } from "./process-manager.ts";
|
|
4
|
+
export type { AttachFence, ProcessStartTimeResult, OtherLogWriterCheck } from "./attach-fencing.ts";
|
|
5
|
+
export { computeAttachFence, getProcessStartTimeMs, detectOtherLogWriters } from "./attach-fencing.ts";
|
|
4
6
|
export type { ReadinessMechanism, HttpReadinessCheck, TcpPortReadinessCheck, LogPatternReadinessCheck, CommandReadinessCheck, CustomHookReadinessCheck, ReadinessCheck, ReadinessResult, AwaitReadinessOptions, } from "./readiness.ts";
|
|
5
7
|
export { READINESS_MECHANISMS, awaitReadiness } from "./readiness.ts";
|
|
6
8
|
export type { CreateExecutionInput, RunOptions, ProcessLifecycleEvent } from "./controller.ts";
|
|
@@ -20,16 +22,6 @@ export type { DependencyVersionMismatch, DependencyVersionCheckResult } from "./
|
|
|
20
22
|
export { checkDependencyVersions } from "./dependency-version-check.ts";
|
|
21
23
|
export type { DeclaredVersionSource, EnvironmentVersionCheckResult } from "./environment-version-check.ts";
|
|
22
24
|
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
25
|
export type { CommandTokenization, ServicesValidation } from "./orchestration.ts";
|
|
34
26
|
export { tokenizeCommand, validateServicesConfiguration, substitutePortPlaceholders } from "./orchestration.ts";
|
|
35
27
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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;
|
|
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,EAAE,WAAW,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AACpG,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAEvG,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
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { withDefaultProcessEnv } from "./env.js";
|
|
2
2
|
export { spawnProcess, attachManagedProcess, isProcessAlive } from "./process-manager.js";
|
|
3
|
+
export { computeAttachFence, getProcessStartTimeMs, detectOtherLogWriters } from "./attach-fencing.js";
|
|
3
4
|
export { READINESS_MECHANISMS, awaitReadiness } from "./readiness.js";
|
|
4
5
|
export { ExecutionController } from "./controller.js";
|
|
5
6
|
export { createProcessCollector } from "./process-collector.js";
|
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;
|
|
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;AAG1F,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAavG,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"}
|
package/dist/orchestration.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Turns a declarative `services` map (
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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
|
|
9
|
-
*
|
|
10
|
-
*
|
|
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
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
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
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
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
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* separately
|
|
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
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
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 `~`
|
|
66
|
-
*
|
|
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
|
|
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"}
|
package/dist/orchestration.js
CHANGED
|
@@ -1,38 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Turns a declarative `services` map (
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* does not create an ordering guarantee; `name` must also appear in the
|
|
12
|
-
* referencing service's own `dependsOn`, or validation refuses.
|
|
13
|
-
*/
|
|
14
|
-
/**
|
|
15
|
-
* Bounded at `{1,256}`, not `+`, since RT-070's own regex audit (prompted by
|
|
16
|
-
* RT-069's ReDoS finding in `evidence-store/redaction.ts`) named this exact
|
|
17
|
-
* shape: an unbounded character class immediately followed by a required
|
|
18
|
-
* literal (`.port}`) that can be absent from the input. On a long string
|
|
19
|
-
* with `${` but no closing `.port}`, an unbounded class here would
|
|
20
|
-
* backtrack once per starting position -- O(n^2). `service.env` values are
|
|
21
|
-
* developer-authored configuration, not runtime/adversarial data, which is
|
|
22
|
-
* why this was flagged low-risk rather than urgent -- but the shape is
|
|
23
|
-
* identical to the one that DID become a real denial-of-service on a
|
|
24
|
-
* different input source the same day, and 256 characters is far more than
|
|
25
|
-
* any real service or dependency name needs.
|
|
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.
|
|
26
10
|
*/
|
|
11
|
+
// Bounded at {1,256}, not `+`: RT-070's regex audit (after RT-069's ReDoS finding in
|
|
12
|
+
// evidence-store/redaction.ts) flagged this exact shape -- unbounded class followed by
|
|
13
|
+
// a literal (`.port}`) that can be absent -- as O(n^2) backtracking on a long
|
|
14
|
+
// unterminated string. Low-risk since `service.env` is developer-authored, not
|
|
15
|
+
// adversarial, but the shape matches a real same-day DoS elsewhere. 256 is far more
|
|
16
|
+
// than any real name needs.
|
|
27
17
|
const PORT_PLACEHOLDER = /\$\{([^}]{1,256})\.port\}/g;
|
|
28
18
|
/**
|
|
29
|
-
* Validates a `services` map and returns a
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* 3. every `${name}.port` placeholder referenced in a service's own `env`
|
|
34
|
-
* has `name` in that same service's `dependsOn` — the placeholder does
|
|
35
|
-
* not itself create the ordering guarantee it depends on.
|
|
19
|
+
* Validates a `services` map and returns a topological spawn order. Checks, all
|
|
20
|
+
* before anything is spawned: every `dependsOn` names a real key; the `dependsOn`
|
|
21
|
+
* graph has no cycle; every `${name}.port` placeholder in a service's `env` has
|
|
22
|
+
* `name` in that service's own `dependsOn`.
|
|
36
23
|
*/
|
|
37
24
|
export function validateServicesConfiguration(services) {
|
|
38
25
|
const names = Object.keys(services);
|
|
@@ -61,11 +48,8 @@ export function validateServicesConfiguration(services) {
|
|
|
61
48
|
}
|
|
62
49
|
}
|
|
63
50
|
}
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
// service-configuration). Neither means nothing tells `run()` how to
|
|
67
|
-
// start this service; both means an ambiguous configuration nothing here
|
|
68
|
-
// should silently pick a side on.
|
|
51
|
+
// Exactly one of `command`/`attach` per service, checked before spawning.
|
|
52
|
+
// Neither: nothing tells run() how to start it. Both: ambiguous, don't guess.
|
|
69
53
|
for (const name of names) {
|
|
70
54
|
const service = services[name];
|
|
71
55
|
const hasCommand = service?.command !== undefined;
|
|
@@ -77,11 +61,8 @@ export function validateServicesConfiguration(services) {
|
|
|
77
61
|
};
|
|
78
62
|
}
|
|
79
63
|
}
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
// would mean refusing service 3 after services 1 and 2 are already
|
|
83
|
-
// running — recoverable via rollback, but needlessly: nothing about this
|
|
84
|
-
// check needs a process to exist.
|
|
64
|
+
// A command that can't be tokenized is a config error -- check before spawning
|
|
65
|
+
// rather than discovering it mid-sequence with earlier services already running.
|
|
85
66
|
for (const name of names) {
|
|
86
67
|
const command = services[name]?.command;
|
|
87
68
|
if (command === undefined)
|
|
@@ -122,13 +103,10 @@ function topologicalOrder(services, names) {
|
|
|
122
103
|
return { valid: true, order };
|
|
123
104
|
}
|
|
124
105
|
/**
|
|
125
|
-
* Replaces every `${name}.port` in `env`'s values with the resolved port
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
* resolve is left untouched rather than silently dropped, so a caller that
|
|
130
|
-
* skipped validation sees an obviously-wrong literal `${...}` instead of a
|
|
131
|
-
* silently empty substitution.
|
|
106
|
+
* Replaces every `${name}.port` in `env`'s values with the resolved port for `name`.
|
|
107
|
+
* Assumes `validateServicesConfiguration` already confirmed the reference. An
|
|
108
|
+
* unresolvable reference is left untouched, not dropped -- a caller that skipped
|
|
109
|
+
* validation sees an obviously-wrong literal instead of a silent empty substitution.
|
|
132
110
|
*/
|
|
133
111
|
export function substitutePortPlaceholders(env, resolvedPorts) {
|
|
134
112
|
const result = {};
|
|
@@ -142,37 +120,24 @@ export function substitutePortPlaceholders(env, resolvedPorts) {
|
|
|
142
120
|
}
|
|
143
121
|
/**
|
|
144
122
|
* Shell operators that only mean anything to a shell. `spawnProcess` uses
|
|
145
|
-
* `child_process.spawn`
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* Refusing is the honest answer. The previous whitespace split passed
|
|
151
|
-
* `node server.mjs > out.log` through as three arguments to `node`, which
|
|
152
|
-
* starts a process that fails in a way pointing at the application rather
|
|
153
|
-
* than at its own configuration. Someone who genuinely wants a shell can
|
|
154
|
-
* say so — `sh -c "..."` tokenizes fine, since the operators are then
|
|
155
|
-
* inside quotes where they belong.
|
|
123
|
+
* `child_process.spawn` without one -- no implicit shell, no injection surface. A
|
|
124
|
+
* command containing these was never going to behave as written; refusing beats the
|
|
125
|
+
* old whitespace-split behavior of silently passing `> out.log` as literal args to
|
|
126
|
+
* `node`. `sh -c "..."` still works for anyone who wants a real shell.
|
|
156
127
|
*/
|
|
157
128
|
const SHELL_OPERATORS = new Set(["|", "&", ";", "<", ">", "`", "$"]);
|
|
158
129
|
/**
|
|
159
|
-
* POSIX-style tokenizer for `ServiceConfiguration.command`: single quotes
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* separately
|
|
163
|
-
* so something has to split it, and doing that by whitespace alone breaks
|
|
164
|
-
* every path with a space in it — `"C:\Program Files\node.exe"` and
|
|
165
|
-
* `python3 -c "import app; app.main()"` both tokenized wrong before.
|
|
130
|
+
* POSIX-style tokenizer for `ServiceConfiguration.command`: single quotes (literal),
|
|
131
|
+
* double quotes (`\` escapes `"` and `\`), backslash escapes outside quotes. Needed
|
|
132
|
+
* because config carries one string (§6) but `spawnProcess` wants `command`/`args`
|
|
133
|
+
* separately, and plain whitespace-split breaks paths with spaces.
|
|
166
134
|
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* for input that cannot mean what it says is how a configuration error
|
|
171
|
-
* arrives disguised as an application failure.
|
|
135
|
+
* Refuses rather than guesses on an unterminated quote, trailing backslash, or
|
|
136
|
+
* unquoted shell operator -- a plausible-but-wrong tokenization would disguise a
|
|
137
|
+
* config error as an application failure.
|
|
172
138
|
*
|
|
173
|
-
* Globs and `~`
|
|
174
|
-
*
|
|
175
|
-
* are frequently intended literally.
|
|
139
|
+
* Globs and `~` pass through literally, unrefused -- exactly what happens with no
|
|
140
|
+
* shell, and frequently intended literally.
|
|
176
141
|
*/
|
|
177
142
|
export function tokenizeCommand(raw) {
|
|
178
143
|
const tokens = [];
|
|
@@ -193,8 +158,7 @@ export function tokenizeCommand(raw) {
|
|
|
193
158
|
const next = raw[i + 1];
|
|
194
159
|
if (next === undefined)
|
|
195
160
|
return { ok: false, reason: 'command ends with a trailing backslash inside a double-quoted string, which escapes nothing' };
|
|
196
|
-
// Only `"` and `\` are escapable
|
|
197
|
-
// else keeps the backslash, as a shell would.
|
|
161
|
+
// Only `"` and `\` are escapable in double quotes; else keep the backslash.
|
|
198
162
|
if (next === '"' || next === "\\") {
|
|
199
163
|
current += next;
|
|
200
164
|
i++;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"orchestration.js","sourceRoot":"","sources":["../src/orchestration.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"orchestration.js","sourceRoot":"","sources":["../src/orchestration.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,28 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `ProcessCollector`: turns `ProcessLifecycleEvent` (`controller.ts`) into
|
|
3
|
-
* `PROCESS_STARTED` / `PROCESS_READY` / `PROCESS_EXITED` Evidence.
|
|
3
|
+
* `PROCESS_STARTED` / `PROCESS_READY` / `PROCESS_EXITED` Evidence. A plain translator
|
|
4
|
+
* with no lifecycle logic of its own — `ExecutionController` decides when each
|
|
5
|
+
* transition happens and calls `RunOptions.onProcessLifecycleEvent`; this collector
|
|
6
|
+
* just turns that call into one `context.emit()`.
|
|
4
7
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* (RUNTIME-CHECKLIST.md §3). This is that orchestration-layer answer: a
|
|
10
|
-
* plain translator with no lifecycle logic of its own. `ExecutionController`
|
|
11
|
-
* decides *when* each transition happens (spawn, readiness settling either
|
|
12
|
-
* way, reap) and calls `RunOptions.onProcessLifecycleEvent` at exactly
|
|
13
|
-
* those moments; this collector's only job is turning one of those calls
|
|
14
|
-
* into one `context.emit()` call. It does not spawn anything, does not
|
|
15
|
-
* decide readiness, and does not know why a process exited — only that it
|
|
16
|
-
* did, and what `ProcessHandle` says about it.
|
|
17
|
-
*
|
|
18
|
-
* **Wiring order is load-bearing.** `start(context)` must be called before
|
|
19
|
-
* `RunOptions.onProcessLifecycleEvent` can fire — i.e. before
|
|
20
|
-
* `ExecutionController.run()` is called with this collector's
|
|
21
|
-
* `handleLifecycleEvent` wired in. `handleLifecycleEvent` throws rather
|
|
22
|
-
* than silently dropping an event if that order is violated: a lost
|
|
23
|
-
* PROCESS_STARTED reads to everything downstream as "this process was
|
|
24
|
-
* never observed," which is a worse and quieter failure than a thrown
|
|
25
|
-
* error at the exact call site that got the order wrong.
|
|
8
|
+
* **Wiring order is load-bearing.** `start(context)` must run before
|
|
9
|
+
* `onProcessLifecycleEvent` can fire. `handleLifecycleEvent` throws rather than
|
|
10
|
+
* silently dropping an event on violation — a lost PROCESS_STARTED would otherwise
|
|
11
|
+
* read downstream as "never observed," a worse, quieter failure than a thrown error.
|
|
26
12
|
*/
|
|
27
13
|
import type { Collector } from "@descryy/runtime-contracts";
|
|
28
14
|
import type { ProcessLifecycleEvent } from "./controller.ts";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-collector.d.ts","sourceRoot":"","sources":["../src/process-collector.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"process-collector.d.ts","sourceRoot":"","sources":["../src/process-collector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAmF,MAAM,4BAA4B,CAAC;AAC7I,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAG7D,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,0GAA0G;IAC1G,oBAAoB,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI,CAAC;CAC1D;AA6DD,wBAAgB,sBAAsB,IAAI,gBAAgB,CAoDzD"}
|
|
@@ -1,42 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `ProcessCollector`: turns `ProcessLifecycleEvent` (`controller.ts`) into
|
|
3
|
-
* `PROCESS_STARTED` / `PROCESS_READY` / `PROCESS_EXITED` Evidence.
|
|
3
|
+
* `PROCESS_STARTED` / `PROCESS_READY` / `PROCESS_EXITED` Evidence. A plain translator
|
|
4
|
+
* with no lifecycle logic of its own — `ExecutionController` decides when each
|
|
5
|
+
* transition happens and calls `RunOptions.onProcessLifecycleEvent`; this collector
|
|
6
|
+
* just turns that call into one `context.emit()`.
|
|
4
7
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* (RUNTIME-CHECKLIST.md §3). This is that orchestration-layer answer: a
|
|
10
|
-
* plain translator with no lifecycle logic of its own. `ExecutionController`
|
|
11
|
-
* decides *when* each transition happens (spawn, readiness settling either
|
|
12
|
-
* way, reap) and calls `RunOptions.onProcessLifecycleEvent` at exactly
|
|
13
|
-
* those moments; this collector's only job is turning one of those calls
|
|
14
|
-
* into one `context.emit()` call. It does not spawn anything, does not
|
|
15
|
-
* decide readiness, and does not know why a process exited — only that it
|
|
16
|
-
* did, and what `ProcessHandle` says about it.
|
|
17
|
-
*
|
|
18
|
-
* **Wiring order is load-bearing.** `start(context)` must be called before
|
|
19
|
-
* `RunOptions.onProcessLifecycleEvent` can fire — i.e. before
|
|
20
|
-
* `ExecutionController.run()` is called with this collector's
|
|
21
|
-
* `handleLifecycleEvent` wired in. `handleLifecycleEvent` throws rather
|
|
22
|
-
* than silently dropping an event if that order is violated: a lost
|
|
23
|
-
* PROCESS_STARTED reads to everything downstream as "this process was
|
|
24
|
-
* never observed," which is a worse and quieter failure than a thrown
|
|
25
|
-
* error at the exact call site that got the order wrong.
|
|
8
|
+
* **Wiring order is load-bearing.** `start(context)` must run before
|
|
9
|
+
* `onProcessLifecycleEvent` can fire. `handleLifecycleEvent` throws rather than
|
|
10
|
+
* silently dropping an event on violation — a lost PROCESS_STARTED would otherwise
|
|
11
|
+
* read downstream as "never observed," a worse, quieter failure than a thrown error.
|
|
26
12
|
*/
|
|
27
13
|
import { COLLECTOR_VERSION } from "./collector-version.js";
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
* Reported `unavailable` on all seven, each with its own honest reason,
|
|
34
|
-
* rather than inventing a field this package doesn't own (`contracts` is
|
|
35
|
-
* outside this lane's boundary this round — flagged to the peer rather than
|
|
36
|
-
* changed unilaterally). A collector that is doing its one real job while
|
|
37
|
-
* `capabilities()` shows nothing but `unavailable` is itself a disclosed
|
|
38
|
-
* gap in the capability model, not a bug in this file.
|
|
39
|
-
*/
|
|
14
|
+
// None of `CollectorCapabilities`' fields is "process lifecycle observation" — the
|
|
15
|
+
// one thing this collector does. Reported `unavailable` on the others with an honest
|
|
16
|
+
// reason rather than inventing a field outside this lane's boundary (`contracts`).
|
|
17
|
+
// This collector doing its job while capabilities() shows all-unavailable is a
|
|
18
|
+
// disclosed gap in the capability model, not a bug here.
|
|
40
19
|
function computeCapabilities() {
|
|
41
20
|
const reason = "ProcessCollector observes process lifecycle (started/ready/exited) only — the capability model has no field for that yet.";
|
|
42
21
|
const status = { availability: "unavailable", reason };
|
|
@@ -64,17 +43,10 @@ function eventTypeOf(kind) {
|
|
|
64
43
|
return "PROCESS_EXITED";
|
|
65
44
|
}
|
|
66
45
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
* unilaterally in a collector, the wrong layer for it. The failure is not
|
|
72
|
-
* lost: `payload.ready` is `false` and `payload.readiness` carries the full
|
|
73
|
-
* `ReadinessResult` (mechanism attempted, elapsed time, reason), so a
|
|
74
|
-
* reader distinguishes "became ready" from "readiness failed" from the
|
|
75
|
-
* payload, not the event type — the same shape `ServiceStartResult`
|
|
76
|
-
* already uses (`succeeded: boolean` alongside a `stage`), not a new one.
|
|
77
|
-
*/
|
|
46
|
+
// `process-ready-failed` still emits `PROCESS_READY` — no separate vocabulary type,
|
|
47
|
+
// and adding one here is the wrong layer. `payload.ready: false` plus the full
|
|
48
|
+
// `ReadinessResult` lets a reader distinguish success from failure via payload, not
|
|
49
|
+
// event type (same shape as `ServiceStartResult`'s `succeeded` + `stage`).
|
|
78
50
|
function payloadOf(event) {
|
|
79
51
|
switch (event.kind) {
|
|
80
52
|
case "process-started":
|
|
@@ -83,9 +55,8 @@ function payloadOf(event) {
|
|
|
83
55
|
case "process-ready-failed":
|
|
84
56
|
return { processId: event.handle.processId, serviceName: event.serviceName, ready: event.readiness.ready, readiness: event.readiness };
|
|
85
57
|
case "process-exited":
|
|
86
|
-
// `phase`
|
|
87
|
-
// "
|
|
88
|
-
// `ProcessLifecycleEvent`'s own doc comment in controller.ts.
|
|
58
|
+
// `phase` distinguishes "crashed on boot" from "finished/stopped after
|
|
59
|
+
// running" — see `ProcessLifecycleEvent` in controller.ts.
|
|
89
60
|
return {
|
|
90
61
|
processId: event.handle.processId,
|
|
91
62
|
serviceName: event.serviceName,
|
|
@@ -106,9 +77,8 @@ export function createProcessCollector() {
|
|
|
106
77
|
return Promise.resolve({ available: true });
|
|
107
78
|
},
|
|
108
79
|
stop() {
|
|
109
|
-
// Idempotent per the Collector contract; nothing
|
|
110
|
-
//
|
|
111
|
-
// only a reference to the context it emits through.
|
|
80
|
+
// Idempotent per the Collector contract; nothing to release -- owns
|
|
81
|
+
// only a reference to the emit context, no process/socket/file handle.
|
|
112
82
|
context = null;
|
|
113
83
|
return Promise.resolve();
|
|
114
84
|
},
|
|
@@ -134,10 +104,8 @@ export function createProcessCollector() {
|
|
|
134
104
|
graphNodeId: null,
|
|
135
105
|
sourceLocation: null,
|
|
136
106
|
stackTrace: null,
|
|
137
|
-
//
|
|
138
|
-
//
|
|
139
|
-
// guessed, same basis LogCollector already uses for its own
|
|
140
|
-
// verbatim-capture confidence of 1.
|
|
107
|
+
// Direct observation of our own orchestration state, never inferred --
|
|
108
|
+
// same basis as LogCollector's verbatim-capture confidence of 1.
|
|
141
109
|
confidence: 1,
|
|
142
110
|
redactionStatus: "pending-redaction",
|
|
143
111
|
collectorVersion: COLLECTOR_VERSION,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-collector.js","sourceRoot":"","sources":["../src/process-collector.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"process-collector.js","sourceRoot":"","sources":["../src/process-collector.ts"],"names":[],"mappings":"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"}
|