threadwire 0.1.6 → 0.1.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.
@@ -0,0 +1,982 @@
1
+ // @ts-nocheck
2
+ /* eslint-disable jsdoc/require-jsdoc */
3
+
4
+ import {randomBytes} from "node:crypto"
5
+ import {lstat, realpath} from "node:fs/promises"
6
+ import {createServer} from "node:http"
7
+ import {isAbsolute, join, normalize, relative} from "node:path"
8
+ import {DockerApi} from "./docker-api.js"
9
+ import {buildWorkerContainerSpec, isDigestImage} from "./isolated-worker.js"
10
+ import {validateRelayWriteProviderArguments} from "./relay-write.js"
11
+ import {codexSessionId, parseCodexEvent} from "./providers/codex.js"
12
+ import {openStateRegistry, validateStateVolume} from "./isolated-state.js"
13
+ import {assertNoNestedMounts} from "./mount-policy.js"
14
+ import {AbsoluteDeadline, deadlineAfter} from "./absolute-deadline.js"
15
+
16
+ const MAX_PREFLIGHT_BYTES = 32_768
17
+ const MAX_RUN_BYTES = 1_048_576
18
+ const PREFLIGHT_TTL_MS = 60_000
19
+ const PREFLIGHT_CAPACITY = 128
20
+ const PREFLIGHT_TASK_CAPACITY = 8
21
+ const GC_INTERVAL_MS = 5_000
22
+ const ACTIVE_RUN_CAPACITY = 16
23
+ const ACTIVE_TASK_CAPACITY = 2
24
+ const WORKER_TIMEOUT_MS = 3_600_000
25
+ const PREFLIGHT_TIMEOUT_MS = 30_000
26
+ const MAX_RAW_OUTPUT_BYTES = 1_048_576
27
+
28
+ /** @param {{environment?: NodeJS.ProcessEnv, docker?: DockerApi, fetchImplementation?: typeof fetch, now?: () => number}} [options] */
29
+ export async function startIsolatedRuntime(options = {}) {
30
+ const environment = options.environment ?? process.env
31
+ const host = environment.THREADWIRE_ISOLATED_RUNTIME_HOST ?? "0.0.0.0"
32
+ const port = portValue(environment.THREADWIRE_ISOLATED_RUNTIME_PORT, 8790)
33
+ const controlToken = safeSetting(environment.THREADWIRE_ISOLATED_RUNTIME_CONTROL_TOKEN, "THREADWIRE_ISOLATED_RUNTIME_CONTROL_TOKEN")
34
+ const workerImage = safeSetting(environment.THREADWIRE_RELAY_WORKER_IMAGE, "THREADWIRE_RELAY_WORKER_IMAGE")
35
+ if (!isDigestImage(workerImage)) throw new Error("THREADWIRE_RELAY_WORKER_IMAGE must use an immutable digest")
36
+ const brokerUrl = normalizedHttpUrl(environment.THREADWIRE_MODEL_BROKER_URL, "THREADWIRE_MODEL_BROKER_URL")
37
+ const brokerAdminToken = safeSetting(environment.THREADWIRE_MODEL_BROKER_ADMIN_TOKEN, "THREADWIRE_MODEL_BROKER_ADMIN_TOKEN")
38
+ const brokerContainer = safeSetting(environment.THREADWIRE_MODEL_BROKER_CONTAINER, "THREADWIRE_MODEL_BROKER_CONTAINER")
39
+ const allowedRoots = parseAllowedRoots(environment.THREADWIRE_ALLOWED_WORKTREE_ROOTS)
40
+ const worktreeVolume = environment.THREADWIRE_WORKTREE_VOLUME
41
+ const sessionTtlMs = positiveDuration(environment.THREADWIRE_SESSION_TTL_MS, 86_400_000)
42
+ const workerTimeoutMs = positiveDuration(environment.THREADWIRE_WORKER_TIMEOUT_MS, WORKER_TIMEOUT_MS)
43
+ const preflightTimeoutMs = positiveDuration(environment.THREADWIRE_PREFLIGHT_TIMEOUT_MS, PREFLIGHT_TIMEOUT_MS)
44
+ const docker = options.docker ?? new DockerApi()
45
+ const fetchImplementation = options.fetchImplementation ?? fetch
46
+ const now = options.now ?? Date.now
47
+ const allowedModels = parseAllowedModels(environment.THREADWIRE_ALLOWED_CODEX_MODELS)
48
+ const stateRegistry = await openStateRegistry({
49
+ file: safeSetting(environment.THREADWIRE_STATE_REGISTRY_FILE, "THREADWIRE_STATE_REGISTRY_FILE"),
50
+ key: safeSetting(environment.THREADWIRE_STATE_AUTH_KEY, "THREADWIRE_STATE_AUTH_KEY"),
51
+ namespace: safeSetting(environment.THREADWIRE_STATE_NAMESPACE, "THREADWIRE_STATE_NAMESPACE"),
52
+ now
53
+ })
54
+ const preflights = new PreflightStore({
55
+ now,
56
+ ttlMs: options.preflightTtlMs ?? PREFLIGHT_TTL_MS,
57
+ capacity: options.preflightCapacity ?? PREFLIGHT_CAPACITY,
58
+ taskCapacity: options.preflightTaskCapacity ?? PREFLIGHT_TASK_CAPACITY
59
+ })
60
+ const activeLineages = new LineageReservations()
61
+ const activeRuns = new ActiveRunAdmission({
62
+ capacity: positiveInteger(environment.THREADWIRE_ACTIVE_RUN_CAPACITY, ACTIVE_RUN_CAPACITY),
63
+ taskCapacity: positiveInteger(environment.THREADWIRE_ACTIVE_TASK_CAPACITY, ACTIVE_TASK_CAPACITY)
64
+ })
65
+ const incomingRequests = new ActiveRunAdmission({capacity: ACTIVE_RUN_CAPACITY, taskCapacity: ACTIVE_RUN_CAPACITY})
66
+ const shutdown = new AbortController()
67
+ const sockets = new Set()
68
+ let stopping = false
69
+ let gcPromise = Promise.resolve()
70
+ const collectState = () => {
71
+ gcPromise = gcPromise.then(async () => {
72
+ if (shutdown.signal.aborted) return
73
+ const collection = deadlineAfter(Math.min(30_000, workerTimeoutMs), {signal: shutdown.signal, timeoutMessage: "Isolated runtime collection timeout"})
74
+ const releaseCollection = activeLineages.beginCollection()
75
+ try {
76
+ const active = new Set(activeLineages.values())
77
+ const current = {
78
+ *[Symbol.iterator]() { yield * active },
79
+ has(lineage) { return active.has(lineage) || activeLineages.has(lineage) }
80
+ }
81
+ for (const lineage of await reconcileDockerResources(docker, brokerContainer, stateRegistry, current, collection.options())) active.add(lineage)
82
+ await stateRegistry.collect(docker, {has: (lineage) => active.has(lineage) || activeLineages.has(lineage)}, collection.options())
83
+ } finally {
84
+ collection.close()
85
+ releaseCollection()
86
+ }
87
+ }).catch(() => {})
88
+ return gcPromise
89
+ }
90
+ const startupActive = await reconcileDockerResources(docker, brokerContainer, stateRegistry, new Set())
91
+ await stateRegistry.collect(docker, new Set(startupActive))
92
+ const gcTimer = setInterval(collectState, Math.min(GC_INTERVAL_MS, sessionTtlMs))
93
+ gcTimer.unref()
94
+
95
+ const server = createServer(async (request, response) => {
96
+ try {
97
+ if (stopping) throw new Error("Isolated runtime is shutting down")
98
+ requireControl(request.headers.authorization, controlToken)
99
+ if (request.method === "GET" && request.url === "/healthz") {
100
+ sendJson(response, 200, {ok: true})
101
+ return
102
+ }
103
+ if (request.method === "POST" && request.url === "/preflight") {
104
+ const releaseIncoming = incomingRequests.acquire("preflight")
105
+ const launchDeadlineAt = requestedDeadline(request.headers["x-threadwire-launch-deadline"], workerTimeoutMs)
106
+ const operation = new AbsoluteDeadline(Math.min(Date.now() + preflightTimeoutMs, launchDeadlineAt), {
107
+ signal: shutdown.signal, request, response, timeoutMessage: "Isolated runtime operation timed out", disconnectMessage: "Isolated runtime caller disconnected"
108
+ })
109
+ try {
110
+ const body = await readJson(request, MAX_PREFLIGHT_BYTES, operation.signal)
111
+ const selection = parsePreflight(body)
112
+ const task = taskIdentity(selection)
113
+ preflights.assertCapacity(task)
114
+ let codexArguments
115
+ try {
116
+ codexArguments = validateRelayWriteProviderArguments(selection.providerArguments)
117
+ } catch (error) {
118
+ throw new ClientError(error instanceof Error ? error.message : "Provider argument is unavailable in relay write mode")
119
+ }
120
+ if (!allowedModels.has(codexArguments.model)) throw new ClientError("Codex model is not allowed")
121
+ const {fingerprint, root: worktreeRoot} = await verifyPrerequisites({
122
+ docker, workerImage, selection, allowedRoots, brokerUrl, brokerAdminToken, fetchImplementation, operation
123
+ })
124
+ let state
125
+ if (selection.resumeSession !== undefined) {
126
+ state = stateRegistry.lookup(selection.resumeSession)
127
+ if (!state || state.task !== task) throw new ClientError("Codex resume state is unavailable")
128
+ const volume = await docker.inspectVolume(state.volume, operation.options()).catch(() => undefined)
129
+ try { validateStateVolume(volume, state.volume, state.labels) } catch { throw new ClientError("Codex resume state is unavailable") }
130
+ } else state = stateRegistry.allocate(task)
131
+ const preflightId = randomBytes(24).toString("base64url")
132
+ preflights.add(preflightId, task, {...selection, codexArguments, state, fingerprint, worktreeRoot, launchDeadlineAt})
133
+ sendJson(response, 200, {ok: true, preflightId, launchDeadlineAt})
134
+ } finally {
135
+ operation.close()
136
+ releaseIncoming()
137
+ }
138
+ return
139
+ }
140
+ if (request.method === "POST" && request.url === "/run") {
141
+ const releaseIncoming = incomingRequests.acquire("run")
142
+ const bodyOperation = new AbsoluteDeadline(Date.now() + preflightTimeoutMs, {signal: shutdown.signal, request, response, timeoutMessage: "Isolated runtime operation timed out"})
143
+ let body
144
+ try {
145
+ body = parseRun(await readJson(request, MAX_RUN_BYTES, bodyOperation.signal))
146
+ } finally {
147
+ bodyOperation.close()
148
+ releaseIncoming()
149
+ }
150
+ const preflight = preflights.consume(body.preflightId)
151
+ if (!preflight) throw new ClientError("Isolated runtime preflight expired")
152
+ const operation = new AbsoluteDeadline(Math.min(preflight.launchDeadlineAt,
153
+ requestedDeadline(request.headers["x-threadwire-launch-deadline"], workerTimeoutMs)), {
154
+ signal: shutdown.signal, request, response, timeoutMessage: "Isolated runtime launch timed out", disconnectMessage: "Isolated runtime caller disconnected"
155
+ })
156
+ const task = taskIdentity(preflight)
157
+ let releaseRun
158
+ let releaseLineage
159
+ try {
160
+ releaseRun = activeRuns.acquire(task)
161
+ releaseLineage = activeLineages.acquire(preflight.state.lineage)
162
+ if (body.resumeSession !== preflight.resumeSession) throw new ClientError("Codex resume state does not match preflight")
163
+ if (JSON.stringify(validateRelayWriteProviderArguments(body.providerArguments)) !== JSON.stringify(preflight.codexArguments)) {
164
+ throw new ClientError("Codex arguments do not match preflight")
165
+ }
166
+ await revalidateFingerprint(preflight.fingerprint)
167
+ operation.throwIfAborted()
168
+ const result = await runIsolatedWorker({
169
+ docker, workerImage, brokerUrl, brokerAdminToken, brokerContainer,
170
+ fetchImplementation, preflight, ...body, task, now, stateRegistry, sessionTtlMs, operation,
171
+ ...(worktreeVolume === undefined ? {} : {worktreeVolume})
172
+ })
173
+ sendJson(response, 200, result)
174
+ } finally {
175
+ operation.close()
176
+ releaseLineage?.()
177
+ releaseRun?.()
178
+ void collectState()
179
+ }
180
+ return
181
+ }
182
+ response.writeHead(404)
183
+ response.end()
184
+ } catch (error) {
185
+ sendJson(response, error instanceof ClientError ? 400 : 503, {
186
+ error: error instanceof ClientError ? error.message : "Isolated runtime unavailable"
187
+ })
188
+ }
189
+ })
190
+ server.on("connection", (socket) => {
191
+ sockets.add(socket)
192
+ socket.once("close", () => sockets.delete(socket))
193
+ })
194
+ await listen(server, port, host)
195
+ return {
196
+ server,
197
+ close: async () => {
198
+ stopping = true
199
+ clearInterval(gcTimer)
200
+ preflights.close()
201
+ shutdown.abort(new Error("Isolated runtime is shutting down"))
202
+ for (const socket of sockets) socket.destroy()
203
+ await boundedClose(server, 1000)
204
+ await Promise.race([gcPromise, new Promise((resolve) => setTimeout(resolve, 1000))])
205
+ },
206
+ config: {host, port}
207
+ }
208
+ }
209
+
210
+ async function verifyPrerequisites(options) {
211
+ const {docker, workerImage, selection, allowedRoots, brokerUrl, brokerAdminToken, fetchImplementation, operation} = options
212
+ const version = /** @type {{ApiVersion?: unknown}} */ (await docker.version(operation.options()))
213
+ if (typeof version.ApiVersion !== "string") throw new Error("Docker API unavailable")
214
+ const image = /** @type {{Id?: unknown}} */ (await docker.inspectImage(workerImage, operation.options()))
215
+ if (typeof image.Id !== "string" || !isDigestImage(image.Id)) throw new Error("Worker image unavailable")
216
+ const validatedWorktree = await validateWorktreeSelection(selection.repositoryRoot, selection.cwd, allowedRoots)
217
+ const health = await abortable(fetchImplementation(new URL("/healthz", brokerUrl), {
218
+ method: "GET",
219
+ redirect: "error",
220
+ signal: operation.signal,
221
+ headers: {authorization: `Bearer ${brokerAdminToken}`}
222
+ }), operation.signal)
223
+ if (!health.ok) throw new Error("Model broker unavailable")
224
+ return validatedWorktree
225
+ }
226
+
227
+ export async function validateWorktree(repositoryRoot, cwd, allowedRoots) {
228
+ return (await validateWorktreeSelection(repositoryRoot, cwd, allowedRoots)).fingerprint
229
+ }
230
+
231
+ export async function validateWorktreeSelection(repositoryRoot, cwd, allowedRoots) {
232
+ const root = allowedRoots
233
+ .filter((allowed) => within(allowed, repositoryRoot))
234
+ .sort((first, second) => second.length - first.length)[0]
235
+ if (root === undefined) throw new ClientError("Configured worktree is unavailable")
236
+ const paths = ancestry(root, repositoryRoot)
237
+ for (const path of ancestry(repositoryRoot, cwd).slice(1)) if (!paths.includes(path)) paths.push(path)
238
+ /** @type {{path: string, dev: string, ino: string}[]} */
239
+ const fingerprint = []
240
+ for (const path of paths) {
241
+ if (!isAbsolute(path) || normalize(path) !== path || path === "/") throw new ClientError("Configured worktree is unavailable")
242
+ const metadata = await lstat(path, {bigint: true})
243
+ if (!metadata.isDirectory() || metadata.isSymbolicLink() || await realpath(path) !== path) {
244
+ throw new ClientError("Configured worktree is unavailable")
245
+ }
246
+ fingerprint.push({path, dev: String(metadata.dev), ino: String(metadata.ino)})
247
+ }
248
+ if (!within(repositoryRoot, cwd) || !allowedRoots.some((allowed) => within(allowed, repositoryRoot))) {
249
+ throw new ClientError("Configured worktree is unavailable")
250
+ }
251
+ await assertNoNestedMounts(repositoryRoot)
252
+ try {
253
+ const gitEntry = await lstat(join(repositoryRoot, ".git"))
254
+ if (gitEntry.isDirectory()) throw new ClientError("Common Git directories cannot enter the worker")
255
+ if (!gitEntry.isFile() || gitEntry.isSymbolicLink()) throw new ClientError("Configured worktree is unavailable")
256
+ } catch (error) {
257
+ if (error instanceof ClientError) throw error
258
+ if (/** @type {NodeJS.ErrnoException} */ (error).code !== "ENOENT") throw error
259
+ }
260
+ return {fingerprint, root}
261
+ }
262
+
263
+ export async function revalidateFingerprint(fingerprint) {
264
+ if (!Array.isArray(fingerprint)) throw new ClientError("Configured worktree changed after preflight")
265
+ for (const expected of fingerprint) {
266
+ const metadata = await lstat(expected.path, {bigint: true}).catch(() => undefined)
267
+ if (!metadata?.isDirectory() || metadata.isSymbolicLink() || String(metadata.dev) !== expected.dev || String(metadata.ino) !== expected.ino || await realpath(expected.path) !== expected.path) {
268
+ throw new ClientError("Configured worktree changed after preflight")
269
+ }
270
+ }
271
+ }
272
+
273
+ export async function runIsolatedWorker(options) {
274
+ const runId = `tw-${randomBytes(12).toString("hex")}`
275
+ const networkName = `${runId}-net`
276
+ const state = options.preflight.state
277
+ const freshState = options.resumeSession === undefined
278
+ let keepFreshState = false
279
+ let networkId
280
+ let containerId
281
+ let grantToken
282
+ let runTracked = false
283
+ const operation = options.operation
284
+ const worktreeSubpath = options.worktreeVolume === undefined
285
+ ? ""
286
+ : deriveVolumeWorktreeSubpath(options.preflight.worktreeRoot, options.preflight.repositoryRoot)
287
+ try {
288
+ operation.throwIfAborted()
289
+ await prepareStateVolume(options.docker, state, freshState, operation.options())
290
+ if (freshState) await options.stateRegistry.track(state, operation.signal)
291
+ const runIdentity = expectedRunIdentity(options, runId, networkName, state, worktreeSubpath)
292
+ const runSeal = options.stateRegistry.sealRun(runIdentity)
293
+ await options.stateRegistry.trackRun(runIdentity, operation.signal)
294
+ runTracked = true
295
+ const resourceLabels = {
296
+ "org.threadwire.namespace": options.stateRegistry.namespace,
297
+ "org.threadwire.run": runId,
298
+ "org.threadwire.lineage": state.lineage,
299
+ "org.threadwire.task": state.labels["org.threadwire.task"],
300
+ "org.threadwire.state-volume": state.volume,
301
+ "org.threadwire.run-seal": runSeal
302
+ }
303
+ const network = /** @type {{Id?: unknown}} */ (await options.docker.createNetwork(networkName, resourceLabels, operation.options()))
304
+ if (typeof network.Id !== "string") throw new Error("Docker network creation failed")
305
+ networkId = network.Id
306
+ await options.docker.connectNetwork(networkId, options.brokerContainer, [], operation.options())
307
+ const networkInspection = await options.docker.inspectNetwork(networkId, operation.options())
308
+ const brokerAddress = brokerNetworkAddress(networkInspection, options.brokerContainer)
309
+ const grantResponse = await abortable(options.fetchImplementation(new URL("/admin/grants", options.brokerUrl), {
310
+ method: "POST",
311
+ redirect: "error",
312
+ signal: operation.signal,
313
+ headers: {authorization: `Bearer ${options.brokerAdminToken}`, "content-type": "application/json"},
314
+ body: JSON.stringify({runId, provider: "codex", networkId, model: options.preflight.codexArguments.model, brokerAddress, ttlMs: Math.min(operation.remaining(), 3_600_000)})
315
+ }), operation.signal)
316
+ if (!grantResponse.ok) throw new Error("Model broker grant failed")
317
+ const grant = await grantResponse.json()
318
+ if (!isRecord(grant) || typeof grant.token !== "string" || !Number.isSafeInteger(grant.port)) throw new Error("Model broker grant failed")
319
+ grantToken = grant.token
320
+ const repository = /** @type {{path: string, ino: string}[]} */ (options.preflight.fingerprint)
321
+ const worktreeMetadata = repository.find((entry) => entry.path === options.preflight.repositoryRoot)
322
+ const cwdMetadata = repository.find((entry) => entry.path === options.preflight.cwd)
323
+ if (worktreeMetadata === undefined || cwdMetadata === undefined) throw new Error("Worktree fingerprint unavailable")
324
+ const spec = buildWorkerContainerSpec({
325
+ image: options.workerImage,
326
+ worktree: options.preflight.repositoryRoot,
327
+ networkName,
328
+ brokerToken: grantToken,
329
+ brokerUrl: `http://${brokerAddress}:${grant.port}/v1`,
330
+ prompt: options.prompt,
331
+ providerArguments: options.preflight.codexArguments.arguments,
332
+ stateVolume: state.volume,
333
+ workingDirectory: `/worktree${relative(options.preflight.repositoryRoot, options.preflight.cwd) === "" ? "" : `/${relative(options.preflight.repositoryRoot, options.preflight.cwd)}`}`,
334
+ worktreeInode: worktreeMetadata.ino,
335
+ cwdInode: cwdMetadata.ino,
336
+ lineage: state.lineage,
337
+ namespace: options.stateRegistry.namespace,
338
+ runId,
339
+ taskHash: state.labels["org.threadwire.task"],
340
+ runSeal,
341
+ ...(options.worktreeVolume === undefined
342
+ ? {}
343
+ : {
344
+ worktreeVolume: {
345
+ name: options.worktreeVolume,
346
+ subpath: worktreeSubpath
347
+ }
348
+ }),
349
+ ...(options.resumeSession === undefined ? {} : {resumeSession: options.resumeSession})
350
+ })
351
+ const container = /** @type {{Id?: unknown}} */ (await options.docker.createContainer(`${runId}-worker`, spec, operation.options()))
352
+ if (typeof container.Id !== "string") throw new Error("Docker worker creation failed")
353
+ containerId = container.Id
354
+ await revalidateFingerprint(options.preflight.fingerprint)
355
+ await validateWorkerMountInventory(await options.docker.inspectContainer(containerId, operation.options()), spec.HostConfig.Mounts)
356
+ const activationResponse = await abortable(options.fetchImplementation(
357
+ new URL(`/admin/grants/${encodeURIComponent(grantToken)}/activate`, options.brokerUrl), {
358
+ method: "POST",
359
+ redirect: "error",
360
+ signal: operation.signal,
361
+ headers: {authorization: `Bearer ${options.brokerAdminToken}`}
362
+ }), operation.signal)
363
+ if (!activationResponse.ok) throw new Error("Model broker grant activation failed")
364
+ await options.docker.startContainer(containerId, operation.options())
365
+ const wait = /** @type {{StatusCode?: unknown}} */ (await options.docker.waitContainer(containerId, operation.options()))
366
+ const logs = /** @type {Buffer} */ (await options.docker.logs(containerId, operation.options()))
367
+ const rawChunks = demultiplexDockerLogChunks(logs)
368
+ const result = {
369
+ exitCode: typeof wait.StatusCode === "number" ? wait.StatusCode : 1,
370
+ records: parseWorkerRecords(Buffer.concat(rawChunks.filter((chunk) => chunk.channel === "stdout").map((chunk) => chunk.data)).toString("utf8")),
371
+ rawChunks: rawChunks.map((chunk) => ({channel: chunk.channel, data: chunk.data.toString("base64")}))
372
+ }
373
+ if (freshState && result.exitCode === 0) {
374
+ const sessionIds = [...new Set(result.records.filter((record) => record.type === "session").map((record) => record.sessionId))]
375
+ if (sessionIds.length === 0) throw new Error("Codex session state was not established")
376
+ await options.stateRegistry.register(sessionIds, state, options.sessionTtlMs, operation.signal)
377
+ keepFreshState = true
378
+ }
379
+ return result
380
+ } finally {
381
+ let resourcesRemoved = true
382
+ // A caller/deadline abort cannot authorize more work, but exact force
383
+ // teardown must remain possible. This supervisor-only emergency budget is
384
+ // bounded and is used solely for already-recorded resource identifiers.
385
+ const emergencyCleanup = operation.signal.aborted
386
+ ? deadlineAfter(5_000, {timeoutMessage: "Isolated runtime emergency cleanup timeout"})
387
+ : undefined
388
+ const cleanupOperation = emergencyCleanup ?? operation
389
+ const cleanupOptions = () => cleanupOperation.options()
390
+ if (grantToken !== undefined) {
391
+ await abortable(options.fetchImplementation(new URL(`/admin/grants/${encodeURIComponent(grantToken)}`, options.brokerUrl), {
392
+ method: "DELETE",
393
+ signal: cleanupOperation.signal,
394
+ headers: {authorization: `Bearer ${options.brokerAdminToken}`}
395
+ }), cleanupOperation.signal).catch(() => process.stderr.write("threadwire-isolated-runtime: grant cleanup failed\n"))
396
+ }
397
+ if (containerId !== undefined) await cleanupDocker(() => options.docker.removeContainer(containerId, cleanupOptions())).catch(() => {
398
+ resourcesRemoved = false
399
+ process.stderr.write("threadwire-isolated-runtime: worker cleanup failed\n")
400
+ })
401
+ if (networkId !== undefined) {
402
+ await cleanupDocker(() => options.docker.disconnectNetwork(networkId, options.brokerContainer, cleanupOptions())).catch(() => {})
403
+ await cleanupDocker(() => options.docker.removeNetwork(networkId, cleanupOptions())).catch(() => {
404
+ resourcesRemoved = false
405
+ process.stderr.write("threadwire-isolated-runtime: network cleanup failed\n")
406
+ })
407
+ }
408
+ if (freshState && !keepFreshState) await cleanupDocker(() => options.docker.removeVolume(state.volume, cleanupOptions())).catch(() => { resourcesRemoved = false })
409
+ if (runTracked && resourcesRemoved) await options.stateRegistry.completeRun(runId, cleanupOperation.signal).catch(() => {})
410
+ emergencyCleanup?.close()
411
+ }
412
+ }
413
+
414
+ async function cleanupDocker(operation) {
415
+ return operation()
416
+ }
417
+
418
+ export async function prepareStateVolume(docker, state, fresh, requestOptions) {
419
+ if (fresh) await docker.createVolume(state.volume, state.labels, requestOptions)
420
+ const volume = await docker.inspectVolume(state.volume, requestOptions).catch(() => undefined)
421
+ try {
422
+ validateStateVolume(volume, state.volume, state.labels)
423
+ } catch {
424
+ throw new ClientError(fresh ? "Codex state volume collision" : "Codex resume state is unavailable")
425
+ }
426
+ }
427
+
428
+ export function validateWorkerMountInventory(container, expected) {
429
+ if (!isRecord(container) || !Array.isArray(container.Mounts) || container.Mounts.length !== expected.length) {
430
+ throw new Error("Worker mount topology unavailable")
431
+ }
432
+ for (const mount of expected) {
433
+ const actual = container.Mounts.find((entry) => isRecord(entry) && entry.Destination === mount.Target)
434
+ const sourceMatches = mount.Type === "volume" ? actual?.Name === mount.Source : actual?.Source === mount.Source
435
+ if (!actual || actual.Type !== mount.Type || !sourceMatches || actual.RW !== !mount.ReadOnly) {
436
+ throw new Error("Worker mount topology unavailable")
437
+ }
438
+ }
439
+ }
440
+
441
+ function parseWorkerRecords(text) {
442
+ const records = []
443
+ for (const line of text.split("\n")) {
444
+ if (line.trim().length === 0) continue
445
+ try {
446
+ const record = JSON.parse(line)
447
+ if (isRecord(record)) {
448
+ records.push(record)
449
+ if (record.type !== "worker-event") {
450
+ const sessionId = codexSessionId(record)
451
+ if (sessionId !== undefined) records.push({type: "session", sessionId})
452
+ for (const event of parseCodexEvent(record)) records.push({type: "worker-event", event})
453
+ }
454
+ }
455
+ } catch {
456
+ records.push({type: "worker-event", event: {type: "diagnostic", level: "warning", summary: "Worker emitted an unreadable event"}})
457
+ }
458
+ }
459
+ return records
460
+ }
461
+
462
+ export function demultiplexDockerLogs(buffer) {
463
+ return Buffer.concat(demultiplexDockerLogChunks(buffer).map((chunk) => chunk.data)).toString("utf8")
464
+ }
465
+
466
+ export function demultiplexDockerLogChunks(buffer) {
467
+ let offset = 0
468
+ const output = []
469
+ let bytes = 0
470
+ while (offset + 8 <= buffer.length) {
471
+ const stream = buffer[offset]
472
+ const length = buffer.readUInt32BE(offset + 4)
473
+ if ((stream !== 1 && stream !== 2) || offset + 8 + length > buffer.length) throw new Error("Worker emitted invalid Docker logs")
474
+ bytes += length
475
+ if (bytes > MAX_RAW_OUTPUT_BYTES) throw new Error("Worker output exceeded capacity")
476
+ output.push({channel: stream === 1 ? "stdout" : "stderr", data: buffer.subarray(offset + 8, offset + 8 + length)})
477
+ offset += 8 + length
478
+ }
479
+ if (offset === buffer.length && output.length > 0) return output
480
+ if (buffer.length > MAX_RAW_OUTPUT_BYTES) throw new Error("Worker output exceeded capacity")
481
+ return [{channel: "stdout", data: buffer}]
482
+ }
483
+
484
+ export function parsePreflight(value) {
485
+ if (!isRecord(value) || value.provider !== "codex" || typeof value.profile !== "string" || typeof value.repositoryRoot !== "string" || typeof value.cwd !== "string" || !Array.isArray(value.providerArguments) || !value.providerArguments.every((item) => typeof item === "string")) {
486
+ throw new ClientError("Invalid isolated runtime preflight")
487
+ }
488
+ if (!bounded(value.profile, 128) || !bounded(value.repositoryRoot, 4096) || !bounded(value.cwd, 4096)
489
+ || value.providerArguments.length > 16 || value.providerArguments.some((item) => !bounded(item, 512))
490
+ || (value.resumeSession !== undefined && !bounded(value.resumeSession, 256))) {
491
+ throw new ClientError("Invalid isolated runtime preflight")
492
+ }
493
+ if (value.resumeSession !== undefined && (typeof value.resumeSession !== "string" || /[\r\n]/u.test(value.resumeSession))) throw new ClientError("Invalid isolated runtime preflight")
494
+ return {
495
+ profile: value.profile,
496
+ repositoryRoot: value.repositoryRoot,
497
+ cwd: value.cwd,
498
+ providerArguments: value.providerArguments,
499
+ ...(value.resumeSession === undefined ? {} : {resumeSession: value.resumeSession})
500
+ }
501
+ }
502
+
503
+ export function parseRun(value) {
504
+ if (!isRecord(value) || typeof value.preflightId !== "string" || typeof value.prompt !== "string" || value.prompt.trim().length === 0 || !Array.isArray(value.providerArguments) || !value.providerArguments.every((item) => typeof item === "string")) {
505
+ throw new ClientError("Invalid isolated runtime run")
506
+ }
507
+ if (!bounded(value.preflightId, 64) || !bounded(value.prompt, 524_288)
508
+ || value.providerArguments.length > 16 || value.providerArguments.some((item) => !bounded(item, 512))
509
+ || (value.resumeSession !== undefined && !bounded(value.resumeSession, 256))) {
510
+ throw new ClientError("Invalid isolated runtime run")
511
+ }
512
+ try {
513
+ validateRelayWriteProviderArguments(value.providerArguments)
514
+ } catch (error) {
515
+ throw new ClientError(error instanceof Error ? error.message : "Provider argument is unavailable in relay write mode")
516
+ }
517
+ if (value.resumeSession !== undefined && (typeof value.resumeSession !== "string" || /[\r\n]/u.test(value.resumeSession))) throw new ClientError("Invalid isolated runtime run")
518
+ return {
519
+ preflightId: value.preflightId,
520
+ prompt: value.prompt,
521
+ providerArguments: value.providerArguments,
522
+ ...(value.resumeSession === undefined ? {} : {resumeSession: value.resumeSession})
523
+ }
524
+ }
525
+
526
+ function requestedDeadline(value, maximumMs) {
527
+ const parsed = Number(value)
528
+ const maximum = Date.now() + maximumMs
529
+ return Number.isSafeInteger(parsed) && parsed > Date.now() ? Math.min(parsed, maximum) : maximum
530
+ }
531
+
532
+ function parseAllowedRoots(value) {
533
+ let roots
534
+ try {
535
+ roots = JSON.parse(safeSetting(value, "THREADWIRE_ALLOWED_WORKTREE_ROOTS"))
536
+ } catch {
537
+ throw new Error("THREADWIRE_ALLOWED_WORKTREE_ROOTS must be a JSON array")
538
+ }
539
+ if (!Array.isArray(roots) || roots.length === 0 || !roots.every((root) => typeof root === "string" && isAbsolute(root) && normalize(root) === root && root !== "/")) {
540
+ throw new Error("THREADWIRE_ALLOWED_WORKTREE_ROOTS must contain normalized absolute paths")
541
+ }
542
+ return roots
543
+ }
544
+
545
+ function within(root, child) {
546
+ const path = relative(root, child)
547
+ return path === "" || (!path.startsWith("..") && !isAbsolute(path))
548
+ }
549
+
550
+ function ancestry(root, child) {
551
+ const remainder = relative(root, child)
552
+ const paths = [root]
553
+ let current = root
554
+ if (remainder === "") return paths
555
+ for (const component of remainder.split("/")) {
556
+ current = `${current}/${component}`
557
+ paths.push(current)
558
+ }
559
+ return paths
560
+ }
561
+
562
+ function taskIdentity(preflight) {
563
+ return `${preflight.profile}\0${preflight.repositoryRoot}`
564
+ }
565
+
566
+ function brokerNetworkAddress(value, containerName) {
567
+ if (!isRecord(value) || !isRecord(value.Containers)) throw new Error("Broker network identity unavailable")
568
+ for (const [id, endpoint] of Object.entries(value.Containers)) {
569
+ if (!isRecord(endpoint)) continue
570
+ if (id === containerName || endpoint.Name === containerName) {
571
+ const address = endpoint.IPv4Address
572
+ if (typeof address !== "string" || !/^(?:\d{1,3}\.){3}\d{1,3}\/\d{1,2}$/u.test(address)) break
573
+ return address.split("/")[0]
574
+ }
575
+ }
576
+ throw new Error("Broker network identity unavailable")
577
+ }
578
+
579
+ async function readJson(request, capacity, signal) {
580
+ const chunks = []
581
+ let bytes = 0
582
+ for await (const chunk of request) {
583
+ if (signal?.aborted) throw signal.reason
584
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)
585
+ bytes += buffer.length
586
+ if (bytes > capacity) throw new ClientError("Request exceeded capacity")
587
+ chunks.push(buffer)
588
+ }
589
+ if (signal?.aborted) throw signal.reason
590
+ try {
591
+ return JSON.parse(Buffer.concat(chunks).toString("utf8"))
592
+ } catch {
593
+ throw new ClientError("Invalid request")
594
+ }
595
+ }
596
+
597
+ function requireControl(value, expected) {
598
+ if (value !== `Bearer ${expected}`) throw new ClientError("Request denied")
599
+ }
600
+
601
+ function normalizedHttpUrl(value, name) {
602
+ const url = new URL(safeSetting(value, name))
603
+ if (!["http:", "https:"].includes(url.protocol) || url.username || url.password || url.search || url.hash) throw new Error(`${name} is invalid`)
604
+ return url
605
+ }
606
+
607
+ function safeSetting(value, name) {
608
+ if (typeof value !== "string" || value.length === 0 || /[\r\n]/u.test(value)) throw new Error(`${name} is required`)
609
+ return value
610
+ }
611
+
612
+ function portValue(value, fallback) {
613
+ if (value === undefined) return fallback
614
+ const number = Number(value)
615
+ if (!/^\d+$/u.test(value) || !Number.isSafeInteger(number) || number < 1 || number > 65535) throw new Error("Invalid isolated runtime port")
616
+ return number
617
+ }
618
+
619
+ function positiveDuration(value, fallback) {
620
+ if (value === undefined) return fallback
621
+ const number = Number(value)
622
+ if (!/^\d+$/u.test(value) || !Number.isSafeInteger(number) || number < 1 || number > 604_800_000) throw new Error("Invalid session TTL")
623
+ return number
624
+ }
625
+
626
+ function positiveInteger(value, fallback) {
627
+ if (value === undefined) return fallback
628
+ const number = Number(value)
629
+ if (!/^\d+$/u.test(value) || !Number.isSafeInteger(number) || number < 1 || number > 1024) throw new Error("Invalid isolated runtime capacity")
630
+ return number
631
+ }
632
+
633
+ function parseAllowedModels(value) {
634
+ let models
635
+ try {
636
+ models = JSON.parse(safeSetting(value, "THREADWIRE_ALLOWED_CODEX_MODELS"))
637
+ } catch {
638
+ throw new Error("THREADWIRE_ALLOWED_CODEX_MODELS must be a JSON array")
639
+ }
640
+ if (!Array.isArray(models) || models.length === 0 || !models.every((model) => typeof model === "string" && /^[A-Za-z0-9._-]{1,128}$/u.test(model))) {
641
+ throw new Error("THREADWIRE_ALLOWED_CODEX_MODELS must contain model identifiers")
642
+ }
643
+ return new Set(models)
644
+ }
645
+
646
+ function sendJson(response, status, value) {
647
+ response.writeHead(status, {"content-type": "application/json"})
648
+ response.end(JSON.stringify(value))
649
+ }
650
+
651
+ function isRecord(value) {
652
+ return typeof value === "object" && value !== null && !Array.isArray(value)
653
+ }
654
+
655
+ function abortable(promise, signal) {
656
+ if (signal.aborted) return Promise.reject(signal.reason)
657
+ return new Promise((resolve, reject) => {
658
+ const abort = () => reject(signal.reason instanceof Error ? signal.reason : new Error("Isolated runtime operation aborted"))
659
+ signal.addEventListener("abort", abort, {once: true})
660
+ promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort))
661
+ })
662
+ }
663
+
664
+ function listen(server, port, host) {
665
+ return new Promise((resolve, reject) => {
666
+ server.once("error", reject)
667
+ server.listen(port, host, () => {
668
+ server.removeListener("error", reject)
669
+ resolve(undefined)
670
+ })
671
+ })
672
+ }
673
+
674
+ class ClientError extends Error {}
675
+
676
+ function bounded(value, maximum) {
677
+ return typeof value === "string" && value.length > 0 && value.length <= maximum && !/[\0\r\n]/u.test(value)
678
+ }
679
+
680
+ export class PreflightStore {
681
+ constructor({now = Date.now, ttlMs = PREFLIGHT_TTL_MS, capacity = PREFLIGHT_CAPACITY, taskCapacity = PREFLIGHT_TASK_CAPACITY} = {}) {
682
+ this.now = now
683
+ this.ttlMs = ttlMs
684
+ this.capacity = capacity
685
+ this.taskCapacity = taskCapacity
686
+ this.entries = new Map()
687
+ this.timer = setInterval(() => this.sweep(), Math.max(10, Math.min(ttlMs, 1000)))
688
+ this.timer.unref()
689
+ }
690
+ sweep() {
691
+ const current = this.now()
692
+ for (const [id, entry] of this.entries) if (entry.expiresAt <= current) this.entries.delete(id)
693
+ }
694
+ add(id, task, value) {
695
+ this.sweep()
696
+ this.assertCapacity(task)
697
+ this.entries.set(id, {task, expiresAt: this.now() + this.ttlMs, value})
698
+ }
699
+ assertCapacity(task) {
700
+ this.sweep()
701
+ let taskCount = 0
702
+ for (const entry of this.entries.values()) if (entry.task === task) taskCount++
703
+ if (this.entries.size >= this.capacity || taskCount >= this.taskCapacity) throw new ClientError("Isolated runtime preflight capacity exhausted")
704
+ }
705
+ consume(id) {
706
+ this.sweep()
707
+ const entry = this.entries.get(id)
708
+ this.entries.delete(id)
709
+ return entry?.value
710
+ }
711
+ get size() { return this.entries.size }
712
+ close() {
713
+ clearInterval(this.timer)
714
+ this.entries.clear()
715
+ }
716
+ }
717
+
718
+ export class LineageReservations {
719
+ constructor() {
720
+ this.active = new Set()
721
+ this.collecting = false
722
+ }
723
+ acquire(lineage) {
724
+ if (this.active.has(lineage)) throw new ClientError("Codex resume state is already active")
725
+ this.active.add(lineage)
726
+ let released = false
727
+ return () => {
728
+ if (released) return
729
+ released = true
730
+ this.active.delete(lineage)
731
+ }
732
+ }
733
+ beginCollection() {
734
+ if (this.collecting) throw new Error("Codex state collection overlap")
735
+ this.collecting = true
736
+ return () => { this.collecting = false }
737
+ }
738
+ values() { return this.active.values() }
739
+ has(lineage) { return this.active.has(lineage) }
740
+ }
741
+
742
+ export class ActiveRunAdmission {
743
+ constructor({capacity = ACTIVE_RUN_CAPACITY, taskCapacity = ACTIVE_TASK_CAPACITY} = {}) {
744
+ this.capacity = capacity
745
+ this.taskCapacity = taskCapacity
746
+ this.active = new Map()
747
+ }
748
+ acquire(task) {
749
+ const taskCount = this.active.get(task) ?? 0
750
+ let total = 0
751
+ for (const count of this.active.values()) total += count
752
+ if (total >= this.capacity || taskCount >= this.taskCapacity) throw new ClientError("Isolated runtime active-run capacity exhausted")
753
+ this.active.set(task, taskCount + 1)
754
+ let released = false
755
+ return () => {
756
+ if (released) return
757
+ released = true
758
+ const remaining = (this.active.get(task) ?? 1) - 1
759
+ if (remaining === 0) this.active.delete(task)
760
+ else this.active.set(task, remaining)
761
+ }
762
+ }
763
+ }
764
+
765
+ export class OperationDeadline extends AbsoluteDeadline {
766
+ constructor(timeoutMs, request, response, now = Date.now) {
767
+ super(now() + timeoutMs, {request, response, now, timeoutMessage: "Isolated runtime operation timed out", disconnectMessage: "Isolated runtime caller disconnected"})
768
+ }
769
+ }
770
+
771
+ function boundedClose(server, timeoutMs) {
772
+ return Promise.race([
773
+ new Promise((resolve) => server.close(() => resolve(undefined))),
774
+ new Promise((resolve) => {
775
+ const timer = setTimeout(resolve, timeoutMs)
776
+ timer.unref()
777
+ })
778
+ ])
779
+ }
780
+
781
+ export async function reconcileDockerResources(docker, brokerContainer, stateRegistry, inProcessLineages = new Set(), requestOptions) {
782
+ const namespace = stateRegistry.namespace
783
+ const activeLineages = new Set(inProcessLineages)
784
+ const activeRuns = new Set()
785
+ const ownedIdentities = new Map(stateRegistry.runRecords().map((identity) => [identity.run, identity]))
786
+ const cleanupFailed = new Set()
787
+ const containers = await docker.listContainers({"org.threadwire.owner": "isolated-runtime"}, true, requestOptions)
788
+ for (const container of Array.isArray(containers) ? containers : []) {
789
+ const labels = validResourceLabels(container?.Labels, namespace, true)
790
+ if (!labels) continue
791
+ const persisted = ownedIdentities.get(labels.run)
792
+ if (!persisted || stateRegistry.sealRun(persisted) !== labels.seal) continue
793
+ const inspection = await docker.inspectContainer(container.Id, requestOptions).catch(() => undefined)
794
+ const identity = ownedContainerIdentity(inspection, labels)
795
+ if (!identity || !stateRegistry.ownsRun(identity, labels.seal)) {
796
+ cleanupFailed.add(labels.run)
797
+ continue
798
+ }
799
+ if (inProcessLineages.has(labels.lineage)) {
800
+ activeLineages.add(labels.lineage)
801
+ activeRuns.add(labels.run)
802
+ continue
803
+ }
804
+ if (inProcessLineages.has(labels.lineage)) {
805
+ activeLineages.add(labels.lineage)
806
+ activeRuns.add(labels.run)
807
+ continue
808
+ }
809
+ await docker.removeContainer(container.Id, requestOptions).catch(() => cleanupFailed.add(labels.run))
810
+ }
811
+ const networks = await docker.listNetworks({"org.threadwire.owner": "isolated-runtime"}, requestOptions)
812
+ for (const network of Array.isArray(networks) ? networks : []) {
813
+ const labels = validResourceLabels(network?.Labels, namespace, false)
814
+ if (!labels || activeRuns.has(labels.run) || cleanupFailed.has(labels.run)) continue
815
+ const identity = ownedIdentities.get(labels.run)
816
+ if (!identity || stateRegistry.sealRun(identity) !== labels.seal) continue
817
+ const inspection = await docker.inspectNetwork(network.Id, requestOptions).catch(() => undefined)
818
+ if (!identity || !ownedNetworkIdentity(inspection, labels, identity, brokerContainer)
819
+ || !stateRegistry.ownsRun(identity, labels.seal)) {
820
+ cleanupFailed.add(labels.run)
821
+ continue
822
+ }
823
+ if (inProcessLineages.has(labels.lineage)) {
824
+ activeLineages.add(labels.lineage)
825
+ activeRuns.add(labels.run)
826
+ continue
827
+ }
828
+ const brokerEndpoint = Object.entries(inspection.Containers ?? {}).find(([, endpoint]) => endpoint?.Name === brokerContainer)
829
+ if (brokerEndpoint) await docker.disconnectNetwork(network.Id, brokerContainer, requestOptions).catch(() => {})
830
+ await docker.removeNetwork(network.Id, requestOptions).catch(() => cleanupFailed.add(labels.run))
831
+ }
832
+ for (const identity of ownedIdentities.values()) {
833
+ if (activeRuns.has(identity.run) || cleanupFailed.has(identity.run)) {
834
+ activeLineages.add(identity.lineage)
835
+ continue
836
+ }
837
+ if (inProcessLineages.has(identity.lineage)) {
838
+ activeLineages.add(identity.lineage)
839
+ continue
840
+ }
841
+ await stateRegistry.completeRun(identity.run, requestOptions?.signal).catch(() => activeLineages.add(identity.lineage))
842
+ }
843
+ return [...activeLineages]
844
+ }
845
+
846
+ function validResourceLabels(value, namespace, container) {
847
+ if (!isRecord(value)) return undefined
848
+ const expectedKeys = [
849
+ "org.threadwire.owner", "org.threadwire.namespace", "org.threadwire.run",
850
+ "org.threadwire.lineage", "org.threadwire.task", "org.threadwire.state-volume",
851
+ "org.threadwire.run-seal",
852
+ ...(container ? ["org.threadwire.network"] : [])
853
+ ]
854
+ if (Object.keys(value).length !== expectedKeys.length || expectedKeys.some((key) => typeof value[key] !== "string")) return undefined
855
+ const run = value["org.threadwire.run"]
856
+ const lineage = value["org.threadwire.lineage"]
857
+ const volume = value["org.threadwire.state-volume"]
858
+ const seal = value["org.threadwire.run-seal"]
859
+ if (value["org.threadwire.owner"] !== "isolated-runtime" || value["org.threadwire.namespace"] !== namespace
860
+ || !/^tw-[0-9a-f]{24}$/u.test(run) || !/^[0-9a-f]{48}$/u.test(lineage)
861
+ || !/^[0-9a-f]{64}$/u.test(value["org.threadwire.task"])
862
+ || !/^[0-9a-f]{64}$/u.test(seal)
863
+ || volume !== `threadwire-state-${namespace}-${lineage}`
864
+ || (container && value["org.threadwire.network"] !== `${run}-net`)) return undefined
865
+ return {run, lineage, volume, seal, task: value["org.threadwire.task"], namespace}
866
+ }
867
+
868
+ function ownedContainerIdentity(container, labels) {
869
+ if (!isRecord(container) || container.Name !== `/${labels.run}-worker`
870
+ || !isRecord(container.Config) || !isRecord(container.HostConfig)
871
+ || container.Config.Image !== container.Image || !isDigestImage(container.Config.Image)
872
+ || JSON.stringify(container.Config.Entrypoint) !== JSON.stringify(["/usr/local/libexec/threadwire/worker-entrypoint"])
873
+ || ![null, undefined].includes(container.Config.Cmd) || container.Config.User !== "10002:10002"
874
+ || typeof container.Config.WorkingDir !== "string" || !within("/worktree", container.Config.WorkingDir)
875
+ || container.HostConfig.NetworkMode !== `${labels.run}-net`
876
+ || !validWorkerSecurity(container.Config, container.HostConfig)
877
+ || !Array.isArray(container.HostConfig.Mounts) || container.HostConfig.Mounts.length !== 2) return undefined
878
+ const inspectedLabels = validResourceLabels(container.Config.Labels, labels.namespace, true)
879
+ if (!inspectedLabels || JSON.stringify(inspectedLabels) !== JSON.stringify(labels)) return undefined
880
+ const state = container.HostConfig.Mounts.find((mount) => mount?.Target === "/home/worker")
881
+ const worktree = container.HostConfig.Mounts.find((mount) => mount?.Target === "/worktree")
882
+ if (state?.Type !== "volume" || state.Source !== labels.volume || state.ReadOnly === true
883
+ || Object.keys(state).some((key) => !["Type", "Source", "Target", "ReadOnly"].includes(key))) return undefined
884
+ if (!validWorktreeMount(worktree)) return undefined
885
+ return runIdentityFrom(labels, container.Config.Image, worktree)
886
+ }
887
+
888
+ function validWorkerSecurity(config, host) {
889
+ if (host.AutoRemove !== false || host.ReadonlyRootfs !== true
890
+ || host.Privileged === true || JSON.stringify(host.CapDrop) !== JSON.stringify(["ALL"])
891
+ || JSON.stringify(host.CapAdd ?? null) !== "null"
892
+ || JSON.stringify(host.SecurityOpt) !== JSON.stringify(["no-new-privileges"])
893
+ || host.PidsLimit !== 128 || host.Memory !== 1_073_741_824 || host.NanoCpus !== 2_000_000_000
894
+ || !isRecord(host.Tmpfs) || Object.keys(host.Tmpfs).length !== 2
895
+ || host.Tmpfs["/tmp"] !== "rw,noexec,nosuid,nodev,size=67108864,uid=10002,gid=10002"
896
+ || host.Tmpfs["/run"] !== "rw,noexec,nosuid,nodev,size=1048576,uid=10002,gid=10002"
897
+ || !Array.isArray(host.Ulimits) || host.Ulimits.length !== 3
898
+ || ![
899
+ ["nofile", 1024, 1024], ["core", 0, 0], ["fsize", 1_073_741_824, 1_073_741_824]
900
+ ].every(([name, soft, hard], index) => host.Ulimits[index]?.Name === name
901
+ && host.Ulimits[index]?.Soft === soft && host.Ulimits[index]?.Hard === hard)) return false
902
+ const forbidden = {
903
+ Binds: [null, []], Devices: [null, []], DeviceRequests: [null, []], PortBindings: [null, {}],
904
+ Links: [null, []], ExtraHosts: [null, []], VolumesFrom: [null, []], Dns: [null, []],
905
+ DnsSearch: [null, []], Sysctls: [null, {}]
906
+ }
907
+ for (const [key, defaults] of Object.entries(forbidden)) {
908
+ if (!defaults.some((value) => JSON.stringify(host[key] ?? null) === JSON.stringify(value))) return false
909
+ }
910
+ if (![undefined, "", "private"].includes(host.PidMode) || ![undefined, "", "private"].includes(host.IpcMode)
911
+ || ![undefined, ""].includes(host.UTSMode) || ![undefined, ""].includes(host.UsernsMode)
912
+ || ![undefined, "", "private"].includes(host.CgroupnsMode) || host.PublishAllPorts === true) return false
913
+ if (!Array.isArray(config.Env) || config.Env.length !== 13 + (config.Env.some((entry) => entry.startsWith("THREADWIRE_RESUME_SESSION=")) ? 1 : 0)) return false
914
+ const names = config.Env.map((entry) => entry.split("=", 1)[0])
915
+ const expected = [
916
+ "HOME", "CODEX_HOME", "TMPDIR", "OPENAI_BASE_URL", "OPENAI_API_KEY", "CODEX_API_KEY",
917
+ "THREADWIRE_PROMPT", "THREADWIRE_CODEX_ARGUMENTS", "THREADWIRE_WORKTREE_INODE", "THREADWIRE_CWD_INODE"
918
+ ]
919
+ return expected.every((name) => names.filter((entry) => entry === name).length === 1)
920
+ && config.Env.includes("PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin")
921
+ && config.Env.includes("NODE_VERSION=22.17.0") && config.Env.includes("YARN_VERSION=1.22.22")
922
+ }
923
+
924
+ function ownedNetworkIdentity(network, labels, identity, brokerContainer) {
925
+ if (!isRecord(network) || network.Name !== `${labels.run}-net` || network.Internal !== true
926
+ || network.Driver !== "bridge" || network.Scope !== "local"
927
+ || network.EnableIPv6 !== false || network.Attachable !== false || network.Ingress !== false
928
+ || network.ConfigOnly !== false || !isRecord(network.Options) || Object.keys(network.Options).length !== 0
929
+ || !isRecord(network.Containers)) return undefined
930
+ const inspectedLabels = validResourceLabels(network.Labels, labels.namespace, false)
931
+ if (!inspectedLabels || JSON.stringify(inspectedLabels) !== JSON.stringify(labels)) return undefined
932
+ const endpoints = Object.values(network.Containers)
933
+ if (endpoints.some((endpoint) => !isRecord(endpoint)
934
+ || ![identity.container, brokerContainer].includes(endpoint.Name))) return undefined
935
+ return true
936
+ }
937
+
938
+ function validWorktreeMount(mount) {
939
+ if (!isRecord(mount) || mount.Target !== "/worktree" || mount.ReadOnly === true) return false
940
+ if (mount.Type === "bind") {
941
+ return Object.keys(mount).every((key) => ["Type", "Source", "Target", "ReadOnly", "BindOptions"].includes(key))
942
+ && typeof mount.Source === "string" && isAbsolute(mount.Source)
943
+ && isRecord(mount.BindOptions) && Object.keys(mount.BindOptions).length === 1
944
+ && mount.BindOptions.Propagation === "rprivate"
945
+ }
946
+ return mount.Type === "volume" && typeof mount.Source === "string"
947
+ && Object.keys(mount).every((key) => ["Type", "Source", "Target", "ReadOnly", "VolumeOptions"].includes(key))
948
+ && isRecord(mount.VolumeOptions) && Object.keys(mount.VolumeOptions).length === 1
949
+ && typeof mount.VolumeOptions.Subpath === "string" && mount.VolumeOptions.Subpath.length > 0
950
+ }
951
+
952
+ function runIdentityFrom(labels, image, worktree) {
953
+ return {
954
+ namespace: labels.namespace, run: labels.run, lineage: labels.lineage, task: labels.task,
955
+ volume: labels.volume, network: `${labels.run}-net`, container: `${labels.run}-worker`,
956
+ image, worktreeType: worktree.Type, worktreeSource: worktree.Source,
957
+ worktreeSubpath: worktree.Type === "volume" ? worktree.VolumeOptions.Subpath : ""
958
+ }
959
+ }
960
+
961
+ function expectedRunIdentity(options, run, network, state, worktreeSubpath) {
962
+ const volumeMode = options.worktreeVolume !== undefined
963
+ return {
964
+ namespace: options.stateRegistry.namespace, run, lineage: state.lineage,
965
+ task: state.labels["org.threadwire.task"], volume: state.volume, network,
966
+ container: `${run}-worker`, image: options.workerImage,
967
+ worktreeType: volumeMode ? "volume" : "bind",
968
+ worktreeSource: volumeMode ? options.worktreeVolume : options.preflight.repositoryRoot,
969
+ worktreeSubpath: volumeMode ? worktreeSubpath : ""
970
+ }
971
+ }
972
+
973
+ export function deriveVolumeWorktreeSubpath(worktreeRoot, repositoryRoot) {
974
+ if (typeof worktreeRoot !== "string" || typeof repositoryRoot !== "string" || !within(worktreeRoot, repositoryRoot)) {
975
+ throw new ClientError("Configured worktree has an invalid volume subpath")
976
+ }
977
+ const subpath = relative(worktreeRoot, repositoryRoot)
978
+ if (subpath === "" || isAbsolute(subpath) || normalize(subpath) !== subpath || subpath.split("/").includes("..")) {
979
+ throw new ClientError("Configured worktree has an invalid volume subpath")
980
+ }
981
+ return subpath
982
+ }