Files
OmniRoute/open-sse/services/combo/protectedPriorityStopStatus.ts
Dizzle 611342609f fix(combo): return 502 for non-quota protected-priority stops (#13439)
Behind the new `PROTECTED_PRIORITY_INFRA_502_ENABLED` flag (default off), protected-priority combo stops caused by provably non-quota infrastructure (provider circuit open, predictive-TTFT latency) surface as 502 instead of a quota-looking 503.

Maintainer rework before merge (kept the idea, no default behavior change):
- The original branch made 502 the default for every stop, including model lockouts and cooldowns, and removed the #8133/#1731 provider-wide skip for 401/5xx without a connection id; both are restored with their regression tests untouched.
- Nineteen cases cover eight gate causes plus predictive latency, flag off and on.

Validated first on the combined board of all 38 PRs of this batch (10 merged as-is, 28 after the maintainer rework) on top of release/v3.8.51 c0f92ec: typecheck:core, check:open-sse-typecheck and check:dashboard-typecheck clean; ESLint clean on every changed file; file-size (rebaselined for the combined growth), complexity, cognitive-complexity, changelog-integrity, docs-counts, docs-sync, migration-numbering and i18n new-key gates green; 735 focused node:test cases with the only batch-caused failure (a flag-count assertion) fixed. Then re-validated alone on the fresh release tip right before this merge: ESLint on the changed files, typecheck:core, check:open-sse-typecheck, the file-size/complexity/changelog gates and this PR's own tests.

Thanks @maxmad64bis!
2026-09-15 15:46:57 -03:00

32 lines
1.4 KiB
TypeScript

/**
* #13439 — HTTP status for a protected-priority stop: a `priority` target marked
* `fallbackOnlyOnQuotaExhaustion` stops the combo instead of falling through, and
* every such stop answers 503, which reads like quota exhaustion.
*
* Only causes that are provably NOT quota, rate limit or cooldown may answer 502:
* - `circuit_open`: the whole-provider breaker opens on 408/5xx only
* (PROVIDER_BREAKER_FAILURE_STATUSES; 429 and request-scoped failures never trip it);
* - `predictive_ttft`: skipped on recorded latency alone.
* Everything else (model lockout, provider/connection cooldown, request exhaustion,
* unavailable credentials, credential gate, concurrency cap, quota cutoff) keeps 503:
* those cannot be proven non-quota.
*
* Opt-in via PROTECTED_PRIORITY_INFRA_502_ENABLED (default off) because it changes a
* client-visible status; a flag-read failure keeps 503.
*
* @internal — not part of the public combo.ts barrel.
*/
import { isFeatureFlagEnabled } from "../../../src/shared/utils/featureFlags.ts";
export type ProtectedPriorityStopCause = "circuit_open" | "predictive_ttft";
export function protectedPriorityStopStatus(cause?: ProtectedPriorityStopCause): 502 | 503 {
if (cause !== "circuit_open" && cause !== "predictive_ttft") return 503;
try {
return isFeatureFlagEnabled("PROTECTED_PRIORITY_INFRA_502_ENABLED") ? 502 : 503;
} catch {
// no-effect: an unreadable flag store keeps the legacy 503
return 503;
}
}