fix(dashboard): let an explicit api_key win over the provider entry's stored one - #67806
Merged
teknium1 merged 1 commit intoJul 20, 2026
Conversation
… stored one
POST /api/model/set accepts an api_key and threads it into
_apply_main_model_assignment. The custom-endpoint work then added a
provider-entry fallback right after it — but unconditionally:
if not base_url and provider_entry.get("base_url"):
base_url = provider_entry["base_url"] # explicit wins
model_cfg = _apply_main_model_assignment(..., base_url, api_key)
if provider_entry.get("api_key"):
model_cfg["api_key"] = provider_entry["api_key"] # explicit LOSES
The two lines disagree about precedence. base_url fills only a gap; api_key
overwrites whatever the caller sent.
So rotating a key through this endpoint returns 200 and silently keeps the
old one:
request api_key : sk-NEW-ROTATED-KEY
stored api_key : sk-STORED-OLD-KEY
That matters beyond the write itself: model.api_key outranks the environment
at client construction, so the stale key keeps authenticating and shadows
anything the operator configures next — the persistent-401 shape
credential_lifecycle.py documents as NousResearch#62269.
A regression, not long-standing. Against 3d97893^ the same request stores
sk-NEW-ROTATED-KEY.
Gate the fallback on `not api_key`, matching the base_url line directly above
it. Switching to a configured provider with no key in the request still adopts
the entry's key — pinned by its own test so the feature's intent doesn't
regress in the other direction.
Collaborator
This was referenced Jul 20, 2026
Contributor
This was referenced Jul 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

What does this PR do?
POST /api/model/setaccepts anapi_keyand threads it into_apply_main_model_assignment. The custom-endpoint work then added aprovider-entry fallback right after it — but unconditionally:
The two lines disagree about precedence.
base_urlfills only a gap;api_keyoverwrites whatever the caller sent.
So rotating a key through this endpoint returns 200 and silently keeps the old
one:
That matters beyond the write itself:
model.api_keyoutranks the environment atclient construction, so the stale key keeps authenticating and shadows anything the
operator configures next — the persistent-401 shape
credential_lifecycle.pydocuments as #62269.
A regression, not long-standing. Against
3d9789357^the same request storessk-NEW-ROTATED-KEY.Related Issue
Fixes #
Type of Change
Changes Made
hermes_cli/web_server.py— gate the fallback onnot api_key, matching thebase_urlline directly above it.tests/hermes_cli/test_web_server.py— explicit key wins; omitted key stilladopts the entry's key (and the
base_urlfill still works).Testing
test_set_model_main_honors_an_explicitly_supplied_api_keyfails onmain.test_set_model_main_falls_back_to_the_provider_entry_keypasses both ways — thatone exists so the fix can't regress the feature's intent in the other direction.
Web-server / model-switch / credential-lifecycle / config suites baseline-compared
against a clean
origin/mainworktree: identical 16 pre-existing failures,627 → 629passed.Checklist
mainand covered by a failing-before/passing-after testorigin/main)