import assert from 'node:assert/strict'; import {randomUUID} from 'node:crypto'; import {EventEmitter} from 'node:events'; import {createRequire, isBuiltin} from 'node:module'; import {fileURLToPath} from 'node:url'; import test from 'node:test'; import {build} from 'esbuild'; const root = fileURLToPath(new URL('../', import.meta.url)); const compiled = await build({ stdin: {contents: `export * from './bot/forward/stream.ts'; export * from './bot/forward/manager.ts'; export * from './utils/forward_protocol.ts';`, resolveDir: root, loader: 'ts'}, bundle: true, platform: 'node', format: 'cjs', write: false, metafile: true, plugins: [{name: 'isolated-node', setup(build) { build.onResolve({filter: /(?:instance\/index\.ts|^socket\.io-client$|console_print\.ts|path_utils\.ts)$/}, args => ({path: args.path.includes('instance/') ? 'registry' : args.path === 'socket.io-client' ? 'socket' : args.path.endsWith('path_utils.ts') ? 'path' : 'console', namespace: 'stub'})); build.onLoad({filter: /.*/, namespace: 'stub'}, ({path}) => ({loader: 'js', contents: { registry: 'export const get_bot_context = () => undefined; export const observe_bot_context = () => () => {};', socket: 'export const io = () => {throw Error("Unexpected real socket")};', console: 'export const console_print = {success: x => x, log() {}};', path: 'export const get_project_root_path = () => {throw Error("Unexpected filesystem access")};', }[path]})); }}], }); assert.ok(Object.keys(compiled.metafile.inputs).every(path => !path.includes('forward_server'))); const require = createRequire(import.meta.url); const module = {exports: {}}; new Function('require', 'module', 'exports', compiled.outputFiles[0].text)(specifier => { assert.ok(isBuiltin(specifier), `Unexpected external import: ${specifier}`); return require(specifier); }, module, module.exports); const {BotStream, NodeForwardManager, validate_rpc, validate_workflow_payload, error_ack} = module.exports; const actions = ['run_once', 'trigger_start', 'trigger_stop', 'stop', 'stop_run', 'reload']; const fails = (action, code = 'INVALID_REQUEST') => assert.throws(action, error => error.code === code); const request = (method, payload, scope = randomUUID(), deadline_at = Date.now() + 2000) => ({ request_id: randomUUID(), correlation_id: randomUUID(), method, payload, forward_session_id: scope, deadline_at, }); const control = (action = 'run_once', context_generation = randomUUID()) => ({ command_id: randomUUID(), context_generation, action, ...(action === 'stop_run' ? {run_id: randomUUID()} : {workflow_id: 'gather'}), }); function fixture(t) { let now = 100; const calls = []; const command = {command_id: randomUUID(), action: 'run_once', workflow_id: 'gather', state: 'accepted'}; const runtime = {source_config_revision: 7, workflows: [{workflow_id: 'gather', generation: 3, enabled: true, start_type: 'event', trigger_state: 'listening', accepted_count: 2, max_runs: null, next_fire_at: null, active_run_ids: [randomUUID()], queued_count: 1, last_error: null}], commands: [command]}; const manager = { control(input) { calls.push(['control', input]); return command; }, get_command(id) { calls.push(['command', id]); return id === command.command_id ? command : undefined; }, get_runtime_snapshot() { calls.push(['runtime']); return runtime; }, }; const context = Object.assign(new EventEmitter(), {bot_status: 'online', bot_instance: {chat() {}}, workflow_manager: manager}); let current = context; const observers = new Set(); const source = {get: () => current, observe(_id, callback) { observers.add(callback); return () => observers.delete(callback); }}; const stream = new BotStream(1, {source, now: () => now}); t.after(() => stream.dispose()); return {stream, manager, runtime, command, calls, context, generation: stream.snapshot().context_generation, set(context) { current = context; for (const listener of observers) listener(context); }, time(value) { now = value; }, }; } test('hot workflow protocol accepts exact action-specific payloads and safe generations', () => { for (const action of actions) { const payload = control(action); const valid = request('workflow.control', payload); assert.equal(validate_rpc(valid), valid); assert.equal(validate_workflow_payload('workflow.control', payload), payload); if (action !== 'stop_run') for (const expected_generation of [1, Number.MAX_SAFE_INTEGER]) { assert.equal(validate_rpc(request('workflow.control', {...payload, expected_generation})).payload.expected_generation, expected_generation); } for (const key of ['command_id', 'context_generation', 'action', action === 'stop_run' ? 'run_id' : 'workflow_id']) { const missing = {...payload}; delete missing[key]; fails(() => validate_rpc(request('workflow.control', missing))); } fails(() => validate_rpc(request('workflow.control', {...payload, extra: true}))); fails(() => validate_rpc(request('workflow.control', {...payload, [action === 'stop_run' ? 'workflow_id' : 'run_id']: randomUUID()}))); if (action !== 'run_once') fails(() => validate_rpc(request('workflow.control', {...payload, input: {}}))); if (action === 'stop_run') fails(() => validate_rpc(request('workflow.control', {...payload, expected_generation: 1}))); } const payload = control(); for (const expected_generation of [0, -1, 1.5, NaN, Infinity, Number.MAX_SAFE_INTEGER + 1, '1', null, undefined]) fails(() => validate_rpc(request('workflow.control', {...payload, expected_generation}))); for (const action of ['', 'start', 'delete', 'constructor', null, undefined, 1]) fails(() => validate_rpc(request('workflow.control', {...payload, action}))); for (const workflow_id of ['', '../x', 'a.b', 'a/b', 'a b', 'x'.repeat(101), '__proto__', 'constructor', 'prototype', 1]) fails(() => validate_rpc(request('workflow.control', {...payload, workflow_id}))); assert.equal(validate_rpc(request('workflow.control', {...payload, workflow_id: 'x'.repeat(100)})).method, 'workflow.control'); }); test('runtime and command reads reject extra fields and require both UUID identities', () => { assert.equal(validate_rpc(request('workflow.runtime', {})).method, 'workflow.runtime'); for (const payload of [undefined, null, [], 1, {workflow_id: 'gather'}, {command_id: randomUUID()}, {[Symbol('extra')]: true}, Object.defineProperty({}, 'hidden', {value: true})]) fails(() => validate_rpc(request('workflow.runtime', payload))); const payload = {command_id: randomUUID(), context_generation: randomUUID()}; assert.equal(validate_rpc(request('workflow.command', payload)).payload, payload); for (const key of ['command_id', 'context_generation']) { for (const value of ['', 'not-a-uuid', 'x'.repeat(36), null, undefined, 1]) { fails(() => validate_rpc(request('workflow.command', {...payload, [key]: value}))); fails(() => validate_rpc(request('workflow.control', {...control(), [key]: value}))); } const missing = {...payload}; delete missing[key]; fails(() => validate_rpc(request('workflow.command', missing))); } fails(() => validate_rpc(request('workflow.control', {...control('stop_run'), run_id: 'invalid'}))); for (const key of ['workflow_id', 'run_id', 'action', 'input', 'expected_generation', 'extra']) fails(() => validate_rpc(request('workflow.command', {...payload, [key]: true}))); }); test('run_once input is strict plain JSON with an exact 64 KiB UTF-8 serialized boundary', () => { const payload = control(); const input = {text: 'x'.repeat(65_536 - Buffer.byteLength(JSON.stringify({text: ''})))}; assert.equal(Buffer.byteLength(JSON.stringify(input)), 65_536); assert.equal(validate_rpc(request('workflow.control', {...payload, input})).payload.input, input); fails(() => validate_rpc(request('workflow.control', {...payload, input: {text: input.text + 'x'}}))); const multibyte = {text: '\u00e9'.repeat(32_768)}; assert.ok(JSON.stringify(multibyte).length < 65_536); assert.ok(Buffer.byteLength(JSON.stringify(multibyte)) > 65_536); fails(() => validate_rpc(request('workflow.control', {...payload, input: multibyte}))); const cycle = {}; cycle.self = cycle; const sparse = Array(2); let deep = {}; for (let index = 0; index < 66; index++) deep = {child: deep}; for (const input of [null, [], 'text', undefined, new Date(), Object.create({inherited: true}), cycle, deep, {sparse}, {value: NaN}, {value: Infinity}, {value: 1n}, {value: undefined}, {value() {}}, JSON.parse('{"__proto__":1}'), {nested: {constructor: 1}}, {[Symbol('key')]: 1}, Object.defineProperty({}, 'hidden', {value: 1})]) fails(() => validate_rpc(request('workflow.control', {...payload, input}))); const plain = Object.assign(Object.create(null), {nested: {values: [false, 0, null]}}); assert.equal(validate_rpc(request('workflow.control', {...payload, input: plain})).payload.input, plain); }); test('hot payload descriptors are rejected without invoking enumerable or hidden accessors', async t => { for (const [method, base, keys] of [ ['workflow.control', control(), ['command_id', 'context_generation', 'action', 'workflow_id', 'expected_generation', 'input', 'extra']], ['workflow.command', {command_id: randomUUID(), context_generation: randomUUID()}, ['command_id', 'context_generation', 'extra']], ['workflow.runtime', {}, ['extra']], ]) for (const key of keys) for (const enumerable of [true, false]) { await t.test(`${method}.${key} enumerable=${enumerable}`, () => { let reads = 0; const payload = Object.defineProperty({...base}, key, {enumerable, get() { reads++; return base[key]; }}); fails(() => validate_rpc(request(method, payload))); assert.equal(reads, 0); }); } for (const enumerable of [true, false]) { let reads = 0; const input = Object.defineProperty({}, 'secret', {enumerable, get() { reads++; return 1; }}); fails(() => validate_rpc(request('workflow.control', {...control(), input}))); assert.equal(reads, 0); } }); test('stream control is synchronous, strips context identity and clones input and accepted command', t => { const app = fixture(t); const payload = {...control('run_once', app.generation), expected_generation: 3, input: {nested: {value: 1}}}; app.command.command_id = payload.command_id; app.manager.control = input => { app.calls.push(input); assert.equal(Object.hasOwn(input, 'context_generation'), false); input.input.nested.value = 2; return app.command; }; const result = app.stream.workflow_control(payload, 200); assert.equal(result instanceof Promise, false); assert.deepEqual(result, app.command); assert.notEqual(result, app.command); assert.equal(payload.input.nested.value, 1); assert.deepEqual(app.calls[0], {command_id: payload.command_id, action: 'run_once', workflow_id: 'gather', expected_generation: 3, input: {nested: {value: 2}}}); result.state = 'completed'; assert.equal(app.command.state, 'accepted'); }); test('stream runtime and command reads work offline, deeply clone state and return null for unknown command', t => { const app = fixture(t); app.context.bot_status = 'offline'; app.context.bot_instance = null; const state = app.stream.workflow_runtime({}, 200); const payload = {command_id: app.command.command_id, context_generation: app.generation}; const accepted = app.stream.workflow_command(payload, 200); assert.deepEqual(state, app.runtime); assert.deepEqual(accepted, app.command); state.workflows[0].active_run_ids.push(randomUUID()); state.commands[0].state = 'failed'; accepted.state = 'completed'; assert.equal(app.runtime.workflows[0].active_run_ids.length, 1); assert.equal(app.command.state, 'accepted'); app.command.state = 'completed'; app.command.result = {status: 'started', run_id: randomUUID()}; const completed = app.stream.workflow_command(payload, 200); assert.deepEqual(completed, app.command); completed.result.run_id = 'mutated'; assert.notEqual(app.command.result.run_id, 'mutated'); app.command.state = 'failed'; delete app.command.result; app.command.error = {code: 'GENERATION_MISMATCH', message: 'Workflow generation changed'}; const failed = app.stream.workflow_command(payload, 200); assert.deepEqual(failed, app.command); failed.error.message = 'mutated'; assert.equal(app.command.error.message, 'Workflow generation changed'); assert.equal(app.stream.workflow_command({...payload, command_id: randomUUID()}, 200), null); }); test('stale context generations reject control and command lookup before any manager dispatch', t => { const app = fixture(t); const original = app.generation; assert.match(original, /^[a-f0-9-]{36}$/i); for (const generation of [randomUUID(), original]) { if (generation === original) { app.set(Object.assign(new EventEmitter(), app.context)); assert.notEqual(app.stream.snapshot().context_generation, original); } fails(() => app.stream.workflow_control(control('run_once', generation), 200), 'CANCELLED'); fails(() => app.stream.workflow_command({command_id: app.command.command_id, context_generation: generation}, 200), 'CANCELLED'); } assert.deepEqual(app.calls, []); }); test('hot stream APIs reject invalid payloads, missing managers and unavailable optional controls', async t => { for (const name of ['runtime', 'control', 'command']) await t.test(name, t => { const app = fixture(t); const payload = name === 'runtime' ? {} : name === 'control' ? control('run_once', app.generation) : {command_id: app.command.command_id, context_generation: app.generation}; const invoke = (input = payload) => app.stream[`workflow_${name}`](input, 200); fails(() => invoke({...payload, extra: true})); assert.deepEqual(app.calls, []); app.context.workflow_manager = null; fails(invoke, 'INTERNAL_ERROR'); app.context.workflow_manager = {}; fails(invoke, 'INTERNAL_ERROR'); app.set(undefined); fails(invoke, 'NO_CONTEXT'); app.stream.dispose(); fails(invoke, 'CANCELLED'); }); }); test('hot stream APIs enforce deadlines, transport and identity before and after synchronous dispatch', async t => { for (const name of ['runtime', 'control', 'command']) { for (const change of ['deadline', 'context', 'instance', 'manager', 'disposed', 'transport']) { await t.test(`${name}: ${change}`, t => { const app = fixture(t); const payload = name === 'runtime' ? {} : name === 'control' ? control('run_once', app.generation) : {command_id: app.command.command_id, context_generation: app.generation}; let stale = false; const transport = () => { if (stale) throw Object.assign(Error('SECRET transport'), {code: 'SESSION_STALE'}); }; const invoke = deadline => app.stream[`workflow_${name}`](payload, deadline, transport); for (const deadline of [100, 99, NaN, Infinity, 1.5, undefined]) fails(() => invoke(deadline), 'TIMEOUT'); stale = true; fails(() => invoke(200), 'SESSION_STALE'); assert.deepEqual(app.calls, []); stale = false; const key = {runtime: 'get_runtime_snapshot', control: 'control', command: 'get_command'}[name]; let dispatched = 0; app.manager[key] = () => { dispatched++; if (change === 'deadline') app.time(200); if (change === 'context') app.set(Object.assign(new EventEmitter(), app.context)); if (change === 'instance') app.context.bot_instance = {}; if (change === 'manager') app.context.workflow_manager = {}; if (change === 'disposed') app.stream.dispose(); if (change === 'transport') stale = true; return name === 'runtime' ? app.runtime : app.command; }; fails(() => invoke(200), change === 'deadline' ? 'TIMEOUT' : change === 'transport' ? 'SESSION_STALE' : 'CANCELLED'); assert.equal(dispatched, 1); }); } } }); async function relay(t, stream) { const command = {forward_id: 1, forward_session_id: randomUUID(), node_session_id: 'session', node_id: 1, bot_id: 1, url: 'http://127.0.0.1:1234', path: '/socket.io', namespace: '/', token: 'opaque', expires_at: Date.now() + 10_000, deadline_at: Date.now() + 2000}; const socket = new EventEmitter(); socket.auth = {}; socket.io = {engine: {writeBuffer: []}}; socket.volatile = {emit() {}}; socket.connect = () => { socket.connected = true; queueMicrotask(() => socket.emit('connect')); }; socket.disconnect = () => { socket.connected = false; socket.emit('disconnect'); }; socket.timeout = () => ({emit(event, _payload, ack) { const {forward_id, forward_session_id, node_session_id, node_id, bot_id, expires_at} = command; const data = event === 'forward_node_ready' ? {node_ready: true} : {forward_id, forward_session_id, node_session_id, node_id, bot_id, expires_at, role: 'node', node_ready: false}; queueMicrotask(() => ack(null, {status: 'success', data})); }}); const manager = new NodeForwardManager(1, 'session', {socket_factory: () => socket, stream_factory: () => stream}); t.after(() => manager.stop()); assert.equal((await manager.ensure(command)).status, 'success'); return {socket, manager, rpc: (method, payload, deadline = Date.now() + 2000) => new Promise(resolve => socket.emit('relay_request', request(method, payload, command.forward_session_id, deadline), resolve))}; } test('real NodeForwardManager dispatches accepted controls, command polling and runtime in invocation order', async t => { const app = fixture(t); app.time(Date.now()); const channel = await relay(t, app.stream); const snapshot = await channel.rpc('bot.snapshot', {}); assert.equal(snapshot.status, 'success'); const generation = snapshot.data.context_generation; assert.equal(generation, app.generation); const payload = {...control('run_once', generation), expected_generation: 3, input: {value: 1}}; app.command.command_id = payload.command_id; assert.deepEqual(await channel.rpc('workflow.control', payload), {status: 'success', data: app.command}); assert.deepEqual(await channel.rpc('workflow.command', {command_id: payload.command_id, context_generation: generation}), {status: 'success', data: app.command}); app.command.state = 'completed'; app.command.result = {status: 'queued', request_id: randomUUID()}; app.context.bot_status = 'offline'; app.context.bot_instance = null; const completed = await channel.rpc('workflow.command', {command_id: payload.command_id, context_generation: generation}); assert.deepEqual(completed, {status: 'success', data: app.command}); completed.data.result.request_id = 'mutated'; const runtime = await channel.rpc('workflow.runtime', {}); assert.deepEqual(runtime, {status: 'success', data: app.runtime}); runtime.data.workflows[0].active_run_ids.length = 0; assert.equal(app.runtime.workflows[0].active_run_ids.length, 1); assert.deepEqual(await channel.rpc('workflow.command', {command_id: randomUUID(), context_generation: generation}), {status: 'success', data: null}); assert.deepEqual(app.calls.map(([name]) => name), ['control', 'command', 'command', 'runtime', 'command']); assert.deepEqual(app.calls[0][1], {command_id: payload.command_id, action: 'run_once', workflow_id: 'gather', expected_generation: 3, input: {value: 1}}); }); test('Node dispatch rejects malformed, stale-context and expired hot requests before manager invocation', async t => { const app = fixture(t); app.time(Date.now()); const channel = await relay(t, app.stream); for (const [method, payload, expected, deadline] of [ ['workflow.runtime', {extra: true}, 'INVALID_REQUEST'], ['workflow.control', {...control('trigger_stop', app.generation), input: {}}, 'INVALID_REQUEST'], ['workflow.control', control(), 'CANCELLED'], ['workflow.command', {command_id: app.command.command_id, context_generation: randomUUID()}, 'CANCELLED'], ['workflow.runtime', {}, 'TIMEOUT', Date.now() - 1], ['workflow.control', control('reload', app.generation), 'TIMEOUT', Date.now() - 1], ['workflow.command', {command_id: app.command.command_id, context_generation: app.generation}, 'TIMEOUT', Date.now() - 1], ]) assert.deepEqual(await channel.rpc(method, payload, deadline), error_ack(expected)); assert.deepEqual(app.calls, []); }); test('Node sanitizes workflow manager failures and retains only approved control error codes', async t => { const app = fixture(t); app.time(Date.now()); const channel = await relay(t, app.stream); for (const [method, key, payload, code] of [ ['workflow.runtime', 'get_runtime_snapshot', {}, 'INTERNAL_ERROR'], ['workflow.command', 'get_command', {command_id: app.command.command_id, context_generation: app.generation}, 'INTERNAL_ERROR'], ['workflow.control', 'control', control('run_once', app.generation), 'INVALID_REQUEST'], ]) { app.manager[key] = () => { throw Error('SECRET manager /private/path password'); }; assert.deepEqual(await channel.rpc(method, payload), error_ack(code)); } app.manager.control = () => { throw Object.assign(Error('SECRET rate limit'), {code: 'RATE_LIMITED'}); }; assert.deepEqual(await channel.rpc('workflow.control', control('reload', app.generation)), error_ack('RATE_LIMITED')); app.manager.control = () => { throw Object.assign(Error('SECRET custom error'), {code: 'PRIVATE_MANAGER_CODE'}); }; assert.deepEqual(await channel.rpc('workflow.control', control('stop', app.generation)), error_ack('INVALID_REQUEST')); }); test('Node transport guards reject hot results when the relay disconnects during manager dispatch', async t => { for (const name of ['runtime', 'control', 'command']) await t.test(name, async t => { const app = fixture(t); app.time(Date.now()); const channel = await relay(t, app.stream); const key = {runtime: 'get_runtime_snapshot', control: 'control', command: 'get_command'}[name]; const payload = name === 'runtime' ? {} : name === 'control' ? control('run_once', app.generation) : {command_id: app.command.command_id, context_generation: app.generation}; app.manager[key] = () => { channel.socket.disconnect(); return name === 'runtime' ? app.runtime : app.command; }; assert.deepEqual(await channel.rpc(`workflow.${name}`, payload), error_ack('SESSION_STALE')); }); });