@dharma-ai-labs/agent-fabric 0.2.133 → 0.2.135

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,502 @@
1
+ import assert from 'node:assert/strict';
2
+ import { chmod, copyFile, mkdir, mkdtemp, readFile, rm, symlink, writeFile } from 'node:fs/promises';
3
+ import { tmpdir } from 'node:os';
4
+ import { join } from 'node:path';
5
+ import test from 'node:test';
6
+ import { spawn } from 'node:child_process';
7
+ import * as lifecycle from './containerRelayLifecycle.js';
8
+ import { enableRelayAutostart, relayAutostartStatus, startRelayAutostart, stopRelayAutostart, disableRelayAutostart } from './relayAutostart.js';
9
+ // The filesystem and lifecycle receipts are real. Only PID1 identity and the OS
10
+ // command boundary are injected: a unit test must never signal host PID1.
11
+ async function fixture() {
12
+ const root = await mkdtemp(join(tmpdir(), 'dharma-container-lifecycle-'));
13
+ const home = join(root, 'device');
14
+ const workspace = join(root, 'checkout');
15
+ await mkdir(join(home, 'relay'), { recursive: true, mode: 0o700 });
16
+ await mkdir(join(workspace, '.dharma'), { recursive: true, mode: 0o700 });
17
+ const uid = process.getuid?.() ?? 1000;
18
+ const identity = { pid: 1, uid, startTicks: '12345',
19
+ argv: ['/usr/bin/node', '/fixture/cli/dist/bin.js', 'relay', 'container-entrypoint'] };
20
+ const marker = { schema: 'dharma.container-entrypoint/v1', home, pid: 1, uid,
21
+ startTicks: identity.startTicks };
22
+ await writeFile(join(home, 'relay', 'container-entrypoint.json'), JSON.stringify(marker), { mode: 0o600 });
23
+ await writeFile(join(workspace, '.dharma', 'approved-policy.json'), '{}', { mode: 0o600 });
24
+ const calls = [];
25
+ const options = { platform: 'linux', uid, userHome: root, home, workspace,
26
+ launcher: join(workspace, '.dharma', 'bin', 'dharma'),
27
+ policy: join(workspace, '.dharma', 'approved-policy.json'), version: '0.2.134',
28
+ containerRuntime: { identity: async () => identity, canonicalEntrypoint: identity.argv[1], runtimeVersion: '0.2.134',
29
+ childIdentity: async (pid) => {
30
+ const actual = await lifecycle.readContainerChildIdentity(pid);
31
+ // A process fixture is parented by this test, not the container's PID1.
32
+ assert.equal(actual.parentPid, process.pid);
33
+ return { ...actual, parentPid: 1 };
34
+ } },
35
+ run: async (file, args) => { calls.push([file, ...args]); return { stdout: 'enabled\n' }; } };
36
+ return { root, home, marker, identity, calls, options };
37
+ }
38
+ // Container PID1 and child identity are Linux /proc contracts. Other hosts
39
+ // qualify rejection/schema behavior through the public command tests.
40
+ const posix = { skip: process.platform !== 'linux' };
41
+ test('owned container PID1 enables startup without claiming or modifying the OS-user systemd slot', posix, async () => {
42
+ const f = await fixture();
43
+ const friday = join(f.root, '.config', 'systemd', 'user', 'dharma-agent-fabric.service');
44
+ await mkdir(join(f.root, '.config', 'systemd', 'user'), { recursive: true });
45
+ await writeFile(friday, 'foreign Friday service', { mode: 0o600 });
46
+ const state = await enableRelayAutostart(f.options);
47
+ assert.equal(state.backend, 'container-entrypoint');
48
+ assert.equal(state.state, 'enabled');
49
+ assert.equal(await readFile(friday, 'utf8'), 'foreign Friday service');
50
+ assert.deepEqual(f.calls, []);
51
+ assert.equal((await relayAutostartStatus(f.options)).state, 'enabled');
52
+ });
53
+ test('container lifecycle start stop and disable only change its owned control receipt', posix, async () => {
54
+ const f = await fixture();
55
+ await enableRelayAutostart(f.options);
56
+ await stopRelayAutostart(f.options);
57
+ const control = join(f.home, 'relay', 'container-control.json');
58
+ assert.equal(JSON.parse(await readFile(control, 'utf8')).running, false);
59
+ await startRelayAutostart(f.options);
60
+ assert.equal(JSON.parse(await readFile(control, 'utf8')).running, true);
61
+ assert.equal((await disableRelayAutostart(f.options)).state, 'disabled');
62
+ assert.equal((await relayAutostartStatus(f.options)).state, 'disabled');
63
+ assert.deepEqual(f.calls, []);
64
+ });
65
+ test('a sleep PID1 cannot assert owned container startup and cannot fall through to systemd', posix, async () => {
66
+ const f = await fixture();
67
+ f.identity.argv = ['sleep', 'infinity'];
68
+ await assert.rejects(enableRelayAutostart(f.options), /container_startup_unavailable/);
69
+ assert.deepEqual(f.calls, []);
70
+ });
71
+ test('stale marker after a different container boot is rejected until the actual entrypoint renews it', posix, async () => {
72
+ const f = await fixture();
73
+ await enableRelayAutostart(f.options);
74
+ f.identity.startTicks = '99999';
75
+ assert.equal((await relayAutostartStatus(f.options)).state, 'unavailable');
76
+ await assert.rejects(startRelayAutostart(f.options), /owned startup|container_startup_unavailable/);
77
+ assert.deepEqual(f.calls, []);
78
+ });
79
+ test('foreign home marker cannot claim ownership', posix, async () => {
80
+ const f = await fixture();
81
+ await writeFile(join(f.home, 'relay', 'container-entrypoint.json'), JSON.stringify({ ...f.marker, home: '/foreign' }));
82
+ await assert.rejects(enableRelayAutostart(f.options), /container_startup_unavailable/);
83
+ assert.deepEqual(f.calls, []);
84
+ });
85
+ function entrypoint() {
86
+ const run = lifecycle.runOwnedContainerEntrypoint;
87
+ assert.equal(typeof run, 'function', 'released container lifecycle has no owned entrypoint loop');
88
+ return run;
89
+ }
90
+ async function until(condition, milliseconds = 3000) {
91
+ const deadline = Date.now() + milliseconds;
92
+ while (!condition()) {
93
+ if (Date.now() >= deadline)
94
+ throw new Error('owned child fixture did not reach its expected state');
95
+ await new Promise(resolve => setTimeout(resolve, 10));
96
+ }
97
+ }
98
+ const exited = (child) => child.exitCode !== null || child.signalCode !== null;
99
+ test('entrypoint starts only its owned supervisor, stops it, and reconnects after an explicit start', posix, async () => {
100
+ const run = entrypoint();
101
+ const f = await fixture();
102
+ const controller = new AbortController();
103
+ const children = [];
104
+ const result = run({ home: f.home, uid: f.options.uid, signal: controller.signal,
105
+ containerRuntime: f.options.containerRuntime, consumerStoreReady: async () => true, pollMs: 10, restartDelayMs: 10,
106
+ spawnRelay: registration => {
107
+ assert.equal(registration.policy, f.options.policy);
108
+ const child = spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)'], { stdio: 'ignore' });
109
+ children.push(child);
110
+ return child;
111
+ } });
112
+ const watchdog = setTimeout(() => controller.abort(), 5000);
113
+ try {
114
+ await enableRelayAutostart(f.options);
115
+ await until(() => children.length === 1);
116
+ await stopRelayAutostart(f.options);
117
+ await until(() => exited(children[0]));
118
+ await startRelayAutostart(f.options);
119
+ await until(() => children.length === 2);
120
+ }
121
+ finally {
122
+ clearTimeout(watchdog);
123
+ controller.abort();
124
+ }
125
+ assert.equal((await result).stopped, true);
126
+ assert.equal(children.every(exited), true);
127
+ assert.deepEqual(f.calls, []);
128
+ });
129
+ test('entrypoint relaunches a failed owned child and renews boot identity while retaining startup configuration', posix, async () => {
130
+ const run = entrypoint();
131
+ const f = await fixture();
132
+ await enableRelayAutostart(f.options);
133
+ const children = [];
134
+ async function boot() {
135
+ const controller = new AbortController();
136
+ const result = run({ home: f.home, uid: f.options.uid, signal: controller.signal,
137
+ containerRuntime: f.options.containerRuntime, consumerStoreReady: async () => true, pollMs: 10, restartDelayMs: 10,
138
+ spawnRelay: () => {
139
+ const child = spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)'], { stdio: 'ignore' });
140
+ children.push(child);
141
+ return child;
142
+ } });
143
+ return { controller, result };
144
+ }
145
+ const first = await boot();
146
+ try {
147
+ await until(() => children.length === 1);
148
+ children[0].kill('SIGTERM');
149
+ await until(() => children.length === 2);
150
+ }
151
+ finally {
152
+ first.controller.abort();
153
+ }
154
+ assert.equal((await first.result).restarts, 1);
155
+ f.identity.startTicks = '54321';
156
+ const second = await boot();
157
+ try {
158
+ await until(() => children.length === 3);
159
+ assert.equal((await relayAutostartStatus(f.options)).state, 'enabled');
160
+ const marker = JSON.parse(await readFile(join(f.home, 'relay', 'container-entrypoint.json'), 'utf8'));
161
+ assert.equal(marker.startTicks, '54321');
162
+ }
163
+ finally {
164
+ second.controller.abort();
165
+ }
166
+ await second.result;
167
+ assert.equal(children.every(exited), true);
168
+ });
169
+ test('unconfigured entrypoint waits without enrolling, calling a provider, or launching a relay', posix, async () => {
170
+ const run = entrypoint();
171
+ const f = await fixture();
172
+ const controller = new AbortController();
173
+ let launches = 0;
174
+ const result = run({ home: f.home, uid: f.options.uid, signal: controller.signal,
175
+ containerRuntime: f.options.containerRuntime, consumerStoreReady: async () => true, pollMs: 10, restartDelayMs: 10,
176
+ spawnRelay: () => { launches++; throw new Error('must not launch'); } });
177
+ await new Promise(resolve => setTimeout(resolve, 40));
178
+ controller.abort();
179
+ await result;
180
+ assert.equal(launches, 0);
181
+ });
182
+ test('corrupt startup authority fails closed and reaps the owned child without leaking raw input', posix, async () => {
183
+ const run = entrypoint();
184
+ const f = await fixture();
185
+ await enableRelayAutostart(f.options);
186
+ const controller = new AbortController();
187
+ let child;
188
+ const result = run({ home: f.home, uid: f.options.uid, signal: controller.signal,
189
+ containerRuntime: f.options.containerRuntime, consumerStoreReady: async () => true, pollMs: 10, restartDelayMs: 10,
190
+ spawnRelay: () => child = spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)'], { stdio: 'ignore' }) });
191
+ const failure = assert.rejects(result, error => {
192
+ assert.match(String(error), /container_startup_unavailable/);
193
+ assert.doesNotMatch(String(error), /CANARY_PRIVATE_INPUT/);
194
+ return true;
195
+ });
196
+ await until(() => Boolean(child));
197
+ await writeFile(join(f.home, 'relay', 'autostart.json'), 'CANARY_PRIVATE_INPUT');
198
+ await failure;
199
+ assert.equal(exited(child), true);
200
+ });
201
+ test('locked protected consumer blocks startup without launching a relay until explicitly unlocked', posix, async () => {
202
+ const run = entrypoint();
203
+ const f = await fixture();
204
+ await enableRelayAutostart(f.options);
205
+ const controller = new AbortController();
206
+ let ready = false;
207
+ const children = [];
208
+ const result = run({ home: f.home, uid: f.options.uid, signal: controller.signal,
209
+ containerRuntime: f.options.containerRuntime, pollMs: 10, restartDelayMs: 10,
210
+ consumerStoreReady: async () => ready,
211
+ spawnRelay: () => {
212
+ const child = spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)'], { stdio: 'ignore' });
213
+ children.push(child);
214
+ return child;
215
+ } });
216
+ try {
217
+ await until(() => false, 50).catch(() => { });
218
+ assert.equal(children.length, 0);
219
+ const heartbeat = JSON.parse(await readFile(join(f.home, 'relay', 'container-heartbeat.json'), 'utf8'));
220
+ assert.equal(heartbeat.lifecycle, 'blocked');
221
+ assert.equal(heartbeat.reason, 'consumer_store_locked_or_unavailable');
222
+ ready = true;
223
+ await until(() => children.length === 1);
224
+ }
225
+ finally {
226
+ controller.abort();
227
+ }
228
+ await result;
229
+ assert.equal(children.every(exited), true);
230
+ });
231
+ test('duplicate owned entrypoint cannot take over a live lifecycle lease', posix, async () => {
232
+ const run = entrypoint();
233
+ const f = await fixture();
234
+ const controller = new AbortController();
235
+ const options = { home: f.home, uid: f.options.uid, signal: controller.signal,
236
+ containerRuntime: f.options.containerRuntime, pollMs: 10, restartDelayMs: 10,
237
+ spawnRelay: () => { throw new Error('unconfigured'); } };
238
+ const first = run(options);
239
+ try {
240
+ await until(() => false, 40).catch(() => { });
241
+ await assert.rejects(run(options), /container_entrypoint_busy/);
242
+ }
243
+ finally {
244
+ controller.abort();
245
+ }
246
+ await first;
247
+ });
248
+ test('configured entrypoint cannot claim running startup from a nonexistent child heartbeat', posix, async () => {
249
+ const f = await fixture();
250
+ await enableRelayAutostart(f.options);
251
+ const control = JSON.parse(await readFile(join(f.home, 'relay', 'container-control.json'), 'utf8'));
252
+ await writeFile(join(f.home, 'relay', 'container-heartbeat.json'), JSON.stringify({
253
+ schema: 'dharma.container-relay-heartbeat/v1', home: f.home, startTicks: f.identity.startTicks,
254
+ polledAt: Date.now(), lifecycle: 'running', reason: null, registrationHash: control.registrationHash,
255
+ childPid: 999999999, childStartTicks: '12345',
256
+ }), { mode: 0o600 });
257
+ assert.notEqual((await relayAutostartStatus(f.options)).lifecycle, 'running');
258
+ });
259
+ test('PID1 must use the exact canonical CLI entrypoint and non-root owner', posix, async () => {
260
+ for (const change of ['script', 'uid', 'extra-argument', 'ticks']) {
261
+ const f = await fixture();
262
+ if (change === 'script')
263
+ f.identity.argv[1] = '/foreign/cli/dist/bin.js';
264
+ if (change === 'uid')
265
+ f.identity.uid++;
266
+ if (change === 'extra-argument')
267
+ f.identity.argv.push('--grant');
268
+ if (change === 'ticks')
269
+ f.identity.startTicks = 'invalid';
270
+ await assert.rejects(enableRelayAutostart(f.options), /container_startup_unavailable/);
271
+ assert.deepEqual(f.calls, []);
272
+ }
273
+ });
274
+ test('private lifecycle marker and control reject unsafe files and malformed contents without reflecting input', posix, async () => {
275
+ for (const name of ['container-entrypoint.json', 'container-control.json']) {
276
+ for (const kind of ['symlink', 'world-writable', 'oversize', 'malformed', 'foreign-uid']) {
277
+ const f = await fixture();
278
+ await enableRelayAutostart(f.options);
279
+ const path = join(f.home, 'relay', name);
280
+ if (kind === 'symlink') {
281
+ const target = join(f.root, 'foreign-canary.json');
282
+ await writeFile(target, 'CANARY_PRIVATE_INPUT', { mode: 0o600 });
283
+ await rm(path);
284
+ await symlink(target, path);
285
+ }
286
+ else if (kind === 'world-writable')
287
+ await chmod(path, 0o666);
288
+ else if (kind === 'oversize')
289
+ await writeFile(path, 'CANARY_PRIVATE_INPUT'.repeat(4096));
290
+ else if (kind === 'malformed')
291
+ await writeFile(path, 'CANARY_PRIVATE_INPUT');
292
+ else
293
+ f.options.uid++;
294
+ const status = await relayAutostartStatus(f.options);
295
+ assert.equal(status.state, 'unavailable', `${name}/${kind}`);
296
+ assert.doesNotMatch(JSON.stringify(status), /CANARY_PRIVATE_INPUT/);
297
+ await assert.rejects(startRelayAutostart(f.options), /owned startup|container_startup_unavailable/);
298
+ assert.deepEqual(f.calls, []);
299
+ }
300
+ }
301
+ });
302
+ test('entrypoint does not launch a registration from a different installed runtime version', posix, async () => {
303
+ const run = entrypoint();
304
+ const f = await fixture();
305
+ await enableRelayAutostart({ ...f.options, version: '0.0.1' });
306
+ const controller = new AbortController();
307
+ let launches = 0;
308
+ const result = run({ home: f.home, uid: f.options.uid, signal: controller.signal,
309
+ containerRuntime: f.options.containerRuntime, consumerStoreReady: async () => true, pollMs: 10, restartDelayMs: 10,
310
+ spawnRelay: () => { launches++; return spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)'], { stdio: 'ignore' }); } });
311
+ await new Promise(resolve => setTimeout(resolve, 50));
312
+ controller.abort();
313
+ await result;
314
+ assert.equal(launches, 0);
315
+ });
316
+ test('stale heartbeat and reused or foreign child identity cannot assert live startup', posix, async () => {
317
+ for (const kind of ['stale', 'reused', 'foreign-parent', 'foreign-owner']) {
318
+ const f = await fixture();
319
+ await enableRelayAutostart(f.options);
320
+ const control = JSON.parse(await readFile(join(f.home, 'relay', 'container-control.json'), 'utf8'));
321
+ const child = spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)'], { stdio: 'ignore' });
322
+ try {
323
+ const identity = await lifecycle.readContainerChildIdentity(child.pid);
324
+ if (kind === 'foreign-parent' || kind === 'foreign-owner') {
325
+ f.options.containerRuntime.childIdentity = async () => ({ ...identity,
326
+ uid: kind === 'foreign-owner' ? identity.uid + 1 : identity.uid,
327
+ parentPid: kind === 'foreign-parent' ? process.pid : 1 });
328
+ }
329
+ await writeFile(join(f.home, 'relay', 'container-heartbeat.json'), JSON.stringify({
330
+ schema: 'dharma.container-relay-heartbeat/v1', home: f.home, startTicks: f.identity.startTicks,
331
+ polledAt: Date.now() - (kind === 'stale' ? 20_000 : 0), lifecycle: 'running', reason: null,
332
+ registrationHash: control.registrationHash, childPid: child.pid,
333
+ childStartTicks: kind === 'reused' ? String(BigInt(identity.startTicks) + 1n) : identity.startTicks,
334
+ }), { mode: 0o600 });
335
+ const status = await relayAutostartStatus(f.options);
336
+ assert.equal(status.state, 'unavailable', kind);
337
+ assert.equal(status.reason, 'container_startup_unavailable', kind);
338
+ }
339
+ finally {
340
+ child.kill('SIGTERM');
341
+ await until(() => exited(child));
342
+ }
343
+ }
344
+ });
345
+ test('concurrent owned controls are atomic and disabling reaps interrupted owned work', posix, async () => {
346
+ const f = await fixture();
347
+ await enableRelayAutostart(f.options);
348
+ const controller = new AbortController();
349
+ const children = [];
350
+ const result = entrypoint()({ home: f.home, uid: f.options.uid, signal: controller.signal,
351
+ containerRuntime: f.options.containerRuntime, consumerStoreReady: async () => true, pollMs: 10, restartDelayMs: 10,
352
+ spawnRelay: () => {
353
+ const child = spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)'], { stdio: 'ignore' });
354
+ children.push(child);
355
+ return child;
356
+ } });
357
+ try {
358
+ await until(() => children.length === 1);
359
+ const registration = await lifecycle.readContainerRegistration(f.options);
360
+ assert.ok(registration);
361
+ await Promise.all(Array.from({ length: 12 }, (_, index) => lifecycle.containerStartupControl(f.options, registration, index % 2 === 0)));
362
+ assert.equal(typeof JSON.parse(await readFile(join(f.home, 'relay', 'container-control.json'), 'utf8')).running, 'boolean');
363
+ // No subsequent writer; disable is terminal for this registration.
364
+ await disableRelayAutostart(f.options);
365
+ await until(() => children.every(exited));
366
+ assert.equal((await relayAutostartStatus(f.options)).state, 'disabled');
367
+ }
368
+ finally {
369
+ controller.abort();
370
+ }
371
+ await result;
372
+ });
373
+ test('SIGTERM to an owned process fixture shuts down and reaps its child normally', posix, async () => {
374
+ const f = await fixture();
375
+ await enableRelayAutostart(f.options);
376
+ const program = `
377
+ import { spawn } from 'node:child_process';
378
+ import { runOwnedContainerEntrypoint, readContainerChildIdentity } from ${JSON.stringify(new URL('./containerRelayLifecycle.js', import.meta.url).href)};
379
+ const controller = new AbortController();
380
+ process.once('SIGTERM', () => controller.abort());
381
+ await runOwnedContainerEntrypoint({ home: ${JSON.stringify(f.home)}, uid: process.getuid(), signal: controller.signal,
382
+ containerRuntime: { identity: async () => (${JSON.stringify(f.identity)}), canonicalEntrypoint: ${JSON.stringify(f.identity.argv[1])}, runtimeVersion: '0.2.134',
383
+ childIdentity: async pid => { const actual = await readContainerChildIdentity(pid);
384
+ if (actual.parentPid !== process.pid) throw new Error('foreign fixture child'); return { ...actual, parentPid: 1 }; } },
385
+ consumerStoreReady: async () => true, pollMs: 10, restartDelayMs: 10,
386
+ spawnRelay: () => { const child = spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)'], { stdio: 'ignore' });
387
+ process.stdout.write(JSON.stringify({ childPid: child.pid }) + '\\n'); return child; } });
388
+ `;
389
+ const runner = spawn(process.execPath, ['--input-type=module', '-e', program], { stdio: ['ignore', 'pipe', 'pipe'] });
390
+ let output = '';
391
+ let errorOutput = '';
392
+ let childPid = 0;
393
+ runner.stdout.on('data', data => { output += String(data); if (output.includes('\n'))
394
+ childPid = JSON.parse(output.trim()).childPid; });
395
+ runner.stderr.on('data', data => { errorOutput += String(data); });
396
+ try {
397
+ await until(() => childPid > 1 || exited(runner));
398
+ assert.ok(childPid > 1, errorOutput || output || 'fixture exited without a child');
399
+ runner.kill('SIGTERM');
400
+ await until(() => exited(runner));
401
+ assert.equal(runner.exitCode, 0, errorOutput);
402
+ assert.throws(() => process.kill(childPid, 0), /ESRCH/);
403
+ assert.equal((await relayAutostartStatus(f.options)).state, 'unavailable');
404
+ assert.ok(await readFile(join(f.home, 'relay', 'autostart.json'), 'utf8'));
405
+ }
406
+ finally {
407
+ if (!exited(runner)) {
408
+ runner.kill('SIGTERM');
409
+ await until(() => exited(runner));
410
+ }
411
+ }
412
+ });
413
+ test('the normal npm client recognizes a separate identical qualified CLI image but rejects changed executable bytes', posix, async () => {
414
+ const f = await fixture();
415
+ const runtime = join(f.root, 'qualified-cli');
416
+ await mkdir(join(runtime, 'dist'), { recursive: true, mode: 0o700 });
417
+ for (const name of ['bin.js', 'index.js', 'containerRelayLifecycle.js']) {
418
+ await copyFile(new URL(`./${name}`, import.meta.url), join(runtime, 'dist', name));
419
+ await chmod(join(runtime, 'dist', name), 0o644);
420
+ }
421
+ await copyFile(new URL('../package.json', import.meta.url), join(runtime, 'package.json'));
422
+ await chmod(join(runtime, 'package.json'), 0o644);
423
+ f.identity.argv[1] = join(runtime, 'dist', 'bin.js');
424
+ const runtimeOptions = { home: f.home, uid: f.options.uid,
425
+ containerRuntime: { identity: async () => f.identity } };
426
+ assert.equal(await lifecycle.containerEntrypointAvailable(runtimeOptions), true);
427
+ await writeFile(join(runtime, 'dist', 'index.js'), 'CANARY_CHANGED_RUNTIME');
428
+ await assert.rejects(lifecycle.containerEntrypointAvailable(runtimeOptions), error => {
429
+ assert.match(String(error), /container_startup_unavailable/);
430
+ assert.doesNotMatch(String(error), /CANARY_CHANGED_RUNTIME/);
431
+ return true;
432
+ });
433
+ });
434
+ test('malformed entrypoint leases cannot be silently discarded as an earlier boot', posix, async () => {
435
+ for (const startTicks of [null, 'CANARY_PRIVATE_INPUT']) {
436
+ const f = await fixture();
437
+ await writeFile(join(f.home, 'relay', 'container-entrypoint.lock'), JSON.stringify({ ...f.marker, startTicks }), { mode: 0o600 });
438
+ const controller = new AbortController();
439
+ const timeout = setTimeout(() => controller.abort(), 100);
440
+ try {
441
+ await assert.rejects(entrypoint()({ home: f.home, uid: f.options.uid, signal: controller.signal,
442
+ containerRuntime: f.options.containerRuntime, consumerStoreReady: async () => true, pollMs: 10, restartDelayMs: 10,
443
+ spawnRelay: () => { throw new Error('must not launch'); } }), error => {
444
+ assert.match(String(error), /container_startup_unavailable/);
445
+ assert.doesNotMatch(String(error), /CANARY_PRIVATE_INPUT/);
446
+ return true;
447
+ });
448
+ assert.equal(JSON.parse(await readFile(join(f.home, 'relay', 'container-entrypoint.lock'), 'utf8')).startTicks, startTicks);
449
+ }
450
+ finally {
451
+ clearTimeout(timeout);
452
+ controller.abort();
453
+ }
454
+ }
455
+ });
456
+ test('entrypoint never starts an owned child after shutdown arrives during consumer preflight', posix, async () => {
457
+ const f = await fixture();
458
+ await enableRelayAutostart(f.options);
459
+ const controller = new AbortController();
460
+ let checking = false;
461
+ let launches = 0;
462
+ let release;
463
+ const consumer = new Promise(resolveReady => { release = () => resolveReady(true); });
464
+ const result = entrypoint()({ home: f.home, uid: f.options.uid, signal: controller.signal,
465
+ containerRuntime: f.options.containerRuntime, consumerStoreReady: async () => { checking = true; return consumer; },
466
+ pollMs: 10, restartDelayMs: 10, spawnRelay: () => {
467
+ launches++;
468
+ return spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)'], { stdio: 'ignore' });
469
+ } });
470
+ await until(() => checking);
471
+ controller.abort();
472
+ release();
473
+ await result;
474
+ assert.equal(launches, 0);
475
+ });
476
+ test('unverifiable freshly spawned child fails closed and is reaped through its owned process handle', posix, async () => {
477
+ const f = await fixture();
478
+ await enableRelayAutostart(f.options);
479
+ const controller = new AbortController();
480
+ let child;
481
+ const result = entrypoint()({ home: f.home, uid: f.options.uid, signal: controller.signal,
482
+ containerRuntime: { ...f.options.containerRuntime, childIdentity: async () => { throw new Error('CANARY_PROC_FAILURE'); } },
483
+ consumerStoreReady: async () => true, pollMs: 10, restartDelayMs: 10,
484
+ spawnRelay: () => child = spawn(process.execPath, ['-e', 'setInterval(() => {}, 1000)'], { stdio: 'ignore' }) });
485
+ try {
486
+ await assert.rejects(result, error => {
487
+ assert.match(String(error), /container_startup_unavailable/);
488
+ assert.doesNotMatch(String(error), /CANARY_PROC_FAILURE/);
489
+ return true;
490
+ });
491
+ assert.ok(child);
492
+ await until(() => exited(child), 100);
493
+ }
494
+ finally {
495
+ controller.abort();
496
+ if (child && !exited(child)) {
497
+ child.kill('SIGTERM');
498
+ await until(() => exited(child));
499
+ }
500
+ }
501
+ });
502
+ //# sourceMappingURL=containerRelayLifecycle.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containerRelayLifecycle.test.js","sourceRoot":"","sources":["../src/containerRelayLifecycle.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=containerRelayPublicCommand.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containerRelayPublicCommand.test.d.ts","sourceRoot":"","sources":["../src/containerRelayPublicCommand.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ import assert from 'node:assert/strict';
2
+ import test from 'node:test';
3
+ import { run } from './index.js';
4
+ test('public container entrypoint command rejects a normal host process before storage or startup mutation', async () => {
5
+ await assert.rejects(run(['relay', 'container-entrypoint']), /container_entrypoint_requires_pid1/);
6
+ });
7
+ test('container entrypoint rejects grant and policy arguments without reflecting private input', async () => {
8
+ for (const flag of ['grant', 'policy', 'organization-id', 'no-relay-daemon']) {
9
+ await assert.rejects(run(['relay', 'container-entrypoint', `--${flag}`, 'CANARY_PRIVATE_INPUT']), error => {
10
+ assert.match(String(error), /container_entrypoint_options_forbidden/);
11
+ assert.doesNotMatch(String(error), /CANARY_PRIVATE_INPUT/);
12
+ return true;
13
+ });
14
+ }
15
+ });
16
+ test('container entrypoint dry-run describes its bounded prerequisite plan without starting a runtime', async () => {
17
+ const value = await run(['relay', 'container-entrypoint', '--dry-run']);
18
+ assert.equal(typeof value, 'object');
19
+ const plan = value;
20
+ assert.equal(plan.stage, 'container_entrypoint_plan');
21
+ assert.equal(plan.started, false);
22
+ assert.equal(plan.requiresPrivateSecretService, true);
23
+ assert.equal(plan.restartCoverage, 'container-entrypoint-only');
24
+ });
25
+ //# sourceMappingURL=containerRelayPublicCommand.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containerRelayPublicCommand.test.js","sourceRoot":"","sources":["../src/containerRelayPublicCommand.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAEjC,IAAI,CAAC,sGAAsG,EAAE,KAAK,IAAI,EAAE;IACtH,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC,EAAE,oCAAoC,CAAC,CAAC;AACrG,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0FAA0F,EAAE,KAAK,IAAI,EAAE;IAC1G,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,iBAAiB,CAAC,EAAE,CAAC;QAC7E,MAAM,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,sBAAsB,EAAE,KAAK,IAAI,EAAE,EAAE,sBAAsB,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE;YACxG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,wCAAwC,CAAC,CAAC;YACtE,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,sBAAsB,CAAC,CAAC;YAC3D,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC;AAGH,IAAI,CAAC,iGAAiG,EAAE,KAAK,IAAI,EAAE;IACjH,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC,OAAO,EAAE,sBAAsB,EAAE,WAAW,CAAC,CAAC,CAAC;IACxE,MAAM,CAAC,KAAK,CAAC,OAAO,KAAK,EAAE,QAAQ,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,KAAgC,CAAC;IAC9C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;IACtD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAClC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,EAAE,IAAI,CAAC,CAAC;IACtD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,EAAE,2BAA2B,CAAC,CAAC;AAClE,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=containerRelaySchema.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containerRelaySchema.test.d.ts","sourceRoot":"","sources":["../src/containerRelaySchema.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,35 @@
1
+ import assert from 'node:assert/strict';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { Ajv2020 } from 'ajv/dist/2020.js';
4
+ import test from 'node:test';
5
+ async function validator(name) {
6
+ const schema = JSON.parse(await readFile(new URL(`./schemas/${name}.schema.json`, import.meta.url), 'utf8'));
7
+ return new Ajv2020({ strict: true, strictRequired: false }).compile(schema);
8
+ }
9
+ test('container startup schema rejects credentials, arbitrary backends and malformed authority paths', async () => {
10
+ const validate = await validator('relay-autostart.v3');
11
+ const value = { schema: 'dharma.relay-autostart/v3', backend: 'container-entrypoint', launcher: '/repo/.dharma/bin/dharma',
12
+ workspace: '/repo', policy: '/repo/.dharma/approved-policy.json', version: '0.2.134', taskName: null };
13
+ assert.equal(validate(value), true);
14
+ for (const change of [{ grant: 'CANARY_PRIVATE_INPUT' }, { backend: 'systemd-user' }, { taskName: 'other' },
15
+ { policy: '../foreign' }, { launcher: '/repo\ncommand' }, { version: 'unpublished arbitrary value' }]) {
16
+ assert.equal(validate({ ...value, ...change }), false);
17
+ }
18
+ });
19
+ test('container lifecycle schema separates configuration from live-child receipt and forbids secret fields', async () => {
20
+ const validate = await validator('container-relay-lifecycle.v1');
21
+ const marker = { schema: 'dharma.container-entrypoint/v1', home: '/private/device', pid: 1, uid: 1000, startTicks: '1234' };
22
+ const control = { schema: 'dharma.container-relay-control/v1', home: '/private/device', registrationHash: 'a'.repeat(64), running: true };
23
+ const running = { schema: 'dharma.container-relay-heartbeat/v1', home: '/private/device', startTicks: '1234', polledAt: 1000,
24
+ lifecycle: 'running', reason: null, registrationHash: 'a'.repeat(64), childPid: 42, childStartTicks: '1235' };
25
+ for (const value of [marker, control, running, { ...running, lifecycle: 'blocked', reason: 'consumer_store_locked_or_unavailable', childPid: null, childStartTicks: null }]) {
26
+ assert.equal(validate(value), true, JSON.stringify(validate.errors));
27
+ assert.equal(validate({ ...value, grant: 'CANARY_PRIVATE_INPUT' }), false);
28
+ }
29
+ for (const change of [{ childStartTicks: null }, { childPid: null }, { lifecycle: 'ready' }, { reason: 'CANARY_PRIVATE_INPUT' },
30
+ { startTicks: 'invalid' }, { polledAt: -1 }])
31
+ assert.equal(validate({ ...running, ...change }), false);
32
+ assert.equal(validate({ ...marker, uid: 0 }), false);
33
+ assert.equal(validate({ ...control, registrationHash: 'foreign' }), false);
34
+ });
35
+ //# sourceMappingURL=containerRelaySchema.test.js.map