test: cover enabled anonymous rate limits

This commit is contained in:
jb
2026-09-19 10:03:04 -04:00
parent 440540657a
commit 614bbf9290
+42 -1
View File
@@ -121,7 +121,48 @@ try {
const liveAssets = await fetch(`${liveBase}/assets`, { headers: cookie }); const liveAssets = await fetch(`${liveBase}/assets`, { headers: cookie });
await assertStatus(liveAssets, 200, 'authenticated asset gate'); await assertStatus(liveAssets, 200, 'authenticated asset gate');
if (trapCalls !== 0) throw new Error(`disabled route performed ${trapCalls} Convex session calls`); if (trapCalls !== 0) throw new Error(`disabled route performed ${trapCalls} Convex session calls`);
console.log(`Rollout-gate HTTP smoke passed: anonymous and authenticated disabled paths avoided provider/session calls`); server.kill('SIGTERM');
await server.exited;
server = undefined;
// Enabled live-mode regression: no-cookie requests resolve to anonymous
// users, so the post-session limiter must not reuse the same IP key. Sync
// reaches its 401 response and chat uses invalid JSON schema to avoid every
// provider while still exercising both limiter passes.
const enabledPort = await freePort();
const enabledBase = `http://127.0.0.1:${enabledPort}`;
const enabledRelease = `gate-enabled-${crypto.randomUUID()}`;
server = Bun.spawn(['bun', 'build/index.js'], {
env: {
...safeEnv, APP_MODE: 'live', APP_ORIGIN: enabledBase, ORIGIN: enabledBase, HOST: '127.0.0.1', PORT: String(enabledPort),
REFERENCE_DIR: referenceDir, APP_RELEASE_ID: enabledRelease, APP_CAPABILITY_ALLOWLIST: 'asset_sync,assistant_dispatch',
CONVEX_URL: `http://127.0.0.1:${trap.port}`, PUBLIC_CONVEX_URL: `http://127.0.0.1:${trap.port}`,
CONVEX_BRIDGE_SECRET: 'synthetic-bridge-secret', TYPESAFE_API_KEY: 'sentinel-not-used',
}, stdout: 'pipe', stderr: 'pipe', stdin: 'ignore',
});
await waitForServer(enabledBase, enabledRelease);
const enabledSyncRequest = () => fetch(`${enabledBase}/api/sync`, { method: 'POST', headers: { origin: enabledBase } });
for (let attempt = 1; attempt <= 6; attempt += 1) {
const response = await enabledSyncRequest();
await assertStatus(response, 401, `enabled anonymous sync denial ${attempt}`);
await response.text();
}
const enabledSyncLimited = await enabledSyncRequest();
await assertStatus(enabledSyncLimited, 429, 'enabled anonymous sync rate limit');
await enabledSyncLimited.text();
const enabledChatRequest = () => fetch(`${enabledBase}/api/chat`, {
method: 'POST', headers: { origin: enabledBase, 'content-type': 'application/json' }, body: '{}',
});
for (let attempt = 1; attempt <= 30; attempt += 1) {
const response = await enabledChatRequest();
await assertStatus(response, 400, `enabled anonymous chat denial ${attempt}`);
await response.text();
}
const enabledChatLimited = await enabledChatRequest();
await assertStatus(enabledChatLimited, 429, 'enabled anonymous chat rate limit');
await enabledChatLimited.text();
if (trapCalls !== 0) throw new Error(`enabled anonymous routes performed ${trapCalls} Convex/provider calls`);
console.log(`Rollout-gate HTTP smoke passed: anonymous thresholds and authenticated disabled paths avoided provider/session calls`);
} finally { } finally {
if (server) { server.kill('SIGTERM'); await server.exited; } if (server) { server.kill('SIGTERM'); await server.exited; }
trap?.stop(); trap?.stop();