test(proxy): prepare empty-provider 404 regressions before normalization

This commit is contained in:
jason.woltje committed 2026-10-25 02:39:25 -05:00
1 parent c93df1608a
commit e7438743ff
7 files changed
+180 -1

No files matched your search

+32
View File
@@ -491,3 +491,35 @@ silently turn unknown failures into empty data. Run lists/CLEAR precede tests.
No product or test changed in this receipt/proposal commit. Proposed patch is
review material, not a fix claim or a substitute for RED/GREEN/upgrade evidence.
## Regression preparation — sage-4460, no Node execution
2026-10-25T07:38Z. Authored11 cases in two new whole test files:
packages/model-proxy/tests/empty-provider.test.mjs (8): exact fixed GET404 ->[],
actual404 receipt/discarded canary body/one request; credentials404 and key-list404
remain proxy-client-refused; provider401/403/500 remain proxy-client-refused;
providerPUT404 remains proxy-client-refused (exercises GET-only guard);200 array
passes through. Every case pins exactly one call and status receipt, no retry,
no response-body/management-key leakage into receipts or error output.
packages/bus/tests/proxy-page-empty-provider.test.mjs (3): fresh404 empty account
list followed by one first-key PUT and a public safe account; malformed200 null
and object each refuse existing proxy-down with no write/retry.
Stand-in addition only: optional emptyProviderResponse controls the empty-route
status/body for these new cases. Existing fake baseline and every old assertion
and timeout remain unchanged. Imports are declared directly to ManagementClient
and the existing management fixture (which imports ProxyPage/client). Static
single-line import declarations are recorded in empty-provider-prepared-imports
and rooted in the prior esbuild graph; no fixture-text search selects tests.
Exact initial RED list: empty-provider-red-run-list.txt. Prepared source/test/patch
hashes: empty-provider-prepared-MANIFEST.sha256. Product files remain unmodified;
proposed-empty-provider.patch is still NOT APPLIED.
Expected first RED: new exact404 client case rejects proxy-client-refused instead
of returning[]; new fresh account case rejects proxy-down before add. No new
refusal code; all negative cases preserve existing named refusals. Observe this
RED under the next CLEAR before applying the approved scoped source patch.
Required later GREEN should include both new whole files and the8 focused whole
files because the helper is shared; full gate and P2 key-join still wait their
separate authorized stage. No Node syntax check, test, acceptance, mutant or
proxy process ran during preparation. Slot remains with Magica331r4.
@@ -0,0 +1,8 @@
ed5dfcda6db77921f90f1eb587fb0044d6472fb613ecaa98445ed42bc04d5d46 packages/model-proxy/tests/empty-provider.test.mjs
c55cc0bb47cd7716a2c31c665cd2dd426e2c54ab7b629637bdc12089dfeb40ce packages/bus/tests/proxy-page-empty-provider.test.mjs
01c18d8d09dac72bed45ce302a88cea449ed22ffde374529cf784bad38adbd72 packages/bus/tests/proxy-page-fixture.mjs
aa73c4cd454742f7745900e8481f7425341ed7d236b104589790ed254c8bd69f packages/model-proxy/src/client.mjs
14acdb4d3fdaabad508eec7378740b13c175d4bdd0c6e707a673138eff82365b packages/bus/src/proxy-page.mjs
b19292cad28bd19427fac932c6150429968e184f4a6f000d948919e76908eb05 agents/poe/work/queue-330/proposed-empty-provider.patch
ea7584f8935251baa9c32bf675343e8c8cbe19a45c4e7dc48675e14b4409bb1c agents/poe/work/queue-330/empty-provider-prepared-imports.json
5d227ae19d600c2fb0e375673045705c4f5bcc00311493a577108caddb38704a agents/poe/work/queue-330/empty-provider-red-run-list.txt
@@ -0,0 +1,34 @@
{
"packages/model-proxy/tests/empty-provider.test.mjs": {
"staticImports": [
"node:test",
"node:assert/strict",
"node:http",
"packages/model-proxy/src/client.mjs"
],
"existingParsedClosureRoots": [
"packages/model-proxy/src/client.mjs"
]
},
"packages/bus/tests/proxy-page-empty-provider.test.mjs": {
"staticImports": [
"node:test",
"node:assert/strict",
"packages/bus/tests/proxy-page-fixture.mjs"
],
"existingParsedClosureRoots": [
"packages/bus/tests/proxy-page-fixture.mjs"
]
},
"packages/bus/tests/proxy-page-fixture.mjs": {
"staticImports": [
"node:http",
"packages/model-proxy/src/client.mjs",
"packages/bus/src/proxy-page.mjs"
],
"existingParsedClosureRoots": [
"packages/model-proxy/src/client.mjs",
"packages/bus/src/proxy-page.mjs"
]
}
}
@@ -0,0 +1,2 @@
packages/model-proxy/tests/empty-provider.test.mjs
packages/bus/tests/proxy-page-empty-provider.test.mjs
@@ -0,0 +1,33 @@
// P4 real client/page regression: fresh pinned proxy404 must allow the first key.
// Malformed successful bodies still fail closed with the existing refusal code.
import test from 'node:test';
import assert from 'node:assert/strict';
import { fakeManagement } from './proxy-page-fixture.mjs';
const route = '/v8/management/config/api-keys/claude';
test('fresh404 yields no accounts, then adds the first key once with no value leakage', async t => {
const canary = 'p4-first-key';
const s = await fakeManagement(t, { emptyProviderResponse: { status: 404, body: { error: 'p4-body-canary' } } });
const empty = await s.call('proxy.accounts');
assert.equal(Array.isArray(empty.accounts), true); assert.equal(empty.accounts.length, 0);
const added = await s.call('proxy.apikey.add', { provider: 'z.ai', key: canary });
assert.equal(added.added, true);
const populated = await s.call('proxy.accounts');
assert.equal(populated.accounts.length, 1); assert.equal(populated.accounts[0].provider, 'z.ai');
assert.equal(s.state.receives, 1, 'one PUT, no retry');
assert.equal(s.state.groups[0].keys[0]['api-key'] === canary, true);
assert.deepEqual(s.state.calls, ['GET /v8/management/credentials', `GET ${route}`, `GET ${route}`, `PUT ${route}`,
'GET /v8/management/credentials', `GET ${route}`]);
assert.deepEqual(s.state.receipts.filter(r => r.call === `GET ${route}`).map(r => r.status), [404, 404, 200]);
for (const value of [canary, 'p4-body-canary', 'p4-management']) {
assert.equal(JSON.stringify([empty, added, populated]).includes(value), false);
assert.equal(JSON.stringify(s.state.receipts).includes(value), false);
}
});
for (const [name, body] of [['null', null], ['object', { groups: [] }]])
test(`malformed200 ${name} remains proxy-down, no retry or write`, async t => {
const s = await fakeManagement(t, { emptyProviderResponse: { status: 200, body } });
await assert.rejects(s.call('proxy.accounts'), { code: 'proxy-down' });
assert.deepEqual(s.state.calls, ['GET /v8/management/credentials', `GET ${route}`]);
assert.equal(s.state.receives, 0);
assert.deepEqual(s.state.receipts.map(r => r.status), [200, 200]);
});
+5 -1
View File
@@ -16,7 +16,11 @@ export async function fakeManagement(t, options = {}) {
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') return reply(200, state.groups);
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++;
@@ -0,0 +1,66 @@
// P4 pinned8.0.42 regression: absent Claude provider config is HTTP404.
// Normalize only that fixed GET; all other methods/endpoints/statuses refuse.
import test from 'node:test';
import assert from 'node:assert/strict';
import http from 'node:http';
import { ManagementClient } from '../src/client.mjs';
const endpoint = '/v8/management/config/api-keys/claude';
const bodyCanary = 'p4-body-canary';
async function fixture(t, status, body = { error: bodyCanary, 'api-key': bodyCanary }) {
const requests = [], receipts = [];
const server = http.createServer(async (req, res) => {
const chunks = []; for await (const chunk of req) chunks.push(chunk);
requests.push({ method: req.method, path: req.url, body: Buffer.concat(chunks).toString('utf8') });
res.writeHead(status, { 'content-type': 'application/json' }); res.end(JSON.stringify(body));
});
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: r => receipts.push(r) });
return { client, requests, receipts };
}
function evidence(s, method, path, status) {
assert.equal(s.requests.length, 1, 'one call, no retry');
assert.deepEqual(s.requests.map(r => [r.method, r.path]), [[method, path]]);
assert.deepEqual(s.receipts, [{ call: `${method} ${path}`, status, keyIds: [] }]);
assert.equal(JSON.stringify(s.receipts).includes(bodyCanary), false);
assert.equal(JSON.stringify(s.receipts).includes('p4-management'), false);
}
async function refused(operation) {
let failure;
try { await operation(); } catch (error) { failure = error; }
assert.equal(failure?.code, 'proxy-client-refused');
assert.equal(failure.message.includes(bodyCanary), false, 'no error-body value escapes');
assert.equal(JSON.stringify(failure).includes(bodyCanary), false);
}
test('empty provider GET404 yields empty array, discards body and receipts actual404 once', async t => {
const s = await fixture(t, 404);
const result = await s.client.getUpstreamGroups();
assert.equal(Array.isArray(result), true); assert.equal(result.length, 0);
assert.equal(JSON.stringify(result).includes(bodyCanary), false);
evidence(s, 'GET', endpoint, 404);
});
for (const status of [401, 403, 500]) test(`provider GET${status} remains proxy-client-refused, no retry`, async t => {
const s = await fixture(t, status);
await refused(() => s.client.getUpstreamGroups());
evidence(s, 'GET', endpoint, status);
});
for (const [method, path] of [['getCredentials', '/v8/management/credentials'], ['getKeys', '/v8/management/config/access/api-keys']])
test(`${method}404 remains proxy-client-refused, no retry`, async t => {
const s = await fixture(t, 404);
await refused(() => s.client[method]());
evidence(s, 'GET', path, 404);
});
test('provider PUT404 remains proxy-client-refused, never treated as empty GET', async t => {
const s = await fixture(t, 404);
await refused(() => s.client.putUpstreamGroups([{ name: 'fixture', keys: [{ 'api-key': 'p4-first-key' }] }]));
evidence(s, 'PUT', endpoint, 404);
assert.equal(s.requests[0].body.includes('p4-first-key'), true);
assert.equal(JSON.stringify(s.receipts).includes('p4-first-key'), false);
});
test('provider GET200 array passes through, with receipt and no retry', async t => {
const s = await fixture(t, 200, [{ name: 'fixture', keys: [] }]);
const result = await s.client.getUpstreamGroups();
assert.equal(Array.isArray(result), true); assert.equal(result.length, 1);
assert.equal(result[0].name === 'fixture' && Array.isArray(result[0].keys), true);
evidence(s, 'GET', endpoint, 200);
});