open-notebook/api
Luis Novo 85336f49fa
fix: actually clear credential fields end to end (frontend payload + API null handling) (#1046)
* fix(frontend): actually clear credential fields when emptied in the edit dialog

Clearing base_url (or the Vertex project/location/credentials_path)
in the credential edit dialog silently did nothing: the submit handler
mapped an emptied field to `undefined`, JSON.stringify dropped the key
from the PUT body, and the backend's partial-update semantics kept the
old value — while the UI reported success.

Emptied fields are now sent as an explicit `null`, which the API
already accepts and persists as a cleared value (verified live).
UpdateCredentialRequest's nullable fields are typed accordingly.

Found in v1.11 release testing (pre-existing, not a release regression):
an Ollama credential with a stale IP in base_url could not be cleared
from the UI.

* fix(api): clear credential fields on explicit null, not just empty string

The update handler guarded every field with 'is not None', so a JSON
null sent to clear base_url (or endpoint/api_version/endpoint_*/
project/location/credentials_path/num_ctx) was silently skipped — the
old value survived while the client saw a 200. Combined with the
frontend bug fixed in the previous commit (emptied fields dropped from
the payload entirely), clearing a credential field was impossible from
the UI: during release testing an Ollama credential kept pointing at a
stale IP after being 'cleared', and only an empty-string PUT crafted by
hand actually cleared it.

Field updates are now keyed on presence in model_fields_set: absent
keeps the old value, explicit null or "" clears. name/modalities/
api_key keep their non-null guards (clearing those is not meaningful).

Regression tests cover null-clears, empty-string-clears, absent-keeps
and the Vertex credentials_path case.

* test(frontend): extract credential update payload builder and cover clear-on-empty

Addresses the cubic review: the frontend half of the fix had no
reproducing test. The edit dialog's payload construction now lives in
a pure buildCredentialUpdatePayload() (frontend/src/lib/
credential-update-payload.ts) used by the component, with tests that
fail on the original bug: an emptied base_url (and Vertex project/
location/credentials_path) must survive JSON.stringify as an explicit
null, unchanged fields must be omitted, and emptied num_ctx clears
via 0.
2026-07-11 09:00:06 -03:00
..
routers fix: actually clear credential fields end to end (frontend payload + API null handling) (#1046) 2026-07-11 09:00:06 -03:00
__init__.py Api podcast migration (#93) 2025-07-17 08:36:11 -03:00
AGENTS.md docs: restructure documentation around AGENTS.md, VISION.md and decision records (#1032) 2026-07-10 15:33:19 -03:00
auth.py chore: remove dead auth helper and fix stale default-password docs (#1026) 2026-07-10 15:47:40 -03:00
chat_service.py Feat/localization tests docker (#371) 2026-01-15 13:51:05 -03:00
CLAUDE.md docs: restructure documentation around AGENTS.md, VISION.md and decision records (#1032) 2026-07-10 15:33:19 -03:00
client.py Feat/localization tests docker (#371) 2026-01-15 13:51:05 -03:00
command_service.py Version 1 (#160) 2025-10-18 12:46:22 -03:00
context_service.py Feat/localization tests docker (#371) 2026-01-15 13:51:05 -03:00
credentials_service.py fix: make the provider connection test resilient to model retirement (#1035) 2026-07-10 16:26:22 -03:00
embedding_service.py Feat/localization tests docker (#371) 2026-01-15 13:51:05 -03:00
episode_profiles_service.py Feat/localization tests docker (#371) 2026-01-15 13:51:05 -03:00
insights_service.py Feat/localization tests docker (#371) 2026-01-15 13:51:05 -03:00
main.py fix: reject oversized request bodies before auth/routing (#1014) 2026-07-10 11:15:18 -03:00
middleware.py fix: reject oversized request bodies before auth/routing (#1014) 2026-07-10 11:15:18 -03:00
models.py fix: restrict CreateCredentialRequest.provider to a known allowlist (#1016) 2026-07-10 13:34:46 -03:00
models_service.py Feat/localization tests docker (#371) 2026-01-15 13:51:05 -03:00
notebook_service.py Feat/localization tests docker (#371) 2026-01-15 13:51:05 -03:00
notes_service.py Feat/localization tests docker (#371) 2026-01-15 13:51:05 -03:00
podcast_api_service.py Version 1 (#160) 2025-10-18 12:46:22 -03:00
podcast_service.py fix: don't leak internal exception text in API error responses (#1017) 2026-07-10 13:40:27 -03:00
search_service.py Feat/localization tests docker (#371) 2026-01-15 13:51:05 -03:00
settings_service.py Feat/localization tests docker (#371) 2026-01-15 13:51:05 -03:00
sources_service.py Feat/localization tests docker (#371) 2026-01-15 13:51:05 -03:00
transformations_service.py feat: per-transformation custom model selection (#978) 2026-07-03 12:30:50 -03:00