Skip to content

fix(router): validate LiteLLM master key and enforce client auth in responses_api (#407) - #467

Merged
sheepdestroyer merged 1 commit into
masterfrom
fix/responses-api-auth-and-masterkey-validation
Aug 13, 2026
Merged

fix(router): validate LiteLLM master key and enforce client auth in responses_api (#407)#467
sheepdestroyer merged 1 commit into
masterfrom
fix/responses-api-auth-and-masterkey-validation

Conversation

@sheepdestroyer

@sheepdestroyersheepdestroyer commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Closes#407

Summary by Sourcery

Enforce secure LiteLLM integration and client authentication for routing and responses APIs while registering OpenRouter models into the LiteLLM DB at startup.

Bug Fixes:

  • Validate LiteLLM master key and fail fast when it is missing, empty, or a placeholder before proxying requests.
  • Ensure LiteLLM-backed proxy routes use a valid master key instead of placeholder or misconfigured backend API keys.
  • Guarantee client requests to /v1/responses include a proper Bearer Authorization header, rejecting unauthenticated calls with 401.
  • Resolve llama server and classifier URLs using explicit environment variables when provided, avoiding unintended HTTPS inference.

Enhancements:

  • Add OpenRouter model registration into LiteLLM via /model/new, loading configurations from config.yaml and purging stale database entries before re-registration.
  • Improve Langfuse tracing by including optional session and user identifiers when starting and updating triage observations.

Tests:

  • Extend responses_api tests to cover client auth enforcement, master key validation failures, and helper behaviour for invalid keys.
  • Add dedicated tests for OpenRouter DB registration, covering static fallback, config-driven registration, and purge behaviour.
  • Adjust routing, lifespan, and roster sync tests to account for the new OpenRouter registration flow, stricter environment configuration, and master key validation.

Summary by CodeRabbit

  • New Features

    • Added automatic OpenRouter model registration from LiteLLM configuration, with fallback support.
    • Added stale deployment cleanup during startup.
    • Added support for explicit Llama server and classifier endpoints.
  • Security

    • Responses API requests now require valid Bearer authentication.
    • Invalid or placeholder LiteLLM credentials are rejected and replaced with validated credentials where appropriate.
    • Proxy authentication now handles invalid or duplicate configured keys.
  • Bug Fixes

    • Improved Langfuse triage tracking with session and user identifiers.
    • Added fail-fast handling for invalid server credentials.

@sourcery-ai

sourcery-aiBot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

This PR hardens LiteLLM integration and router security by validating the LiteLLM master key, enforcing client Bearer auth on the /v1/responses endpoint, improving LiteLLM/OpenRouter model registration, and tightening tracing and proxy behavior, with tests updated accordingly.

Sequence diagram for secured responses_api flow

sequenceDiagram
actor Client
participant Router as responses_api
participant LiteLLM as LiteLLM_admin
Client->>Router: HTTP POST /v1/responses
Router->>Router: read Authorization header
Router-->>Client: HTTP 401 (Missing or invalid Authorization) [if header invalid]
Router->>Router: _validate_litellm_master_key()
Router-->>Client: HTTP 500 (invalid master key) [on validation failure]
Router->>LiteLLM: forward request with Bearer LITELLM_MASTER_KEY
LiteLLM-->>Router: response
Router-->>Client: proxied response
Loading

Sequence diagram for OpenRouter model DB registration at lifespan

sequenceDiagram
participant App as lifespan
participant Registrar as _register_openrouter_models_in_db
participant DB as _purge_stale_deployments
participant LiteLLM as LiteLLM_admin
App->>Registrar: _register_openrouter_models_in_db(litellm_master_key)
Registrar->>Registrar: load config.yaml for model_list
Registrar->>DB: _purge_stale_deployments(DATABASE_URL, "openrouter-%")
DB-->>Registrar: purge complete
loop each openrouter model
Registrar->>LiteLLM: client.post(/model/new, headers=Authorization Bearer master_key)
LiteLLM-->>Registrar: HTTP 200/201 or error
end
Registrar-->>App: registration summary logged
Loading

File-Level Changes

ChangeDetailsFiles
Honor explicit LLAMA_SERVER_URL and LLAMA_CLASSIFIER_URL environment variables when resolving llama endpoints, and prioritize them over config and canonical URLs.
  • Read LLAMA_SERVER_URL and LLAMA_CLASSIFIER_URL directly from the environment
  • Use env values as primary inputs for raw_server and raw_classifier
  • Prefer env URLs when resolving final server and classifier endpoints before falling back to HTTPS/canonical/local defaults
router/main.py
Introduce strict validation of the LiteLLM master key and reuse it consistently for LiteLLM-backed operations, including execute_proxy.
  • Add a shared set of invalid LiteLLM master key placeholders
  • Implement _validate_litellm_master_key helper that trims, validates, and raises HTTP 500 on invalid keys
  • Use _validate_litellm_master_key in responses_api instead of reading LITELLM_MASTER_KEY directly
  • Refactor execute_proxy to treat missing/placeholder/api-key-equal-to-master-key as invalid and then call _validate_litellm_master_key
router/main.py
router/tests/test_responses_api.py
router/tests/test_routing_behavior.py
tests/conftest.py
Require client Bearer authentication on the /v1/responses endpoint and extend tests to cover auth and master-key failure scenarios.
  • Add Authorization header parsing and Bearer token validation at the start of responses_api, returning 401 on missing/invalid tokens
  • Update existing responses_api tests to include a valid Bearer token in request headers and set a test LITELLM_MASTER_KEY
  • Add new tests ensuring responses_api rejects missing/invalid Authorization headers and fails fast with 500 on invalid master key values
  • Add direct tests for _validate_litellm_master_key raising HTTP 500 on invalid keys
router/main.py
router/tests/test_responses_api.py
Add OpenRouter model registration into LiteLLM’s DB during app lifespan, with config-driven discovery, static fallback, and stale deployment purging.
  • Implement _register_openrouter_models_in_db to load OpenRouter model definitions from LiteLLM config.yaml via asyncio.to_thread, filter openrouter-* models, and register them via /model/new
  • Provide a static openrouter-auto fallback when config-based discovery fails
  • Purge stale openrouter-% deployments from LiteLLM DB before re-registering
  • Invoke _register_openrouter_models_in_db from the FastAPI lifespan startup path and integrate it with existing LiteLLM master key handling
router/main.py
router/tests/test_lifespan.py
router/tests/test_register_openrouter_models_in_db.py
router/tests/test_sync_adaptive_router_roster.py
Improve Langfuse tracing integration in triage by conditionally attaching session_id and user_id to observations and updates.
  • Build kwargs dictionaries for lf.start_observation and parent_obs.update instead of passing fixed parameters
  • Inject session_id and user_id into Langfuse observation start/update calls only when available in trace context
  • Maintain existing metadata and output fields while making trace context extension more robust
router/main.py
Adjust routing and test setup to use consistent test master/router keys and ensure client auth when hitting chat completions.
  • Set default LITELLM_MASTER_KEY and ROUTER_API_KEY values in tests/conftest.py and routing tests
  • Update chat completions routing behavior test to send a Bearer Authorization header and patch LITELLM_MASTER_KEY for fallback behavior
  • Relax sync_adaptive_router_roster test assertion to allow multiple purge calls
router/tests/test_routing_behavior.py
tests/conftest.py
router/tests/test_sync_adaptive_router_roster.py

Assessment against linked issues

IssueObjectiveAddressedExplanation
#407Validate the LITELLM_MASTER_KEY before constructing Authorization headers in responses_api and execute_proxy pathways to fail fast on missing or placeholder keys.
#407Enforce caller authentication on the /v1/responses and /responses endpoints by requiring a valid Bearer Authorization header before proxying upstream.
#407Implement dynamic OpenRouter model sync on lifespan startup by loading OpenRouter models from LiteLLM config into the LiteLLM DB and purging stale openrouter-* database entries.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitaiBot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@sheepdestroyer, you've reached your PR review limit, so we couldn't start this review.

Next review available in:116 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3357ca1f-9597-4c5d-b4cb-995e0dbdc8c9

📥 Commits

Reviewing files that changed from the base of the PR and between 61dcc5c and 45ffe6c.

📒 Files selected for processing (3)
  • router/main.py
  • router/tests/test_responses_api.py
  • router/tests/test_sync_adaptive_router_roster.py
📝 Walkthrough

Walkthrough

The router prioritizes explicit Llama endpoints, validates LiteLLM master keys, enforces Responses API client authentication, registers OpenRouter models during startup, propagates Langfuse identifiers, and updates related tests and test environment defaults.

Changes

Router hardening and startup synchronization

Layer / File(s)Summary
Endpoint and credential validation
router/main.py, router/tests/test_routing_behavior.py, tests/conftest.py
Explicit Llama URLs take priority. LiteLLM master keys reject missing and placeholder values. Backend proxy authentication uses validated LiteLLM credentials when configured keys are invalid.
Responses API authentication
router/main.py, router/tests/test_responses_api.py, router/tests/test_routing_behavior.py
Responses API requests require Bearer authorization. Upstream requests use the validated master key. Tests cover valid requests and invalid client or server credentials.
OpenRouter startup registration
router/main.py, router/tests/test_lifespan.py, router/tests/test_register_openrouter_models_in_db.py, router/tests/test_sync_adaptive_router_roster.py
Startup loads configured or fallback OpenRouter models, purges stale deployments, registers models, and continues after registration failures.
Langfuse observation identifiers
router/main.py
Parent observation creation and updates include session and user identifiers when available.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
participant Client
participant ResponsesAPI
participant LiteLLM
Client->>ResponsesAPI: send Bearer-authenticated request
ResponsesAPI->>ResponsesAPI: validate client header and master key
ResponsesAPI->>LiteLLM: proxy with validated credential
LiteLLM-->>ResponsesAPI: return upstream response
ResponsesAPI-->>Client: return response
Loading
sequenceDiagram
participant ApplicationLifespan
participant LiteLLMConfig
participant DeploymentDatabase
participant LiteLLM
ApplicationLifespan->>LiteLLMConfig: load OpenRouter definitions
LiteLLMConfig-->>ApplicationLifespan: return configured or fallback models
ApplicationLifespan->>DeploymentDatabase: purge stale deployments
ApplicationLifespan->>LiteLLM: register models
Loading

Possibly related PRs

Suggested labels:litellm

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 0.00% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly identifies the primary changes: LiteLLM master-key validation and client authentication for the Responses API.
Linked Issues check✅ PassedThe changes implement the linked requirements for key validation, client authentication, OpenRouter model registration, and stale-entry purging [#407].
Out of Scope Changes check✅ PassedThe code and test changes remain related to the linked issue’s authentication, configuration, model registration, and startup requirements.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/responses-api-auth-and-masterkey-validation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@sourcery-aisourcery-aiBot 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.

Hey - I've found 3 issues, and left some high level feedback:

  • The _validate_litellm_master_key helper logs the raw master key value on error, which risks leaking secrets into logs; consider redacting or omitting the actual key string in the log message.
  • Client auth enforcement was added to responses_api but not to chat_completions or other endpoints that use the router; if the intent is consistent client authentication, consider centralizing this check or applying it uniformly.
  • Using HTTPException directly in _validate_litellm_master_key couples this low-level helper to the HTTP layer and makes it harder to reuse; consider raising a custom exception and translating to HTTPException at the endpoint boundary instead.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments- The `_validate_litellm_master_key` helper logs the raw master key value on error, which risks leaking secrets into logs; consider redacting or omitting the actual key string in the log message.
- Client auth enforcement was added to `responses_api` but not to `chat_completions` or other endpoints that use the router; if the intent is consistent client authentication, consider centralizing this check or applying it uniformly.
- Using `HTTPException` directly in `_validate_litellm_master_key` couples this low-level helper to the HTTP layer and makes it harder to reuse; consider raising a custom exception and translating to `HTTPException` at the endpoint boundary instead.
## Individual Comments### Comment 1
<locationpath="router/main.py"line_range="806-808" />
<code_context>
+ Raises:
+ HTTPException(500): If master key is missing, empty, or placeholder string.+ """
+ key = (os.getenv("LITELLM_MASTER_KEY") or "").strip()
+ if not key or key in _INVALID_MASTER_KEYS or "PLACEHOLDER" in key.upper():
+ logger.error(f"Invalid or missing LITELLM_MASTER_KEY: '{key}'")+ raise HTTPException(+ status_code=500,
</code_context>
<issue_to_address>
**🚨 issue (security):** Avoid logging the raw master key value to prevent secret exposure in logs.
The current error log prints the full `LITELLM_MASTER_KEY`, which can expose the secret in log storage and monitoring systems. Instead, log only that the key is invalid/missing, and if needed include non-sensitive metadata (e.g., length or a partially redacted prefix) rather than the full value.
</issue_to_address>
### Comment 2
<locationpath="router/main.py"line_range="2307-2311" />
<code_context>
(such as gpt-4o-mini, local-qwen-3.6-hass) and tool/streaming executions.
"""
+# Enforce client authentication+ auth_header = request.headers.get("Authorization") or request.headers.get("authorization")
+ if not auth_header or not auth_header.startswith("Bearer "):
+ raise HTTPException(status_code=401, detail="Missing or invalid Authorization header")+ client_token = auth_header[7:].strip()
+ if not client_token:
+ raise HTTPException(status_code=401, detail="Missing or invalid Authorization header")+
</code_context>
<issue_to_address>
**issue (bug_risk):** Authorization scheme checking is case-sensitive and may reject otherwise valid headers.
`auth_header.startswith("Bearer ")` will fail for `bearer` or other case variants, even though RFC 6750 specifies a case-insensitive scheme. Consider parsing and normalizing the scheme (e.g., split on space and check `scheme.lower() == "bearer"`) to avoid returning 401 for otherwise valid headers.
</issue_to_address>
### Comment 3
<locationpath="router/tests/test_register_openrouter_models_in_db.py"line_range="18-21" />
<code_context>
+ yield+++@pytest.mark.asyncio
+async def test_register_openrouter_models_no_master_key(mock_env, caplog):
+ await _register_openrouter_models_in_db(None)
+ assert "No LiteLLM master key provided" in caplog.text
++
</code_context>
<issue_to_address>
**suggestion (testing):** Consider adding a test for behavior when `DATABASE_URL` is missing to validate the non-purge branch
Current tests exercise the purge path (with `DATABASE_URL` set) and registration from static fallback and config, but not the branch where `DATABASE_URL` is absent. Please add a test that runs `_register_openrouter_models_in_db` with no `DATABASE_URL` and asserts that `_purge_stale_deployments` is not called and the warning is logged, so this control flow is covered.
Suggested implementation:
```python@pytest.fixturedefmock_env():
with patch.dict(os.environ, {
"DATABASE_URL": "postgresql://test:test@localhost:5432/test",
"ROUTER_API_KEY": "test_api_key"
}, clear=False):
yield@pytest.mark.asyncioasyncdeftest_register_openrouter_models_no_database_url(caplog, monkeypatch):
# Ensure DATABASE_URL is not present to exercise the non-purge branch
monkeypatch.delenv("DATABASE_URL", raising=False)
# Patch _purge_stale_deployments to verify it is not calledwith patch("router.main._purge_stale_deployments") as mock_purge:
await _register_openrouter_models_in_db(None)
mock_purge.assert_not_called()
# Assert that the expected warning is logged when DATABASE_URL is missingassert"DATABASE_URL not set; skipping stale deployment purge"in caplog.text
```1. Ensure the warning string in the assertion matches the actual log message emitted in `_register_openrouter_models_in_db` when `DATABASE_URL` is absent; update the string in the test if the wording differs.
2. If `_register_openrouter_models_in_db` logs via a logger with a specific name or level, you may want to set `caplog.set_level(...)` appropriately at the start of the test to guarantee capture of the warning.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment threadrouter/main.py Outdated
Comment threadrouter/main.py
Comment on lines +2307 to +2311
auth_header = request.headers.get("Authorization") or request.headers.get("authorization")
if not auth_header or not auth_header.startswith("Bearer "):
raise HTTPException(status_code=401, detail="Missing or invalid Authorization header")
client_token = auth_header[7:].strip()
if not client_token:

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.

issue (bug_risk): Authorization scheme checking is case-sensitive and may reject otherwise valid headers.

auth_header.startswith("Bearer ") will fail for bearer or other case variants, even though RFC 6750 specifies a case-insensitive scheme. Consider parsing and normalizing the scheme (e.g., split on space and check scheme.lower() == "bearer") to avoid returning 401 for otherwise valid headers.

Comment on lines +18 to +21
@pytest.mark.asyncio
async def test_register_openrouter_models_no_master_key(mock_env, caplog):
await _register_openrouter_models_in_db(None)
assert "No LiteLLM master key provided" in caplog.text

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.

suggestion (testing): Consider adding a test for behavior when DATABASE_URL is missing to validate the non-purge branch

Current tests exercise the purge path (with DATABASE_URL set) and registration from static fallback and config, but not the branch where DATABASE_URL is absent. Please add a test that runs _register_openrouter_models_in_db with no DATABASE_URL and asserts that _purge_stale_deployments is not called and the warning is logged, so this control flow is covered.

Suggested implementation:

@pytest.fixturedefmock_env():
withpatch.dict(os.environ, {
"DATABASE_URL": "postgresql://test:test@localhost:5432/test",
"ROUTER_API_KEY": "test_api_key"
}, clear=False):
yield@pytest.mark.asyncioasyncdeftest_register_openrouter_models_no_database_url(caplog, monkeypatch):
# Ensure DATABASE_URL is not present to exercise the non-purge branchmonkeypatch.delenv("DATABASE_URL", raising=False)
# Patch _purge_stale_deployments to verify it is not calledwithpatch("router.main._purge_stale_deployments") asmock_purge:
await_register_openrouter_models_in_db(None)
mock_purge.assert_not_called()
# Assert that the expected warning is logged when DATABASE_URL is missingassert"DATABASE_URL not set; skipping stale deployment purge"incaplog.text
  1. Ensure the warning string in the assertion matches the actual log message emitted in _register_openrouter_models_in_db when DATABASE_URL is absent; update the string in the test if the wording differs.
  2. If _register_openrouter_models_in_db logs via a logger with a specific name or level, you may want to set caplog.set_level(...) appropriately at the start of the test to guarantee capture of the warning.

@coderabbitaicoderabbitaiBot 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.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@router/main.py`:
- Around line 806-812: Update the validation error logging around the
LITELLM_MASTER_KEY check to use a generic message without interpolating or
exposing key. Preserve the existing invalid-key condition and HTTPException
behavior while removing the secret value from logger.error.
- Around line 2306-2312: Update the client authentication logic around
auth_header and client_token to compare the extracted Bearer token with the
configured client credential, rejecting mismatches with HTTP 401 before any
LiteLLM/upstream processing. Add coverage verifying an invalid token returns 401
and does not trigger the upstream request.
- Around line 998-1005: Align the registration condition in the model-loading
flow with the purge query’s OpenRouter selection rule: either register only
names matching the openrouter- prefix or update purge to also match targets
beginning with openrouter/. Ensure non-prefixed aliases such as gpt-4o-mini-tts
are handled consistently across restarts, and add a regression test covering
that alias.
In `@router/tests/test_register_openrouter_models_in_db.py`:
- Around line 64-70: The test fixture’s OpenRouter alias gpt-4o-mini-tts is not
covered by the openrouter- name prefix, so stale rows can persist. Update
_register_openrouter_models_in_db to identify managed OpenRouter rows by their
persisted provider target or complete managed model set, purge removed aliases
including gpt-4o-mini-tts, and add a test verifying this alias is removed when
absent from configuration.
In `@router/tests/test_sync_adaptive_router_roster.py`:
- Line 71: Update the purge verification in the sync_adaptive_router_roster test
to assert exactly one awaited call with the expected agent-% argument, replacing
the broad mock_purge.assert_called() check while preserving the existing
contract.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b20f0e3a-ff23-4e18-a590-f9b51a742346

📥 Commits

Reviewing files that changed from the base of the PR and between e4de284 and 61dcc5c.

📒 Files selected for processing (7)
  • router/main.py
  • router/tests/test_lifespan.py
  • router/tests/test_register_openrouter_models_in_db.py
  • router/tests/test_responses_api.py
  • router/tests/test_routing_behavior.py
  • router/tests/test_sync_adaptive_router_roster.py
  • tests/conftest.py

Comment threadrouter/main.py
Comment threadrouter/main.py
Comment threadrouter/main.py
Comment on lines +64 to +70
{
"model_name": "gpt-4o-mini-tts",
"litellm_params": {"model": "openrouter/openai/tts-1"}
},
{
"model_name": "local-qwen-3.6",
"litellm_params": {"model": "openai/local-qwen-3.6"}

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.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Purge OpenRouter aliases that do not use the openrouter- prefix.

Line 66 configures an OpenRouter deployment with the name gpt-4o-mini-tts. _register_openrouter_models_in_db only purges names matching openrouter-%. If this alias is later removed from configuration, it remains in the LiteLLM database and can stay selectable.

Identify stale OpenRouter rows from their persisted provider target or from the complete managed model set. Add a removal test for this alias.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@router/tests/test_register_openrouter_models_in_db.py` around lines 64 - 70,
The test fixture’s OpenRouter alias gpt-4o-mini-tts is not covered by the
openrouter- name prefix, so stale rows can persist. Update
_register_openrouter_models_in_db to identify managed OpenRouter rows by their
persisted provider target or complete managed model set, purge removed aliases
including gpt-4o-mini-tts, and add a test verifying this alias is removed when
absent from configuration.

Comment threadrouter/tests/test_sync_adaptive_router_roster.py Outdated
…g in responses_api, and purge openrouter aliases
@sheepdestroyer
sheepdestroyerforce-pushed the fix/responses-api-auth-and-masterkey-validation branch from e800aed to 45ffe6cCompareAugust 13, 2026 10:39
@sheepdestroyer
sheepdestroyer merged commit fd811fc into masterAug 13, 2026
6 of 7 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(router): validate LiteLLM master key and enforce client auth in responses_api (PR #384 follow-up)

1 participant

@sheepdestroyer