fix(providers): clear the base-URL field when the gateway stops returning one - #52
Merged
Merged
Conversation
…ning one
Two problems in the same form, both of which kept an API key on screen.
The effect that mirrors `GET /secrets` into the base-URL field was guarded
on truthiness:
if (secrets.data?.api_url) setUrl(secrets.data.api_url);
so it only ever filled the field and never emptied it. A value the
gateway stopped returning stayed rendered until a page reload. That is
exactly what happens the moment the gateway starts withholding an
`api_url` that holds an API key: the server returns null, the effect
re-runs because the dependency changed, the guard skips the write, and
the key remains visible in the console.
Verified against a live gateway, with the panel's own Refresh button and
no page reload. Before: the field still showed the value the server had
already stopped returning. After: it clears. Same sequence, same server,
same browser.
Both inputs were also placeholder-only. They sit next to each other, one
takes a URL and one takes a credential, and a placeholder disappears the
moment either is focused — so the field that has just been cleared is
also the one whose purpose is least visible while typing into it. Pasting
a key into the base-URL field is what put a credential into config.toml
in plaintext in the first place. Give both a real `<label htmlFor>` using
the pattern already used in the channels panel, name the base URL as
"not your API key", and move the "leave blank to keep current" hint into
the key field's placeholder where it is not competing with a label.
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.
Summary
Two problems in the Providers form, both of which kept an API key on screen.
1. The base-URL field never cleared. The effect mirroring
GET /secretsinto the field was guarded on truthiness:so it only ever filled the field and never emptied it. A value the gateway stopped returning stayed rendered until a page reload — and that is exactly what happens when the gateway starts withholding an
api_urlthat holds an API key (RantAIClaw#444): the server returnsnull, the effect re-runs because the dependency changed, the guard skips the write, and the key stays visible in the console.2. Both inputs were placeholder-only. They sit next to each other, one takes a URL and one takes a credential, and a placeholder disappears the moment either is focused — so the field that has just been cleared is also the one whose purpose is least visible while you type into it. Pasting a key into the base-URL field is what put a credential into
config.tomlin plaintext to begin with.What changed
setUrl(secrets.data?.api_url ?? "")— mirror the server's value even when it is absent.<label htmlFor>+id, using the pattern already inchannels-panel.tsx. The base URL is named "API base URL — optional, not your API key"; the "leave blank to keep current" hint moves into the key field's placeholder where it no longer competes with a label. The base-URL placeholder becomes an example URL, which is what a placeholder is for.What did not change
No API calls, no state shape, no save logic, no other panel.
SecretsInfo.api_urlwas already typedstring | null— this only stops the client ignoring thenull.Related
api_urlreturnnullwhen it holds a credential. This PR is what makes the console actually reflect that; without it the key stays on screen until reload.Validation
Component tests were not added:
vitest.config.mtsruns in thenodeenvironment and includes onlysrc/**/*.test.ts, so there is no DOM/testing-library setup to hang a component test on. Adding one would mean pulling in jsdom and a rendering library for a one-line state fix. Verified by driving the real console instead.Browser verification, against a live gateway on an isolated config dir:
api_url: "https://probe.example.com/v1", page loadedapi_url: null, panel Refresh clicked, no page reloadSame sequence, same gateway, same browser. The control is the point: reverting only the changed line reproduces the stale value, so this is not a test that would pass either way.
Build provenance was checked rather than assumed — the served bundle was grepped for the new label before any conclusion was drawn from it. Worth noting for anyone reproducing:
next startdoes not work with this project'soutput: standaloneconfig and will silently serve a stale build; usenode .next/standalone/server.jswith.next/staticandpubliccopied in.Risk
Low. One state assignment and markup around two existing inputs.
secrets.datachange rather than only on truthy ones, so a refresh overwrites whatever is typed in the base-URL field. That was already true for non-empty server values; this extends it to the empty case, which is the intended behaviour — refresh means "show me what the server has".useAsyncnever clearsdataduring a refresh (it only assigns on success), so an in-flight or failed refresh cannot blank the field.Rollback
git revert. Nothing depends on this and no data shape changed.