test: cover enabled anonymous rate limits
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user