41 lines
2.6 KiB
JavaScript
41 lines
2.6 KiB
JavaScript
// Row 298: the real runtime routes the human scope verb to the durable
|
|
// organization writer. Everything lives under a scratch config/data root.
|
|
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { mkdirSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import { startBroker } from '../src/runtime.mjs';
|
|
import { businessDoc, rolesCopy, systemFor, writeJson } from '../../organization/tests/helpers.mjs';
|
|
|
|
// Break caught: missing runtime setter routing or losing the organization receipt.
|
|
test('row 298 runtime: human scope approval writes the file and organization history at the supplied revision', async t => {
|
|
const root = mkdtempSync(join(tmpdir(), 'scope-runtime-'));
|
|
let runtime;
|
|
t.after(async () => { await runtime?.close(); rmSync(root, { recursive: true, force: true }); });
|
|
const rolesDir = rolesCopy(root);
|
|
const file = writeJson(join(root, 'businesses/demo.json'), businessDoc(root, 'demo'));
|
|
mkdirSync(join(root, 'data'), { mode: 0o700 });
|
|
runtime = await startBroker({ dataRoot: join(root, 'data'),
|
|
businesses: { demo: { 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: { authority: { withinRole: [], crossRole: [] } } } } },
|
|
organization: { dir: root, rolesDir, system: systemFor(root) },
|
|
});
|
|
const human = runtime.broker.bindHuman({ business: 'demo', human: 'jason', via: 'cli', outsideAgent: true });
|
|
const call = (verb, args = {}) => runtime.broker.request(human, { verb, args });
|
|
const before = call('grants.scope');
|
|
assert.deepEqual(before.scope, {});
|
|
const scope = { gitea: { agents: ['coder'], projects: ['stack'] } };
|
|
const saved = call('grants.scope.set', { revision: before.revision, scope });
|
|
assert.deepEqual(JSON.parse(readFileSync(file, 'utf8')).launch.grantScope, scope);
|
|
assert.deepEqual(call('grants.scope').scope, scope);
|
|
assert.notEqual(saved.revision, before.revision);
|
|
const entries = readFileSync(join(root, 'businesses/.history/demo/changes.jsonl'), 'utf8').trim().split('\n').map(JSON.parse);
|
|
assert.equal(entries.at(-1).state, 'committed');
|
|
assert.equal(entries.at(-1).actor, 'jason');
|
|
assert.equal(entries.at(-1).changes[0].path, 'launch.grantScope');
|
|
const bytes = readFileSync(file, 'utf8');
|
|
assert.throws(() => call('grants.scope.set', { revision: before.revision, scope: {} }), e => e.code === 'revision-conflict');
|
|
assert.equal(readFileSync(file, 'utf8'), bytes);
|
|
});
|