Skip to content

feat(tui): re-check the gateway key at startup like the desktop app - #353

Merged
quickbeard merged 2 commits into
mainfrom
feat/tui-key-preflight
Sep 10, 2026
Merged

quickbeard merged 2 commits into
mainfrom
feat/tui-key-preflight

Conversation

@quickbeard

Copy link
Copy Markdown
Owner

Summary

Replaces #352, which GitHub closed when #351's branch was deleted on merge and will not reopen after the rebase. Same commits, rebased onto main.

The desktop app has run a startup key pre-flight since #296: it validates the stored gateway key, re-mints it silently through the SSO session when the gateway rejects it, and only asks for a sign-in when that is impossible. The TUI had nothing of the sort, so a key the gateway had since rejected left it "connected" and 401ing on every message, with /configure as the only way back.

  • Shared pre-flight. The controller's ensureKey logic moves into @codev/gateway as ensureGatewayKey (injectable fns for tests, host fetchImpl, timeout cap). The desktop controller now delegates to it and adopts the refreshed session; its wire type and tests are unchanged. The result distinguishes needs-login reasons: no-key vs rejected.
  • TUI startup check. One-shot effect in app.tsx after sync completes. refreshed merges the key into the auth registry for every provider id (current + legacy spellings), then dispose + bootstrap like the configure flow. rejected opens DialogConfigure in a new dismissable mode when no dialog is up. no-key (a machine set up with some other provider, or not at all) is ignored so non-gateway users are never nagged.
  • Test isolation. TUI view tests boot the real app, and the pre-flight reads (and can write) the shared auth file under ~/.codev/~/.codev-hub. A new test/preload.ts sets CODEV_TEST_HOME to an empty temp home, same convention as core's Global and packages/opencode/test/preload.ts. bunfig.toml is an upstream file, so it has a DIVERGENCES.md row; the app.tsx row is extended.

Test plan

  • packages/codev-gateway: bun test (75 pass) — new ensure-key.test.ts ports the desktop cases plus timeout cap, no-key vs rejected, and fetchImpl plumbing
  • packages/desktop: bun test src/main/gateway-sso (22 pass), bun typecheck
  • packages/tui: full bun test (269 pass, 0 fail) with the preload, bun typecheck
  • Manual: TUI with a revoked gateway key and a live SSO session starts and chats without a prompt; with a dead SSO session it opens the configure dialog and esc closes it

🤖 Generated with Claude Code

https://claude.ai/code/session_01UtPnKQ9ATvc9kd1v74zC4Y

Move the desktop controller's ensureKey logic into @codev/gateway as
ensureGatewayKey so both shells run the same pre-flight: validate the
stored gateway key, re-mint it silently through the SSO session when the
gateway rejects it, and only ask for a sign-in when that is impossible.
The result now says why a login is needed ("no-key" vs "rejected").

The TUI runs it once after sync completes. A refreshed key is merged into
the auth registry for every provider id the check names, then the
instance is disposed and re-bootstrapped; a rejected key that cannot be
renewed opens the configure dialog in a new dismissable mode. Machines
without a gateway key are left alone.

TUI tests boot the real app, so a new test preload sets CODEV_TEST_HOME to
an empty temp home; without it a developer's run would probe the real
gateway with their real key.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtPnKQ9ATvc9kd1v74zC4Y
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UtPnKQ9ATvc9kd1v74zC4Y
@quickbeard
quickbeard force-pushed the feat/tui-key-preflight branch from ec290f4 to 2a7b064 Compare September 10, 2026 03:47
@quickbeard
quickbeard merged commit b843261 into main Sep 10, 2026
1 of 5 checks passed
@quickbeard
quickbeard deleted the feat/tui-key-preflight branch September 10, 2026 03:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant