Skip to content

Make TUI startup non-blocking on IAP (APP-5220) - #14796

Merged
kevinyang372 merged 2 commits into
masterfrom
factory/app-5220-nonfatal-iap-local
Aug 7, 2026
Merged

Make TUI startup non-blocking on IAP (APP-5220)#14796
kevinyang372 merged 2 commits into
masterfrom
factory/app-5220-nonfatal-iap-local

Conversation

@warp-agent-staging

@warp-agent-staging warp-agent-staging Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

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 IapManager to mint a token; IAP resolves out of band. This removes a ~60s startup stall for headless/sandboxed local-channel TUI clients that hold a valid WARP_API_KEY but 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 until IapManager minted a token, and on the 60s AccessUnavailable timeout dropped the pending authentication — so the API key was never consumed and the client stayed on the login screen:

[WARN] Warp Staging IAP token fetch failed: failed to mint Warp identity token: ... missing authentication credentials
[ERROR] Staging IAP access unavailable before startup user authentication

Staging currently doesn't enforce IAP (warp-terraform environments/staging/main.tfenable_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_access now starts startup auth immediately rather than gating on IAP. It still subscribes to IapManager: if a valid IAP token later lands, it retries auth (guarded by auth_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::Tui via startup_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":

  • Cannot affect production. IapConfig is compiled in only on staging builds (Dev/Local channels); production/release builds have iap_config: None, so IapManager::is_enabled() is false and this path is never reached there regardless of launch mode.
  • GUI/CLI untouched. Restricting to the TUI launch mode leaves every other front-end's startup-auth semantics exactly as before.

Recovery when IAP is required (the safety-critical case)

Verified from code that the reactive path genuinely recovers, rather than assuming it:

  • The startup auth request (fetch_user → GraphQL GetUser) detects an IAP challenge: crates/graphql/src/client.rs returns IapChallengeBlockedgraphql_helpers.rs fires AuthEvent::IapChallengeReceived → the ServerApiProvider event loop calls IapManager::handle_challengestart_refresh (mints a token).
  • That first request is one-shot (no built-in retry), so the retry is provided by the 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_url host is local (e.g. localhost). This ticket is the other case: the local channel pointed at the real staging.warp.dev URL, where that host check is false so IAP is still attempted. The two changes are complementary and non-overlapping.

Verification

Deterministic:

  • Regression test 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 --lib passes.
  • cargo fmt -p warp -- --check clean; cargo clippy -p warp --all-targets --tests -- -D warnings clean.

Live TUI proof (primary acceptance test) — built the internal local-channel warp-tui and ran it against staging with a valid WARP_API_KEY:

  • The composer ("Signed in as kevin@warp.dev") is reached within a few seconds — no ~60s stall. The runtime log shows Authenticating via pending API key at 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 fatal Staging IAP access unavailable before startup user authentication string 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.

)

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>
@cla-bot cla-bot Bot added the cla-signed label Aug 6, 2026
@warp-agent-staging warp-agent-staging Bot added the warpy-factory Label associated to the "Wob the Wuilder" factory on staging, also known as Warpy Factory. label Aug 6, 2026
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>
@warp-agent-staging warp-agent-staging Bot changed the title Make staging IAP-access failure non-fatal on the local channel (APP-5220) Make TUI startup non-blocking on IAP (APP-5220) Aug 6, 2026
@warp-agent-staging
warp-agent-staging Bot marked this pull request as ready for review August 6, 2026 16:46
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>
@kevinyang372
kevinyang372 merged commit da449ab into master Aug 7, 2026
54 of 60 checks passed
@kevinyang372
kevinyang372 deleted the factory/app-5220-nonfatal-iap-local branch August 7, 2026 20:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed warpy-factory Label associated to the "Wob the Wuilder" factory on staging, also known as Warpy Factory.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants