Make TUI startup non-blocking on IAP (APP-5220) - #14796
Merged
Merged
Conversation
) On the internal `local` channel, a startup staging-IAP-access failure no longer drops the pending startup user authentication. Instead it proceeds with authentication and relies on the existing reactive IAP-challenge path to mint a token if the server actually enforces IAP. Dev and every release channel keep the fail-closed behavior. Co-Authored-By: Warp Agent <agent@warp.dev>
Scope the change to the TUI launch mode: startup user authentication now proceeds immediately instead of waiting on IapManager to mint a staging IAP token. If the server actually enforces IAP, the first token-less request hits an IAP challenge that kicks a token mint; a subscription retries auth once a valid token lands so login still recovers. Non-TUI front-ends keep the prior blocking behavior. Co-Authored-By: Warp Agent <agent@warp.dev>
kevinyang372
approved these changes
Aug 6, 2026
bholmesdev
pushed a commit
that referenced
this pull request
Aug 7, 2026
## Summary Adds a `/connect-grok` TUI slash command that acts as a shortcut into the Grok (xAI) account connection flow. Today that flow is only reachable via `/api-keys` → selecting the "X premium or SuperGrok subscription" row; this command jumps straight there. What changed: - New `SlashCommandKind::ConnectGrok` variant and a `CONNECT_GROK` `StaticCommand` (`TuiOnly`, `AI_ENABLED`, no argument, description "Connect your Grok (X Premium / SuperGrok) account"), registered in the command list so it is discoverable via the slash-command fuzzy filter. - `TuiApiKeysMenuModel::open_and_connect_grok` opens the inline api-keys menu and reuses the existing `edit_provider(LLMProvider::Xai)` path, so the already-connected case and every policy gate (SuperGrok flag / BYOK enabled / org allows member keys) surface the exact same messaging as selecting the Grok provider row. - A `SlashCommandKind::ConnectGrok` dispatch arm in the TUI `execute_tui_slash_command` that records the standard slash-command acceptance telemetry. - The GUI dispatch match lists `ConnectGrok` in its TUI-only bucket (the command is TUI-only). Per the ticket's non-blocking UX note, `/connect-grok` immediately initiates the connect (equivalent to selecting the Grok row) rather than merely pre-focusing it, reusing `edit_provider(Xai)` so the already-connected / policy-gated cases are handled identically. ## Verification Deterministic checks (all pass): `./script/format`, and `cargo clippy -p warp -p warp_tui --tests -- -D warnings` (clean on the touched crates). Regression tests added (all pass via `cargo nextest`): - `connect_grok_command_is_tui_only_and_has_no_arguments` (`app/.../static_commands/commands_tests.rs`) — asserts `/connect-grok` is registered TUI-only with `AI_ENABLED`, no argument, the expected description, and is absent from the GUI surface. - `open_and_connect_grok_matches_selecting_the_grok_row` (`crates/warp_tui/src/api_keys_menu_tests.rs`) — asserts the shortcut lands in the identical menu state (open, same footer, same header) as opening the menu and selecting/accepting the Grok row, proving it reuses `edit_provider(Xai)`. - `connect_grok_slash_command_opens_the_api_keys_menu_in_grok_flow` (`crates/warp_tui/src/terminal_session_view_tests.rs`) — asserts executing `/connect-grok` opens the api-keys menu (ApiKeys suggestions mode) and clears the input. Note on the full test suite: only the touched packages/modules were run locally; the PR's CI is the full-suite backstop. A pre-existing `clippy::let_and_return` lint in the untouched `warp_completer` crate surfaces only under `--all-features -D warnings` and is unrelated to this change (confirmed reproducible on clean `master`). ### Visual proof — captured Live-TUI visual proof of `/connect-grok` has now been captured against the internal `local` `warp-tui` build (signed in via `WARP_API_KEY` as `kevin@warp.dev`), driven under `tmux` and recorded to video. The recording and stills below show the two states the ticket calls for: 1. **Slash-command menu** — typing `/connect-grok` surfaces the command with description "Connect your Grok (X Premium / SuperGrok) account". ([still](https://oz.staging.warp.dev/artifacts/019fd839-2075-7346-88ff-a45a5b3b14db)) 2. **Grok connect flow** — executing `/connect-grok` opens the API keys menu jumped straight into the Grok connect path: the **"X premium or SuperGrok subscription (Connecting...)"** row is selected with footer **"Connect X premium/SuperGrok | enter to confirm | esc to cancel"** — identical to opening `/api-keys` and selecting the "X premium or SuperGrok subscription" row. ([still](https://oz.staging.warp.dev/artifacts/019fd839-3485-7ee6-8324-50d77a8f9775)) Deterministic `tmux capture-pane` frames of the two states: ```text /connect-grok Connect your Grok (X Premium / SuperGrok) account ▏ > /connect-grok ``` ```text API keys Anthropic API key (Not connected) Google API key (Not connected) OpenAI API key (Not connected) X premium or SuperGrok subscription (Connecting...) Connect X premium/SuperGrok | enter to confirm | esc to cancel ``` **How the proof was captured (honest disclosure).** The earlier blocker was that the sandbox TUI could not start because staging IAP failed *before* user authentication. To make the TUI startable here, the IAP-startup fix from the **separate, not-yet-merged** PR #14796 (`factory/app-5220-nonfatal-iap-local`) was applied to the **local working tree only**. It was **not** committed or pushed to this branch: this PR's (#14759) committed diff is unchanged and its branch head is byte-identical to before the proof run. The `/connect-grok` code exercised is exactly this PR's code, but this proof did **not** run on the branch as-is — it required #14796's IAP fix locally to get the TUI past startup. The full OAuth leg (browser hand-off + credential storage) was not exercised: the sandbox has no browser and the OS keyring is unavailable (`org.freedesktop.secrets` not provided). Reaching the Grok connect state shown above is the behavior this PR adds and is the same state as the existing `/api-keys` → Grok row. CHANGELOG-IMPROVEMENT: Add a `/connect-grok` TUI slash command that jumps straight into connecting your Grok (X Premium / SuperGrok) account. Originating thread: https://warpdev.slack.com/archives/C0BDQDW8V5E/p1785973349809639 <!-- factory-agent: {"source":"factory-agent","task_id":"APP-5200","task_source":"linear","task_url":"https://linear.app/warpdotdev/issue/APP-5200/tui-add-a-connect-grok-slash-command-as-a-shortcut-into-the-grok","oz_run_id":"019fd458-9746-7e7c-b3d0-3074cdb1952d","repo":"warpdotdev/warp","review_rework_attempts":1} --> <!-- oz:computer-use-videos start --> ### Computer-use video recordings [View video recording](https://oz.staging.warp.dev/artifacts/019fd839-0d31-73bc-8875-6b6036d99685) - APP-5200 visual proof (video, 14s): internal `local` warp-tui signed in, /connect-grok shown in slash-command menu, then executing it opens the API keys menu jumped into the Grok connect flow ("X premium or SuperGrok subscription (Connecting...)"). Captured with PR #14796's IAP startup fix applied to the local working tree only; PR #14759's committed diff is unchanged. <!-- oz:computer-use-videos end --> _Conversation: https://staging.warp.dev/conversation/157ffbbb-4e64-4030-9a03-5485949514f2_ _Run: https://oz.staging.warp.dev/runs/019fd458-9746-7e7c-b3d0-3074cdb1952d_ _Proof-capture run: https://oz.staging.warp.dev/runs/019fd81b-2c9d-7933-bb2f-18dad49221de_ _This PR was generated with [Oz](https://warp.dev/oz)._ Co-authored-by: Oz <oz-agent@warp.dev> Co-authored-by: Warp Agent <agent@warp.dev>
3 tasks
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.
Summary
The TUI (Warp Agent CLI) no longer blocks its startup on staging Google IAP. Startup user authentication now proceeds immediately instead of waiting on
IapManagerto mint a token; IAP resolves out of band. This removes a ~60s startup stall for headless/sandboxedlocal-channel TUI clients that hold a validWARP_API_KEYbut cannot mint an IAP token, while remaining correct if staging re-enables IAP.Root cause
Interactive startup auth is routed through
authenticate_user_after_iap_access(app/src/lib.rs), which deferred both the API-key and refresh-user authentication untilIapManagerminted a token, and on the 60sAccessUnavailabletimeout dropped the pending authentication — so the API key was never consumed and the client stayed on the login screen:Staging currently doesn't enforce IAP (
warp-terraform environments/staging/main.tf→enable_iap = false), but that has flip-flopped (enabled 2026-07-12 #1207, reverted 2026-07-20 #1325), so the fix must not hard-code "staging has no IAP."The fix
For the TUI launch mode,
authenticate_user_after_iap_accessnow starts startup auth immediately rather than gating on IAP. It still subscribes toIapManager: if a valid IAP token later lands, it retries auth (guarded byauth_state.user_id()so it doesn't redundantly re-auth when the optimistic attempt already succeeded). Non-TUI front-ends keep the prior blocking behavior unchanged.Scope and reasoning
The non-blocking behavior is gated to
LaunchMode::Tuiviastartup_auth_is_non_blocking(launch_mode), matching the requester's "in TUI". This is the narrowest scope that satisfies "don't block TUI startup on IAP":IapConfigis compiled in only on staging builds (Dev/Local channels); production/release builds haveiap_config: None, soIapManager::is_enabled()is false and this path is never reached there regardless of launch mode.Recovery when IAP is required (the safety-critical case)
Verified from code that the reactive path genuinely recovers, rather than assuming it:
fetch_user→ GraphQLGetUser) detects an IAP challenge:crates/graphql/src/client.rsreturnsIapChallengeBlocked→graphql_helpers.rsfiresAuthEvent::IapChallengeReceived→ theServerApiProviderevent loop callsIapManager::handle_challenge→start_refresh(mints a token).StateChanged→start-auth subscription retained here: once a valid token lands, auth is retried and login succeeds. This is why the subscription is kept rather than removed — a naive "fire once, never wait" would kick the mint but leave login failed the day staging re-enables IAP.Relationship to REMOTE-2540
REMOTE-2540 (PR #14756) disables IAP only when the resolved
server_root_urlhost is local (e.g.localhost). This ticket is the other case: thelocalchannel pointed at the realstaging.warp.devURL, where that host check is false so IAP is still attempted. The two changes are complementary and non-overlapping.Verification
Deterministic:
startup_auth_is_non_blocking_only_for_tui(app/src/lib_tests.rs) pins the scope: TUI ⇒ non-blocking; App/CommandLine/Test/RemoteServerProxy/RemoteServerDaemon ⇒ blocking.cargo nextest run -p warp --libpasses.cargo fmt -p warp -- --checkclean;cargo clippy -p warp --all-targets --tests -- -D warningsclean.Live TUI proof (primary acceptance test) — built the internal
local-channelwarp-tuiand ran it against staging with a validWARP_API_KEY:Authenticating via pending API keyat the same timestamp IAP minting begins (16:43:06Z), i.e. auth fires immediately; IAP token fetch fails in the background without blocking; and the fatalStaging IAP access unavailable before startup user authenticationstring appears 0 times.Before (login gate): https://oz.staging.warp.dev/artifacts/019fd7e5-3645-75c2-a003-76982898a660
After (signed-in composer, no stall): https://oz.staging.warp.dev/artifacts/019fd7f6-a15b-700f-ad86-8bd6434396cd
Computer-use video recordings
View video recording - APP-5220 refreshed live proof (non-blocking): local-channel warp-tui reaches the signed-in composer within a few seconds with no ~60s IAP stall; startup auth fires immediately and IAP resolves in the background.
Originating thread: https://warpdev.slack.com/archives/C0BDQDW8V5E/p1785973349809639
Conversation: https://staging.warp.dev/conversation/6c79c189-68f8-4130-975f-fa83ea764d87
Run: https://oz.staging.warp.dev/runs/019fd7c5-ed84-7ec9-9cd5-f2565087b741
This PR was generated with Oz.