50 lines
3.5 KiB
JavaScript
50 lines
3.5 KiB
JavaScript
// Local management stand-in. All credentials made up, kept only in this test's
|
|
// memory; logs collect endpoint names, never query strings, headers or bodies.
|
|
import http from 'node:http';
|
|
import { ManagementClient } from '../../model-proxy/src/client.mjs';
|
|
import { ProxyPage } from '../src/proxy-page.mjs';
|
|
export async function fakeManagement(t, options = {}) {
|
|
const state = { files: [], groups: [], keys: ['msk-fixture-sentinel-x', 'foreign-key'], receives: 0,
|
|
calls: [], receipts: [], priorityNoop: false, patchStatus: 200, ...options };
|
|
let nextId = 1;
|
|
const server = http.createServer(async (req, res) => {
|
|
const u = new URL(req.url, 'http://localhost');
|
|
const chunks = []; for await (const c of req) chunks.push(c);
|
|
const value = chunks.length ? JSON.parse(Buffer.concat(chunks)) : null;
|
|
state.calls.push(req.method + ' ' + u.pathname);
|
|
const reply = (status, body) => { res.writeHead(status, { 'content-type': 'application/json' }); res.end(JSON.stringify(body)); };
|
|
if (req.headers.authorization !== 'Bearer p4-management') return reply(401, { error: 'refused' });
|
|
if (u.pathname === '/v8/management/credentials') return reply(200, { files: state.files, observed_at: '2026-10-24T00:00:00Z' });
|
|
if (u.pathname === '/v8/management/config/api-keys/claude') {
|
|
if (req.method === 'GET') {
|
|
if (state.groups.length === 0 && state.emptyProviderResponse)
|
|
return reply(state.emptyProviderResponse.status, state.emptyProviderResponse.body);
|
|
return reply(200, state.groups);
|
|
}
|
|
// Stand-in treats auth_index as derived/read-only metadata.
|
|
if (value.some(g => (g.keys ?? []).some(k => Object.hasOwn(k, 'auth_index')))) return reply(422, { error: 'derived field' });
|
|
state.receives++;
|
|
if (!state.priorityNoop) state.groups = value.map(g => ({ ...g, keys: g.keys.map(k => ({ ...k, auth_index: state.groups.flatMap(old => old.keys ?? []).find(old => old['api-key'] === k['api-key'])?.auth_index ?? `upstream-${nextId++}` })) }));
|
|
return reply(200, { status: 'ok' });
|
|
}
|
|
if (u.pathname === '/v8/management/credentials/fields') {
|
|
if (state.patchStatus !== 200) return reply(state.patchStatus, { error: 'p4-private-detail' });
|
|
const row = state.files.find(f => f.name === value.name);
|
|
if (!row) return reply(404, { error: 'not found' });
|
|
if (!state.priorityNoop) row.priority = value.priority;
|
|
return reply(200, { status: 'ok' });
|
|
}
|
|
if (u.pathname === '/v8/management/config/access/api-keys') return reply(200, state.keys);
|
|
if (u.pathname === '/v8/management/oauth/auth-url') return reply(200, { status: 'ok', state: 'p4-state', url: 'https://claude.ai/oauth/authorize?state=p4-state' });
|
|
if (u.pathname === '/v8/management/oauth/status') return reply(200, { status: 'wait' });
|
|
if (u.pathname === '/v8/management/oauth/callback' || u.pathname === '/v8/management/oauth/session') return reply(200, { status: 'ok' });
|
|
return reply(404, {});
|
|
});
|
|
await new Promise(r => server.listen(0, '127.0.0.1', r));
|
|
t.after(() => new Promise(r => server.close(r)));
|
|
const client = new ManagementClient({ baseUrl: `http://127.0.0.1:${server.address().port}`, key: 'p4-management', receipt: entry => state.receipts.push(entry) });
|
|
const page = new ProxyPage({ client, instanceTag: 'fixture', lock: options.lock ?? null, org: options.org ?? null, keyRecords: () => options.records ?? [] });
|
|
const call = (verb, args = {}) => page.request(verb, args, { business: 'demo', human: 'owner' });
|
|
return { state, page, call, client, server };
|
|
}
|