gui: take the credential read off the Servers page's first paint - #210
Merged
Conversation
rowSignature decided whether to rebuild a server row, and it read the stored credential only while the row was expanded. The row menu reads it too, and that menu is on every row: Log out OAuth appears exactly when a credential is stored. So dropping a credential while the row was collapsed changed nothing the signature could see, the cached node was reused, and the menu went on offering to log out of a server with nothing left to log out of. Disabled servers took that path directly — logoutCredential repaints instead of probing when the server is off — and it is also the shape any future non-probing refresh of credential state would hit. The signature now carries hasStoredCredential unconditionally. The full status stays gated on expanded on purpose: the daemon computes expires_in per request, so an unconditional status entry would rebuild every row on every read for a countdown only the open panel draws. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Opening Servers held the "Reading the registry…" skeleton until both the registry read and a full credential-metadata read had answered. Only the first one describes the list. The second walks every server and reads its OAuth state and access token out of the secrets chain, which on macOS is a `security` subprocess per entry, run under one lock. Measured against a headless daemon on a seven-server registry with three authorized servers: GET /v1/servers answers in 0.1-0.4ms, GET /v1/auth in 120-137ms. The page paid the second on every navigation, because the router builds a fresh page per mount and this cache is page-local. The read now runs beside the fleet probe and repaints when it lands. The two surfaces that read a status are the expanded Authorization panel and the row menu's Log out item, and rowSignature covers both, so the late answer rebuilds exactly the rows it changes. Overlapping reads are ordered by epoch — a page-entry refresh and the read a completed login runs are both legitimate, and the older must not restore what the newer replaced — and a second draw arriving inside the window joins rather than starting a duplicate, while an explicit Refresh still re-asks. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Opening the Servers page held a skeleton ("Reading the registry…") until BOTH the
registry read and a full credential-metadata read had answered. The second one costs
a keychain lookup per stored entry — a
/usr/bin/securitysubprocess each, on macOS —serialized under the secrets chain's lock. On a seven-server registry that measured
~120ms of subprocess time in front of the first paint, on every navigation to the page,
because the router builds a fresh page instance per mount and nothing is cached across
one.
The list itself never needed it. Credential state reaches only two surfaces, and both
are now covered by the row signature, so a late answer repaints exactly the rows it
changes.
rowSignature, so a row whosecredential state changed is rebuilt even while collapsed
probe and repaint when it lands