// #1873 T1: the definition writes on the bus. Only the business's human at the cli reaches them, // and the writer runs the credential store's held-secret check on what it would write. import test from 'node:test'; import assert from 'node:assert/strict'; import { appendFileSync, chmodSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { DEFINITION_BUS_KEYS } from '../src/broker.mjs'; import { startBroker } from '../src/runtime.mjs'; import { DEFINITION_BUS_VERBS } from '../../organization/src/definition-verbs.mjs'; import { businessDoc, rolesCopy, systemFor, writeJson } from '../../organization/tests/helpers.mjs'; const TOKEN = 'fixture-held-token-t1-5c0e9a'; const SCOUT = { role: { tools: ['read'], network: 'none', authority: { withinRole: [], crossRole: [] }, credentials: [] }, instructions: 'Read and report.\n' }; function files(dir) { return readdirSync(dir, { withFileTypes: true }).flatMap((e) => e.isDirectory() ? files(join(dir, e.name)) : e.isFile() ? [join(dir, e.name)] : []); } test('T1 the broker checks the same four definition verbs the runtime maps', () => { assert.deepEqual(Object.keys(DEFINITION_BUS_KEYS).sort(), Object.keys(DEFINITION_BUS_VERBS).sort()); }); test('T1 definition writes: the human at the cli writes, every other caller refuses, and a held token never lands', async (t) => { const root = mkdtempSync(join(tmpdir(), 'mosaic-def-bus-')); const rolesDir = rolesCopy(root); const doc = businessDoc(root, 'demo'); const file = writeJson(join(root, 'businesses/demo.json'), { ...doc, plugins: { ...doc.plugins, harness: ['pi'] } }); const data = join(root, 'data'); mkdirSync(data, { mode: 0o700 }); const token = join(root, 'held.token'); writeFileSync(token, TOKEN, { mode: 0o600 }); chmodSync(token, 0o600); const bus = await startBroker({ dataRoot: data, businesses: { demo: { id: 'demo', human: 'jason', arbiters: { technical: 'chief', delivery: 'chief' }, vars: { 'bus.tester': true }, roles: { chief: { definition: 'chief-of-staff', authority: { withinRole: ['decision.resolve.technical', 'decision.resolve.delivery'], crossRole: [] } }, coder: { authority: { withinRole: [], crossRole: [] }, credentials: { gitea: { file: token, rotateBy: '2099-01-01' } } }, } } }, organization: { dir: root, rolesDir, system: systemFor(root) } }); t.after(async () => { await bus.close(); rmSync(root, { recursive: true, force: true }); }); const b = bus.broker; const human = b.bindHuman({ business: 'demo', human: 'jason', via: 'cli', outsideAgent: true }); const revision = () => b.request(human, { verb: 'limits' }).revision; const invent = (name) => ({ verb: 'definition.invent', args: { revision: revision(), name, definition: SCOUT } }); // An agent, a reader and the tester never reach the writer. const before = readFileSync(file); const agent = b.bindLaunch({ business: 'demo', role: 'coder', run: 'coder-run', harness: 'pi', address: 'coder-run' }); for (const cap of [agent, b.bindReader({ business: 'demo' })]) assert.throws(() => b.request(cap, invent('scout')), /human-required/); assert.throws(() => b.request(b.bindTester({ business: 'demo' }), invent('scout')), /tester-refused/); // Unknown and missing arguments refuse; an actor can't be forged through them. assert.throws(() => b.request(human, { verb: 'definition.invent', args: { ...invent('scout').args, actor: 'mallory' } }), /invalid-request/); assert.throws(() => b.request(human, { verb: 'definition.remove', args: { revision: revision(), name: 'scout' } }), /invalid-request/); assert.deepEqual(readFileSync(file), before); // The human's invent commits, as the human, with a receipt that carries no role text. const receipt = b.request(human, invent('scout')); assert.deepEqual({ ...receipt, revision: 0, transaction: 0 }, { verb: 'invent', organization: 'demo', definition: 'scout', rev: 1, revision: 0, transaction: 0 }); assert.equal(JSON.parse(readFileSync(file, 'utf8')).definitions.scout.instructions, SCOUT.instructions); const last = JSON.parse(readFileSync(join(root, 'businesses/.history/demo/changes.jsonl'), 'utf8').trim().split('\n').at(-1)); assert.equal(last.actor, 'jason'); assert.equal(last.state, 'committed'); // A writer refusal passes by its code. assert.throws(() => b.request(human, invent('scout')), /definition-exists/); // The bus refuses a request that carries the held token, and the writer refuses a template whose // contract carries it (the import request itself holds no token). Neither writes. const written = readFileSync(file); assert.throws(() => b.request(human, { verb: 'definition.invent', args: { revision: revision(), name: 'leak', definition: { ...SCOUT, instructions: `Use ${TOKEN}.\n` } } }), (e) => e.code === 'credential-leak' && !e.message.includes(TOKEN)); appendFileSync(join(rolesDir, 'coder.md'), `\nUse ${TOKEN} for the forge.\n`); assert.throws(() => b.request(human, { verb: 'definition.import', args: { revision: revision(), template: 'coder' } }), (e) => e.code === 'invalid-request' && !e.message.includes(TOKEN) && !String(e.stack).includes(TOKEN)); assert.deepEqual(readFileSync(file), written); for (const path of [...files(data), ...files(join(root, 'businesses'))]) assert.ok(!readFileSync(path).includes(TOKEN), path); });