Files
stack/packages/bus/tests/project-await.test.mjs

62 lines
3.1 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { mkdtempSync, rmSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { Store } from '../src/store.mjs';
import { Broker, BusError } from '../src/broker.mjs';
function fixture(t, project, secretCheck = () => {}) {
const root = mkdtempSync(join(tmpdir(), 'project-await-'));
const store = new Store(root);
t.after(() => { store.close(); rmSync(root, { recursive: true, force: true }); });
const business = { id: 'demo', human: 'jason', arbiters: { technical: 'chief', delivery: 'chief' }, roles: {chief: { definition: 'chief-of-staff', authority: { withinRole: ['decision.resolve.technical', 'decision.resolve.delivery'], crossRole: [] } },
coder: { definition: 'coder', authority: { withinRole: ['record.write'], crossRole: [] } },
} };
const broker = new Broker({ store, businesses: { demo: business }, project, secretCheck });
const cap = broker.bindLaunch({ business: 'demo', role: 'coder', run: 'run', harness: 'pi', address: 'coder' });
const call = (verb, args = {}) => broker.request(cap, { verb, args });
call('role.claim');
return { broker, cap, call, store };
}
test('D1: committed write with a failed receipt refuses outcome-unknown without action.allowed', async t => {
let f, committed = false;
f = fixture(t, { async writeRecord() {
committed = true;
f.call('role.release');
return { path: 'docs/result.md', commit: 'a'.repeat(40) };
} });
let returned;
await assert.rejects(async () => {
returned = await f.call('record.write', { project: 'stack', path: 'docs/result.md', record: '# Result' });
}, { code: 'outcome-unknown' });
assert.equal(committed, true);
assert.equal(returned, undefined);
assert.deepEqual(f.store.all("SELECT body FROM events WHERE kind='action.allowed' AND json_extract(body,'$.action')='record.write'"), []);
});
test('D2: spec.read refuses without content if its role is released during the read', async t => {
let f;
f = fixture(t, { async readSpec() {
f.call('role.release');
return { content: 'CONTENT-MUST-NOT-RETURN' };
} });
let returned;
await assert.rejects(async () => { returned = await f.call('spec.read', { project: 'stack' }); }, { code: 'not-holder' });
assert.equal(returned, undefined);
assert.ok(!JSON.stringify(f.store.all('SELECT body FROM events')).includes('CONTENT-MUST-NOT-RETURN'));
});
for (const field of ['content', 'subject']) test(`D3: spec.read secret check refuses flagged ${field} without content`, async t => {
const marker = 'FLAGGED-SPEC-VALUE';
const result = { content: field === 'content' ? marker : '# Safe', log: [{ subject: field === 'subject' ? marker : 'Safe' }] };
const f = fixture(t, { async readSpec() { return result; } }, value => {
if (JSON.stringify(value).includes(marker)) throw new BusError('secret-refused');
});
let returned;
await assert.rejects(async () => { returned = await f.call('spec.read', { project: 'stack' }); }, { code: 'secret-refused' });
assert.equal(returned, undefined);
assert.ok(!JSON.stringify(f.store.all('SELECT body FROM events')).includes(marker));
});