@descryy/runtime-controller 0.3.6 → 0.3.8
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/package.json +5 -5
- package/dist/attach-fencing.d.ts +0 -109
- package/dist/attach-fencing.d.ts.map +0 -1
- package/dist/attach-fencing.js +0 -215
- package/dist/attach-fencing.js.map +0 -1
- package/dist/capability-registry.d.ts +0 -9
- package/dist/capability-registry.d.ts.map +0 -1
- package/dist/capability-registry.js +0 -32
- package/dist/capability-registry.js.map +0 -1
- package/dist/collector-version.d.ts +0 -3
- package/dist/collector-version.d.ts.map +0 -1
- package/dist/collector-version.js +0 -5
- package/dist/collector-version.js.map +0 -1
- package/dist/container-sandbox.d.ts +0 -104
- package/dist/container-sandbox.d.ts.map +0 -1
- package/dist/container-sandbox.js +0 -152
- package/dist/container-sandbox.js.map +0 -1
- package/dist/controller.d.ts +0 -138
- package/dist/controller.d.ts.map +0 -1
- package/dist/controller.js +0 -449
- package/dist/controller.js.map +0 -1
- package/dist/dependency-version-check.d.ts +0 -36
- package/dist/dependency-version-check.d.ts.map +0 -1
- package/dist/dependency-version-check.js +0 -72
- package/dist/dependency-version-check.js.map +0 -1
- package/dist/env.d.ts +0 -10
- package/dist/env.d.ts.map +0 -1
- package/dist/env.js +0 -12
- package/dist/env.js.map +0 -1
- package/dist/environment-metadata.d.ts +0 -15
- package/dist/environment-metadata.d.ts.map +0 -1
- package/dist/environment-metadata.js +0 -63
- package/dist/environment-metadata.js.map +0 -1
- package/dist/environment-version-check.d.ts +0 -40
- package/dist/environment-version-check.d.ts.map +0 -1
- package/dist/environment-version-check.js +0 -176
- package/dist/environment-version-check.js.map +0 -1
- package/dist/execution-safety.d.ts +0 -96
- package/dist/execution-safety.d.ts.map +0 -1
- package/dist/execution-safety.js +0 -140
- package/dist/execution-safety.js.map +0 -1
- package/dist/index.d.ts +0 -29
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -16
- package/dist/index.js.map +0 -1
- package/dist/orchestration.d.ts +0 -55
- package/dist/orchestration.d.ts.map +0 -1
- package/dist/orchestration.js +0 -219
- package/dist/orchestration.js.map +0 -1
- package/dist/process-collector.d.ts +0 -20
- package/dist/process-collector.d.ts.map +0 -1
- package/dist/process-collector.js +0 -116
- package/dist/process-collector.js.map +0 -1
- package/dist/process-identity.d.ts +0 -46
- package/dist/process-identity.d.ts.map +0 -1
- package/dist/process-identity.js +0 -186
- package/dist/process-identity.js.map +0 -1
- package/dist/process-manager.d.ts +0 -118
- package/dist/process-manager.d.ts.map +0 -1
- package/dist/process-manager.js +0 -310
- package/dist/process-manager.js.map +0 -1
- package/dist/readiness.d.ts +0 -122
- package/dist/readiness.d.ts.map +0 -1
- package/dist/readiness.js +0 -214
- package/dist/readiness.js.map +0 -1
- package/dist/sandbox.d.ts +0 -94
- package/dist/sandbox.d.ts.map +0 -1
- package/dist/sandbox.js +0 -228
- package/dist/sandbox.js.map +0 -1
package/dist/orchestration.d.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/**
|
|
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.
|
|
6
|
-
*
|
|
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.
|
|
10
|
-
*/
|
|
11
|
-
import type { ServiceConfiguration } from "@descryy/runtime-contracts";
|
|
12
|
-
export type ServicesValidation = {
|
|
13
|
-
readonly valid: true;
|
|
14
|
-
readonly order: readonly string[];
|
|
15
|
-
} | {
|
|
16
|
-
readonly valid: false;
|
|
17
|
-
readonly reason: string;
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
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`.
|
|
24
|
-
*/
|
|
25
|
-
export declare function validateServicesConfiguration(services: Readonly<Record<string, ServiceConfiguration>>): ServicesValidation;
|
|
26
|
-
/**
|
|
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.
|
|
31
|
-
*/
|
|
32
|
-
export declare function substitutePortPlaceholders(env: Readonly<Record<string, string>> | undefined, resolvedPorts: ReadonlyMap<string, number>): Record<string, string>;
|
|
33
|
-
export type CommandTokenization = {
|
|
34
|
-
readonly ok: true;
|
|
35
|
-
readonly command: string;
|
|
36
|
-
readonly args: readonly string[];
|
|
37
|
-
} | {
|
|
38
|
-
readonly ok: false;
|
|
39
|
-
readonly reason: string;
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
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.
|
|
46
|
-
*
|
|
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.
|
|
50
|
-
*
|
|
51
|
-
* Globs and `~` pass through literally, unrefused -- exactly what happens with no
|
|
52
|
-
* shell, and frequently intended literally.
|
|
53
|
-
*/
|
|
54
|
-
export declare function tokenizeCommand(raw: string): CommandTokenization;
|
|
55
|
-
//# sourceMappingURL=orchestration.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
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
DELETED
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
/**
|
|
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.
|
|
6
|
-
*
|
|
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.
|
|
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.
|
|
17
|
-
const PORT_PLACEHOLDER = /\$\{([^}]{1,256})\.port\}/g;
|
|
18
|
-
/**
|
|
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`.
|
|
23
|
-
*/
|
|
24
|
-
export function validateServicesConfiguration(services) {
|
|
25
|
-
const names = Object.keys(services);
|
|
26
|
-
for (const name of names) {
|
|
27
|
-
for (const dep of services[name]?.dependsOn ?? []) {
|
|
28
|
-
if (!(dep in services)) {
|
|
29
|
-
return { valid: false, reason: `service "${name}" depends on "${dep}", which is not in services` };
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
const orderResult = topologicalOrder(services, names);
|
|
34
|
-
if (!orderResult.valid) {
|
|
35
|
-
return orderResult;
|
|
36
|
-
}
|
|
37
|
-
for (const name of names) {
|
|
38
|
-
const declared = new Set(services[name]?.dependsOn ?? []);
|
|
39
|
-
for (const value of Object.values(services[name]?.env ?? {})) {
|
|
40
|
-
for (const match of value.matchAll(PORT_PLACEHOLDER)) {
|
|
41
|
-
const referenced = match[1];
|
|
42
|
-
if (referenced !== undefined && !declared.has(referenced)) {
|
|
43
|
-
return {
|
|
44
|
-
valid: false,
|
|
45
|
-
reason: `service "${name}" references "\${${referenced}.port}" in env but does not declare "${referenced}" in dependsOn`,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
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.
|
|
53
|
-
for (const name of names) {
|
|
54
|
-
const service = services[name];
|
|
55
|
-
const hasCommand = service?.command !== undefined;
|
|
56
|
-
const hasAttach = service?.attach !== undefined;
|
|
57
|
-
if (hasCommand === hasAttach) {
|
|
58
|
-
return {
|
|
59
|
-
valid: false,
|
|
60
|
-
reason: `service "${name}" must declare exactly one of "command" (spawn) or "attach" (attach to an already-running process), not ${hasCommand ? "both" : "neither"}`,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
}
|
|
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.
|
|
66
|
-
for (const name of names) {
|
|
67
|
-
const command = services[name]?.command;
|
|
68
|
-
if (command === undefined)
|
|
69
|
-
continue;
|
|
70
|
-
const tokenized = tokenizeCommand(command);
|
|
71
|
-
if (!tokenized.ok) {
|
|
72
|
-
return { valid: false, reason: `service "${name}": ${tokenized.reason}` };
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return orderResult;
|
|
76
|
-
}
|
|
77
|
-
function topologicalOrder(services, names) {
|
|
78
|
-
const order = [];
|
|
79
|
-
const visited = new Set();
|
|
80
|
-
const visiting = new Set();
|
|
81
|
-
function visit(name) {
|
|
82
|
-
if (visited.has(name))
|
|
83
|
-
return null;
|
|
84
|
-
if (visiting.has(name))
|
|
85
|
-
return `cycle detected in dependsOn involving "${name}"`;
|
|
86
|
-
visiting.add(name);
|
|
87
|
-
for (const dep of services[name]?.dependsOn ?? []) {
|
|
88
|
-
const err = visit(dep);
|
|
89
|
-
if (err !== null)
|
|
90
|
-
return err;
|
|
91
|
-
}
|
|
92
|
-
visiting.delete(name);
|
|
93
|
-
visited.add(name);
|
|
94
|
-
order.push(name);
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
for (const name of names) {
|
|
98
|
-
const err = visit(name);
|
|
99
|
-
if (err !== null) {
|
|
100
|
-
return { valid: false, reason: err };
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return { valid: true, order };
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
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.
|
|
110
|
-
*/
|
|
111
|
-
export function substitutePortPlaceholders(env, resolvedPorts) {
|
|
112
|
-
const result = {};
|
|
113
|
-
for (const [key, value] of Object.entries(env ?? {})) {
|
|
114
|
-
result[key] = value.replace(PORT_PLACEHOLDER, (literal, name) => {
|
|
115
|
-
const port = resolvedPorts.get(name);
|
|
116
|
-
return port === undefined ? literal : String(port);
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
return result;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Shell operators that only mean anything to a shell. `spawnProcess` uses
|
|
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.
|
|
127
|
-
*/
|
|
128
|
-
const SHELL_OPERATORS = new Set(["|", "&", ";", "<", ">", "`", "$"]);
|
|
129
|
-
/**
|
|
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.
|
|
134
|
-
*
|
|
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.
|
|
138
|
-
*
|
|
139
|
-
* Globs and `~` pass through literally, unrefused -- exactly what happens with no
|
|
140
|
-
* shell, and frequently intended literally.
|
|
141
|
-
*/
|
|
142
|
-
export function tokenizeCommand(raw) {
|
|
143
|
-
const tokens = [];
|
|
144
|
-
let current = "";
|
|
145
|
-
let started = false; // distinguishes an empty quoted token ('') from no token
|
|
146
|
-
let quote = null;
|
|
147
|
-
for (let i = 0; i < raw.length; i++) {
|
|
148
|
-
const char = raw[i];
|
|
149
|
-
if (quote === "'") {
|
|
150
|
-
if (char === "'")
|
|
151
|
-
quote = null;
|
|
152
|
-
else
|
|
153
|
-
current += char;
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
if (quote === '"') {
|
|
157
|
-
if (char === "\\") {
|
|
158
|
-
const next = raw[i + 1];
|
|
159
|
-
if (next === undefined)
|
|
160
|
-
return { ok: false, reason: 'command ends with a trailing backslash inside a double-quoted string, which escapes nothing' };
|
|
161
|
-
// Only `"` and `\` are escapable in double quotes; else keep the backslash.
|
|
162
|
-
if (next === '"' || next === "\\") {
|
|
163
|
-
current += next;
|
|
164
|
-
i++;
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
current += char;
|
|
168
|
-
}
|
|
169
|
-
continue;
|
|
170
|
-
}
|
|
171
|
-
if (char === '"')
|
|
172
|
-
quote = null;
|
|
173
|
-
else
|
|
174
|
-
current += char;
|
|
175
|
-
continue;
|
|
176
|
-
}
|
|
177
|
-
if (char === "'" || char === '"') {
|
|
178
|
-
quote = char;
|
|
179
|
-
started = true;
|
|
180
|
-
continue;
|
|
181
|
-
}
|
|
182
|
-
if (char === "\\") {
|
|
183
|
-
const next = raw[i + 1];
|
|
184
|
-
if (next === undefined)
|
|
185
|
-
return { ok: false, reason: "command ends with a trailing backslash, which escapes nothing" };
|
|
186
|
-
current += next;
|
|
187
|
-
started = true;
|
|
188
|
-
i++;
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
if (SHELL_OPERATORS.has(char)) {
|
|
192
|
-
return {
|
|
193
|
-
ok: false,
|
|
194
|
-
reason: `command contains the shell operator "${char}" outside quotes, but processes are spawned without a shell — ` +
|
|
195
|
-
`it would be passed to the program as a literal argument rather than interpreted. ` +
|
|
196
|
-
`Use an explicit shell (sh -c "...") if that is what you meant.`,
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
if (/\s/.test(char)) {
|
|
200
|
-
if (started) {
|
|
201
|
-
tokens.push(current);
|
|
202
|
-
current = "";
|
|
203
|
-
started = false;
|
|
204
|
-
}
|
|
205
|
-
continue;
|
|
206
|
-
}
|
|
207
|
-
current += char;
|
|
208
|
-
started = true;
|
|
209
|
-
}
|
|
210
|
-
if (quote !== null)
|
|
211
|
-
return { ok: false, reason: `command has an unterminated ${quote === '"' ? "double" : "single"} quote` };
|
|
212
|
-
if (started)
|
|
213
|
-
tokens.push(current);
|
|
214
|
-
const [head, ...rest] = tokens;
|
|
215
|
-
if (head === undefined || head === "")
|
|
216
|
-
return { ok: false, reason: "command is empty" };
|
|
217
|
-
return { ok: true, command: head, args: rest };
|
|
218
|
-
}
|
|
219
|
-
//# sourceMappingURL=orchestration.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"orchestration.js","sourceRoot":"","sources":["../src/orchestration.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `ProcessCollector`: turns `ProcessLifecycleEvent` (`controller.ts`) into
|
|
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()`.
|
|
7
|
-
*
|
|
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.
|
|
12
|
-
*/
|
|
13
|
-
import type { Collector } from "@descryy/runtime-contracts";
|
|
14
|
-
import type { ProcessLifecycleEvent } from "./controller.ts";
|
|
15
|
-
export interface ProcessCollector extends Collector {
|
|
16
|
-
/** Wire as `RunOptions.onProcessLifecycleEvent` — see the module doc for the ordering this depends on. */
|
|
17
|
-
handleLifecycleEvent(event: ProcessLifecycleEvent): void;
|
|
18
|
-
}
|
|
19
|
-
export declare function createProcessCollector(): ProcessCollector;
|
|
20
|
-
//# sourceMappingURL=process-collector.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
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,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `ProcessCollector`: turns `ProcessLifecycleEvent` (`controller.ts`) into
|
|
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()`.
|
|
7
|
-
*
|
|
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.
|
|
12
|
-
*/
|
|
13
|
-
import { COLLECTOR_VERSION } from "./collector-version.js";
|
|
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.
|
|
19
|
-
function computeCapabilities() {
|
|
20
|
-
const reason = "ProcessCollector observes process lifecycle (started/ready/exited) only — the capability model has no field for that yet.";
|
|
21
|
-
const status = { availability: "unavailable", reason };
|
|
22
|
-
return {
|
|
23
|
-
domObservation: status,
|
|
24
|
-
consoleObservation: status,
|
|
25
|
-
networkObservation: status,
|
|
26
|
-
backendLogAccess: status,
|
|
27
|
-
distributedTrace: status,
|
|
28
|
-
sourceMapping: status,
|
|
29
|
-
stackCapture: status,
|
|
30
|
-
processLifecycle: { availability: "available", reason: null },
|
|
31
|
-
databaseObservation: status,
|
|
32
|
-
externalServiceObservation: status,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
function eventTypeOf(kind) {
|
|
36
|
-
switch (kind) {
|
|
37
|
-
case "process-started":
|
|
38
|
-
return "PROCESS_STARTED";
|
|
39
|
-
case "process-ready":
|
|
40
|
-
case "process-ready-failed":
|
|
41
|
-
return "PROCESS_READY";
|
|
42
|
-
case "process-exited":
|
|
43
|
-
return "PROCESS_EXITED";
|
|
44
|
-
}
|
|
45
|
-
}
|
|
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`).
|
|
50
|
-
function payloadOf(event) {
|
|
51
|
-
switch (event.kind) {
|
|
52
|
-
case "process-started":
|
|
53
|
-
return { processId: event.handle.processId, serviceName: event.serviceName, pid: event.handle.pid, command: event.handle.command, startedAt: event.handle.startedAt };
|
|
54
|
-
case "process-ready":
|
|
55
|
-
case "process-ready-failed":
|
|
56
|
-
return { processId: event.handle.processId, serviceName: event.serviceName, ready: event.readiness.ready, readiness: event.readiness };
|
|
57
|
-
case "process-exited":
|
|
58
|
-
// `phase` distinguishes "crashed on boot" from "finished/stopped after
|
|
59
|
-
// running" — see `ProcessLifecycleEvent` in controller.ts.
|
|
60
|
-
return {
|
|
61
|
-
processId: event.handle.processId,
|
|
62
|
-
serviceName: event.serviceName,
|
|
63
|
-
exitCode: event.handle.exitCode,
|
|
64
|
-
signal: event.handle.signal,
|
|
65
|
-
exitedAt: event.handle.exitedAt,
|
|
66
|
-
phase: event.phase,
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
export function createProcessCollector() {
|
|
71
|
-
const capabilities = computeCapabilities();
|
|
72
|
-
let context = null;
|
|
73
|
-
return {
|
|
74
|
-
collectorId: "process-collector",
|
|
75
|
-
start(ctx) {
|
|
76
|
-
context = ctx;
|
|
77
|
-
return Promise.resolve({ available: true });
|
|
78
|
-
},
|
|
79
|
-
stop() {
|
|
80
|
-
// Idempotent per the Collector contract; nothing to release -- owns
|
|
81
|
-
// only a reference to the emit context, no process/socket/file handle.
|
|
82
|
-
context = null;
|
|
83
|
-
return Promise.resolve();
|
|
84
|
-
},
|
|
85
|
-
capabilities() {
|
|
86
|
-
return capabilities;
|
|
87
|
-
},
|
|
88
|
-
handleLifecycleEvent(event) {
|
|
89
|
-
if (context === null) {
|
|
90
|
-
throw new Error(`ProcessCollector.handleLifecycleEvent("${event.kind}") called before start() — ` +
|
|
91
|
-
`wire handleLifecycleEvent as RunOptions.onProcessLifecycleEvent only after start() has resolved, ` +
|
|
92
|
-
`or this event (and everything downstream of it) is silently unobserved rather than loudly wrong.`);
|
|
93
|
-
}
|
|
94
|
-
context.emit({
|
|
95
|
-
timestamp: new Date().toISOString(),
|
|
96
|
-
source: event.kind === "process-exited" ? "process-exit" : "backend-process",
|
|
97
|
-
service: event.serviceName,
|
|
98
|
-
process: event.handle.processId,
|
|
99
|
-
eventType: eventTypeOf(event.kind),
|
|
100
|
-
payload: payloadOf(event),
|
|
101
|
-
traceId: null,
|
|
102
|
-
requestId: null,
|
|
103
|
-
correlationId: null,
|
|
104
|
-
graphNodeId: null,
|
|
105
|
-
sourceLocation: null,
|
|
106
|
-
stackTrace: null,
|
|
107
|
-
// Direct observation of our own orchestration state, never inferred --
|
|
108
|
-
// same basis as LogCollector's verbatim-capture confidence of 1.
|
|
109
|
-
confidence: 1,
|
|
110
|
-
redactionStatus: "pending-redaction",
|
|
111
|
-
collectorVersion: COLLECTOR_VERSION,
|
|
112
|
-
});
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
//# sourceMappingURL=process-collector.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"process-collector.js","sourceRoot":"","sources":["../src/process-collector.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* RT-024's named hole, closed for the two mechanisms that can carry it:
|
|
3
|
-
* "none of readiness's five mechanisms confirm the listener is THIS run's
|
|
4
|
-
* process -- a stale listener from a dead run satisfies http/tcp-port
|
|
5
|
-
* identically." Ephemeral-by-default (`allocateEphemeralPort`) closes the
|
|
6
|
-
* common case by construction; this closes the fixed-port case by
|
|
7
|
-
* detection, for real, via `/proc` -- not a heuristic guess.
|
|
8
|
-
*
|
|
9
|
-
* **Mechanism.** A TCP listening socket on Linux is a row in `/proc/net/tcp`
|
|
10
|
-
* (or `/proc/net/tcp6`) carrying an inode; a process's open file descriptors
|
|
11
|
-
* are symlinks under `/proc/<pid>/fd/*` named `socket:[<inode>]` when that fd
|
|
12
|
-
* is a socket. If the expected pid's fd table holds a socket whose inode
|
|
13
|
-
* matches a LISTEN row for the target port, that pid really does own the
|
|
14
|
-
* listener -- not a name-based guess, a kernel-backed fact.
|
|
15
|
-
*
|
|
16
|
-
* **Scope, disclosed rather than silently narrowed.** Linux only (`/proc`
|
|
17
|
-
* doesn't exist elsewhere) and only for a process in the same pid namespace
|
|
18
|
-
* as this one -- true for every spawn this repo produces today: a direct
|
|
19
|
-
* spawn, and a bwrap-wrapped one (bwrap execs into the target without
|
|
20
|
-
* `--unshare-pid`, so `child.pid` names the real process, not a wrapper).
|
|
21
|
-
* **Not true for `sandboxBackend: "container"`** -- a published Docker port
|
|
22
|
-
* is commonly owned by a host-side `docker-proxy` process, not the pid this
|
|
23
|
-
* module would be asked to verify, so a mismatch there would be a false
|
|
24
|
-
* positive. Callers must not invoke this for the container backend; See
|
|
25
|
-
* `controller.ts`'s call site, which guards on exactly that condition.
|
|
26
|
-
* Anything this function cannot determine returns `"unsupported"`, never a
|
|
27
|
-
* fabricated "verified" or a false "mismatch".
|
|
28
|
-
*
|
|
29
|
-
* **The spawned pid, or any of its descendants.** A launcher that forks the
|
|
30
|
-
* real server is the ordinary case: `sh -c "..."`, `npm run dev`, `dotnet run`
|
|
31
|
-
* (which builds and then runs the app as its child). The pid this run holds is
|
|
32
|
-
* the launcher's, and the listener belongs to a process under it — still this
|
|
33
|
-
* run's own process tree, which is exactly the property RT-024 asked for. The
|
|
34
|
-
* tree is walked from `/proc/<pid>/stat`'s parent-pid field, a kernel fact like
|
|
35
|
-
* the fd table, and a decoy outside that tree is refused exactly as before.
|
|
36
|
-
* Checking the spawned pid alone made every forking launcher time out at
|
|
37
|
-
* readiness (every .NET managed-lifecycle test, found at release integration).
|
|
38
|
-
*/
|
|
39
|
-
export type IdentityVerification = "verified" | "mismatch" | "unsupported";
|
|
40
|
-
/**
|
|
41
|
-
* Does `expectedPid` -- or a process descended from it -- own the socket
|
|
42
|
-
* listening on `port`, on this host, right now? A real kernel-state check, not
|
|
43
|
-
* a guess -- see module header for the mechanism and its disclosed scope.
|
|
44
|
-
*/
|
|
45
|
-
export declare function verifyListeningSocketOwner(port: number, expectedPid: number): IdentityVerification;
|
|
46
|
-
//# sourceMappingURL=process-identity.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"process-identity.d.ts","sourceRoot":"","sources":["../src/process-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAIH,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,UAAU,GAAG,aAAa,CAAC;AAgH3E;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,oBAAoB,CAqBlG"}
|