Skip to content

fix(configure): dedupe racing plugin-credentials render + pre-fill from current values (#223, #224)#226

Merged
hyoshi merged 1 commit into
mainfrom
fix/dashboard-plugin-credentials-race-and-prefill
Jun 12, 2026
Merged

fix(configure): dedupe racing plugin-credentials render + pre-fill from current values (#223, #224)#226
hyoshi merged 1 commit into
mainfrom
fix/dashboard-plugin-credentials-race-and-prefill

Conversation

@hyoshi

@hyoshi hyoshi commented Jun 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Two coupled fixes for the dashboard "Plugin credentials" section (both touch dashboard.js, so they ship together). Closes #223, closes #224.

#223 — cards rendered twice (concurrent render race)

renderPluginCredentials() is async (clear → await fetch → append). The double renderAll() at init runs two calls that interleave, so both append → every card twice.

  • A monotonic pluginRenderSeq generation counter: a call bails after the await if a newer render started, so only the latest result appends.
  • container.textContent = "" moved to after the await (right before append) so a superseded render never empties the section.

#224 — forms blank after restart (no read-back)

The list endpoint shipped field specs only, so the form had nothing to pre-fill.

  • The handler annotates each declared field with stored state: configured (truthy value stored) always; value (verbatim) for non-secret fields only.
  • Secret values never ship — only the boolean — so a secret never round-trips to the browser. Blank-keeps-stored save contract unchanged.
  • dashboard.js pre-fills non-secret inputs from field.value and keys the secret placeholder off field.configured.

Security

  • Secrets never leave the store (asserted: "SECRET" not in json.dumps(body)); only a boolean configured flag is exposed.
  • Non-secret ids already appear in the operator's loopback UI elsewhere — no new exposure.

Test plan

Note: the one local-only test_mcp_server_plugin_wiring failure is the dev venv's installed bridge adding plugins; passes in clean CI.

…om current values (#223, #224)

#223 — Plugin-credentials cards rendered twice. renderPluginCredentials is
async (clear → await fetch → append); the double renderAll() at init runs
two calls that interleave, so both append (2N cards). Guard with a
monotonic generation counter: a call bails after the await if a newer
render started, and the clear now happens after the await (right before
append) so a superseded render never empties the section.

#224 — Plugin-credentials forms were blank after a configure restart. The
list endpoint shipped field specs only. The handler now annotates each
declared field with its stored state for pre-fill: `configured` (a truthy
value is stored) always, plus `value` (verbatim) for NON-secret fields.
Secret values never ship — only the boolean — so a secret never
round-trips to the browser; the blank-keeps-stored save contract is
unchanged. dashboard.js pre-fills non-secret inputs from field.value and
keys the secret placeholder off field.configured.
@hyoshi
hyoshi merged commit b46a4d8 into main Jun 12, 2026
9 checks passed
@hyoshi
hyoshi deleted the fix/dashboard-plugin-credentials-race-and-prefill branch June 12, 2026 18:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment