Files
stack/packages/bus/tests/model-proxy.test.mjs

39 lines
5.2 KiB
JavaScript

// P1's human proof boundary; all records and fixture input under short TMPDIR.
import test from 'node:test';
import assert from 'node:assert/strict';
import { mkdtempSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { Broker } from '../src/broker.mjs';
import { Store } from '../src/store.mjs';
const role={authority:{withinRole:['message.send'],crossRole:[]}};
function fixture(t,proxyInit){const store=new Store(mkdtempSync(join(tmpdir(),'p1-bus-')));t.after(()=>store.close());const b=new Broker({store,proxyInit,businesses:{demo:{id:'demo',human:'owner',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:role}}}});return {store,b,human:b.bindHuman({business:'demo',human:'owner',via:'cli',outsideAgent:true}),tester:b.bindTester({business:'demo'}),reader:b.bindReader({business:'demo'}),agent:b.bindLaunch({business:'demo',role:'coder',run:'p1-run',harness:'pi'})};}
test('proxy.init only accepts path-bound outside-agent human; refuses agent/tester/reader',async t=>{const calls=[];const f=fixture(t,async a=>{calls.push(a);return {port:a.port,binary:'/fixture'};});for(const cap of [f.tester,f.agent])assert.throws(()=>f.b.request(cap,{verb:'proxy.init',args:{key:'p1-management'}}),e=>e.code==='human-required');assert.throws(()=>f.b.request(f.reader,{verb:'proxy.init',args:{key:'p1-management'}}),e=>e.code==='read-only');assert.equal(calls.length,0);assert.deepEqual(await f.b.request(f.human,{verb:'proxy.init',args:{key:'p1-management',port:18432}}),{port:18432,binary:'/fixture'});assert.equal(JSON.stringify(f.store.all('SELECT body FROM events')).includes('p1-management'),false);});
for(const [code,args]of [['proxy-key-invalid',{key:'a\nb'}],['proxy-config-invalid',{key:'p1-management',port:8317}],['invalid-request',{key:'p1-management',binary:'/forged'}]])test(`proxy.init ${code}`,t=>{const f=fixture(t,()=>{throw Error('must not call');});assert.throws(()=>f.b.request(f.human,{verb:'proxy.init',args}),e=>e.code===code);});
test('proxy.init not-configured',t=>{const f=fixture(t,null);assert.throws(()=>f.b.request(f.human,{verb:'proxy.init',args:{key:'p1-management'}}),e=>e.code==='not-configured');});
test('proxy.init callback error redacts key and maps outcome to named refusal',async t=>{const f=fixture(t,()=>{throw Error('p1-management');});await assert.rejects(f.b.request(f.human,{verb:'proxy.init',args:{key:'p1-management'}}),e=>e.code==='proxy-init-failed'&&!e.message.includes('p1-management'));assert.equal(JSON.stringify(f.store.all('SELECT body FROM events')).includes('p1-management'),false);});
test('socket awaits proxy.init and does not return a Promise object or retain human cap',async t=>{const {serve}=await import('../src/server.mjs');const {Client}=await import('../src/client.mjs');const f=fixture(t,async()=>{await new Promise(r=>setTimeout(r,10));return {port:18432,binary:'/fixture'};});const root=mkdtempSync(join(tmpdir(),'p1-sock-'));const socket=join(root,'s');const server=await serve({broker:f.b,path:socket,peerReader:{read:async()=>({pid:process.pid,uid:process.getuid(),gid:process.getgid()}),close(){}},authenticateHuman:()=>f.b.bindHuman({business:'demo',human:'owner',via:'cli',outsideAgent:true})});t.after(()=>server.close());const client=new Client({path:socket,human:{business:'demo',pid:process.pid,startTime:'1',nonce:'fixture'}});assert.deepEqual(await client.call('proxy.init',{key:'p1-management'}),{port:18432,binary:'/fixture'});});
test('proxy-init-failed: extra callback fields cannot return a management key',async t=>{const f=fixture(t,async()=>({port:18432,binary:'/fixture',key:'p1-management'}));await assert.rejects(f.b.request(f.human,{verb:'proxy.init',args:{key:'p1-management'}}),e=>e.code==='proxy-init-failed');assert.equal(JSON.stringify(f.store.all('SELECT body FROM events')).includes('p1-management'),false);});
// P2 R2-N1: catches local broker predicates diverging from management-client rules.
for (const [label, key] of [['Latin-1', 'fx331-caf\u00e9'], ['leading space', ' fx331-key'], ['trailing space', 'fx331-key '], ['internal space', 'fx331 key']]) {
test(`proxy-key-invalid: broker rejects ${label} before initializer`, async t => {
let called = false;
const f = fixture(t, () => { called = true; return { port: 18432, binary: '/fixture' }; });
let pending;
try {
assert.throws(() => { pending = f.b.request(f.human, { verb: 'proxy.init', args: { key } }); }, e => e.code === 'proxy-key-invalid');
} finally { await Promise.resolve(pending).catch(() => {}); }
assert.equal(called, false);
assert.equal(JSON.stringify(f.store.all('SELECT body FROM events')).includes(key), false);
});
}
for (const [field, code, value] of [['rotateGraceMinutes', 'proxy-rotate-grace-invalid', 1441], ['firstOutputSeconds', 'proxy-first-output-invalid', 3601]]) {
test(`proxy.init ${code}: human setting validated before initializer`, t => {
let called = false; const f = fixture(t, () => { called = true; });
assert.throws(() => f.b.request(f.human, { verb: 'proxy.init', args: { key: 'fx331-manage', [field]: value } }), e => e.code === code);
assert.equal(called, false);
});
}