fix: auth preflight (#18117)

Fix app-server startup when `remote_control = true` is enabled without
ChatGPT auth.

Remote control now starts in a degraded/retrying state instead of
failing app-server initialization, so Desktop is not stranded before the
initial initialize handshake.
This commit is contained in:
jif-oai
2026-04-16 16:17:11 +01:00
committed by GitHub
Unverified
parent 6adba99f4d
commit 76ea694db5
2 changed files with 38 additions and 14 deletions
@@ -4,7 +4,6 @@ mod protocol;
mod websocket;
use crate::transport::remote_control::websocket::RemoteControlWebsocket;
use crate::transport::remote_control::websocket::load_remote_control_auth;
pub use self::protocol::ClientId;
use self::protocol::ServerEvent;
@@ -59,9 +58,6 @@ pub(crate) async fn start_remote_control(
} else {
None
};
if initial_enabled {
validate_remote_control_auth(&auth_manager).await?;
}
let (enabled_tx, enabled_rx) = watch::channel(initial_enabled);
let join_handle = tokio::spawn(async move {
@@ -86,15 +82,5 @@ pub(crate) async fn start_remote_control(
))
}
pub(crate) async fn validate_remote_control_auth(
auth_manager: &Arc<AuthManager>,
) -> io::Result<()> {
match load_remote_control_auth(auth_manager).await {
Ok(_) => Ok(()),
Err(err) if err.kind() == io::ErrorKind::WouldBlock => Ok(()),
Err(err) => Err(err),
}
}
#[cfg(test)]
mod tests;
@@ -480,6 +480,44 @@ async fn remote_control_start_allows_remote_control_invalid_url_when_disabled()
.expect("remote control task should join");
}
#[tokio::test]
async fn remote_control_start_allows_missing_auth_when_enabled() {
let listener = TcpListener::bind("127.0.0.1:0")
.await
.expect("listener should bind");
let remote_control_url = remote_control_url_for_listener(&listener);
let codex_home = TempDir::new().expect("temp dir should create");
let auth_manager = AuthManager::shared(
codex_home.path().to_path_buf(),
/*enable_codex_api_key_env*/ false,
AuthCredentialsStoreMode::File,
);
let (transport_event_tx, _transport_event_rx) =
mpsc::channel::<TransportEvent>(CHANNEL_CAPACITY);
let shutdown_token = CancellationToken::new();
let (remote_task, _remote_handle) = start_remote_control(
remote_control_url,
/*state_db*/ None,
auth_manager,
transport_event_tx,
shutdown_token.clone(),
/*app_server_client_name_rx*/ None,
/*initial_enabled*/ true,
)
.await
.expect("remote control should start before ChatGPT auth is available");
timeout(Duration::from_millis(100), listener.accept())
.await
.expect_err("remote control should wait for auth before connecting");
shutdown_token.cancel();
timeout(Duration::from_secs(1), remote_task)
.await
.expect("remote control task should stop")
.expect("remote control task should join");
}
#[tokio::test]
async fn remote_control_handle_set_enabled_stops_and_restarts_connections() {
let listener = TcpListener::bind("127.0.0.1:0")