Skip to content

fix(proxy): add combo scope to fail-closed proxy guard - #13551

Merged
diegosouzapw merged 2 commits into
cheaper-inference:release/v3.8.51from
KooshaPari:pr/13469-combo-proxy-guard
Sep 17, 2026
Merged

diegosouzapw merged 2 commits into
cheaper-inference:release/v3.8.51from
KooshaPari:pr/13469-combo-proxy-guard

Conversation

@KooshaPari

Copy link
Copy Markdown
Contributor

Fixes #13469

Problem

The hasBlockingProxyAssignment guard only checked account, provider, and global scopes. Combo-scoped proxy assignments were not checked, so a fully dead combo pool fell through to direct egress — leaking the host IP address despite the operator having configured combo-level proxies.

Fix

Add the combo scope to the SQL guard query, alongside the existing three scopes. A dead combo pool now blocks egress like the other three scopes.

Changes

  • src/lib/db/proxies/guards.ts: Add combo scope to SQL query and optional comboName parameter

…-inference#13469)

The hasBlockingProxyAssignment guard only checked account, provider, and
global scopes. Combo-scoped proxy assignments were not checked, so a fully
dead combo pool fell through to direct egress — leaking the host IP.

- Add combo scope to the SQL guard query
- Add optional comboName parameter to hasBlockingProxyAssignment
- A dead combo pool now blocks egress like the other three scopes
Copilot AI lite review requested due to automatic review settings September 13, 2026 10:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@diegosouzapw

Copy link
Copy Markdown
Collaborator

Thanks for #13469. Holding. hasBlockingProxyAssignment() gains a comboName parameter, but its only caller (src/sse/handlers/chatHelpers.ts:957) still passes two arguments. The combo-scope clause therefore always binds NULL and never matches, so the fail-closed behavior doesn't change yet.

Could you thread the combo name through that call site and add a test that assigns a dead proxy at scope = 'combo' and asserts the request is blocked?

@diegosouzapw

Copy link
Copy Markdown
Collaborator

Thanks for #13469 — the SQL guard change is correct in isolation, but hasBlockingProxyAssignment()
gains a comboName parameter that its only caller (src/sse/handlers/chatHelpers.ts:957) still
doesn't pass, so the combo-scope clause always binds NULL and never matches — the fail-closed
behavior for combo-scoped pools doesn't actually change yet. Could you thread the combo name
through that call site and add a test that assigns a dead proxy at scope = 'combo' and asserts
the request is blocked?

…ope guard (cheaper-inference#13469)

hasBlockingProxyAssignment() gained a comboName parameter and a combo-scope
SQL clause, but its only caller, safeResolveProxy() in chatHelpers.ts, never
passed it — the clause always bound NULL and never matched a real combo
scope_id, so a fully dead combo-scoped proxy pool still fell through to
direct egress. Thread comboName from handleSingleModelChat (where it is
already in scope) through safeResolveProxy into the guard, and add tests
covering both the guard predicate and the end-to-end wiring.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
@diegosouzapw
diegosouzapw merged commit 2855741 into cheaper-inference:release/v3.8.51 Sep 17, 2026
10 of 16 checks passed
diegosouzapw added a commit that referenced this pull request Sep 17, 2026
…e moved (#14002)

Measured on the clean tip (83fa432), not on a branch. Each ceiling was
attributed to the PR that moved it before being raised — no blanket rebaseline:

- src/sse/handlers/chatHelpers.ts 1245 -> 1246 (#13551, combo scope on the
  fail-closed proxy guard)
- open-sse/handlers/chatCore.ts 6203 -> 6219 (#12905 DSML/preamble, #13910
  disguised-2xx classification, #12904 single post-translation system prompt)
- open-sse/utils/stream.ts 3123 -> 3140 (#12905, and #12906 empty_response 502
  retry + reasoning-aware timeout)
- tests/integration/chat-pipeline.test.ts 1736 -> 1740 (#13419, the two exact
  header assertions updated for charset=utf-8)

Other gates re-measured on the same tip and already green: typecheck:core,
check:open-sse-typecheck, check:docs-counts, and the #2331-adjacent
chatcore-translation-paths xhigh-effort case that was red before this wave.
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…ence#13551)

* fix(proxy): add combo scope to fail-closed proxy guard (fixes cheaper-inference#13469)

The hasBlockingProxyAssignment guard only checked account, provider, and
global scopes. Combo-scoped proxy assignments were not checked, so a fully
dead combo pool fell through to direct egress — leaking the host IP.

- Add combo scope to the SQL guard query
- Add optional comboName parameter to hasBlockingProxyAssignment
- A dead combo pool now blocks egress like the other three scopes

* fix(proxy): thread comboName through safeResolveProxy to the combo-scope guard (cheaper-inference#13469)

hasBlockingProxyAssignment() gained a comboName parameter and a combo-scope
SQL clause, but its only caller, safeResolveProxy() in chatHelpers.ts, never
passed it — the clause always bound NULL and never matched a real combo
scope_id, so a fully dead combo-scoped proxy pool still fell through to
direct egress. Thread comboName from handleSingleModelChat (where it is
already in scope) through safeResolveProxy into the guard, and add tests
covering both the guard predicate and the end-to-end wiring.

Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: Koosha Pari <koosha@phenotype.ai>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
muhamadgalihsaputra pushed a commit to niyatna/NiyatnaRoute that referenced this pull request Sep 27, 2026
…e moved (cheaper-inference#14002)

Measured on the clean tip (bebb827), not on a branch. Each ceiling was
attributed to the PR that moved it before being raised — no blanket rebaseline:

- src/sse/handlers/chatHelpers.ts 1245 -> 1246 (cheaper-inference#13551, combo scope on the
  fail-closed proxy guard)
- open-sse/handlers/chatCore.ts 6203 -> 6219 (cheaper-inference#12905 DSML/preamble, cheaper-inference#13910
  disguised-2xx classification, cheaper-inference#12904 single post-translation system prompt)
- open-sse/utils/stream.ts 3123 -> 3140 (cheaper-inference#12905, and cheaper-inference#12906 empty_response 502
  retry + reasoning-aware timeout)
- tests/integration/chat-pipeline.test.ts 1736 -> 1740 (cheaper-inference#13419, the two exact
  header assertions updated for charset=utf-8)

Other gates re-measured on the same tip and already green: typecheck:core,
check:open-sse-typecheck, check:docs-counts, and the cheaper-inference#2331-adjacent
chatcore-translation-paths xhigh-effort case that was red before this wave.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(resilience): Fail-closed proxy guard does not cover the combo scope: a fully dead combo pool falls through to direct egress

3 participants