1. Stale bus host lock refusals from bus status, start, stop and restart name mosaic bus recover ORG. 2. org definitions: unknown org, unknown or malformed name and bad id give one refusal or usage line, no stack trace, no host path. 3. Pack, board and workflow refusals print their hint as template save does; tested with the real CliError transport shape. 4. console start and stop clear a console/start.lock whose named supervisor (pid and start time) is gone; a live or unnamed holder refuses. 5. Template save keeps free text verbatim and writes no placeholders; the preview lists each field that mentions an org-specific name. 6. A request the shim never sent (no socket, connect refused) exits 5 and the CLI reports bus-not-running with the start and recover line. 7. autonomy-precondition carries the check that failed, including on the hire paths. 8. Saving under an existing template name refuses template-exists with a next step; refusal table entry added, channel-proof pins moved.
55 lines
3.0 KiB
JavaScript
55 lines
3.0 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { dirname, join } from 'node:path';
|
|
import { orgPaths } from '../src/config.mjs';
|
|
|
|
test('organization paths are rooted together and reject overlong sockets', () => {
|
|
const root = '/var/mosaic/org-runtime/alpha';
|
|
assert.deepEqual(orgPaths(root), {
|
|
socket: join(root, 'bus/broker.sock'), busDir: join(root, 'bus'),
|
|
runs: join(root, 'runs'), launches: join(root, 'launches'),
|
|
sessions: join(root, 'sessions'), workspaces: join(root, 'workspaces'),
|
|
threads: join(root, 'threads'), hostDir: join(root, 'bus-host'),
|
|
});
|
|
assert.throws(() => orgPaths('/' + 'a'.repeat(110)), /socket.*long/i);
|
|
assert.throws(() => orgPaths('relative'), /absolute/i);
|
|
});
|
|
|
|
import { bootConfig, loadSystem } from '../src/config.mjs';
|
|
import { fixture, tmp } from './helpers.mjs';
|
|
|
|
test('broker boot keeps instance and organization roots distinct', (t) => {
|
|
const f = fixture(tmp(t));
|
|
const root = join(f.dataRoot, 'org-runtime', 'acme');
|
|
const boot = bootConfig({ system: loadSystem({ env: f.env }), businessId: 'acme', orgRoot: root, env: f.env });
|
|
assert.equal(boot.dataRoot, root);
|
|
assert.equal(boot.instanceRoot, f.dataRoot);
|
|
assert.deepEqual(boot.org, { id: 'acme' });
|
|
assert.equal(boot.instanceDataRoot, f.dataRoot);
|
|
assert.equal(boot.instanceConfigDir, dirname(f.config));
|
|
});
|
|
|
|
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
import { claimHostLock, hostLock, startTimeOf } from '../src/host.mjs';
|
|
test('organization host claim refuses a stale lock without removing it', t => {
|
|
const root = tmp(t);
|
|
mkdirSync(join(root, 'bus-host'), { mode: 0o700 });
|
|
const stale = { pid: 99999999, startTime: '0', business: 'alpha', startedAt: 'old' };
|
|
writeFileSync(hostLock(root), JSON.stringify(stale), { mode: 0o600 });
|
|
const mine = { pid: process.pid, startTime: startTimeOf(process.pid), business: 'alpha', startedAt: 'now' };
|
|
// E2E6 fix 1: the message stays; the next line names the verb that clears the dead host.
|
|
assert.throws(() => claimHostLock(root, mine, { refuseStale: true }), e => e.message === 'stale bus host lock' && e.exitCode === 3
|
|
&& e.next === 'if the bus host died, clear it with mosaic bus recover alpha; recover refuses while the host still runs');
|
|
assert.deepEqual(JSON.parse(readFileSync(hostLock(root), 'utf8')), stale);
|
|
// A lock naming no valid organization id still names the verb, with a placeholder.
|
|
writeFileSync(hostLock(root), JSON.stringify({ ...stale, business: '../x\nsecret' }), { mode: 0o600 });
|
|
assert.throws(() => claimHostLock(root, mine, { refuseStale: true }), e => e.next === 'if the bus host died, clear it with mosaic bus recover <org>; recover refuses while the host still runs');
|
|
});
|
|
|
|
import { busStatus } from '../src/org-bus.mjs';
|
|
test('an inaccessible registry refuses as a configuration error', async t => {
|
|
const root = tmp(t);
|
|
await assert.rejects(busStatus({ configDir: join(root, 'missing'), dataRoot: root, instance: 'test' }, 'alpha'),
|
|
error => error.exitCode === 3 && /registry/i.test(error.message));
|
|
});
|