@catalyst-cloud/cli 0.16.3 → 0.16.6

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,1202 @@
1
+ // packages/host-isolation/src/darwin-thoughts-producer.ts
2
+ import fs from "node:fs";
3
+ import {
4
+ createHash,
5
+ createPrivateKey,
6
+ createPublicKey,
7
+ randomBytes,
8
+ sign
9
+ } from "node:crypto";
10
+ import { execFile, execFileSync } from "node:child_process";
11
+ import { userInfo } from "node:os";
12
+ import { basename, dirname, isAbsolute, join, normalize, relative } from "node:path";
13
+
14
+ // packages/protocol/src/darwin-thoughts-custody.ts
15
+ var DARWIN_THOUGHTS_CUSTODY_VERSION = 1;
16
+ var DARWIN_THOUGHTS_PRIVATE_ROOT = "/run/catalyst-thoughts-private";
17
+ var DARWIN_THOUGHTS_MAX_EXCHANGE_MS = 30000;
18
+ var DARWIN_THOUGHTS_MAX_PAYLOAD_BYTES = 16384;
19
+ var AUTHORITY_FIELDS = [
20
+ "version",
21
+ "installationId",
22
+ "publicKey",
23
+ "nativeUid",
24
+ "nativeGid",
25
+ "nativeHome",
26
+ "endpoint",
27
+ "daemonId",
28
+ "thoughtsRoot",
29
+ "locksRoot",
30
+ "requestsRoot",
31
+ "responsesRoot"
32
+ ];
33
+ var REQUEST_FIELDS = [
34
+ "version",
35
+ "installationId",
36
+ "nonce",
37
+ "tenant",
38
+ "repository",
39
+ "issuedAtMs",
40
+ "expiresAtMs"
41
+ ];
42
+ var RESPONSE_FIELDS = [
43
+ "version",
44
+ "kind",
45
+ "authority",
46
+ "request",
47
+ "observedAtMs",
48
+ "expiresAtMs",
49
+ "nativeBootId",
50
+ "producerInstance"
51
+ ];
52
+ var STAT_FIELDS = [
53
+ "path",
54
+ "device",
55
+ "inode",
56
+ "uid",
57
+ "gid",
58
+ "mode",
59
+ "isDirectory",
60
+ "isSymbolicLink"
61
+ ];
62
+ var HEX_NONCE = /^[a-f0-9]{64}$/;
63
+ var TOKEN = /^[A-Za-z0-9][A-Za-z0-9_.:-]{0,127}$/;
64
+ var TENANT = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,127}$/;
65
+ var OWNER = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,99}$/;
66
+ var REPOSITORY = /^[A-Za-z0-9_.-]{1,100}$/;
67
+ var PUBLIC_KEY = /^MCowBQYDK2VwAyEA[A-Za-z0-9+/]{42}[AEIMQUYcgkosw048]=$/;
68
+ var UINT64_MAX = "18446744073709551615";
69
+ var MAX_PATH_CHARS = 4096;
70
+ function invalid(reason) {
71
+ throw new Error(reason);
72
+ }
73
+ function plainRecord(value) {
74
+ if (value === null || typeof value !== "object" || Array.isArray(value))
75
+ return false;
76
+ const prototype = Object.getPrototypeOf(value);
77
+ return prototype === null || prototype === Object.prototype;
78
+ }
79
+ function exact(value, required, optional, reason) {
80
+ if (!plainRecord(value))
81
+ return invalid(reason);
82
+ const fields = Reflect.ownKeys(value);
83
+ if (required.some((key) => !Object.hasOwn(value, key)) || fields.some((key) => typeof key !== "string" || !required.includes(key) && !optional.includes(key)) || fields.some((key) => !Object.hasOwn(Object.getOwnPropertyDescriptor(value, key) ?? {}, "value")))
84
+ return invalid(reason);
85
+ return value;
86
+ }
87
+ function matches(value, pattern, reason) {
88
+ if (typeof value !== "string" || !pattern.test(value))
89
+ return invalid(reason);
90
+ return value;
91
+ }
92
+ function integer(value, min, max, reason) {
93
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < min || value > max)
94
+ return invalid(reason);
95
+ return value;
96
+ }
97
+ function path(value, reason) {
98
+ if (typeof value !== "string" || value.length > MAX_PATH_CHARS || !value.startsWith("/") || value === "/" || value.endsWith("/") || Array.from(value).some((character) => character.charCodeAt(0) < 32 || character.charCodeAt(0) === 127) || value.slice(1).split("/").some((part) => part === "" || part === "." || part === ".."))
99
+ return invalid(reason);
100
+ return value;
101
+ }
102
+ function below(child, parent) {
103
+ return child.startsWith(parent + "/");
104
+ }
105
+ function tuple(tenant, repository, reason) {
106
+ const tenantName = matches(tenant, TENANT, reason);
107
+ if (typeof repository !== "string" || repository.length > 201)
108
+ return invalid(reason);
109
+ const parts = repository.split("/");
110
+ const owner = matches(parts[0], OWNER, reason);
111
+ const name = matches(parts[1], REPOSITORY, reason);
112
+ if (parts.length !== 2 || name === "." || name === "..")
113
+ return invalid(reason);
114
+ return { tenant: tenantName, repository: owner + "/" + name };
115
+ }
116
+ function parseDarwinThoughtsAuthority(value) {
117
+ const reason = "darwin_thoughts_authority_invalid";
118
+ const row = exact(value, AUTHORITY_FIELDS, [], reason);
119
+ if (row.version !== DARWIN_THOUGHTS_CUSTODY_VERSION)
120
+ return invalid(reason);
121
+ const nativeHome = path(row.nativeHome, reason);
122
+ const thoughtsRoot = path(row.thoughtsRoot, reason);
123
+ const locksRoot = path(row.locksRoot, reason);
124
+ const requestsRoot = path(row.requestsRoot, reason);
125
+ const responsesRoot = path(row.responsesRoot, reason);
126
+ const roots = [thoughtsRoot, locksRoot, requestsRoot, responsesRoot];
127
+ if (roots.some((root) => !below(root, nativeHome)) || roots.some((root, index) => roots.some((other, otherIndex) => index !== otherIndex && (root === other || below(root, other) || below(other, root)))))
128
+ return invalid(reason);
129
+ if (typeof row.endpoint !== "string" || !row.endpoint.startsWith("unix://"))
130
+ return invalid(reason);
131
+ const endpoint = "unix://" + path(row.endpoint.slice(7), reason);
132
+ return Object.freeze({
133
+ version: DARWIN_THOUGHTS_CUSTODY_VERSION,
134
+ installationId: matches(row.installationId, HEX_NONCE, reason),
135
+ publicKey: matches(row.publicKey, PUBLIC_KEY, reason),
136
+ nativeUid: integer(row.nativeUid, 1, 4294967294, reason),
137
+ nativeGid: integer(row.nativeGid, 0, 4294967294, reason),
138
+ nativeHome,
139
+ endpoint,
140
+ daemonId: matches(row.daemonId, TOKEN, reason),
141
+ thoughtsRoot,
142
+ locksRoot,
143
+ requestsRoot,
144
+ responsesRoot
145
+ });
146
+ }
147
+ function deriveDarwinThoughtsTargets(authority, tenant, repository) {
148
+ const installed = parseDarwinThoughtsAuthority(authority);
149
+ const selected = tuple(tenant, repository, "darwin_thoughts_tuple_invalid");
150
+ const suffix = selected.tenant + "/" + selected.repository;
151
+ const privateRoot = DARWIN_THOUGHTS_PRIVATE_ROOT;
152
+ return Object.freeze({
153
+ checkoutSource: installed.thoughtsRoot + "/" + suffix,
154
+ lockSource: installed.locksRoot + "/" + selected.tenant,
155
+ requestSource: installed.requestsRoot + "/" + suffix,
156
+ responseSource: installed.responsesRoot + "/" + suffix,
157
+ publicCheckoutTarget: "/srv/catalyst/tenants/" + selected.tenant + "/repos/" + selected.repository,
158
+ privateCheckoutTarget: privateRoot + "/checkouts/" + suffix,
159
+ privateLockTarget: privateRoot + "/locks/" + selected.tenant,
160
+ privateRequestTarget: privateRoot + "/requests/" + suffix,
161
+ privateResponseTarget: privateRoot + "/responses/" + suffix
162
+ });
163
+ }
164
+ function parseDarwinThoughtsRequest(value) {
165
+ const reason = "darwin_thoughts_request_invalid";
166
+ const row = exact(value, REQUEST_FIELDS, [], reason);
167
+ if (row.version !== DARWIN_THOUGHTS_CUSTODY_VERSION)
168
+ return invalid(reason);
169
+ const selected = tuple(row.tenant, row.repository, reason);
170
+ const issuedAtMs = integer(row.issuedAtMs, 1, Number.MAX_SAFE_INTEGER, reason);
171
+ const expiresAtMs = integer(row.expiresAtMs, 1, Number.MAX_SAFE_INTEGER, reason);
172
+ if (expiresAtMs <= issuedAtMs || expiresAtMs - issuedAtMs > DARWIN_THOUGHTS_MAX_EXCHANGE_MS)
173
+ return invalid(reason);
174
+ return Object.freeze({
175
+ version: DARWIN_THOUGHTS_CUSTODY_VERSION,
176
+ installationId: matches(row.installationId, HEX_NONCE, reason),
177
+ nonce: matches(row.nonce, HEX_NONCE, reason),
178
+ ...selected,
179
+ issuedAtMs,
180
+ expiresAtMs
181
+ });
182
+ }
183
+ function decimal(value, nonzero, reason) {
184
+ const text = matches(value, /^(0|[1-9][0-9]{0,19})$/, reason);
185
+ if (nonzero && text === "0" || text.length === 20 && text > UINT64_MAX)
186
+ return invalid(reason);
187
+ return text;
188
+ }
189
+ function statIdentity(value, expectedPath, authority, native, git) {
190
+ const reason = "darwin_thoughts_response_invalid";
191
+ const row = exact(value, STAT_FIELDS, [], reason);
192
+ const observedPath = path(row.path, reason);
193
+ const uid = integer(row.uid, 0, 4294967294, reason);
194
+ const gid = integer(row.gid, 0, 4294967294, reason);
195
+ const mode = integer(row.mode, 0, 4095, reason);
196
+ if (observedPath !== expectedPath || row.isDirectory !== true || row.isSymbolicLink !== false || (native ? uid !== authority.nativeUid || gid !== authority.nativeGid : uid !== 0 && uid !== 10001) || (mode & 448) !== 448 || (mode & 3602) !== 0 || !git && (mode & 7) !== 0)
197
+ return invalid(reason);
198
+ return Object.freeze({
199
+ path: observedPath,
200
+ device: decimal(row.device, false, reason),
201
+ inode: decimal(row.inode, true, reason),
202
+ uid,
203
+ gid,
204
+ mode,
205
+ isDirectory: true,
206
+ isSymbolicLink: false
207
+ });
208
+ }
209
+ function parseDarwinThoughtsResponse(value, context) {
210
+ const reason = "darwin_thoughts_response_invalid";
211
+ try {
212
+ const basic = exact(value, RESPONSE_FIELDS, [
213
+ "nativeCheckout",
214
+ "nativeLock",
215
+ "engineCheckout",
216
+ "engineLock",
217
+ "nativeGit",
218
+ "engineGit",
219
+ "reason"
220
+ ], reason);
221
+ if (basic.version !== DARWIN_THOUGHTS_CUSTODY_VERSION)
222
+ return invalid(reason);
223
+ const authority = parseDarwinThoughtsAuthority(basic.authority);
224
+ const request = parseDarwinThoughtsRequest(basic.request);
225
+ const installed = parseDarwinThoughtsAuthority(context.authority);
226
+ const expected = parseDarwinThoughtsRequest(context.request);
227
+ const nowMs = integer(context.nowMs, 1, Number.MAX_SAFE_INTEGER, reason);
228
+ if (canonicalDarwinThoughtsJson(authority) !== canonicalDarwinThoughtsJson(installed) || canonicalDarwinThoughtsJson(request) !== canonicalDarwinThoughtsJson(expected) || request.installationId !== authority.installationId || request.issuedAtMs > nowMs || request.expiresAtMs <= nowMs)
229
+ return invalid(reason);
230
+ const observedAtMs = integer(basic.observedAtMs, 1, Number.MAX_SAFE_INTEGER, reason);
231
+ const expiresAtMs = integer(basic.expiresAtMs, 1, Number.MAX_SAFE_INTEGER, reason);
232
+ if (observedAtMs < request.issuedAtMs || observedAtMs > nowMs || expiresAtMs <= observedAtMs || expiresAtMs <= nowMs || expiresAtMs > request.expiresAtMs)
233
+ return invalid(reason);
234
+ const binding = {
235
+ version: DARWIN_THOUGHTS_CUSTODY_VERSION,
236
+ authority,
237
+ request,
238
+ observedAtMs,
239
+ expiresAtMs,
240
+ nativeBootId: matches(basic.nativeBootId, TOKEN, reason),
241
+ producerInstance: matches(basic.producerInstance, HEX_NONCE, reason)
242
+ };
243
+ if (basic.kind === "refused") {
244
+ const row = exact(value, [...RESPONSE_FIELDS, "reason"], [], reason);
245
+ return Object.freeze({
246
+ ...binding,
247
+ kind: "refused",
248
+ reason: matches(row.reason, /^[a-z][a-z0-9_]{0,127}$/, reason)
249
+ });
250
+ }
251
+ if (basic.kind !== "accepted")
252
+ return invalid(reason);
253
+ const row = exact(value, [...RESPONSE_FIELDS, "nativeCheckout", "nativeLock", "engineCheckout", "engineLock"], ["nativeGit", "engineGit"], reason);
254
+ const paths = deriveDarwinThoughtsTargets(authority, request.tenant, request.repository);
255
+ const hasGit = Object.hasOwn(row, "nativeGit");
256
+ if (hasGit !== Object.hasOwn(row, "engineGit"))
257
+ return invalid(reason);
258
+ return Object.freeze({
259
+ ...binding,
260
+ kind: "accepted",
261
+ nativeCheckout: statIdentity(row.nativeCheckout, paths.checkoutSource, authority, true, false),
262
+ nativeLock: statIdentity(row.nativeLock, paths.lockSource, authority, true, false),
263
+ engineCheckout: statIdentity(row.engineCheckout, paths.checkoutSource, authority, false, false),
264
+ engineLock: statIdentity(row.engineLock, paths.lockSource, authority, false, false),
265
+ ...hasGit ? {
266
+ nativeGit: statIdentity(row.nativeGit, paths.checkoutSource + "/.git", authority, true, true),
267
+ engineGit: statIdentity(row.engineGit, paths.checkoutSource + "/.git", authority, false, true)
268
+ } : {}
269
+ });
270
+ } catch {
271
+ return invalid(reason);
272
+ }
273
+ }
274
+ function utf8Bytes(text, reason) {
275
+ let size = 0;
276
+ for (let index = 0;index < text.length; index++) {
277
+ const char = text.charCodeAt(index);
278
+ if (char <= 127)
279
+ size++;
280
+ else if (char <= 2047)
281
+ size += 2;
282
+ else if (char >= 55296 && char <= 56319) {
283
+ const next = text.charCodeAt(++index);
284
+ if (!(next >= 56320 && next <= 57343))
285
+ return invalid(reason);
286
+ size += 4;
287
+ } else {
288
+ if (char >= 56320 && char <= 57343)
289
+ return invalid(reason);
290
+ size += 3;
291
+ }
292
+ }
293
+ return size;
294
+ }
295
+ function canonicalDarwinThoughtsJson(value) {
296
+ const reason = "darwin_thoughts_json_invalid";
297
+ const seen = new Set;
298
+ let nodes = 0;
299
+ function encode(input, depth) {
300
+ if (++nodes > 4096 || depth > 16)
301
+ return invalid(reason);
302
+ if (input === null)
303
+ return "null";
304
+ if (typeof input === "boolean")
305
+ return input ? "true" : "false";
306
+ if (typeof input === "number") {
307
+ if (!Number.isSafeInteger(input) || Object.is(input, -0))
308
+ return invalid(reason);
309
+ return String(input);
310
+ }
311
+ if (typeof input === "string") {
312
+ if (utf8Bytes(input, reason) > DARWIN_THOUGHTS_MAX_PAYLOAD_BYTES)
313
+ return invalid(reason);
314
+ return JSON.stringify(input);
315
+ }
316
+ if (typeof input !== "object" || seen.has(input))
317
+ return invalid(reason);
318
+ seen.add(input);
319
+ try {
320
+ if (Array.isArray(input)) {
321
+ const keys = Reflect.ownKeys(input);
322
+ if (input.length > 4096 || Object.keys(input).length !== input.length || keys.length !== input.length + 1 || keys.some((key) => key !== "length" && (typeof key !== "string" || !/^(0|[1-9][0-9]*)$/.test(key) || !Object.hasOwn(Object.getOwnPropertyDescriptor(input, key) ?? {}, "value"))))
323
+ return invalid(reason);
324
+ return "[" + input.map((item) => encode(item, depth + 1)).join(",") + "]";
325
+ }
326
+ if (!plainRecord(input) || Reflect.ownKeys(input).some((key) => typeof key !== "string"))
327
+ return invalid(reason);
328
+ const keys = Object.keys(input).sort();
329
+ if (keys.length > 4096 || Reflect.ownKeys(input).length !== keys.length)
330
+ return invalid(reason);
331
+ return "{" + keys.map((key) => {
332
+ const descriptor = Object.getOwnPropertyDescriptor(input, key);
333
+ if (!descriptor || !Object.hasOwn(descriptor, "value"))
334
+ return invalid(reason);
335
+ return JSON.stringify(key) + ":" + encode(descriptor.value, depth + 1);
336
+ }).join(",") + "}";
337
+ } finally {
338
+ seen.delete(input);
339
+ }
340
+ }
341
+ const result = encode(value, 0);
342
+ if (utf8Bytes(result, reason) > DARWIN_THOUGHTS_MAX_PAYLOAD_BYTES)
343
+ return invalid(reason);
344
+ return result;
345
+ }
346
+
347
+ // packages/host-isolation/src/darwin-thoughts-producer.ts
348
+ class ProducerError extends Error {
349
+ reason;
350
+ constructor(reason) {
351
+ super("darwin_thoughts_producer:" + reason);
352
+ this.reason = reason;
353
+ }
354
+ }
355
+ function fail(reason) {
356
+ throw new ProducerError(reason);
357
+ }
358
+ function canonicalPath(value, reason) {
359
+ if (typeof value !== "string" || !isAbsolute(value) || normalize(value) !== value || value === "/" || value.includes("\x00") || value.endsWith("/"))
360
+ fail(reason);
361
+ return value;
362
+ }
363
+ function below2(path, root) {
364
+ const rel = relative(root, path);
365
+ return rel !== "" && rel !== ".." && !rel.startsWith("../") && !isAbsolute(rel);
366
+ }
367
+ function within(path, root) {
368
+ return path === root || below2(path, root);
369
+ }
370
+ function exact2(value, fields, reason) {
371
+ if (!value || typeof value !== "object" || Array.isArray(value))
372
+ fail(reason);
373
+ const row = value;
374
+ if (Object.keys(row).length !== fields.length || fields.some((key) => !Object.hasOwn(row, key)))
375
+ fail(reason);
376
+ return row;
377
+ }
378
+ function parseCanonical(bytes, reason) {
379
+ try {
380
+ const text = bytes.toString("utf8");
381
+ const value = JSON.parse(text);
382
+ if (!Buffer.from(text).equals(bytes) || canonicalDarwinThoughtsJson(value) !== text)
383
+ fail(reason);
384
+ return value;
385
+ } catch {
386
+ return fail(reason);
387
+ }
388
+ }
389
+ function same(a, b) {
390
+ return a.dev === b.dev && a.ino === b.ino && a.uid === b.uid && a.gid === b.gid && a.mode === b.mode && (a.isDirectory() || a.nlink === b.nlink);
391
+ }
392
+ function unlinkIfPresent(path) {
393
+ try {
394
+ fs.unlinkSync(path);
395
+ } catch (error) {
396
+ if (error.code !== "ENOENT")
397
+ throw error;
398
+ }
399
+ }
400
+
401
+ class NativeCustody {
402
+ principal;
403
+ ports;
404
+ held = new Map;
405
+ constructor(principal, ports) {
406
+ this.principal = principal;
407
+ this.ports = ports;
408
+ }
409
+ stat(path, stat) {
410
+ return this.ports.nativeStat(path, stat);
411
+ }
412
+ hold(path, directory, privateMode = false, publicGit = false) {
413
+ const prior = this.held.get(path);
414
+ if (prior) {
415
+ this.recheckOne(prior);
416
+ this.policy(prior.stat, directory, privateMode, publicGit);
417
+ return prior;
418
+ }
419
+ let fd;
420
+ try {
421
+ fd = fs.openSync(path, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK | (directory ? fs.constants.O_DIRECTORY : 0));
422
+ } catch {
423
+ return fail(directory ? "native_path_unsafe" : "private_file_custody_unsafe");
424
+ }
425
+ try {
426
+ const stat = this.stat(path, fs.fstatSync(fd, { bigint: true }));
427
+ this.policy(stat, directory, privateMode, publicGit);
428
+ const held = { path, fd, stat };
429
+ this.recheckOne(held);
430
+ this.held.set(path, held);
431
+ return held;
432
+ } catch (error) {
433
+ fs.closeSync(fd);
434
+ throw error;
435
+ }
436
+ }
437
+ policy(stat, directory, privateMode, publicGit) {
438
+ if (stat.uid !== BigInt(this.principal.uid) || stat.gid !== BigInt(this.principal.gid))
439
+ fail("native_owner_mismatch");
440
+ const mode = Number(stat.mode & 0o7777n);
441
+ if (directory ? !stat.isDirectory() : !stat.isFile() || stat.nlink !== 1n)
442
+ fail("native_path_unsafe");
443
+ if (directory) {
444
+ if ((mode & 3602) !== 0 || (mode & 448) !== 448 || !publicGit && (mode & 7) !== 0 || privateMode && mode !== 448)
445
+ fail("native_directory_custody_unsafe");
446
+ } else if (mode !== 384)
447
+ fail("private_file_custody_unsafe");
448
+ }
449
+ walk(path, create = false, mode = 488, privateLeaf = false, publicGit = false) {
450
+ canonicalPath(path, "native_path_unsafe");
451
+ if (!within(path, this.principal.home))
452
+ fail("native_path_outside_home");
453
+ this.hold(this.principal.home, true, false, true);
454
+ let cursor = this.principal.home;
455
+ const components = relative(cursor, path).split("/").filter(Boolean);
456
+ for (let index = 0;index < components.length; index++) {
457
+ this.recheck();
458
+ cursor = join(cursor, components[index]);
459
+ let missing = false;
460
+ try {
461
+ fs.lstatSync(cursor);
462
+ } catch (error) {
463
+ if (error.code !== "ENOENT")
464
+ fail("native_path_unsafe");
465
+ missing = true;
466
+ }
467
+ if (missing) {
468
+ if (!create)
469
+ fail("native_path_missing");
470
+ try {
471
+ fs.mkdirSync(cursor, { mode });
472
+ } catch (error) {
473
+ if (error.code !== "EEXIST")
474
+ fail("native_path_create_failed");
475
+ }
476
+ }
477
+ this.hold(cursor, true, privateLeaf && index === components.length - 1, index < components.length - 1 || publicGit);
478
+ }
479
+ return this.hold(path, true, privateLeaf, publicGit || path === this.principal.home);
480
+ }
481
+ read(path, max) {
482
+ this.walk(dirname(path));
483
+ const held = this.hold(path, false);
484
+ if (held.stat.size > BigInt(max))
485
+ fail("private_file_custody_unsafe");
486
+ const bytes = Buffer.alloc(Number(held.stat.size));
487
+ if (fs.readSync(held.fd, bytes, 0, bytes.length, 0) !== bytes.length)
488
+ fail("private_file_custody_unsafe");
489
+ this.recheckOne(held);
490
+ const after = this.stat(path, fs.fstatSync(held.fd, { bigint: true }));
491
+ if (after.size !== held.stat.size || after.mtimeNs !== held.stat.mtimeNs || after.ctimeNs !== held.stat.ctimeNs)
492
+ fail("private_file_descriptor_changed");
493
+ return bytes;
494
+ }
495
+ recheckOne(held) {
496
+ try {
497
+ const current = this.stat(held.path, fs.fstatSync(held.fd, { bigint: true }));
498
+ const named = this.stat(held.path, fs.lstatSync(held.path, { bigint: true }));
499
+ if (!same(held.stat, current) || !same(current, named))
500
+ fail("native_descriptor_changed");
501
+ if (held.stat.isFile() && (current.size !== held.stat.size || current.mtimeNs !== held.stat.mtimeNs || current.ctimeNs !== held.stat.ctimeNs))
502
+ fail("native_descriptor_changed");
503
+ } catch {
504
+ fail("native_descriptor_changed");
505
+ }
506
+ }
507
+ recheck() {
508
+ for (const held of this.held.values())
509
+ this.recheckOne(held);
510
+ }
511
+ drop(path) {
512
+ const held = this.held.get(path);
513
+ if (held) {
514
+ this.recheckOne(held);
515
+ fs.closeSync(held.fd);
516
+ this.held.delete(path);
517
+ }
518
+ }
519
+ gitMetadata(path, deadlineMs) {
520
+ const entries = new Map;
521
+ const receive = (entry) => {
522
+ const stat = this.stat(entry, fs.lstatSync(entry, { bigint: true }));
523
+ const mode = Number(stat.mode & 0o7777n);
524
+ if (stat.uid !== BigInt(this.principal.uid) || stat.gid !== BigInt(this.principal.gid) || (mode & 3602) !== 0 || !stat.isDirectory() && (!stat.isFile() || stat.nlink !== 1n))
525
+ fail("native_custody_unavailable");
526
+ return stat;
527
+ };
528
+ const walk = (directory, depth) => {
529
+ if (depth > 32 || this.ports.now() >= deadlineMs)
530
+ fail("native_git_metadata_bounds");
531
+ const before = receive(directory);
532
+ if (!before.isDirectory())
533
+ fail("native_custody_unavailable");
534
+ entries.set(directory, before);
535
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
536
+ if (entries.size >= 16384 || this.ports.now() >= deadlineMs)
537
+ fail("native_git_metadata_bounds");
538
+ const child = join(directory, entry.name);
539
+ const stat = receive(child);
540
+ entries.set(child, stat);
541
+ if (stat.isDirectory())
542
+ walk(child, depth + 1);
543
+ }
544
+ if (!same(before, receive(directory)))
545
+ fail("native_git_metadata_changed");
546
+ };
547
+ walk(path, 0);
548
+ return () => {
549
+ this.recheck();
550
+ for (const [entry, before] of entries) {
551
+ if (this.ports.now() >= deadlineMs)
552
+ fail("native_git_metadata_bounds");
553
+ const after = receive(entry);
554
+ if (!same(before, after) || !before.isDirectory() && (before.size !== after.size || before.mtimeNs !== after.mtimeNs || before.ctimeNs !== after.ctimeNs))
555
+ fail("native_git_metadata_changed");
556
+ }
557
+ };
558
+ }
559
+ retireExpiredRequest(path) {
560
+ const held = this.hold(path, false);
561
+ this.recheck();
562
+ fs.unlinkSync(path);
563
+ this.held.delete(path);
564
+ fs.closeSync(held.fd);
565
+ }
566
+ close() {
567
+ for (const held of this.held.values())
568
+ fs.closeSync(held.fd);
569
+ this.held.clear();
570
+ }
571
+ identity(held) {
572
+ return {
573
+ path: held.path,
574
+ device: held.stat.dev.toString(),
575
+ inode: held.stat.ino.toString(),
576
+ uid: Number(held.stat.uid),
577
+ gid: Number(held.stat.gid),
578
+ mode: Number(held.stat.mode & 0o7777n),
579
+ isDirectory: true,
580
+ isSymbolicLink: false
581
+ };
582
+ }
583
+ }
584
+ function installed(configPath, ports) {
585
+ const principal = ports.principal();
586
+ if (principal.platform !== "darwin" || principal.uid <= 0 || principal.euid !== principal.uid || !Number.isSafeInteger(principal.uid) || !Number.isSafeInteger(principal.gid))
587
+ fail("native_principal_invalid");
588
+ canonicalPath(principal.home, "native_principal_home_invalid");
589
+ canonicalPath(configPath, "config_path_unsafe");
590
+ if (!below2(configPath, principal.home))
591
+ fail("native_principal_home_authority_mismatch");
592
+ const custody = new NativeCustody(principal, ports);
593
+ try {
594
+ custody.walk(dirname(configPath), false, 448, true);
595
+ const row = exact2(parseCanonical(custody.read(configPath, 16384), "config_invalid"), [
596
+ "version",
597
+ "authority",
598
+ "privateKeyFile",
599
+ "supervisorImage",
600
+ "dockerExecutable",
601
+ "dockerExecutableSha256"
602
+ ], "config_invalid");
603
+ if (row.version !== 1)
604
+ fail("config_invalid");
605
+ const authority = parseDarwinThoughtsAuthority(row.authority);
606
+ if (authority.nativeUid !== principal.uid || authority.nativeGid !== principal.gid || authority.nativeHome !== principal.home)
607
+ fail("native_principal_authority_mismatch");
608
+ const privateKeyFile = canonicalPath(row.privateKeyFile, "key_path_unsafe");
609
+ const dockerExecutable = canonicalPath(row.dockerExecutable, "config_executable_unsafe");
610
+ if (typeof row.supervisorImage !== "string" || !/^[a-z0-9][a-z0-9./:_-]*@sha256:[a-f0-9]{64}$/.test(row.supervisorImage) || typeof row.dockerExecutableSha256 !== "string" || !/^[a-f0-9]{64}$/.test(row.dockerExecutableSha256))
611
+ fail("config_invalid");
612
+ for (const root of [
613
+ authority.thoughtsRoot,
614
+ authority.locksRoot,
615
+ authority.requestsRoot,
616
+ authority.responsesRoot
617
+ ]) {
618
+ if (within(configPath, root) || within(privateKeyFile, root) || within(dockerExecutable, root) || within(dirname(configPath), root) || within(root, dirname(configPath)) || within(dirname(privateKeyFile), root) || within(root, dirname(privateKeyFile)))
619
+ fail("key_mount_path_unsafe");
620
+ custody.walk(root, false, 448, root === authority.requestsRoot || root === authority.responsesRoot);
621
+ }
622
+ if (dirname(privateKeyFile) !== dirname(configPath))
623
+ fail("key_state_directory_mismatch");
624
+ let key;
625
+ try {
626
+ key = createPrivateKey({
627
+ key: custody.read(privateKeyFile, 4096),
628
+ type: "pkcs8",
629
+ format: "der"
630
+ });
631
+ } catch {
632
+ return fail("key_custody_invalid");
633
+ }
634
+ if (key.asymmetricKeyType !== "ed25519" || createPublicKey(key).export({ type: "spki", format: "der" }).toString("base64") !== authority.publicKey)
635
+ fail("key_authority_mismatch");
636
+ const config = {
637
+ version: 1,
638
+ authority,
639
+ privateKeyFile,
640
+ dockerExecutable,
641
+ supervisorImage: row.supervisorImage,
642
+ dockerExecutableSha256: row.dockerExecutableSha256
643
+ };
644
+ custody.recheck();
645
+ return { config, principal, custody, key, configPath };
646
+ } catch (error) {
647
+ custody.close();
648
+ throw error;
649
+ }
650
+ }
651
+ function registryFile(state) {
652
+ return join(dirname(state.configPath), "known-tuples.json");
653
+ }
654
+ function readRegistry(state) {
655
+ const path = registryFile(state);
656
+ try {
657
+ fs.lstatSync(path);
658
+ } catch (error) {
659
+ if (error.code === "ENOENT")
660
+ return [];
661
+ throw error;
662
+ }
663
+ const row = exact2(parseCanonical(state.custody.read(path, 16384), "registry_invalid"), ["version", "installationId", "tuples"], "registry_invalid");
664
+ if (row.version !== 1 || row.installationId !== state.config.authority.installationId || !Array.isArray(row.tuples) || row.tuples.length > 128)
665
+ fail("registry_invalid");
666
+ const seen = new Set;
667
+ return row.tuples.map((value) => {
668
+ const tuple = exact2(value, ["tenant", "repository"], "registry_invalid");
669
+ if (typeof tuple.tenant !== "string" || typeof tuple.repository !== "string")
670
+ fail("registry_invalid");
671
+ deriveDarwinThoughtsTargets(state.config.authority, tuple.tenant, tuple.repository);
672
+ const id = tuple.tenant + "/" + tuple.repository;
673
+ if (seen.has(id))
674
+ fail("registry_invalid");
675
+ seen.add(id);
676
+ return { tenant: tuple.tenant, repository: tuple.repository };
677
+ });
678
+ }
679
+ function writePrivate(state, path, bytes, replace, beforePublish) {
680
+ state.custody.walk(dirname(path), false, 448, true);
681
+ state.custody.recheck();
682
+ if (!replace) {
683
+ try {
684
+ fs.lstatSync(path);
685
+ fail("response_already_exists");
686
+ } catch (error) {
687
+ if (error.code !== "ENOENT")
688
+ throw error;
689
+ }
690
+ }
691
+ const temporary = join(dirname(path), ".producer-" + randomBytes(16).toString("hex"));
692
+ const fd = fs.openSync(temporary, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_NOFOLLOW, 384);
693
+ try {
694
+ fs.writeFileSync(fd, bytes);
695
+ fs.fsyncSync(fd);
696
+ state.custody.recheck();
697
+ beforePublish?.();
698
+ if (replace)
699
+ fs.renameSync(temporary, path);
700
+ else {
701
+ fs.linkSync(temporary, path);
702
+ fs.unlinkSync(temporary);
703
+ }
704
+ const parentFd = fs.openSync(dirname(path), fs.constants.O_RDONLY | fs.constants.O_DIRECTORY | fs.constants.O_NOFOLLOW);
705
+ try {
706
+ fs.fsyncSync(parentFd);
707
+ } finally {
708
+ fs.closeSync(parentFd);
709
+ }
710
+ } finally {
711
+ fs.closeSync(fd);
712
+ unlinkIfPresent(temporary);
713
+ }
714
+ }
715
+ function remember(state, request) {
716
+ const tuples = readRegistry(state);
717
+ if (tuples.some((tuple) => tuple.tenant === request.tenant && tuple.repository === request.repository))
718
+ return;
719
+ if (tuples.length >= 128)
720
+ fail("registry_capacity_exceeded");
721
+ tuples.push({ tenant: request.tenant, repository: request.repository });
722
+ state.custody.drop(registryFile(state));
723
+ writePrivate(state, registryFile(state), Buffer.from(canonicalDarwinThoughtsJson({
724
+ version: 1,
725
+ installationId: state.config.authority.installationId,
726
+ tuples
727
+ })), true);
728
+ }
729
+ function fresh(request, deadlineMs, ports) {
730
+ const now = ports.now();
731
+ if (!Number.isSafeInteger(deadlineMs) || deadlineMs <= now || request.issuedAtMs > now || request.expiresAtMs <= now)
732
+ fail("request_deadline_expired");
733
+ }
734
+ function makeProducer(ports) {
735
+ const producerInstance = randomBytes(32).toString("hex");
736
+ async function answer(options) {
737
+ const state = installed(options.configPath, ports);
738
+ try {
739
+ const { authority } = state.config;
740
+ canonicalPath(options.requestFile, "request_path_invalid");
741
+ let request;
742
+ try {
743
+ request = parseDarwinThoughtsRequest(parseCanonical(state.custody.read(options.requestFile, 4096), "request_invalid"));
744
+ } catch {
745
+ return fail("request_invalid");
746
+ }
747
+ fresh(request, options.deadlineMs, ports);
748
+ if (request.installationId !== authority.installationId || basename(options.requestFile) !== request.nonce + ".json")
749
+ fail("request_authority_invalid");
750
+ const targets = deriveDarwinThoughtsTargets(authority, request.tenant, request.repository);
751
+ const global = dirname(options.requestFile) === authority.requestsRoot;
752
+ if (!global && (dirname(options.requestFile) !== targets.requestSource || !readRegistry(state).some((tuple) => tuple.tenant === request.tenant && tuple.repository === request.repository)))
753
+ fail("request_channel_invalid");
754
+ const responseDirectory = global ? authority.responsesRoot : targets.responseSource;
755
+ const deadlineMs = Math.min(options.deadlineMs, request.expiresAtMs);
756
+ let response;
757
+ try {
758
+ const checkout = state.custody.walk(targets.checkoutSource, true);
759
+ const lock = state.custody.walk(targets.lockSource, true);
760
+ state.custody.walk(targets.requestSource, true, 448, true);
761
+ state.custody.walk(targets.responseSource, true, 448, true);
762
+ let git;
763
+ const gitPath = join(targets.checkoutSource, ".git");
764
+ try {
765
+ fs.lstatSync(gitPath);
766
+ git = state.custody.walk(gitPath, false, 488, false, true);
767
+ } catch (error) {
768
+ if (error.code !== "ENOENT")
769
+ throw error;
770
+ }
771
+ const recheckGit = git ? state.custody.gitMetadata(gitPath, deadlineMs) : undefined;
772
+ fresh(request, deadlineMs, ports);
773
+ const engine = await (ports.engine ?? ((input) => observeEngine(state, input, ports)))({
774
+ image: state.config.supervisorImage,
775
+ endpoint: authority.endpoint,
776
+ nonce: request.nonce,
777
+ deadlineMs,
778
+ checkoutPath: targets.checkoutSource,
779
+ lockPath: targets.lockSource
780
+ });
781
+ fresh(request, deadlineMs, ports);
782
+ state.custody.recheck();
783
+ recheckGit?.();
784
+ if (engine.daemonId !== authority.daemonId || engine.endpoint !== authority.endpoint || engine.nonce !== request.nonce || Boolean(engine.git) !== Boolean(git))
785
+ fail("engine_binding_mismatch");
786
+ response = parseDarwinThoughtsResponse({
787
+ version: 1,
788
+ kind: "accepted",
789
+ authority,
790
+ request,
791
+ observedAtMs: ports.now(),
792
+ expiresAtMs: deadlineMs,
793
+ nativeBootId: state.principal.nativeBootId,
794
+ producerInstance,
795
+ nativeCheckout: state.custody.identity(checkout),
796
+ nativeLock: state.custody.identity(lock),
797
+ engineCheckout: engine.checkout,
798
+ engineLock: engine.lock,
799
+ ...git ? { nativeGit: state.custody.identity(git), engineGit: engine.git } : {}
800
+ }, { authority, request, nowMs: ports.now() });
801
+ } catch (error) {
802
+ fresh(request, deadlineMs, ports);
803
+ response = parseDarwinThoughtsResponse({
804
+ version: 1,
805
+ kind: "refused",
806
+ authority,
807
+ request,
808
+ observedAtMs: ports.now(),
809
+ expiresAtMs: deadlineMs,
810
+ nativeBootId: state.principal.nativeBootId,
811
+ producerInstance,
812
+ reason: error instanceof ProducerError ? error.reason : "native_custody_refused"
813
+ }, { authority, request, nowMs: ports.now() });
814
+ }
815
+ if (response.kind === "refused")
816
+ state.custody.close();
817
+ const publication = installed(options.configPath, ports);
818
+ try {
819
+ if (canonicalDarwinThoughtsJson(publication.config) !== canonicalDarwinThoughtsJson(state.config))
820
+ fail("authority_descriptor_changed");
821
+ const received = publication.custody.read(options.requestFile, 4096);
822
+ if (!received.equals(Buffer.from(canonicalDarwinThoughtsJson(request))))
823
+ fail("request_descriptor_changed");
824
+ fresh(request, deadlineMs, ports);
825
+ const payload = canonicalDarwinThoughtsJson(response);
826
+ const envelope = canonicalDarwinThoughtsJson({
827
+ version: 1,
828
+ payload,
829
+ signature: sign(null, Buffer.from(payload), publication.key).toString("base64")
830
+ });
831
+ if (response.kind === "accepted")
832
+ remember(publication, request);
833
+ writePrivate(publication, join(responseDirectory, request.nonce + ".json"), Buffer.from(envelope), false, () => {
834
+ fresh(request, deadlineMs, ports);
835
+ if (response.kind === "accepted")
836
+ state.custody.recheck();
837
+ });
838
+ } finally {
839
+ publication.custody.close();
840
+ }
841
+ return {
842
+ kind: response.kind,
843
+ nonce: request.nonce,
844
+ ...response.kind === "refused" ? { reason: response.reason } : {}
845
+ };
846
+ } finally {
847
+ state.custody.close();
848
+ }
849
+ }
850
+ async function runOnce(options) {
851
+ const state = installed(options.configPath, ports);
852
+ const pending = [];
853
+ try {
854
+ if (!Number.isSafeInteger(options.deadlineMs) || options.deadlineMs <= ports.now())
855
+ fail("producer_deadline_expired");
856
+ const authority = state.config.authority;
857
+ const channels = [
858
+ { request: authority.requestsRoot, response: authority.responsesRoot },
859
+ ...readRegistry(state).map((tuple) => {
860
+ const targets = deriveDarwinThoughtsTargets(authority, tuple.tenant, tuple.repository);
861
+ return { request: targets.requestSource, response: targets.responseSource };
862
+ })
863
+ ];
864
+ for (const channel of channels) {
865
+ state.custody.walk(channel.request, false, 448, true);
866
+ state.custody.walk(channel.response, false, 448, true);
867
+ const directory = fs.opendirSync(channel.request);
868
+ try {
869
+ let entries = 0;
870
+ let entry;
871
+ while ((entry = directory.readSync()) !== null) {
872
+ if (++entries > 256 || pending.length >= 32)
873
+ fail("request_inbox_capacity_exceeded");
874
+ if (!/^[a-f0-9]{64}\.json$/.test(entry.name))
875
+ continue;
876
+ if (!entry.isFile())
877
+ fail("request_custody_unsafe");
878
+ const requestPath = join(channel.request, entry.name);
879
+ const request = parseDarwinThoughtsRequest(parseCanonical(state.custody.read(requestPath, 4096), "request_invalid"));
880
+ const targets = deriveDarwinThoughtsTargets(state.config.authority, request.tenant, request.repository);
881
+ if (request.installationId !== state.config.authority.installationId || request.nonce + ".json" !== entry.name || channel.request !== state.config.authority.requestsRoot && channel.request !== targets.requestSource)
882
+ fail("request_authority_invalid");
883
+ if (request.expiresAtMs <= ports.now() && request.issuedAtMs <= ports.now()) {
884
+ state.custody.retireExpiredRequest(requestPath);
885
+ continue;
886
+ }
887
+ const response = join(channel.response, entry.name);
888
+ let exists = true;
889
+ try {
890
+ fs.lstatSync(response);
891
+ } catch (error) {
892
+ if (error.code !== "ENOENT")
893
+ throw error;
894
+ exists = false;
895
+ }
896
+ if (exists) {
897
+ state.custody.read(response, 16384);
898
+ continue;
899
+ }
900
+ pending.push(join(channel.request, entry.name));
901
+ }
902
+ } finally {
903
+ directory.closeSync();
904
+ }
905
+ }
906
+ state.custody.recheck();
907
+ } finally {
908
+ state.custody.close();
909
+ }
910
+ let accepted = 0;
911
+ let refused = 0;
912
+ for (const requestFile of pending) {
913
+ const result = await answer({ ...options, requestFile });
914
+ if (result.kind === "accepted")
915
+ accepted++;
916
+ else
917
+ refused++;
918
+ }
919
+ return { accepted, refused };
920
+ }
921
+ return { answer, runOnce };
922
+ }
923
+ function nativePrincipal() {
924
+ if (process.platform !== "darwin" || !process.getuid || !process.geteuid || !process.getgid)
925
+ fail("native_principal_invalid");
926
+ const nativeHome = fs.realpathSync(userInfo().homedir);
927
+ const boot = execFileSync("/usr/sbin/sysctl", ["-n", "kern.boottime"], {
928
+ cwd: "/",
929
+ env: { PATH: "/usr/bin:/bin:/usr/sbin:/sbin" },
930
+ timeout: 1000,
931
+ maxBuffer: 1024,
932
+ encoding: "utf8",
933
+ stdio: ["ignore", "pipe", "ignore"]
934
+ });
935
+ if (!boot.trim())
936
+ fail("native_boot_unavailable");
937
+ return {
938
+ platform: process.platform,
939
+ uid: process.getuid(),
940
+ euid: process.geteuid(),
941
+ gid: process.getgid(),
942
+ home: nativeHome,
943
+ nativeBootId: createHash("sha256").update(boot).digest("hex")
944
+ };
945
+ }
946
+ function runDarwinThoughtsProducerOnce(options) {
947
+ return makeProducer({
948
+ principal: nativePrincipal,
949
+ now: Date.now,
950
+ nativeStat: (_path, stat) => stat
951
+ }).runOnce(options);
952
+ }
953
+ function command(executable, args, deadlineMs, now) {
954
+ const remaining = deadlineMs - now();
955
+ if (remaining <= 0)
956
+ fail("request_deadline_expired");
957
+ return new Promise((resolve, reject) => {
958
+ execFile(executable, args, {
959
+ cwd: "/",
960
+ env: { PATH: "/usr/bin:/bin:/usr/sbin:/sbin" },
961
+ timeout: remaining,
962
+ killSignal: "SIGKILL",
963
+ maxBuffer: 16384,
964
+ encoding: "utf8"
965
+ }, (error, stdout) => error ? reject(new ProducerError("engine_command_refused")) : resolve(stdout.trim()));
966
+ });
967
+ }
968
+ var ENGINE_PROGRAM = [
969
+ 'const fs=require("node:fs"),args=JSON.parse(process.argv[1]);',
970
+ 'const identity=(alias,path)=>{const s=fs.lstatSync(alias,{bigint:true});if(!s.isDirectory()||s.isSymbolicLink())throw Error("directory");return {path,device:String(s.dev),inode:String(s.ino),uid:Number(s.uid),gid:Number(s.gid),mode:Number(s.mode&4095n),isDirectory:true,isSymbolicLink:false};};',
971
+ "const t=setTimeout(()=>process.exit(124),Math.min(args.remaining,30000));t.unref();",
972
+ 'const checkout=identity("/checkout",args.checkoutPath),lock=identity("/lock",args.lockPath);',
973
+ 'for(const alias of ["/checkout","/lock"]){const d=alias+"/"+args.challengeDirectory;if(fs.readFileSync(d+"/native","utf8")!==args.nonce)throw Error("challenge");fs.writeFileSync(d+"/engine",args.nonce,{flag:"wx",mode:384});}',
974
+ 'let git;try{git=identity("/checkout/.git",args.checkoutPath+"/.git");}catch(e){if(e.code!=="ENOENT")throw e;}',
975
+ "console.log(JSON.stringify({checkout,lock,...(git?{git}:{})}));"
976
+ ].join(`
977
+ `);
978
+ async function observeEngine(state, input, ports) {
979
+ const { config, custody } = state;
980
+ const executable = config.dockerExecutable;
981
+ if (fs.realpathSync(executable) !== executable)
982
+ fail("config_executable_unsafe");
983
+ const executableFd = fs.openSync(executable, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);
984
+ let executableStat;
985
+ try {
986
+ executableStat = fs.fstatSync(executableFd, { bigint: true });
987
+ if (!executableStat.isFile() || (executableStat.mode & 0o7022n) !== 0n || (executableStat.mode & 0o111n) === 0n || executableStat.uid !== 0n && executableStat.uid !== BigInt(state.principal.uid) || executableStat.size > 256n * 1024n * 1024n || createHash("sha256").update(fs.readFileSync(executableFd)).digest("hex") !== config.dockerExecutableSha256)
988
+ fail("config_executable_unsafe");
989
+ } finally {
990
+ fs.closeSync(executableFd);
991
+ }
992
+ const dockerConfig = fs.mkdtempSync(join(dirname(state.configPath), ".docker-empty-"));
993
+ const challengeDirectory = ".catalyst-custody-" + randomBytes(16).toString("hex");
994
+ const helperName = "catalyst-custody-" + randomBytes(16).toString("hex");
995
+ const helperLabel = "dev.catalystcloud.thoughts-custody-helper";
996
+ const helperToken = config.authority.installationId + ":" + randomBytes(32).toString("hex");
997
+ const scratch = [];
998
+ let id;
999
+ let cachedImage;
1000
+ let createAttempted = false;
1001
+ const receiveHelperIdentity = (output, acknowledgedId) => {
1002
+ let parsed;
1003
+ try {
1004
+ parsed = JSON.parse(output);
1005
+ } catch {
1006
+ return fail("engine_helper_cleanup_unproved");
1007
+ }
1008
+ if (!Array.isArray(parsed) || parsed.length !== 1 || !parsed[0] || typeof parsed[0] !== "object" || Array.isArray(parsed[0]))
1009
+ fail("engine_helper_cleanup_unproved");
1010
+ const row = parsed[0];
1011
+ if (!row.Config || typeof row.Config !== "object" || Array.isArray(row.Config))
1012
+ fail("engine_helper_cleanup_unproved");
1013
+ const receivedConfig = row.Config;
1014
+ if (!receivedConfig.Labels || typeof receivedConfig.Labels !== "object" || Array.isArray(receivedConfig.Labels))
1015
+ fail("engine_helper_cleanup_unproved");
1016
+ const labels = receivedConfig.Labels;
1017
+ if (typeof row.Id !== "string" || !/^[a-f0-9]{64}$/.test(row.Id) || acknowledgedId !== undefined && row.Id !== acknowledgedId || row.Name !== "/" + helperName || row.Image !== cachedImage || receivedConfig.Image !== input.image || labels[helperLabel] !== helperToken)
1018
+ fail("engine_helper_cleanup_unproved");
1019
+ return row.Id;
1020
+ };
1021
+ const docker = async (args, deadlineMs = input.deadlineMs) => {
1022
+ if (!same(executableStat, fs.lstatSync(executable, { bigint: true })))
1023
+ fail("config_executable_changed");
1024
+ custody.recheck();
1025
+ return command(executable, ["--config", dockerConfig, "--host", input.endpoint, ...args], deadlineMs, ports.now);
1026
+ };
1027
+ let result;
1028
+ try {
1029
+ cachedImage = await docker(["image", "inspect", "--format", "{{.Id}}", input.image]);
1030
+ if (!/^sha256:[a-f0-9]{64}$/.test(cachedImage))
1031
+ fail("engine_cached_image_unavailable");
1032
+ const daemonId = await docker(["info", "--format", "{{.ID}}"]);
1033
+ if (daemonId !== config.authority.daemonId)
1034
+ fail("engine_binding_mismatch");
1035
+ for (const root of [input.checkoutPath, input.lockPath]) {
1036
+ custody.recheck();
1037
+ const path = join(root, challengeDirectory);
1038
+ fs.mkdirSync(path, { mode: 448 });
1039
+ scratch.push(path);
1040
+ custody.hold(path, true, true);
1041
+ fs.writeFileSync(join(path, "native"), input.nonce, { flag: "wx", mode: 384 });
1042
+ }
1043
+ const remaining = input.deadlineMs - ports.now();
1044
+ if (remaining <= 0)
1045
+ fail("request_deadline_expired");
1046
+ const helperArgs = canonicalDarwinThoughtsJson({
1047
+ remaining,
1048
+ nonce: input.nonce,
1049
+ challengeDirectory,
1050
+ checkoutPath: input.checkoutPath,
1051
+ lockPath: input.lockPath
1052
+ });
1053
+ createAttempted = true;
1054
+ const created = await docker([
1055
+ "create",
1056
+ "--pull=never",
1057
+ "--name",
1058
+ helperName,
1059
+ "--label",
1060
+ helperLabel + "=" + helperToken,
1061
+ "--network",
1062
+ "none",
1063
+ "--read-only",
1064
+ "--cap-drop",
1065
+ "ALL",
1066
+ "--security-opt",
1067
+ "no-new-privileges",
1068
+ "--user",
1069
+ "10001:10001",
1070
+ "--memory",
1071
+ "64m",
1072
+ "--memory-swap",
1073
+ "64m",
1074
+ "--cpus",
1075
+ "1",
1076
+ "--pids-limit",
1077
+ "32",
1078
+ "--workdir",
1079
+ "/",
1080
+ "--mount",
1081
+ "type=bind,src=" + input.checkoutPath + ",dst=/checkout",
1082
+ "--mount",
1083
+ "type=bind,src=" + input.lockPath + ",dst=/lock",
1084
+ "--entrypoint",
1085
+ "/usr/bin/timeout",
1086
+ input.image,
1087
+ "--signal=KILL",
1088
+ Math.max(1, Math.ceil(remaining / 1000)) + "s",
1089
+ "/usr/bin/env",
1090
+ "-i",
1091
+ "PATH=/usr/bin:/bin",
1092
+ "BUN_RUNTIME_TRANSPILER_CACHE_PATH=0",
1093
+ "/usr/local/bin/bun",
1094
+ "--config=/dev/null",
1095
+ "--no-env-file",
1096
+ "--cwd=/",
1097
+ "-e",
1098
+ ENGINE_PROGRAM,
1099
+ helperArgs
1100
+ ]);
1101
+ if (!/^[a-f0-9]{64}$/.test(created))
1102
+ fail("engine_helper_identity_invalid");
1103
+ id = created;
1104
+ id = receiveHelperIdentity(await docker(["inspect", helperName]), id);
1105
+ const output = await docker(["start", "--attach", id]);
1106
+ if (await docker(["inspect", "--format", "{{.State.ExitCode}}", id]) !== "0")
1107
+ fail("engine_helper_refused");
1108
+ custody.recheck();
1109
+ for (const path of scratch) {
1110
+ if (custody.read(join(path, "engine"), 128).toString("utf8") !== input.nonce)
1111
+ fail("engine_challenge_mismatch");
1112
+ }
1113
+ const parsed = JSON.parse(output);
1114
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
1115
+ fail("engine_helper_output_invalid");
1116
+ const row = parsed;
1117
+ if (Object.keys(row).some((key) => !["checkout", "lock", "git"].includes(key)))
1118
+ fail("engine_helper_output_invalid");
1119
+ result = {
1120
+ value: {
1121
+ daemonId,
1122
+ endpoint: input.endpoint,
1123
+ nonce: input.nonce,
1124
+ checkout: row.checkout,
1125
+ lock: row.lock,
1126
+ ...Object.hasOwn(row, "git") ? { git: row.git } : {}
1127
+ }
1128
+ };
1129
+ } catch (error) {
1130
+ result = { error };
1131
+ }
1132
+ let cleanupUnproved = false;
1133
+ if (createAttempted) {
1134
+ const cleanupStarted = performance.now();
1135
+ const cleanupDocker = (args) => {
1136
+ const remaining = 2000 - (performance.now() - cleanupStarted);
1137
+ if (remaining <= 0 || !same(executableStat, fs.lstatSync(executable, { bigint: true })))
1138
+ fail("engine_helper_cleanup_unproved");
1139
+ return command(executable, ["--config", dockerConfig, "--host", input.endpoint, ...args], ports.now() + Math.ceil(remaining), ports.now);
1140
+ };
1141
+ try {
1142
+ if (await cleanupDocker(["info", "--format", "{{.ID}}"]) !== config.authority.daemonId || await cleanupDocker(["image", "inspect", "--format", "{{.Id}}", input.image]) !== cachedImage)
1143
+ fail("engine_helper_cleanup_unproved");
1144
+ let received;
1145
+ for (let attempt = 0;attempt < 32; attempt++) {
1146
+ try {
1147
+ received = await cleanupDocker(["inspect", helperName]);
1148
+ break;
1149
+ } catch {
1150
+ if (id !== undefined || performance.now() - cleanupStarted >= 1900)
1151
+ throw new ProducerError("engine_helper_cleanup_unproved");
1152
+ await new Promise((resolve) => setTimeout(resolve, 25));
1153
+ }
1154
+ }
1155
+ if (received === undefined)
1156
+ fail("engine_helper_cleanup_unproved");
1157
+ id = receiveHelperIdentity(received, id);
1158
+ const list = ["ps", "--all", "--no-trunc", "--quiet", "--filter", "id=" + id];
1159
+ if (await cleanupDocker(list) !== id)
1160
+ fail("engine_helper_cleanup_unproved");
1161
+ await cleanupDocker(["rm", "--force", id]);
1162
+ if (await cleanupDocker(list) !== "")
1163
+ fail("engine_helper_cleanup_unproved");
1164
+ } catch {
1165
+ cleanupUnproved = true;
1166
+ }
1167
+ }
1168
+ for (const path of scratch) {
1169
+ custody.drop(join(path, "engine"));
1170
+ custody.drop(path);
1171
+ for (const file of ["native", "engine"]) {
1172
+ unlinkIfPresent(join(path, file));
1173
+ }
1174
+ fs.rmdirSync(path);
1175
+ }
1176
+ fs.rmdirSync(dockerConfig);
1177
+ if (cleanupUnproved)
1178
+ fail("engine_helper_cleanup_unproved");
1179
+ if ("error" in result)
1180
+ throw result.error;
1181
+ return result.value;
1182
+ }
1183
+
1184
+ // deploy/self-host/darwin-thoughts-custody/producer-entry.ts
1185
+ if (process.argv.length !== 4 || !/^[1-9][0-9]{12,15}$/.test(process.argv[3] ?? "")) {
1186
+ process.stderr.write(`darwin_thoughts_producer:arguments_invalid
1187
+ `);
1188
+ process.exitCode = 1;
1189
+ } else {
1190
+ try {
1191
+ const result = await runDarwinThoughtsProducerOnce({
1192
+ configPath: process.argv[2],
1193
+ deadlineMs: Number(process.argv[3])
1194
+ });
1195
+ process.stdout.write(JSON.stringify(result) + `
1196
+ `);
1197
+ } catch {
1198
+ process.stderr.write(`darwin_thoughts_producer:refused
1199
+ `);
1200
+ process.exitCode = 1;
1201
+ }
1202
+ }