From 4073dcd23108b2ed1e37a9acbab29f34789e2bbc Mon Sep 17 00:00:00 2001 From: chopratejas Date: Sat, 2 May 2026 11:18:53 -0700 Subject: [PATCH] fix(proxy): route Codex subscription /backend-api/* catchall to chatgpt.com Codex CLI in subscription mode polls /backend-api/wham/usage, fetches agent identity JWKS from /backend-api/wham/agent-identities/jwks, and hits other auxiliary /backend-api/* endpoints during startup. The HTTP catchall in _select_passthrough_base_url ignored ChatGPT auth and routed all unmatched paths to api.openai.com, which 404s on every backend-api path. Codex interprets that as "session invalid" and refuses subscription auth. Add a single branch at the top of _select_passthrough_base_url: when _resolve_codex_routing_headers reports ChatGPT auth (explicit ChatGPT-Account-Id header or JWT with chatgpt_account_id claim), return https://chatgpt.com so the catchall forwards to the right host. No-op for Anthropic (x-api-key, no JWT), Gemini (x-goog-api-key, no JWT), OpenAI API key (sk- tokens fail JWT decode), and explicit-route OpenAI passthroughs (/v1/embeddings, /v1/moderations, etc. don't go through the catchall). Only behavior change is the targeted unblock for subscription Codex. --- headroom/providers/proxy_routes.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/headroom/providers/proxy_routes.py b/headroom/providers/proxy_routes.py index 3e839e149..929973c3e 100644 --- a/headroom/providers/proxy_routes.py +++ b/headroom/providers/proxy_routes.py @@ -26,6 +26,16 @@ def _api_target(proxy: Any, provider_name: str) -> str: def _select_passthrough_base_url(proxy: Any, headers: dict[str, str]) -> str: + # Codex CLI subscription mode hits a wide surface under + # `/backend-api/*` (rate-limit polling, agent identity, JWT + # refresh, cloud tasks). Without this branch the catchall + # routes those to api.openai.com which 404s, and Codex + # interprets the failure as "session invalid" and refuses + # to use subscription auth at all. The check is a no-op + # for non-ChatGPT-authed requests. + _, is_chatgpt_auth = _resolve_codex_routing_headers(headers) + if is_chatgpt_auth: + return "https://chatgpt.com" if headers.get("x-goog-api-key"): return _api_target(proxy, "gemini") if headers.get("api-key"):