@catalyst-cloud/cli 0.16.4 → 0.16.7

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.
@@ -0,0 +1,680 @@
1
+ import fs from "node:fs";
2
+ import { createHash, createPrivateKey, createPublicKey, generateKeyPairSync, randomBytes } from "node:crypto";
3
+ import { execFile } from "node:child_process";
4
+ import { userInfo } from "node:os";
5
+ import { dirname, isAbsolute, join, normalize, relative, resolve } from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ import { canonicalDarwinThoughtsJson, parseDarwinThoughtsAuthority, parseDarwinThoughtsRequest, verifyDarwinThoughtsCustodyResponse, } from "../vendor/self-host/darwin-thoughts-custody/verifier.mjs";
8
+ const LABEL = "dev.catalystcloud.runner.darwin-thoughts-custody";
9
+ const vendor = resolve(dirname(fileURLToPath(import.meta.url)), "../vendor/self-host/darwin-thoughts-custody");
10
+ function fail(reason) { throw Error("darwin_thoughts_custody_install:" + reason); }
11
+ function path(value) {
12
+ if (!isAbsolute(value) || normalize(value) !== value || value.includes("\0") ||
13
+ value.endsWith("/") || value === "/")
14
+ fail("principal_path_unsafe");
15
+ return value;
16
+ }
17
+ function below(value, root) {
18
+ const rel = relative(root, value);
19
+ return rel !== "" && rel !== ".." && !rel.startsWith("../") && !isAbsolute(rel);
20
+ }
21
+ function image(value) {
22
+ if (!/^[a-z0-9][a-z0-9./:_-]*@sha256:[a-f0-9]{64}$/.test(value))
23
+ fail("image_pin_invalid");
24
+ }
25
+ function same(a, b) {
26
+ return a.dev === b.dev && a.ino === b.ino && a.mode === b.mode && a.uid === b.uid &&
27
+ a.gid === b.gid && (a.isDirectory() || (a.nlink === b.nlink && a.size === b.size &&
28
+ a.mtimeNs === b.mtimeNs && a.ctimeNs === b.ctimeNs));
29
+ }
30
+ class Custody {
31
+ principal;
32
+ ports;
33
+ held = new Map();
34
+ constructor(principal, ports) {
35
+ this.principal = principal;
36
+ this.ports = ports;
37
+ }
38
+ hold(value, directory, privateDirectory = false, publicAncestor = false) {
39
+ let held = this.held.get(value);
40
+ if (!held) {
41
+ let fd;
42
+ try {
43
+ fd = fs.openSync(value, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW |
44
+ fs.constants.O_NONBLOCK | (directory ? fs.constants.O_DIRECTORY : 0));
45
+ }
46
+ catch {
47
+ return fail("state_custody_unsafe");
48
+ }
49
+ const stat = this.ports.stat(value, fs.fstatSync(fd, { bigint: true }));
50
+ held = { fd, stat };
51
+ this.held.set(value, held);
52
+ }
53
+ this.recheck();
54
+ const stat = held.stat;
55
+ const mode = Number(stat.mode & 4095n);
56
+ if (stat.uid !== BigInt(this.principal.uid) || stat.gid !== BigInt(this.principal.gid))
57
+ fail("native_owner_mismatch");
58
+ if (directory) {
59
+ if (!stat.isDirectory() || (mode & 0o7022) !== 0 || (mode & 0o700) !== 0o700 ||
60
+ (!publicAncestor && (mode & 0o007) !== 0) || (privateDirectory && mode !== 0o700))
61
+ fail("directory_custody_unsafe");
62
+ }
63
+ else if (!stat.isFile() || stat.nlink !== 1n || mode !== 0o600)
64
+ fail("file_custody_unsafe");
65
+ return held;
66
+ }
67
+ walk(value, create = false, mode = 0o700, privateLeaf = false, publicAncestors = false) {
68
+ path(value);
69
+ if (value !== this.principal.home && !below(value, this.principal.home))
70
+ fail("principal_home_authority_mismatch");
71
+ this.hold(this.principal.home, true, false, true);
72
+ let cursor = this.principal.home;
73
+ const levels = relative(cursor, value).split("/").filter(Boolean);
74
+ for (let index = 0; index < levels.length; index++) {
75
+ this.recheck();
76
+ cursor = join(cursor, levels[index]);
77
+ try {
78
+ fs.lstatSync(cursor);
79
+ }
80
+ catch (error) {
81
+ if (error.code !== "ENOENT" || !create)
82
+ fail("state_custody_unsafe");
83
+ try {
84
+ fs.mkdirSync(cursor, { mode });
85
+ }
86
+ catch (caught) {
87
+ if (caught.code !== "EEXIST")
88
+ fail("state_create_failed");
89
+ }
90
+ }
91
+ this.hold(cursor, true, privateLeaf && index === levels.length - 1, publicAncestors || index < levels.length - 1);
92
+ }
93
+ return this.hold(value, true, privateLeaf, publicAncestors || value === this.principal.home);
94
+ }
95
+ read(value, maximum = 65536) {
96
+ this.walk(dirname(value), false, 0o700, false, dirname(value) === join(this.principal.home, "Library", "LaunchAgents"));
97
+ const held = this.hold(value, false);
98
+ if (held.stat.size > BigInt(maximum))
99
+ fail("file_custody_unsafe");
100
+ const bytes = Buffer.alloc(Number(held.stat.size));
101
+ if (fs.readSync(held.fd, bytes, 0, bytes.length, 0) !== bytes.length)
102
+ fail("file_custody_unsafe");
103
+ this.recheck();
104
+ return bytes;
105
+ }
106
+ create(value, bytes) {
107
+ this.walk(dirname(value), false, 0o700, false, dirname(value) === join(this.principal.home, "Library", "LaunchAgents"));
108
+ this.recheck();
109
+ const fd = fs.openSync(value, fs.constants.O_WRONLY | fs.constants.O_CREAT |
110
+ fs.constants.O_EXCL | fs.constants.O_NOFOLLOW, 0o600);
111
+ try {
112
+ fs.writeFileSync(fd, bytes);
113
+ fs.fsyncSync(fd);
114
+ }
115
+ finally {
116
+ fs.closeSync(fd);
117
+ }
118
+ this.hold(value, false);
119
+ }
120
+ recheck() {
121
+ for (const [value, held] of this.held) {
122
+ const current = this.ports.stat(value, fs.fstatSync(held.fd, { bigint: true }));
123
+ const named = this.ports.stat(value, fs.lstatSync(value, { bigint: true }));
124
+ if (!same(held.stat, current) || !same(current, named))
125
+ fail("descriptor_custody_changed");
126
+ }
127
+ }
128
+ close() { for (const held of this.held.values())
129
+ fs.closeSync(held.fd); this.held.clear(); }
130
+ }
131
+ function parse(bytes) {
132
+ let value;
133
+ try {
134
+ value = JSON.parse(bytes.toString("utf8"));
135
+ }
136
+ catch {
137
+ return fail("state_config_invalid");
138
+ }
139
+ if (!Buffer.from(canonicalDarwinThoughtsJson(value)).equals(bytes))
140
+ fail("state_config_invalid");
141
+ return value;
142
+ }
143
+ function record(value, keys) {
144
+ if (!value || typeof value !== "object" || Array.isArray(value))
145
+ fail("state_config_invalid");
146
+ const row = value;
147
+ if (Object.keys(row).length !== keys.length || keys.some(key => !Object.hasOwn(row, key)))
148
+ fail("state_config_invalid");
149
+ return row;
150
+ }
151
+ function xml(value) { return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;"); }
152
+ function executable(value, principal, roots) {
153
+ path(value);
154
+ if (fs.realpathSync(value) !== value || roots.some(root => value === root || below(value, root)))
155
+ fail("executable_custody_unsafe");
156
+ const fd = fs.openSync(value, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);
157
+ try {
158
+ const stat = fs.fstatSync(fd, { bigint: true });
159
+ if (!stat.isFile() || (stat.mode & 3602n) !== 0n || (stat.mode & 73n) === 0n ||
160
+ (stat.uid !== 0n && stat.uid !== BigInt(principal.uid)) || stat.size > 256n * 1024n * 1024n)
161
+ fail("executable_custody_unsafe");
162
+ const digest = createHash("sha256").update(fs.readFileSync(fd)).digest("hex");
163
+ if (!same(stat, fs.lstatSync(value, { bigint: true })))
164
+ fail("executable_custody_changed");
165
+ return digest;
166
+ }
167
+ finally {
168
+ fs.closeSync(fd);
169
+ }
170
+ }
171
+ function factory(ports) {
172
+ async function install(input, signal) {
173
+ const alive = () => {
174
+ if (signal?.aborted)
175
+ fail("installation_cancelled");
176
+ if (ports.now() >= input.deadlineMs)
177
+ fail("installation_deadline_expired");
178
+ };
179
+ alive();
180
+ const principal = ports.principal();
181
+ path(principal.home);
182
+ path(input.dir);
183
+ if (principal.platform !== "darwin" || !Number.isSafeInteger(principal.uid) || principal.uid <= 0 ||
184
+ principal.euid !== principal.uid || !Number.isSafeInteger(principal.gid) ||
185
+ !below(input.dir, principal.home))
186
+ fail("native_principal_authority_mismatch");
187
+ if (!Number.isSafeInteger(input.deadlineMs) || input.deadlineMs <= ports.now() ||
188
+ input.deadlineMs - ports.now() > 30000)
189
+ fail("deadline_invalid");
190
+ image(input.supervisorImage);
191
+ image(input.runnerImage);
192
+ const state = join(dirname(input.dir), "darwin-thoughts-custody");
193
+ const requestsRoot = join(dirname(input.dir), "darwin-thoughts-requests");
194
+ const responsesRoot = join(dirname(input.dir), "darwin-thoughts-responses");
195
+ const thoughtsRoot = join(input.dir, "thoughts");
196
+ const locksRoot = join(input.dir, "locks");
197
+ const configPath = join(state, "producer.json");
198
+ const privateKeyFile = join(state, "private-key.der");
199
+ const custody = new Custody(principal, ports);
200
+ try {
201
+ custody.walk(input.dir);
202
+ for (const root of [thoughtsRoot, locksRoot])
203
+ custody.walk(root, true, 0o750);
204
+ for (const root of [requestsRoot, responsesRoot])
205
+ custody.walk(root, true, 0o700, true);
206
+ let existing = false;
207
+ try {
208
+ fs.lstatSync(state);
209
+ existing = true;
210
+ }
211
+ catch (error) {
212
+ if (error.code !== "ENOENT")
213
+ throw error;
214
+ }
215
+ const executables = ports.executables();
216
+ const roots = [thoughtsRoot, locksRoot, requestsRoot, responsesRoot];
217
+ const nodeHash = executable(executables.nodeExecutable, principal, roots);
218
+ const dockerHash = executable(executables.dockerExecutable, principal, roots);
219
+ let authority;
220
+ if (existing) {
221
+ custody.walk(state, false, 0o700, true);
222
+ const runtime = record(parse(custody.read(join(state, "runtime.json"), 4096)), ["version", "nodeExecutable", "nodeExecutableSha256"]);
223
+ if (runtime.version !== 1 || runtime.nodeExecutable !== executables.nodeExecutable ||
224
+ runtime.nodeExecutableSha256 !== nodeHash)
225
+ fail("runtime_custody_mismatch");
226
+ const row = record(parse(custody.read(configPath, 16384)), ["version", "authority", "privateKeyFile", "supervisorImage", "dockerExecutable", "dockerExecutableSha256"]);
227
+ authority = parseDarwinThoughtsAuthority(row.authority);
228
+ if (row.version !== 1 || authority.nativeUid !== principal.uid || authority.nativeGid !== principal.gid ||
229
+ authority.nativeHome !== principal.home || authority.thoughtsRoot !== thoughtsRoot ||
230
+ authority.locksRoot !== locksRoot || authority.requestsRoot !== requestsRoot ||
231
+ authority.responsesRoot !== responsesRoot || row.privateKeyFile !== privateKeyFile ||
232
+ row.supervisorImage !== input.supervisorImage || row.dockerExecutable !== executables.dockerExecutable ||
233
+ row.dockerExecutableSha256 !== dockerHash)
234
+ fail("existing_authority_mismatch");
235
+ let key;
236
+ try {
237
+ key = createPrivateKey({ key: custody.read(privateKeyFile, 4096), type: "pkcs8", format: "der" });
238
+ }
239
+ catch {
240
+ return fail("private_key_custody_invalid");
241
+ }
242
+ if (key.asymmetricKeyType !== "ed25519" || createPublicKey(key).export({ type: "spki", format: "der" }).toString("base64") !== authority.publicKey)
243
+ fail("private_key_authority_mismatch");
244
+ }
245
+ custody.recheck();
246
+ alive();
247
+ const engine = await ports.engineIdentity({ ...executables, principal,
248
+ supervisorImage: input.supervisorImage, runnerImage: input.runnerImage, deadlineMs: input.deadlineMs, signal });
249
+ alive();
250
+ if (!/^unix:\/\/\/[^,\0]+$/.test(engine.endpoint) || normalize(engine.endpoint.slice(7)) !== engine.endpoint.slice(7) ||
251
+ !engine.cachedSupervisor || !engine.cachedRunner || !/^[A-Za-z0-9][A-Za-z0-9_.:-]{0,255}$/.test(engine.daemonId))
252
+ fail("engine_endpoint_or_cache_invalid");
253
+ if (engine.runnerCustodyVersion !== "v1")
254
+ fail("runner_custody_label_unqualified");
255
+ if (authority && (authority.endpoint !== engine.endpoint || authority.daemonId !== engine.daemonId))
256
+ fail("engine_authority_mismatch");
257
+ custody.recheck();
258
+ if (!authority) {
259
+ custody.walk(state, true, 0o700, true);
260
+ custody.create(join(state, "runtime.json"), Buffer.from(canonicalDarwinThoughtsJson({
261
+ version: 1, nodeExecutable: executables.nodeExecutable, nodeExecutableSha256: nodeHash,
262
+ })));
263
+ const key = generateKeyPairSync("ed25519");
264
+ authority = parseDarwinThoughtsAuthority({
265
+ version: 1, installationId: randomBytes(32).toString("hex"),
266
+ publicKey: key.publicKey.export({ type: "spki", format: "der" }).toString("base64"),
267
+ nativeUid: principal.uid, nativeGid: principal.gid, nativeHome: principal.home,
268
+ endpoint: engine.endpoint, daemonId: engine.daemonId, thoughtsRoot, locksRoot, requestsRoot, responsesRoot,
269
+ });
270
+ custody.create(privateKeyFile, key.privateKey.export({ type: "pkcs8", format: "der" }));
271
+ custody.create(configPath, Buffer.from(canonicalDarwinThoughtsJson({
272
+ version: 1, authority, privateKeyFile, supervisorImage: input.supervisorImage,
273
+ dockerExecutable: executables.dockerExecutable, dockerExecutableSha256: dockerHash,
274
+ })));
275
+ }
276
+ const artifacts = ports.artifacts();
277
+ for (const [name, bytes] of [["producer.mjs", artifacts.producer], ["watchdog.mjs", artifacts.watchdog],
278
+ ["watchdog-deadline.mjs", artifacts.deadline]]) {
279
+ const file = join(state, name);
280
+ if (existing) {
281
+ if (!custody.read(file, 1048576).equals(bytes))
282
+ fail("artifact_custody_mismatch");
283
+ }
284
+ else
285
+ custody.create(file, bytes);
286
+ }
287
+ const agentDirectory = join(principal.home, "Library", "LaunchAgents");
288
+ custody.walk(agentDirectory, true, 0o700, false, true);
289
+ const plistPath = join(agentDirectory, LABEL + ".plist");
290
+ let template = artifacts.serviceTemplate;
291
+ for (const [key, value] of Object.entries({
292
+ NODE_EXECUTABLE: executables.nodeExecutable, WATCHDOG_FILE: join(state, "watchdog.mjs"),
293
+ PRODUCER_FILE: join(state, "producer.mjs"), CONFIG_FILE: configPath,
294
+ }))
295
+ template = template.replaceAll("@@" + key + "@@", xml(value));
296
+ if (template.includes("@@"))
297
+ fail("service_template_invalid");
298
+ if (existing) {
299
+ if (!custody.read(plistPath).equals(Buffer.from(template)))
300
+ fail("service_custody_mismatch");
301
+ }
302
+ else
303
+ custody.create(plistPath, Buffer.from(template));
304
+ custody.recheck();
305
+ alive();
306
+ await ports.service({ ...executables, uid: principal.uid, serviceLabel: LABEL, plistPath, deadlineMs: input.deadlineMs, signal });
307
+ alive();
308
+ const receipt = await ports.receiveBootstrap({ ...executables, authority, configPath,
309
+ supervisorImage: input.supervisorImage, deadlineMs: input.deadlineMs, signal });
310
+ alive();
311
+ if (ports.now() >= input.deadlineMs)
312
+ fail("startup_proof_expired");
313
+ verifyDarwinThoughtsCustodyResponse(receipt.bytes, { authority, request: parseDarwinThoughtsRequest(receipt.request),
314
+ nowMs: ports.now(), engineCheckout: receipt.engineCheckout, engineLock: receipt.engineLock,
315
+ ...(receipt.engineGit ? { engineGit: receipt.engineGit } : {}) });
316
+ custody.recheck();
317
+ return { authority, envAuthority: canonicalDarwinThoughtsJson(authority), requestsRoot,
318
+ responsesRoot, configPath, serviceLabel: LABEL };
319
+ }
320
+ finally {
321
+ custody.close();
322
+ }
323
+ }
324
+ return { install };
325
+ }
326
+ /** Internal test seam; normal callers cannot supply principal, executable or daemon overrides. */
327
+ export const createDarwinThoughtsInstallerTestHarness = factory;
328
+ function actualPrincipal() {
329
+ if (process.platform !== "darwin" || !process.getuid || !process.geteuid || !process.getgid)
330
+ fail("native_principal_unavailable");
331
+ return { platform: process.platform, uid: process.getuid(), euid: process.geteuid(),
332
+ gid: process.getgid(), home: fs.realpathSync(userInfo().homedir) };
333
+ }
334
+ function actualExecutables() {
335
+ const nodeExecutable = fs.realpathSync(process.execPath);
336
+ for (const directory of (process.env.PATH ?? "").split(":")) {
337
+ if (!isAbsolute(directory))
338
+ continue;
339
+ try {
340
+ const candidate = fs.realpathSync(join(directory, "docker"));
341
+ if (fs.statSync(candidate).isFile())
342
+ return { nodeExecutable, dockerExecutable: candidate };
343
+ }
344
+ catch { /* Continue to the next actual PATH directory. */ }
345
+ }
346
+ return fail("docker_executable_unavailable");
347
+ }
348
+ async function command(executable, args, deadlineMs, maxBuffer = 16384, signal) {
349
+ const budget = deadlineMs - Date.now();
350
+ if (budget <= 0)
351
+ fail("command_deadline_expired");
352
+ if (signal?.aborted)
353
+ return { code: 1, stdout: "", stderr: "command_cancelled" };
354
+ const started = performance.now();
355
+ return new Promise(resolve => {
356
+ let child;
357
+ let deadlineTimer;
358
+ let fallbackTimer;
359
+ let settled = false;
360
+ let stopping = false;
361
+ const finish = (result) => {
362
+ if (settled)
363
+ return;
364
+ settled = true;
365
+ if (deadlineTimer !== undefined)
366
+ clearTimeout(deadlineTimer);
367
+ if (fallbackTimer !== undefined)
368
+ clearTimeout(fallbackTimer);
369
+ signal?.removeEventListener("abort", stop);
370
+ resolve(result);
371
+ };
372
+ const stop = () => {
373
+ if (settled || stopping)
374
+ return;
375
+ stopping = true;
376
+ if (deadlineTimer !== undefined)
377
+ clearTimeout(deadlineTimer);
378
+ // Kill only the child returned by this invocation. A missing close/callback
379
+ // cannot prevent an independent bounded refusal of this command receipt.
380
+ try {
381
+ child?.kill("SIGKILL");
382
+ }
383
+ catch { /* The bounded refusal still applies. */ }
384
+ if (!settled)
385
+ fallbackTimer = setTimeout(() => finish({
386
+ code: 1, stdout: "", stderr: "command_receipt_unreceived",
387
+ }), 250);
388
+ };
389
+ try {
390
+ child = execFile(executable, args, { cwd: "/",
391
+ env: { PATH: "/usr/bin:/bin:/usr/sbin:/sbin" }, timeout: budget,
392
+ killSignal: "SIGKILL", maxBuffer, encoding: "utf8", signal,
393
+ }, (error, stdout, stderr) => {
394
+ const refused = stopping || signal?.aborted || performance.now() - started >= budget;
395
+ finish({ code: error || refused ? 1 : 0,
396
+ stdout: refused ? "" : stdout.trim(), stderr: refused ? "command_receipt_unreceived" : stderr.trim() });
397
+ });
398
+ }
399
+ catch {
400
+ finish({ code: 1, stdout: "", stderr: "command_start_unreceived" });
401
+ }
402
+ if (!settled) {
403
+ deadlineTimer = setTimeout(stop, Math.max(0, budget - (performance.now() - started)));
404
+ signal?.addEventListener("abort", stop, { once: true });
405
+ if (signal?.aborted)
406
+ stop();
407
+ }
408
+ });
409
+ }
410
+ /** Internal receipt seam for controlled child-process fixtures; no production override. */
411
+ export const receiveDarwinThoughtsCommandForTest = command;
412
+ async function actualEngine(input) {
413
+ const config = join(input.principal.home, ".docker");
414
+ const host = process.env.DOCKER_HOST;
415
+ const context = process.env.DOCKER_CONTEXT;
416
+ if (host !== undefined && context !== undefined)
417
+ fail("engine_selector_conflict");
418
+ if (context !== undefined && !/^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/.test(context))
419
+ fail("engine_context_selector_invalid");
420
+ let selected = host;
421
+ if (selected === undefined) {
422
+ const received = await command(input.dockerExecutable, ["--config", config,
423
+ "context", "inspect", ...(context === undefined ? [] : [context]),
424
+ "--format", "{{.Endpoints.docker.Host}}"], input.deadlineMs, 16384, input.signal);
425
+ if (received.code !== 0)
426
+ fail("engine_context_unreceived");
427
+ selected = received.stdout;
428
+ }
429
+ if (!/^unix:\/\/\/[^,\0]+$/.test(selected) ||
430
+ normalize(selected.slice(7)) !== selected.slice(7))
431
+ fail("engine_endpoint_invalid");
432
+ const run = (args) => command(input.dockerExecutable, ["--config", config, "--host", selected, ...args], input.deadlineMs, 16384, input.signal);
433
+ const daemon = await run(["info", "--format", "{{.ID}}"]);
434
+ const supervisor = await run(["image", "inspect", "--format", "{{.Id}}", input.supervisorImage]);
435
+ const runner = await run(["image", "inspect", "--format", "{{json .}}", input.runnerImage]);
436
+ if (daemon.code !== 0)
437
+ fail("engine_identity_unavailable");
438
+ let runnerId;
439
+ let runnerCustodyVersion;
440
+ if (runner.code === 0) {
441
+ let parsed;
442
+ try {
443
+ parsed = JSON.parse(runner.stdout);
444
+ }
445
+ catch {
446
+ fail("runner_cache_metadata_unreceived");
447
+ }
448
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
449
+ fail("runner_cache_metadata_unreceived");
450
+ const row = parsed;
451
+ if (typeof row.Id !== "string" || !/^sha256:[a-f0-9]{64}$/.test(row.Id) ||
452
+ !row.Config || typeof row.Config !== "object" || Array.isArray(row.Config))
453
+ fail("runner_cache_metadata_unreceived");
454
+ runnerId = row.Id;
455
+ const labels = row.Config.Labels;
456
+ if (labels !== null && labels !== undefined &&
457
+ (typeof labels !== "object" || Array.isArray(labels)))
458
+ fail("runner_cache_metadata_unreceived");
459
+ if (labels && Object.hasOwn(labels, LABEL)) {
460
+ const version = labels[LABEL];
461
+ if (typeof version !== "string")
462
+ fail("runner_cache_metadata_unreceived");
463
+ runnerCustodyVersion = version;
464
+ }
465
+ }
466
+ return { endpoint: selected, daemonId: daemon.stdout,
467
+ cachedSupervisor: supervisor.code === 0 && /^sha256:[a-f0-9]{64}$/.test(supervisor.stdout),
468
+ cachedRunner: runnerId !== undefined,
469
+ ...(runnerCustodyVersion === undefined ? {} : { runnerCustodyVersion }) };
470
+ }
471
+ function actualArtifacts() {
472
+ const manifest = JSON.parse(fs.readFileSync(join(vendor, "manifest.json"), "utf8"));
473
+ const read = (name, expected) => {
474
+ const bytes = fs.readFileSync(join(vendor, name));
475
+ if (createHash("sha256").update(bytes).digest("hex") !== expected)
476
+ fail("vendored_artifact_invalid");
477
+ return bytes;
478
+ };
479
+ const sourceHash = (name) => manifest.inputs["deploy/self-host/darwin-thoughts-custody/" + name];
480
+ read("verifier.mjs", manifest.verifierSha256);
481
+ return { producer: read("producer.mjs", manifest.artifactSha256),
482
+ watchdog: read("watchdog.mjs", sourceHash("watchdog.mjs")),
483
+ deadline: read("watchdog-deadline.mjs", sourceHash("watchdog-deadline.mjs")),
484
+ serviceTemplate: read("service.plist.in", sourceHash("service.plist.in")).toString("utf8") };
485
+ }
486
+ async function actualService(input) {
487
+ const target = "user/" + input.uid + "/" + input.serviceLabel;
488
+ const loaded = await command("/bin/launchctl", ["print", target], input.deadlineMs, 16384, input.signal);
489
+ if (loaded.code !== 0) {
490
+ const boot = await command("/bin/launchctl", ["bootstrap", "user/" + input.uid, input.plistPath], input.deadlineMs, 16384, input.signal);
491
+ if (boot.code !== 0)
492
+ fail("background_service_bootstrap_refused");
493
+ }
494
+ const start = await command("/bin/launchctl", ["kickstart", target], input.deadlineMs, 16384, input.signal);
495
+ if (start.code !== 0 || (await command("/bin/launchctl", ["print", target], input.deadlineMs, 16384, input.signal)).code !== 0)
496
+ fail("background_service_receiving_refused");
497
+ }
498
+ async function actualBootstrap(input) {
499
+ const authority = input.authority;
500
+ const name = "catalyst-custody-bootstrap-" + randomBytes(16).toString("hex");
501
+ const token = randomBytes(32).toString("hex");
502
+ const config = join(dirname(input.configPath), ".bootstrap-docker");
503
+ try {
504
+ fs.mkdirSync(config, { mode: 0o700 });
505
+ }
506
+ catch (error) {
507
+ if (error.code !== "EEXIST" ||
508
+ !fs.lstatSync(config).isDirectory() || fs.lstatSync(config).isSymbolicLink() ||
509
+ fs.lstatSync(config).uid !== authority.nativeUid || fs.lstatSync(config).gid !== authority.nativeGid ||
510
+ (fs.lstatSync(config).mode & 0o7777) !== 0o700 || fs.readdirSync(config).length !== 0)
511
+ fail("bootstrap_docker_config_unsafe");
512
+ }
513
+ const executableStat = fs.lstatSync(input.dockerExecutable, { bigint: true });
514
+ const installed = JSON.parse(fs.readFileSync(input.configPath, "utf8"));
515
+ const digest = executable(input.dockerExecutable, { platform: "darwin", uid: authority.nativeUid,
516
+ euid: authority.nativeUid, gid: authority.nativeGid, home: authority.nativeHome }, [authority.thoughtsRoot, authority.locksRoot, authority.requestsRoot, authority.responsesRoot]);
517
+ if (installed.dockerExecutable !== input.dockerExecutable || installed.dockerExecutableSha256 !== digest)
518
+ fail("bootstrap_executable_unreceived");
519
+ const docker = (args, deadlineMs = input.deadlineMs, signal = input.signal ?? null) => {
520
+ if (!same(executableStat, fs.lstatSync(input.dockerExecutable, { bigint: true })))
521
+ fail("bootstrap_executable_changed");
522
+ return command(input.dockerExecutable, ["--config", config, "--host", authority.endpoint, ...args], deadlineMs, args[0] === "start" ? 32768 : 16384, signal ?? undefined);
523
+ };
524
+ let id;
525
+ let cachedImage;
526
+ let createAttempted = false;
527
+ const receiveIdentity = (received, acknowledgedId) => {
528
+ if (received.code !== 0)
529
+ fail("bootstrap_cleanup_unproved");
530
+ let parsed;
531
+ try {
532
+ parsed = JSON.parse(received.stdout);
533
+ }
534
+ catch {
535
+ return fail("bootstrap_cleanup_unproved");
536
+ }
537
+ if (!Array.isArray(parsed) || parsed.length !== 1 || !parsed[0] ||
538
+ typeof parsed[0] !== "object" || Array.isArray(parsed[0]))
539
+ fail("bootstrap_cleanup_unproved");
540
+ const row = parsed[0];
541
+ if (!row.Config || typeof row.Config !== "object" || Array.isArray(row.Config))
542
+ fail("bootstrap_cleanup_unproved");
543
+ const receivedConfig = row.Config;
544
+ if (!receivedConfig.Labels || typeof receivedConfig.Labels !== "object" || Array.isArray(receivedConfig.Labels))
545
+ fail("bootstrap_cleanup_unproved");
546
+ const labels = receivedConfig.Labels;
547
+ if (typeof row.Id !== "string" || !/^[a-f0-9]{64}$/.test(row.Id) ||
548
+ (acknowledgedId !== undefined && row.Id !== acknowledgedId) || row.Name !== "/" + name ||
549
+ row.Image !== cachedImage || receivedConfig.Image !== input.supervisorImage ||
550
+ labels["dev.catalystcloud.custody-token"] !== token)
551
+ fail("bootstrap_cleanup_unproved");
552
+ return row.Id;
553
+ };
554
+ const program = [
555
+ 'const fs=require("node:fs"),v=await import("/custody-verifier.mjs"),a=JSON.parse(process.argv[1]);',
556
+ 'const tenant="custody-bootstrap",repository="catalyst/custody-probe",t=v.deriveDarwinThoughtsTargets(a.authority,tenant,repository);',
557
+ 'let gitPath;try{fs.lstatSync(t.checkoutSource+"/.git");gitPath=t.checkoutSource+"/.git";}catch(e){if(e.code!=="ENOENT")throw e;}',
558
+ 'let received;',
559
+ 'const proof=await v.requestFreshDarwinThoughtsBootstrap({authority:a.authority,tenant,repository,requestDir:a.authority.requestsRoot,responseDir:a.authority.responsesRoot,checkoutPath:t.checkoutSource,lockPath:t.lockSource,...(gitPath?{gitPath}:{}),deadlineMs:a.deadlineMs,onProof:(receipt)=>{received=receipt.bytes.toString("base64");}});',
560
+ 'const identity=(path)=>{const s=fs.lstatSync(path,{bigint:true});return {path,device:String(s.dev),inode:String(s.ino),uid:Number(s.uid),gid:Number(s.gid),mode:Number(s.mode&4095n),isDirectory:s.isDirectory(),isSymbolicLink:s.isSymbolicLink()};};',
561
+ 'if(!received)throw Error("signed_receipt_unavailable");',
562
+ 'console.log(v.canonicalDarwinThoughtsJson({bytes:received,request:proof.request,engineCheckout:identity(t.checkoutSource),engineLock:identity(t.lockSource),...(gitPath?{engineGit:identity(gitPath)}:{})}));',
563
+ ].join("\n");
564
+ let result;
565
+ try {
566
+ const daemon = await docker(["info", "--format", "{{.ID}}"]);
567
+ const image = await docker(["image", "inspect", "--format", "{{.Id}}", input.supervisorImage]);
568
+ if (daemon.code !== 0 || daemon.stdout !== authority.daemonId || image.code !== 0 ||
569
+ !/^sha256:[a-f0-9]{64}$/.test(image.stdout))
570
+ fail("bootstrap_engine_unreceived");
571
+ cachedImage = image.stdout;
572
+ // Keep the random name and label before awaiting create: an absent or invalid CLI ACK
573
+ // cannot establish that the selected daemon did not persist the helper.
574
+ createAttempted = true;
575
+ const created = await docker(["create", "--pull=never", "--name", name,
576
+ "--label", "dev.catalystcloud.custody-token=" + token, "--network", "none", "--read-only",
577
+ "--cap-drop", "ALL", "--security-opt", "no-new-privileges", "--user", "10001:10001",
578
+ "--memory", "256m", "--memory-swap", "256m", "--pids-limit", "32", "--workdir", "/",
579
+ ...[authority.thoughtsRoot, authority.locksRoot, authority.requestsRoot, authority.responsesRoot]
580
+ .flatMap(root => ["--mount", "type=bind,src=" + root + ",dst=" + root +
581
+ (root === authority.responsesRoot ? ",readonly" : "")]),
582
+ "--mount", "type=bind,src=" + join(vendor, "verifier.mjs") + ",dst=/custody-verifier.mjs,readonly",
583
+ "--entrypoint", "/usr/bin/timeout", input.supervisorImage, "--signal=KILL",
584
+ Math.max(1, Math.ceil((input.deadlineMs - Date.now()) / 1000)) + "s", "/usr/bin/env", "-i",
585
+ "PATH=/usr/bin:/bin", "BUN_RUNTIME_TRANSPILER_CACHE_PATH=0", "/usr/local/bin/bun", "--config=/dev/null", "--no-env-file", "--cwd=/",
586
+ "-e", program, canonicalDarwinThoughtsJson({ authority, deadlineMs: input.deadlineMs })]);
587
+ if (created.code !== 0 || !/^[a-f0-9]{64}$/.test(created.stdout))
588
+ fail("bootstrap_create_unreceived");
589
+ id = created.stdout;
590
+ const beforeStartDaemon = await docker(["info", "--format", "{{.ID}}"]);
591
+ const beforeStartImage = await docker(["image", "inspect", "--format", "{{.Id}}", input.supervisorImage]);
592
+ if (beforeStartDaemon.code !== 0 || beforeStartDaemon.stdout !== authority.daemonId ||
593
+ beforeStartImage.code !== 0 || beforeStartImage.stdout !== cachedImage)
594
+ fail("bootstrap_cleanup_unproved");
595
+ id = receiveIdentity(await docker(["inspect", name]), id);
596
+ const started = await docker(["start", "--attach", id]);
597
+ if (started.code !== 0)
598
+ fail("bootstrap_proof_refused");
599
+ const value = JSON.parse(started.stdout);
600
+ if (typeof value.bytes !== "string" || value.bytes.length > 21848 ||
601
+ Buffer.from(value.bytes, "base64").toString("base64") !== value.bytes)
602
+ fail("bootstrap_signed_receipt_unavailable");
603
+ result = { value: { bytes: Buffer.from(value.bytes, "base64"), request: value.request,
604
+ engineCheckout: value.engineCheckout, engineLock: value.engineLock,
605
+ ...(value.engineGit ? { engineGit: value.engineGit } : {}) } };
606
+ }
607
+ catch (error) {
608
+ result = { error };
609
+ }
610
+ if (createAttempted) {
611
+ // Cleanup has one independent monotonic budget and ignores caller cancellation. Every
612
+ // recovery and deletion remains scoped to the received executable, daemon and cached image.
613
+ const cleanupStarted = performance.now();
614
+ const cleanupDocker = (args) => {
615
+ const remaining = 2000 - (performance.now() - cleanupStarted);
616
+ if (remaining <= 0)
617
+ fail("bootstrap_cleanup_unproved");
618
+ // Pass no caller signal; cancellation of admission cannot cancel disposal of our helper.
619
+ return docker(args, Date.now() + Math.ceil(remaining), null);
620
+ };
621
+ try {
622
+ const daemon = await cleanupDocker(["info", "--format", "{{.ID}}"]);
623
+ const image = await cleanupDocker(["image", "inspect", "--format", "{{.Id}}", input.supervisorImage]);
624
+ if (daemon.code !== 0 || daemon.stdout !== authority.daemonId || image.code !== 0 ||
625
+ image.stdout !== cachedImage)
626
+ fail("bootstrap_cleanup_unproved");
627
+ let received;
628
+ for (let attempt = 0; attempt < 32; attempt++) {
629
+ const current = await cleanupDocker(["inspect", name]);
630
+ if (current.code === 0) {
631
+ received = current;
632
+ break;
633
+ }
634
+ if (id !== undefined || performance.now() - cleanupStarted >= 1900)
635
+ fail("bootstrap_cleanup_unproved");
636
+ await new Promise(resolve => setTimeout(resolve, 25));
637
+ }
638
+ if (received === undefined)
639
+ fail("bootstrap_cleanup_unproved");
640
+ id = receiveIdentity(received, id);
641
+ const list = ["ps", "--all", "--no-trunc", "--quiet", "--filter", "id=" + id];
642
+ const present = await cleanupDocker(list);
643
+ if (present.code !== 0 || present.stdout !== id)
644
+ fail("bootstrap_cleanup_unproved");
645
+ const removed = await cleanupDocker(["rm", "--force", id]);
646
+ if (removed.code !== 0)
647
+ fail("bootstrap_cleanup_unproved");
648
+ const absent = await cleanupDocker(list);
649
+ if (absent.code !== 0 || absent.stdout !== "")
650
+ fail("bootstrap_cleanup_unproved");
651
+ }
652
+ catch {
653
+ fail("bootstrap_cleanup_unproved");
654
+ }
655
+ }
656
+ if ("error" in result)
657
+ throw result.error;
658
+ return result.value;
659
+ }
660
+ /** Internal test seam for the production bootstrap transport, without command overrides. */
661
+ export const receiveDarwinThoughtsBootstrapForTest = actualBootstrap;
662
+ /** Closed production installer; no principal, key, runtime or Engine override. */
663
+ function validateInstallLayout(home, dir) {
664
+ path(home);
665
+ path(dir);
666
+ if (dir !== join(home, ".local", "state", "catalyst", "runner"))
667
+ fail("native_workspace_layout_unqualified");
668
+ }
669
+ /** Pure internal fixture seam; production always supplies the actual OS home. */
670
+ export const validateDarwinThoughtsInstallLayoutForTest = validateInstallLayout;
671
+ /** Actual command path for fixed executable fixtures, never an installation override. */
672
+ export const inspectDarwinThoughtsEngineForTest = actualEngine;
673
+ export function installDarwinThoughtsCustody(input, signal) {
674
+ if (signal?.aborted)
675
+ fail("installation_cancelled");
676
+ validateInstallLayout(actualPrincipal().home, input.dir);
677
+ return factory({ principal: actualPrincipal, now: Date.now, stat: (_path, stat) => stat,
678
+ executables: actualExecutables, artifacts: actualArtifacts, engineIdentity: actualEngine,
679
+ service: actualService, receiveBootstrap: actualBootstrap }).install(input, signal);
680
+ }