69 lines
3.2 KiB
JavaScript
69 lines
3.2 KiB
JavaScript
// FED R7 fixture, sage-3625: the ancestry walk is a stand-in for Jason's
|
|
// shell. Keep this override in a test-only process, never in product code.
|
|
// As channel-fixture.mjs, real pid/uid/argv/startTime/nonce checks remain;
|
|
// verifyHuman sees ppid=1 instead of walking the development agent's tree.
|
|
import { mock } from 'node:test';
|
|
const humanUrl = new URL('../../../bus/src/human.mjs', import.meta.url).href;
|
|
const real = await import(humanUrl);
|
|
mock.module(humanUrl, { namedExports: {
|
|
readProcess: real.readProcess,
|
|
verifyHuman: (proof, options) => real.verifyHuman(proof, {
|
|
...options, readProcess: pid => ({ ...real.readProcess(pid), ppid: 1 }),
|
|
}),
|
|
} });
|
|
const { startBroker } = await import('../../../bus/src/runtime.mjs');
|
|
const { BusError } = await import('../../../bus/src/broker.mjs');
|
|
const { loadSystem, bootConfig } = await import('../../src/config.mjs');
|
|
const { createLauncher } = await import('../../src/launcher.mjs');
|
|
const { fakeHarnesses } = await import('../helpers.mjs');
|
|
const { writeFileSync } = await import('node:fs');
|
|
const [business, adapter, ready] = process.argv.slice(2);
|
|
const system = loadSystem();
|
|
const runtime = await startBroker(bootConfig({ system, businessId: business }));
|
|
const hooks = [], cleanups = [];
|
|
const ops = {
|
|
'request.admission': m => runtime.admission(m),
|
|
identity: m => runtime.identity(m.cap),
|
|
authorizeLaunch: m => runtime.authorizeLaunch(m.cap, m.instance),
|
|
refuse: m => runtime.refuse(m.cap, m.code, m.subject),
|
|
endLaunch: m => runtime.endLaunch(m.record),
|
|
credentialStatus: m => runtime.credentialStatus(m.business, m.role),
|
|
threadsState: m => runtime.threadsState(m.business),
|
|
threadIdle: m => runtime.threadIdle(m.record),
|
|
mayLaunch: m => runtime.mayLaunch(m),
|
|
landHeld: m => runtime.landHeld(m.record),
|
|
landHolders: m => runtime.landHolders(m.business),
|
|
landRelease: m => runtime.landRelease(m.record),
|
|
sessionClears: m => runtime.sessionClears(m.business),
|
|
lifecycleRequests: m => runtime.lifecycleRequests(m.business),
|
|
};
|
|
const wrap = fn => async value => {
|
|
try { return fn(value); }
|
|
catch (e) { throw Object.assign(new Error(e.message), { code: e instanceof BusError ? e.code : 'fixture-host-refused' }); }
|
|
};
|
|
const host = {
|
|
business, path: runtime.path, dataRoot: system.dataRoot,
|
|
op: wrap(m => { if (!Object.hasOwn(ops, m.op)) throw new BusError('invalid-host-request'); return ops[m.op](m); }),
|
|
bindLaunch: wrap(record => runtime.bindLaunch(record)),
|
|
beforeClose: fn => void hooks.push(fn),
|
|
};
|
|
const launcher = createLauncher({ host, system,
|
|
makeLoader: await fakeHarnesses({ after: fn => cleanups.push(fn) }, { pi: adapter }, write => write('channel', 'webui',
|
|
`export * from ${JSON.stringify(new URL('../../../plugins/channel/webui/index.mjs', import.meta.url).href)};`)),
|
|
readOnly: [new URL('./thread-adapter.mjs', import.meta.url).pathname],
|
|
harnessVersion: '0.85.1', sessionDefaults: { pollInterval: 600000 }, threadTickMs: 100,
|
|
});
|
|
let closing = false;
|
|
async function close() {
|
|
if (closing) return;
|
|
closing = true;
|
|
for (const fn of hooks) await fn(0);
|
|
await runtime.close();
|
|
for (const fn of cleanups) await fn();
|
|
process.exit(0);
|
|
}
|
|
process.once('SIGTERM', close);
|
|
process.once('SIGINT', close);
|
|
await launcher.listen();
|
|
writeFileSync(ready, 'ready\n', { mode: 0o600 });
|