Copilot review round 6.
- The Basic credential is now form-urlencoded per RFC 6749 §2.3.1. Round 1
matched the SDK's raw `id:secret` on the theory that a credential should be
presented the same way here as at the token endpoint; that does not hold — a
client authenticated with `client_secret_post` never exercised the SDK's
Basic path, so there is no precedent to match, and the raw form is ambiguous
for an id containing `:` and makes `btoa` throw on a non-Latin-1 secret. The
fixture decodes each half.
- The ctx-less grant read is suppressed on the store's issuer *stamp* rather
than on the token's value. The active slot can hold client information
without a token, in which case the read falls back to the legacy grant — and
a value collision with any other issuer would have dropped that grant
unrevoked and unreported.
- The TUI announced "OAuth state cleared" on the keypress, so with a bounded
revocation request it said so while the work was still in flight and then
removed it when the work finished. `onClearOAuth` returns a promise;
`AuthTab` shows "Clearing OAuth state…" until it settles, ignores repeats
while one is in flight, and skips exactly the revision bump its own clear
caused so the confirmation is not immediately reset by it.
- `handleClearOAuth` now claims an attempt and retires a superseded one, the
way `handleDisconnect` does: the await can keep it suspended for seconds,
long enough for the user to switch servers and have server A's outcome —
including its disconnect — land on server B.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177mPHAdECD18nLLCTwR5rh
Signed-off-by: cliffhall <cliff@futurescale.com>