You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
use build-time VITE auth config in Rust while preserving runtime env overrides
route shared needsLogin requests through the native Tauri auth bridge instead of web redirects
Tests
cargo test --manifest-path apps/stage-tauri/Cargo.toml commands::auth -- --test-threads=1
pnpm -F @proj-airi/stage-tauri exec vitest run src/auth-session.test.ts
pnpm -F @proj-airi/stage-ui exec vitest run src/stores/auth.test.ts
pnpm -F @proj-airi/stage-tauri typecheck
pnpm -F @proj-airi/stage-ui typecheck
Notes
stage-tauri typecheck required rebuilding ignored @proj-airi/tauri-eventa dist output locally before running, because the worktree had stale generated contract types.
Records auth-oidc-flow as implementation-complete-runtime-evidence-pending at 43093934e and advances the mission pointer to end-to-end-user-session.
Tests: jq empty docs/missions/d74b01dc-52da-4992-8a61-ea0a07bd800e/features.json docs/missions/d74b01dc-52da-4992-8a61-ea0a07bd800e/state.json docs/missions/d74b01dc-52da-4992-8a61-ea0a07bd800e/validation-state.json docs/missions/d74b01dc-52da-4992-8a61-ea0a07bd800e/handoffs/2026-07-06T02-17-08-237Z__auth-oidc-flow__codex-orchestrator-2026-07-06.json; jq -c . docs/missions/d74b01dc-52da-4992-8a61-ea0a07bd800e/progress_log.jsonl >/dev/null.
Use build-time OIDC config in Rust with runtime env override fallback.
Route shared needsLogin through the Stage Tauri native auth bridge and keep Tauri out of the shared web redirect path.
Tests: cargo test --manifest-path apps/stage-tauri/Cargo.toml commands::auth -- --test-threads=1
Tests: pnpm -F @proj-airi/stage-tauri exec vitest run src/auth-session.test.ts
Tests: pnpm -F @proj-airi/stage-ui exec vitest run src/stores/auth.test.ts
Tests: pnpm -F @proj-airi/stage-tauri typecheck
Tests: pnpm -F @proj-airi/stage-ui typecheck
We reviewed changes in 4f77c23...227580c on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.
AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request implements the OIDC authentication flow for the Stage Tauri application, introducing Rust commands for loopback-based PKCE login and token exchange, Tauri Eventa contracts, and a settings account UI in the frontend. The code review highlights several critical security and robustness improvements for the loopback listener in auth.rs. Specifically, the reviewer recommends validating the OIDC state inside the connection acceptance loop to prevent mismatched state requests from aborting the flow, adding a timeout and error handling to the loopback listener to mitigate Denial of Service (DoS) vulnerabilities, and configuring a timeout on the reqwest Client used for token exchange to avoid indefinite hangs.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
The reason will be displayed to describe this comment to others. Learn more.
Pass the expected_state parameter to accept_loopback_callback so that state validation can be performed directly inside the connection acceptance loop. This prevents malicious or mismatched state requests from aborting the entire OIDC login flow.
The reason will be displayed to describe this comment to others. Learn more.
The current loopback listener is highly fragile and vulnerable to denial-of-service or accidental aborts. Specifically:
Any read error or connection reset in read_http_request immediately returns an Err via ?, aborting the entire login flow.
Any write error in write_loopback_response also aborts the entire login flow.
A single slow connection can block the loopback server indefinitely because requests are handled sequentially.
Mismatched state checks are performed outside the loop, meaning a single request with an invalid state will terminate the listener before the genuine callback arrives.
To resolve these issues, we should:
Add a timeout (e.g., 5 seconds) to read_http_request using tokio::time::timeout.
Ignore read/write errors and continue the loop to accept subsequent connections.
Validate the state parameter inside the loop against expected_state and only return Ok(callback) when they match.
asyncfnaccept_loopback_callback(listener:TcpListener,expected_state:&str,) -> Result<LoopbackCallback,String>{loop{let(mut stream, _) = listener
.accept().await.map_err(|error| format!("Failed to accept OIDC callback: {error}"))?;let request = match tokio::time::timeout(Duration::from_secs(5),read_http_request(&mut stream)).await{Ok(Ok(req)) => req,
_ => continue,};ifis_options_callback(&request){let _ = write_loopback_response(&mut stream,"HTTP/1.1 204 No Content","").await;continue;}matchparse_loopback_callback_request(&request){Ok(callback) => {if callback.state != expected_state {let _ = write_loopback_response(&mut stream,"HTTP/1.1 400 Bad Request","<html><body><h2>State mismatch</h2></body></html>",).await;continue;}let _ = write_loopback_response(&mut stream,"HTTP/1.1 200 OK","<html><body><h2>Authentication successful!</h2><p>You can close this window and return to the app.</p></body></html>",).await;returnOk(callback);}Err(CallbackParseError::MissingParameters) => {let _ = write_loopback_response(&mut stream,"HTTP/1.1 400 Bad Request","<html><body><h2>Missing parameters</h2></body></html>",).await;}Err(CallbackParseError::Oidc(description)) => {let _ = write_loopback_response(&mut stream,"HTTP/1.1 200 OK","<html><body><h2>Authentication failed</h2><p>You can close this window.</p></body></html>",).await;returnErr(description);}Err(CallbackParseError::UnsupportedRequest) => {let _ = write_loopback_response(&mut stream,"HTTP/1.1 404 Not Found","<html><body><h2>Not found</h2></body></html>",).await;}}}}
The reason will be displayed to describe this comment to others. Learn more.
Configure a timeout on the reqwest::Client used for token exchange. By default, reqwest::Client has no timeout, which can cause the login flow to hang indefinitely if the OIDC token endpoint is unresponsive.
let response = reqwest::Client::builder().timeout(Duration::from_secs(15)).build().map_err(|error| format!("Failed to build HTTP client: {error}"))?
.post(config.token_url()).header("Content-Type","application/x-www-form-urlencoded").body(body).send().await.map_err(|error| format!("Token exchange failed: {error}"))?;
The reason will be displayed to describe this comment to others. Learn more.
`authErrorMessage` has a cyclomatic complexity of 11 with "medium" risk
A function with high cyclomatic complexity can be hard to understand and
maintain. Cyclomatic complexity is a software metric that measures the number of
independent paths through a function. A higher cyclomatic complexity indicates
that the function has more decision points and is more complex.
The reason will be displayed to describe this comment to others. Learn more.
Found `async` function without any `await` expressions
A function that does not contain any await expressions should not be async (except for some edge cases in TypeScript which are discussed below). Asynchronous functions in JavaScript behave differently than other functions in two important ways:
The reason will be displayed to describe this comment to others. Learn more.
Found `async` function without any `await` expressions
A function that does not contain any await expressions should not be async (except for some edge cases in TypeScript which are discussed below). Asynchronous functions in JavaScript behave differently than other functions in two important ways:
The reason will be displayed to describe this comment to others. Learn more.
Found `async` function without any `await` expressions
A function that does not contain any await expressions should not be async (except for some edge cases in TypeScript which are discussed below). Asynchronous functions in JavaScript behave differently than other functions in two important ways:
The reason will be displayed to describe this comment to others. Learn more.
Unexpected empty async arrow function
Having empty functions hurts readability, and is considered a code-smell. There's almost always a way to avoid using them. If you must use one, consider adding a comment to inform the reader of its purpose.
The reason will be displayed to describe this comment to others. Learn more.
Unexpected empty async arrow function
Having empty functions hurts readability, and is considered a code-smell. There's almost always a way to avoid using them. If you must use one, consider adding a comment to inform the reader of its purpose.
The reason will be displayed to describe this comment to others. Learn more.
`applyStageTauriAuthCallback` has a cyclomatic complexity of 6 with "medium" risk
A function with high cyclomatic complexity can be hard to understand and
maintain. Cyclomatic complexity is a software metric that measures the number of
independent paths through a function. A higher cyclomatic complexity indicates
that the function has more decision points and is more complex.
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
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
Tests
Notes