Files
stack/packages/bus/tests/model-retirement-boundary.test.mjs
jason.woltje 362893d043 feat: integrate reviewed proxy page and managed model keys
Source-candidate: poe d9a564e6d20f5f0fd75ce45b12cbbf8bb4c9d568\nSource-candidate: magica38ba5762b06716db1dee00d0afec162656488f5c\nValidated321whole-file phase plus whole bus1349/model-proxy100/webui490; final gate tooling checks pending, not landed.
2026-10-26 12:04:21 -05:00

87 lines
5.1 KiB
JavaScript

// B1/647: discovery changes while real retirement HTTP is in flight.
import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import http from 'node:http';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { createHash, randomBytes } from 'node:crypto';
import { Credentials } from '../src/credentials.mjs';
import { BusError } from '../src/broker.mjs';
import { ModelKeys } from '../src/model-keys.mjs';
import { ManagementClient } from '../../model-proxy/src/client.mjs';
const id = value => createHash('sha256').update(value).digest('hex').slice(0, 12);
async function fixture(t, boundary) {
const root = fs.mkdtempSync(join(tmpdir(), 'b1-boundary-'));
let server, credentials;
t.after(async () => {
try { credentials?.close(); }
finally {
server?.closeAllConnections();
if (server?.listening) await new Promise(resolve => server.close(resolve));
fs.rmSync(root, { recursive: true, force: true });
}
});
const configDir = join(root, 'config'), storeRoot = join(configDir, 'secrets', 'agents');
fs.mkdirSync(storeRoot, { recursive: true, mode: 0o700 });
const sentinel = `msk-${id(configDir)}-sentinel-${randomBytes(32).toString('base64url')}`;
const state = { keys: [sentinel], armed: false, discoveryFailed: false, calls: [], faults: 0, refusals: 0 };
const receipts = [];
server = http.createServer(async (req, res) => {
const management = req.url === '/v8/management/config/access/api-keys';
state.calls.push(management ? req.method : 'PROBE');
if (management) {
if (req.headers.authorization !== 'Bearer fx647-manage') { res.writeHead(401); res.end('{}'); return; }
if (req.method === 'GET') {
if (state.armed && boundary === 'management-GET' && !state.discoveryFailed) { state.discoveryFailed = true; state.faults++; }
res.end(JSON.stringify(state.keys)); return;
}
const chunks = []; for await (const chunk of req) chunks.push(chunk);
state.keys = JSON.parse(Buffer.concat(chunks));
res.end(JSON.stringify({ status: 'ok' })); return;
}
const status = state.keys.includes(req.headers.authorization?.slice(7)) ? 200 : 401;
if (state.armed && boundary === 'confirmed-401' && status === 401) { state.discoveryFailed = true; state.faults++; }
res.writeHead(status); res.end('{}');
});
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
const baseUrl = `http://127.0.0.1:${server.address().port}`;
credentials = new Credentials({ storeRoot, dataRoot: join(root, 'data'), modelAgents: ['demo/chief'] });
const manager = new ModelKeys({ credentials, configDir, baseUrl,
client: new ManagementClient({ baseUrl, key: 'fx647-manage', receipt: entry => receipts.push(entry) }),
receipt: entry => receipts.push(entry),
// Fault models authoritative discovery becoming uncertain. Do not replace the
// controller, mutation method, HTTP operation or private-record implementation.
runs: () => { if (state.discoveryFailed) { state.refusals++; throw new BusError('proxy-stop-failed'); } return []; } });
await manager.reconcile(); const first = await manager.ensure('demo/chief'); await manager.rotate('demo/chief');
state.calls.length = 0; receipts.length = 0; state.armed = true;
return { state, receipts, credentials, manager, oldKey: first.key, oldId: id(first.key),
retained: () => assert.equal(credentials.modelRecord('demo/chief').retiring.some(r => r.keyId === id(first.key)), true, 'local retiring record retained'),
valueFree: () => {
const output = JSON.stringify(receipts);
assert.equal(output.includes(first.key), false);
assert.equal(output.includes('fx647-manage'), false);
assert.equal(output.includes(credentials.modelRecord('demo/chief').key), false);
} };
}
test('B1 discovery failure during fresh management GET refuses before retirement PUT', async t => {
const f = await fixture(t, 'management-GET');
await assert.rejects(f.manager.sweep(), error => error.code === 'proxy-stop-failed', 'fresh discovery refusal required before remote mutation');
assert.equal(f.state.faults, 1); assert.equal(f.state.refusals, 1);
assert.deepEqual(f.state.calls, ['GET'], 'no removal PUT or extra mutation after discovery failure');
assert.equal(f.state.keys.includes(f.oldKey), true, 'remote old key retained');
f.retained(); f.valueFree();
});
test('B1 discovery failure during confirmed401 refuses before retiring metadata deletion', async t => {
const f = await fixture(t, 'confirmed-401');
await assert.rejects(f.manager.sweep(), error => error.code === 'proxy-stop-failed', 'fresh discovery refusal required before local deletion');
assert.equal(f.state.faults, 1); assert.equal(f.state.refusals, 1);
assert.deepEqual(f.state.calls, ['GET', 'PUT', 'GET', 'PROBE'], 'one remote revoke, no rollback or extra mutation');
assert.equal(f.state.keys.includes(f.oldKey), false, 'remote key already revoked; no rollback claim');
assert.ok(f.receipts.some(entry => entry.call === 'GET /v1/models' && entry.status === 401 && entry.keyIds.includes(f.oldId)), 'observed remote401 receipt');
f.retained(); f.valueFree();
});