From 1029ff0747d7746d39a4496b6fbe975738eca4ab Mon Sep 17 00:00:00 2001 From: Sienna Meridian Satterwhite Date: Fri, 20 Mar 2026 14:31:59 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20auth=20login=20UX=20=E2=80=94=20timeout,?= =?UTF-8?q?=20Ctrl+C,=20suppress=20K8s=20error,=20center=20HTML?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 5-minute timeout on callback wait (Ctrl+C now works) - Skip K8s client_id lookup when no cluster configured (removes noisy ERROR) - Center the success page HTML to match Sunbeam Studios branding --- src/auth.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/auth.rs b/src/auth.rs index 8dd7dff..8453fd3 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -273,6 +273,14 @@ async fn refresh_token(cached: &AuthTokens) -> Result { /// Try to read the client_id from K8s secret `oidc-sunbeam-cli` in `ory` namespace. /// Falls back to the default client ID. async fn resolve_client_id() -> String { + // Try reading from K8s secret — silently fall back if cluster is unreachable. + // The tracing ERROR from kube client init is noisy; suppress by not even trying + // when we know the cluster isn't configured. + let host = crate::config::get_production_host(); + if host.is_empty() && crate::kube::ssh_host().is_empty() { + // No cluster configured, skip K8s lookup + return DEFAULT_CLIENT_ID.to_string(); + } match crate::kube::kube_get_secret_field("ory", "oidc-sunbeam-cli", "client_id").await { Ok(id) if !id.is_empty() => id, _ => DEFAULT_CLIENT_ID.to_string(), @@ -340,7 +348,15 @@ async fn wait_for_callback( ) -> Result { use tokio::io::{AsyncReadExt, AsyncWriteExt}; - let (mut stream, _) = listener.accept().await.ctx("Failed to accept callback connection")?; + // Wait up to 5 minutes for the callback, or until Ctrl+C + let accept_result = tokio::time::timeout( + std::time::Duration::from_secs(300), + listener.accept(), + ) + .await + .map_err(|_| SunbeamError::identity("Login timed out (5 min). Try again with `sunbeam auth login`."))?; + + let (mut stream, _) = accept_result.ctx("Failed to accept callback connection")?; let mut buf = vec![0u8; 4096]; let n = stream @@ -389,10 +405,15 @@ async fn wait_for_callback( // Send success response let html = concat!( - "", + "
", "

Authentication successful

", "

You can close this tab and return to the terminal.

", - "" + "
" ); let response = format!( "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: {}\r\nConnection: close\r\n\r\n{}",