feat(api): add opt-in API-key provider quota-policy bypass scope (#5731)

Adds an opt-in per-API-key scope (policy:bypass-provider-quota) that lets a key skip provider/account-side quota cutoffs during routing. Operator USD budgets/usage limits still enforced unconditionally (fail-closed, before the bypass). Default-off; UI toggle + badge in API Manager. Integrated into release/v3.8.43.
This commit is contained in:
WITALO ROCHA
2026-06-30 23:45:29 -03:00
committed by GitHub
parent f669335218
commit dafeb42baf
9 changed files with 150 additions and 15 deletions

View File

@@ -1278,12 +1278,22 @@ export async function handleComboChat({
log.warn("COMBO", "Failed to retrieve Last Known Good Provider. This is non-fatal.", { err });
}
const autoCandidateResilienceSettings =
relayOptions?.bypassProviderQuotaPolicy === true
? {
...resilienceSettings,
quotaPreflight: {
...resilienceSettings.quotaPreflight,
enabled: false,
},
}
: resilienceSettings;
const candidates = await buildAutoCandidates(
eligibleTargets,
combo.name,
relayOptions?.sessionId,
resetWindowConfig,
resilienceSettings
autoCandidateResilienceSettings
);
const routableCandidates = candidates.filter(
(candidate) => candidate.quotaCutoffBlocked !== true

View File

@@ -63,6 +63,7 @@ export type IsModelAvailable = (
export type ComboRelayOptions = {
sessionId?: string | null;
config?: Record<string, unknown> | null;
bypassProviderQuotaPolicy?: boolean;
[key: string]: unknown;
};

View File

@@ -23,6 +23,7 @@ import { readActiveOnlyPreference, writeActiveOnlyPreference } from "./apiManage
import { buildApiKeyCreateScopes, mergeApiKeyPermissionScopes } from "./apiManagerScopes";
import { SELF_ACCOUNT_QUOTA_SCOPE, SELF_USAGE_SCOPE } from "@/shared/constants/selfServiceScopes";
import { extractApiErrorMessage } from "@/shared/http/apiErrorMessage";
import { hasProviderQuotaBypassScope } from "@/shared/constants/apiKeyPolicyScopes";
import { UsageLimitSettings } from "./components/UsageLimitSettings";
// Constants for validation
@@ -958,6 +959,7 @@ export default function ApiManagerPageClient() {
: 0;
const hasThrottle = throttleDelayMs > 0;
const hasManageScope = Array.isArray(key.scopes) && key.scopes.includes("manage");
const hasProviderQuotaBypass = hasProviderQuotaBypassScope(key.scopes);
const hasJsonStreamDefault = key.streamDefaultMode === "json";
const hasLocalUsageCommand = key.allowUsageCommand === true;
const maxSessions = typeof key.maxSessions === "number" ? key.maxSessions : 0;
@@ -985,9 +987,7 @@ export default function ApiManagerPageClient() {
</div>
<div className="col-span-3 flex items-center gap-1.5">
<code className="text-sm text-text-muted font-mono truncate">
{visibleKeys.has(key.id)
? (revealedKeys.get(key.id) ?? key.key)
: key.key}
{visibleKeys.has(key.id) ? (revealedKeys.get(key.id) ?? key.key) : key.key}
</code>
{allowKeyReveal ? (
<>
@@ -1114,6 +1114,12 @@ export default function ApiManagerPageClient() {
USD quota
</span>
)}
{hasProviderQuotaBypass && (
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-amber-500/10 text-amber-700 dark:text-amber-300 text-[11px] font-medium">
<span className="material-symbols-outlined text-[12px]">alt_route</span>
Bypass quota policy
</span>
)}
{hasSessionLimit && (
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-indigo-500/10 text-indigo-600 dark:text-indigo-400 text-[11px] font-medium">
<span className="material-symbols-outlined text-[12px]">group</span>
@@ -1588,6 +1594,9 @@ const PermissionsModal = memo(function PermissionsModal({
const [selfAccountQuotaEnabled, setSelfAccountQuotaEnabled] = useState(
Array.isArray(apiKey?.scopes) && apiKey.scopes.includes(SELF_ACCOUNT_QUOTA_SCOPE)
);
const [bypassProviderQuotaPolicyEnabled, setBypassProviderQuotaPolicyEnabled] = useState(
hasProviderQuotaBypassScope(apiKey?.scopes)
);
const [maxSessions, setMaxSessions] = useState(
typeof apiKey?.maxSessions === "number" && apiKey.maxSessions > 0 ? apiKey.maxSessions : 0
);
@@ -1822,6 +1831,7 @@ const PermissionsModal = memo(function PermissionsModal({
manageEnabled,
selfUsageEnabled,
selfAccountQuotaEnabled,
bypassProviderQuotaPolicyEnabled,
}),
allowAllEndpoints ? [] : selectedEndpoints,
streamDefaultMode,
@@ -1851,6 +1861,7 @@ const PermissionsModal = memo(function PermissionsModal({
manageEnabled,
selfUsageEnabled,
selfAccountQuotaEnabled,
bypassProviderQuotaPolicyEnabled,
scheduleEnabled,
scheduleFrom,
scheduleUntil,
@@ -2451,6 +2462,31 @@ const PermissionsModal = memo(function PermissionsModal({
/>
</div>
{/* Advanced Provider Quota Policy Override */}
<div className="flex items-start justify-between gap-3 p-3 rounded-lg border border-amber-500/20 bg-amber-500/5">
<div className="flex flex-col gap-1 pr-2">
<p className="text-sm font-medium text-text-main">Bypass provider quota cutoffs</p>
<p className="text-xs text-text-muted">
Allows this key to ignore upstream provider/account cutoff policy during routing. API
key USD quotas still apply.
</p>
</div>
<button
type="button"
role="switch"
aria-checked={bypassProviderQuotaPolicyEnabled}
onClick={() => setBypassProviderQuotaPolicyEnabled((prev) => !prev)}
className={`inline-flex shrink-0 items-center gap-1.5 px-2.5 py-1.5 rounded-md text-xs font-semibold transition-colors ${
bypassProviderQuotaPolicyEnabled
? "bg-amber-500/15 text-amber-700 dark:text-amber-300 border border-amber-500/30"
: "bg-black/5 dark:bg-white/5 text-text-muted border border-border"
}`}
>
<span className="material-symbols-outlined text-[14px]">alt_route</span>
{bypassProviderQuotaPolicyEnabled ? tc("enabled") : tc("disabled")}
</button>
</div>
{/* Disable Non-Public Models Toggle */}
<div className="flex items-start justify-between gap-3 p-3 rounded-lg border border-border bg-surface/40">
<div className="flex flex-col gap-1">

View File

@@ -1,7 +1,5 @@
import {
SELF_ACCOUNT_QUOTA_SCOPE,
SELF_USAGE_SCOPE,
} from "@/shared/constants/selfServiceScopes";
import { SELF_ACCOUNT_QUOTA_SCOPE, SELF_USAGE_SCOPE } from "@/shared/constants/selfServiceScopes";
import { API_KEY_BYPASS_PROVIDER_QUOTA_SCOPE } from "@/shared/constants/apiKeyPolicyScopes";
const MANAGEMENT_SCOPE = "manage";
@@ -9,12 +7,14 @@ export interface CreateScopeOptions {
manageEnabled: boolean;
selfUsageEnabled?: boolean;
selfAccountQuotaEnabled?: boolean;
bypassProviderQuotaPolicyEnabled?: boolean;
}
export interface PermissionScopeOptions {
manageEnabled: boolean;
selfUsageEnabled: boolean;
selfAccountQuotaEnabled: boolean;
bypassProviderQuotaPolicyEnabled: boolean;
}
export function buildApiKeyCreateScopes(options: CreateScopeOptions): string[] {
@@ -25,6 +25,9 @@ export function buildApiKeyCreateScopes(options: CreateScopeOptions): string[] {
if (selfUsageEnabled && options.selfAccountQuotaEnabled === true) {
scopes.push(SELF_ACCOUNT_QUOTA_SCOPE);
}
if (options.bypassProviderQuotaPolicyEnabled === true) {
scopes.push(API_KEY_BYPASS_PROVIDER_QUOTA_SCOPE);
}
return scopes;
}
@@ -41,6 +44,7 @@ export function mergeApiKeyPermissionScopes(
SELF_ACCOUNT_QUOTA_SCOPE,
options.selfUsageEnabled && options.selfAccountQuotaEnabled
);
setScope(scopes, API_KEY_BYPASS_PROVIDER_QUOTA_SCOPE, options.bypassProviderQuotaPolicyEnabled);
return [...scopes];
}

View File

@@ -0,0 +1,5 @@
export const API_KEY_BYPASS_PROVIDER_QUOTA_SCOPE = "policy:bypass-provider-quota";
export function hasProviderQuotaBypassScope(scopes: readonly string[] | null | undefined): boolean {
return Array.isArray(scopes) && scopes.includes(API_KEY_BYPASS_PROVIDER_QUOTA_SCOPE);
}

View File

@@ -90,6 +90,7 @@ export interface ApiKeyMetadata {
throttleDelayMs?: number | null;
maxSessions?: number | null;
rateLimits?: RateLimitRule[] | null;
scopes?: string[];
allowedEndpoints?: string[];
disableNonPublicModels?: boolean;
allowUsageCommand?: boolean;

View File

@@ -87,6 +87,7 @@ import { RequestTelemetry, recordTelemetry } from "../../shared/utils/requestTel
import { generateRequestId } from "../../shared/utils/requestId";
import { logAuditEvent } from "../../lib/compliance/index";
import { enforceApiKeyPolicy } from "../../shared/utils/apiKeyPolicy";
import { hasProviderQuotaBypassScope } from "../../shared/constants/apiKeyPolicyScopes";
import { cloneLogPayload } from "@/lib/logPayloads";
import { handleInternalUsageCommand } from "@/lib/usage/internalUsageCommand";
import {
@@ -330,6 +331,7 @@ export async function handleChat(
return policy.rejection;
}
const apiKeyInfo = policy.apiKeyInfo;
const bypassProviderQuotaPolicy = hasProviderQuotaBypassScope(apiKeyInfo?.scopes);
telemetry.endPhase();
// Guardrail pre-call pipeline — prompt injection, PII masking, and future custom rules.
@@ -627,6 +629,7 @@ export async function handleChat(
sessionKey: sessionAffinityKey,
...(target?.allowRateLimitedConnection ? { allowRateLimitedConnections: true } : {}),
...(target?.connectionId ? { forcedConnectionId: target.connectionId } : {}),
...(bypassProviderQuotaPolicy ? { bypassQuotaPolicy: true } : {}),
}
);
if (!creds || creds.allRateLimited) return false;
@@ -642,6 +645,18 @@ export async function handleChat(
]);
const relayConfig =
combo.strategy === "context-relay" ? resolveComboConfig(combo, settings) : null;
const relayOptions =
combo.strategy === "context-relay" || bypassProviderQuotaPolicy
? {
...(combo.strategy === "context-relay"
? {
sessionId,
config: relayConfig,
}
: {}),
...(bypassProviderQuotaPolicy ? { bypassProviderQuotaPolicy: true } : {}),
}
: undefined;
telemetry.endPhase();
// Context-relay keeps generation in combo.ts, but handoff injection lives here
@@ -706,13 +721,7 @@ export async function handleChat(
settings,
allCombos,
apiKeyAllowedConnections: apiKeyInfo?.allowedConnections ?? null,
relayOptions:
combo.strategy === "context-relay"
? {
sessionId,
config: relayConfig,
}
: undefined,
relayOptions,
signal: request?.signal ?? null,
correlationId: reqId,
});
@@ -956,6 +965,7 @@ async function handleSingleModelChat(
return runtimeOptions.providerId;
})();
const forceLiveComboTest = runtimeOptions.forceLiveComboTest === true;
const bypassProviderQuotaPolicy = hasProviderQuotaBypassScope(apiKeyInfo?.scopes);
const hasForcedConnection =
typeof runtimeOptions.forcedConnectionId === "string" &&
runtimeOptions.forcedConnectionId.trim().length > 0;
@@ -1099,6 +1109,9 @@ async function handleSingleModelChat(
bypassQuotaPolicy: true,
}
: {}),
...(!forceLiveComboTest && bypassProviderQuotaPolicy
? { bypassQuotaPolicy: true }
: {}),
...(runtimeOptions.forcedConnectionId
? { forcedConnectionId: runtimeOptions.forcedConnectionId }
: {}),

View File

@@ -0,0 +1,34 @@
import test from "node:test";
import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import {
API_KEY_BYPASS_PROVIDER_QUOTA_SCOPE,
hasProviderQuotaBypassScope,
} from "../../src/shared/constants/apiKeyPolicyScopes.ts";
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
test("provider quota bypass scope helper is explicit and strict", () => {
assert.equal(API_KEY_BYPASS_PROVIDER_QUOTA_SCOPE, "policy:bypass-provider-quota");
assert.equal(hasProviderQuotaBypassScope([API_KEY_BYPASS_PROVIDER_QUOTA_SCOPE]), true);
assert.equal(hasProviderQuotaBypassScope(["policy:other"]), false);
assert.equal(hasProviderQuotaBypassScope(null), false);
});
test("chat handler maps API key provider quota bypass scope to auth bypass option", () => {
const source = fs.readFileSync(path.join(repoRoot, "src/sse/handlers/chat.ts"), "utf8");
assert.match(source, /hasProviderQuotaBypassScope\(apiKeyInfo\?\.scopes\)/);
assert.match(source, /bypassProviderQuotaPolicy[\s\S]*bypassQuotaPolicy: true/);
assert.match(source, /relayOptions[\s\S]*bypassProviderQuotaPolicy: true/);
});
test("auto combo disables hard provider quota cutoffs when relay requests bypass", () => {
const source = fs.readFileSync(path.join(repoRoot, "open-sse/services/combo.ts"), "utf8");
assert.match(source, /relayOptions\?\.bypassProviderQuotaPolicy === true/);
assert.match(source, /quotaPreflight:[\s\S]*enabled: false/);
});

View File

@@ -9,10 +9,18 @@ import {
SELF_ACCOUNT_QUOTA_SCOPE,
SELF_USAGE_SCOPE,
} from "../../src/shared/constants/selfServiceScopes.ts";
import { API_KEY_BYPASS_PROVIDER_QUOTA_SCOPE } from "../../src/shared/constants/apiKeyPolicyScopes.ts";
test("create scopes enable own usage by default without shared account quota", () => {
assert.deepEqual(buildApiKeyCreateScopes({ manageEnabled: false }), [SELF_USAGE_SCOPE]);
assert.deepEqual(buildApiKeyCreateScopes({ manageEnabled: true }), ["manage", SELF_USAGE_SCOPE]);
assert.deepEqual(
buildApiKeyCreateScopes({
manageEnabled: false,
bypassProviderQuotaPolicyEnabled: true,
}),
[SELF_USAGE_SCOPE, API_KEY_BYPASS_PROVIDER_QUOTA_SCOPE]
);
assert.deepEqual(
buildApiKeyCreateScopes({
manageEnabled: false,
@@ -28,6 +36,7 @@ test("permission scope merge preserves unrelated scopes while toggling managed s
manageEnabled: true,
selfUsageEnabled: true,
selfAccountQuotaEnabled: true,
bypassProviderQuotaPolicyEnabled: true,
});
assert.deepEqual(scopes, [
@@ -35,6 +44,7 @@ test("permission scope merge preserves unrelated scopes while toggling managed s
SELF_USAGE_SCOPE,
"manage",
SELF_ACCOUNT_QUOTA_SCOPE,
API_KEY_BYPASS_PROVIDER_QUOTA_SCOPE,
]);
});
@@ -45,8 +55,29 @@ test("permission scope merge removes shared quota visibility when own usage is d
manageEnabled: false,
selfUsageEnabled: false,
selfAccountQuotaEnabled: true,
bypassProviderQuotaPolicyEnabled: false,
}
);
assert.deepEqual(scopes, ["custom:scope"]);
});
test("permission scope merge toggles provider quota policy bypass without dropping custom scopes", () => {
const enabled = mergeApiKeyPermissionScopes(["custom:scope"], {
manageEnabled: false,
selfUsageEnabled: false,
selfAccountQuotaEnabled: false,
bypassProviderQuotaPolicyEnabled: true,
});
assert.deepEqual(enabled, ["custom:scope", API_KEY_BYPASS_PROVIDER_QUOTA_SCOPE]);
const disabled = mergeApiKeyPermissionScopes(enabled, {
manageEnabled: false,
selfUsageEnabled: false,
selfAccountQuotaEnabled: false,
bypassProviderQuotaPolicyEnabled: false,
});
assert.deepEqual(disabled, ["custom:scope"]);
});