From 01041967de3863a4d163dba03cc0b088f1f15bf7 Mon Sep 17 00:00:00 2001 From: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com> Date: Fri, 29 May 2026 00:58:58 -0300 Subject: [PATCH] fix(quota): honor explicit per-connection preflight opt-out (#2831) (#2844) Integrated into release/v3.8.6. --- CHANGELOG.md | 1 + src/sse/services/auth.ts | 9 +++++++ tests/unit/sse-auth.test.ts | 52 +++++++++++++++++++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 428e911361..ee1d046103 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ ### 🔧 Bug Fixes +- **fix(quota):** honor explicit per-connection `quotaPreflightEnabled: false` even when the provider has global window defaults — adds early-return guard before the AND-of-negations gate in auth.ts ([#2831]) - **api:** include noAuth providers (opencode, etc.) in `/v1/models` active aliases so their models surface without a DB connection row (#2798) - **opencode-go:** route Qwen3.x via Claude messages format and repair `fixMissingToolResponses` helper for Claude-shape upstreams (#2791 — thanks @jeferssonlemes) - **validation:** register missing validation helper checks for web-cookie providers (`claude-web`, `gemini-web`, `copilot-web`, `t3-web`) (#2793 — thanks @oyi77) diff --git a/src/sse/services/auth.ts b/src/sse/services/auth.ts index 24cb3015c6..1e25be2dae 100644 --- a/src/sse/services/auth.ts +++ b/src/sse/services/auth.ts @@ -1494,6 +1494,15 @@ export async function getProviderCredentialsWithQuotaPreflight( // Otherwise the resolver would return the factory default for every // window, and a near-exhausted account would still be caught by the // normal 429 → cooldown path. + // Explicit per-connection opt-out always wins over global/provider defaults. + // isQuotaPreflightEnabled is strict-=== true (back-compat), so it returns + // false for both "not set" and "explicit false" — we need an explicit check + // here to distinguish them. + const legacyForceDisable = + (credentials as { providerSpecificData?: Record }) + .providerSpecificData?.quotaPreflightEnabled === false; + if (legacyForceDisable) return credentials; + const hasConnectionOverrides = Object.keys(perConnectionWindowOverrides).length > 0; const legacyForceEnable = isQuotaPreflightEnabled(credentials); if ( diff --git a/tests/unit/sse-auth.test.ts b/tests/unit/sse-auth.test.ts index 5b57edbe46..0109b87e01 100644 --- a/tests/unit/sse-auth.test.ts +++ b/tests/unit/sse-auth.test.ts @@ -364,6 +364,58 @@ test("getProviderCredentialsWithQuotaPreflight invokes the fetcher when an overr assert.equal(fetcherCalls, 1, "fetcher should have been invoked exactly once"); }); +test("getProviderCredentialsWithQuotaPreflight: explicit quotaPreflightEnabled:false bypasses preflight even when provider has global window defaults (#2831)", async () => { + // Regression: when a provider has providerWindowDefaults set AND a connection + // carries quotaWindowThresholds, the AND-of-negations gate in auth.ts would + // proceed to preflight even if the connection explicitly opted out with + // providerSpecificData.quotaPreflightEnabled === false. + const conn = await seedConnection("github", { + name: "github-explicit-opt-out", + apiKey: "ghp-opt-out-test", + providerSpecificData: { quotaPreflightEnabled: false }, + }); + // Give the connection per-window overrides (simulates a user-configured + // threshold) — this is the field that previously caused the gate to keep going. + await (await import("../../src/lib/db/providers.ts")).updateProviderConnection(conn.id, { + quotaWindowThresholds: { primary: 50 }, + }); + + // Seed provider-level window defaults so providerHasDefaults === true. + await settingsDb.updateSettings({ + resilienceSettings: { + quotaPreflight: { + defaultThresholdPercent: 2, + warnThresholdPercent: 20, + providerWindowDefaults: { github: { primary: 10 } }, + }, + }, + }); + + const quotaPreflight = await import("../../open-sse/services/quotaPreflight.ts"); + let fetcherCalls = 0; + quotaPreflight.registerQuotaFetcher("github", async () => { + fetcherCalls++; + // Return a quota that would block if preflight actually ran. + return { used: 98, total: 100, percentUsed: 0.98 }; + }); + + const selected = await auth.getProviderCredentialsWithQuotaPreflight("github"); + + assert.equal( + fetcherCalls, + 0, + "fetcher must NOT run when connection explicitly opts out with quotaPreflightEnabled: false" + ); + assert.equal( + (selected as any).connectionId, + conn.id, + "opted-out connection must be returned directly without being blocked by preflight" + ); + + // Cleanup: reset settings so subsequent tests see factory defaults. + await settingsDb.updateSettings({ resilienceSettings: {} }); +}); + test("getProviderCredentials keeps separate codex affinity per session", async () => { await settingsDb.updateSettings({ fallbackStrategy: "round-robin",