import assert from 'node:assert/strict'; import net from 'node:net'; import test from 'node:test'; import { orchestratorServerInternals, startOrchestratorServer, } from './server.mjs'; async function reservePort() { const server = net.createServer(); await new Promise((resolve, reject) => { server.once('error', reject); server.listen(0, '127.0.0.1', resolve); }); const { port } = server.address(); await new Promise((resolve, reject) => { server.close((error) => (error ? reject(error) : resolve())); }); return port; } test('orchestrator server owns checkpoint and Executor Job Store lifecycle', async (t) => { const port = await reservePort(); const running = await startOrchestratorServer({ env: { MEMIND_ORCHESTRATOR_CHECKPOINT_MODE: 'memory', MEMIND_ORCHESTRATOR_HOST: '127.0.0.1', MEMIND_ORCHESTRATOR_PORT: String(port), }, logger: { log() {} }, }); let closed = false; t.after(async () => { if (!closed) await running.close(); }); assert.equal(running.checkpoint.kind, 'memory'); assert.equal(running.executorJobs.kind, 'memory'); const response = await fetch(`http://127.0.0.1:${port}/ready`); assert.equal(response.status, 200); const ready = await response.json(); assert.equal(ready.ready, true); assert.deepEqual(ready.executorGateway.store, { kind: 'memory', durable: false, }); await running.close(); closed = true; assert.equal(running.server.listening, false); }); test('orchestrator server fails closed for exposed or executable configurations without tokens', () => { assert.throws( () => orchestratorServerInternals.assertSecureServerConfig({ host: '0.0.0.0', executionEnabled: false, }), (error) => error.code === 'ORCHESTRATOR_SERVICE_TOKEN_REQUIRED', ); assert.throws( () => orchestratorServerInternals.assertSecureServerConfig({ host: '127.0.0.1', executionEnabled: true, serviceToken: 'service-token', }), (error) => error.code === 'ORCHESTRATOR_EXECUTION_TOKENS_REQUIRED', ); assert.throws( () => orchestratorServerInternals.assertSecureServerConfig({ host: '127.0.0.1', executionEnabled: true, serviceToken: 'shared-token', workerToken: 'shared-token', }), (error) => error.code === 'ORCHESTRATOR_EXECUTION_TOKENS_NOT_DISTINCT', ); assert.doesNotThrow( () => orchestratorServerInternals.assertSecureServerConfig({ host: '0.0.0.0', executionEnabled: true, serviceToken: 'service-token', workerToken: 'worker-token', }), ); }); test('orchestrator retention sweep is disabled by default and applies an explicit cutoff', async () => { const calls = []; let intervalCallback = null; let cleared = false; const runtime = { async purgeTerminalRuns(options) { calls.push(options); return { deleted: [], failures: [] }; }, }; assert.equal( orchestratorServerInternals.startRetentionSweep(runtime, { retentionDays: 0, }), null, ); const sweep = orchestratorServerInternals.startRetentionSweep(runtime, { retentionDays: 30, intervalMs: 60 * 60 * 1000, nowMs: () => 40 * 24 * 60 * 60 * 1000, setIntervalFn(callback) { intervalCallback = callback; return { unref() {} }; }, clearIntervalFn() { cleared = true; }, logger: { log() {}, warn() {} }, }); assert.equal(sweep.retentionDays, 30); intervalCallback(); await new Promise((resolve) => setImmediate(resolve)); assert.deepEqual(calls, [{ before: 10 * 24 * 60 * 60 * 1000, limit: 100, dryRun: false, }]); sweep.stop(); assert.equal(cleared, true); });