// P4 named mutant: API key echoed in a response, error, log or durable record. // Real HTTP -> human capability -> broker -> page -> management client -> fake. import test from 'node:test'; import assert from 'node:assert/strict'; import { request } from 'node:http'; import { mkdtempSync, readdirSync, readFileSync, rmSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { fakeManagement } from '../../bus/tests/proxy-page-fixture.mjs'; import { Store } from '../../bus/src/store.mjs'; import { Broker } from '../../bus/src/broker.mjs'; import { startServer } from '../src/serve.mjs'; import { createSsoSession } from './helpers/sso-session.mjs'; const scan = root => readdirSync(root, { withFileTypes: true }).flatMap(e => e.isDirectory() ? scan(join(root, e.name)) : [readFileSync(join(root, e.name))]); test('API-key canary reaches fake once and zero responses/logs/receipts/store files', async t => { const canary = 'p4-canary-key'; const fake = await fakeManagement(t); const root = mkdtempSync(join(tmpdir(), 'p4-canary-')); const store = new Store(root); t.after(() => { store.close(); rmSync(root, { recursive: true, force: true }); }); const b = new Broker({ store, proxyPage: (...args) => fake.page.request(...args), businesses: { demo: { id: 'demo', human: 'owner', roles: {chief: { definition: 'chief-of-staff', authority: { withinRole: ['decision.resolve.technical', 'decision.resolve.delivery'], crossRole: [] } }, coder: { authority: { withinRole: [], crossRole: [] } } }, arbiters: { technical: 'chief', delivery: 'chief' } } } }); const cap = b.bindHuman({ business: 'demo', human: 'owner', via: 'cli', outsideAgent: true }); const logs = [], output = []; const auth = await createSsoSession(t, { host: 'console.example', owner: { sub: 'owner-sub', name: 'owner' } }); const server = await startServer({ port: 0, sso: auth.sso, send: async () => ({}), proxyCall: (verb, args) => b.request(cap, { verb, args }), log: line => logs.push(line) }); t.after(() => new Promise(r => server.close(r))); const session = await auth.signIn(server.address().port); const headers = auth.writeHeaders(session); const call = (path, data) => new Promise((resolve, reject) => { const req = request({ hostname: '127.0.0.1', port: server.address().port, path, method: data ? 'POST' : 'GET', headers }, res => { let text = ''; res.on('data', c => text += c); res.on('end', () => { output.push(text); resolve(res.statusCode); }); }); req.on('error', reject); req.end(data ? JSON.stringify(data) : undefined); }); // Capture process output during the operation as well as structured log // callbacks. Even a deliberate log-leak mutant must never print its canary. const stdout = process.stdout.write, stderr = process.stderr.write; const capture = (chunk, ...rest) => { output.push(Buffer.from(chunk)); const cb = rest.at(-1); if (typeof cb === 'function') cb(); return true; }; let added, accounts; try { process.stdout.write = capture; process.stderr.write = capture; added = await call('/api/proxy/apikey/add', { provider: 'z.ai', key: canary }); accounts = await call('/api/proxy/accounts'); } finally { process.stdout.write = stdout; process.stderr.write = stderr; } assert.equal(added, 200); assert.equal(accounts, 200); assert.equal(fake.state.receives, 1); assert.equal(fake.state.groups[0].keys[0]['api-key'] === canary, true); for (const bytes of [...output, ...logs, JSON.stringify(fake.state.receipts), ...scan(root)]) assert.equal(Buffer.from(bytes).includes(Buffer.from(canary)), false, 'credential value escaped'); }); test('OAuth URLs, state and code stay out of broker records and management receipts', async t => { const fake = await fakeManagement(t); const root = mkdtempSync(join(tmpdir(), 'p4-oauth-')); const store = new Store(root); t.after(() => { store.close(); rmSync(root, { recursive: true, force: true }); }); const b = new Broker({ store, proxyPage: (...args) => fake.page.request(...args), businesses: { demo: { id: 'demo', human: 'owner', roles: {chief: { definition: 'chief-of-staff', authority: { withinRole: ['decision.resolve.technical', 'decision.resolve.delivery'], crossRole: [] } }, coder: { authority: { withinRole: [], crossRole: [] } } }, arbiters: { technical: 'chief', delivery: 'chief' } } } }); const cap = b.bindHuman({ business: 'demo', human: 'owner', via: 'cli', outsideAgent: true }); const call = (verb, args = {}) => b.request(cap, { verb, args }); const login = await call('proxy.login.start', { provider: 'claude' }); const callback = 'http://localhost/callback?state=' + login.state + '&code=p4-private-code'; assert.deepEqual(await call('proxy.login.submit', { redirect_url: callback }), { status: 'wait' }); assert.deepEqual(await call('proxy.login.status', { state: login.state }), { status: 'wait' }); for (const value of [login.url, login.state, callback, 'p4-private-code']) { assert.equal(JSON.stringify(fake.state.receipts).includes(value), false); for (const bytes of scan(root)) assert.equal(bytes.includes(Buffer.from(value)), false); } });