Skip to content

Surface Sign In errors in Account settings - #3624

Closed
austinywang wants to merge 51 commits into
mainfrom
issue-3617-sign-in-error-surface
Closed

austinywang wants to merge 51 commits into
mainfrom
issue-3617-sign-in-error-surface

Conversation

@austinywang

@austinywang austinywang commented May 6, 2026 •

Copy link
Copy Markdown
Contributor

Closes #3617

Fixes #3617

Summary

  • Stores visible sign-in failures in AuthManager instead of only logging ASWebAuthenticationSession/callback errors.
  • Shows the localized failure message under Settings > Account > Sign In and guards duplicate sign-in attempts while a session is in flight.
  • Documents the v0.64.0 Settings > Sign In addition and this fix in CHANGELOG.md.

Validation

  • Added AuthManagerSignInErrorTests for invalid callback error state.
  • Ran git diff --check.
  • Ran python3 -m json.tool Resources/Localizable.xcstrings.
  • Did not run local tests per repository instruction.

Note

Medium Risk
Touches authentication flows, token persistence, and concurrent sign-in/sign-out/callback handling; behavior is well covered by new tests but mistakes could affect session state.

Overview
Account Sign In failures now show a generic localized message under the button in Settings instead of failing silently (fixes #3617). The UI reads AuthManager.lastSignInError; user cancel on ASWebAuthenticationSession stays suppressed.

AuthManager now records errors for web-auth failures, invalid callbacks (only during an active browser attempt), session.start() failure, callback refresh failures, and credential sign-in failures, and clears them on success, a new attempt, or sign-out. beginSignInAndAwait can time out and cancel the web session so late callbacks do not sign the user in after sign-out or timeout. Credential and applySignInResult paths use the same auth-mutation gating as browser sign-in so concurrent sign-out does not leave tokens or a stuck loading state.

Errors and helpers move to AuthManagerErrors.swift; the account row moves to Settings/AuthSettingsRow.swift with red trailing error text and a guard while loading/restoring. New AuthManagerSignInErrorTests cover the concurrency and error-display cases; changelog and settings.account.error.signInFailed strings are added.

Reviewed by Cursor Bugbot for commit ba35199. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Surfaces a localized, generic error when Sign In fails in Settings > Account and hardens auth concurrency to prevent stale or duplicate updates. Keeps raw error strings out of the UI and resolves #3617.

  • Bug Fixes

    • Show a generic localized error under Sign In; clear on new attempts, success, sign-out, and during apply; suppress canceledLogin.
    • Browser sign-in: surface session.start failures; time out and cancel stalled sessions; prevent delayed callbacks (timeout or sign-out) from authenticating; keep loading ownership with the active web session; beginSignInAndAwait returns authoritative state on sync-start failures and timeouts.
    • Concurrency guards: await token writes in async applySignInResult; gate loading/auth updates behind the active mutation; prevent auth restore after concurrent sign-out; suppress stale callback/credential errors; keep superseded credential sign-ins internal.
  • Refactors

    • Extract AuthSignInError/AuthManagerError to AuthManagerErrors.swift with localized copy (settings.account.error.signInFailed); move the UI row to Settings/AuthSettingsRow.swift; inject credential sign-in for tests; add translations, tests (AuthManagerSignInErrorTests), and CHANGELOG entry.

Written for commit ba35199. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Sign-in failures in Account settings are now shown to users rather than only being logged.
  • New Features

    • Added a Settings > Sign In row with sign-in/sign-out controls, loading state, and visible error messages.
  • Localization

    • Sign-in failure message added for English, Japanese, Ukrainian, and Korean.
  • Tests

    • Added and updated tests to verify sign-in error reporting, callback handling, and token seeding sequencing.

Review Change Stack

Settings sign-in errors currently disappear into logs, so this adds a behavioral regression test for invalid callback handling before the production error surface exists.

Constraint: Do not run local tests for this repository; CI owns test execution.

Confidence: high

Scope-risk: narrow

Tested: Not run locally by instruction.

Not-tested: Local cmux-unit execution.
Settings auth previously converted ASWebAuthenticationSession and callback failures into log lines only, so users saw the web sheet disappear without any actionable state. AuthManager now stores a typed visible error, keeps in-flight web sessions from being cancelled by duplicate entry, and clears stale errors on successful sign-in paths.

Constraint: Settings strings must use String(localized:) and Localizable.xcstrings entries.

Constraint: Local tests are intentionally not run in this repo; CI owns test execution.

Rejected: Keep using NSLog-only failures | leaves issue 3617 with no visible user feedback.

Confidence: medium

Scope-risk: narrow

Tested: git diff --check; python3 -m json.tool Resources/Localizable.xcstrings

Not-tested: Local unit/UI tests by instruction.
@vercel

vercel Bot commented May 6, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment May 31, 2026 1:05am
cmux-staging Building Building Preview, Comment May 31, 2026 1:05am

@coderabbitai

coderabbitai Bot commented May 6, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds user-visible sign-in error surfacing: extracts auth errors to a new errors file, exposes lastSignInError on AuthManager and populates it across sign-in flows, introduces an AuthSettingsRow SwiftUI view, adds localization, registers files in the Xcode project, and adds tests asserting error visibility.

Changes

Sign-In Error Visibility & Settings UI

Layer / File(s) Summary
Error Types & Helpers
Sources/Auth/AuthManagerErrors.swift, Sources/Auth/AuthManager.swift
New AuthManagerError and AuthSignInError enums, AuthManager nonisolated helpers signInError(from:) and shouldSuppressWebAuthError(_:), and moved logger into AuthManager scope.
AuthManager State & Flows
Sources/Auth/AuthManager.swift
Adds @Published private(set) var lastSignInError: AuthSignInError?; removes in-file AuthManagerError; sets/resets lastSignInError across beginSignIn, ASWebAuthenticationSession completion, handleCallbackURL, token seeding/refresh, applySignInResult, credential sign-in success, and signOut; cancels/clears webAuthSession appropriately.
UI Component
Sources/Settings/AuthSettingsRow.swift
New SwiftUI AuthSettingsRow view that shows sign-in status, sign-in/out button, loading indicator, and displays authManager.lastSignInError localized message.
Settings Placement
Sources/cmuxApp.swift
Removed the inline AuthSettingsRow implementation from the app file; replaced by the dedicated view file.
Localization
Resources/Localizable.xcstrings
Adds settings.account.error.signInFailed localized strings (en, ja, uk, ko).
Tests
cmuxTests/AuthManagerSignInErrorTests.swift, cmuxTests/AuthManagerBrowserSignInTests.swift
New test verifying invalid callback surfaces lastSignInError (.authManager(.invalidCallback)) with a TestTokenStore actor; one existing test now awaits sign-in seeding to fix sequencing.
Xcode Project & Changelog
GhosttyTabs.xcodeproj/project.pbxproj, CHANGELOG.md
Registers AuthManagerErrors.swift, AuthSettingsRow.swift, and AuthManagerSignInErrorTests.swift in project references/build phases; updates CHANGELOG Unreleased and 0.64.3 notes.

Sequence Diagram(s)

sequenceDiagram
    participant User as "User / Settings UI"
    participant UI as "AuthSettingsRow"
    participant AM as "AuthManager"
    participant AS as "ASWebAuthenticationSession"
    participant TS as "TokenStore"

    User->>UI: Tap "Sign In…"
    UI->>AM: beginSignIn()
    AM->>AS: create & start session (auth URL)
    AS-->>AM: completion(callbackURL?, error?)
    alt error (canceled or other)
        AM->>AM: shouldSuppressWebAuthError? -> log & return OR
        AM->>AM: set lastSignInError = .message(...) or .authManager(...)
        AM-->>UI: published lastSignInError
        UI-->>User: show localized error
    else callbackURL present
        AM->>AM: handleCallbackURL(callbackURL)
        AM->>TS: seed/refresh tokens
        TS-->>AM: tokens
        AM->>UI: publish authenticated state (lastSignInError = nil)
        UI-->>User: update to signed-in state
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • manaflow-ai/cmux#3027: Main PR’s changes to AuthManager (error types, lastSignInError, applySignInResult signature), AuthSettingsRow, AuthManagerErrors, AppDelegate callback handling, and related tests directly overlap with this work.
  • manaflow-ai/cmux#3843: Modifies AuthManager sign-in/session and callback handling and adds related tests; closely related to these changes.

Poem

🐰
I hopped through logs and found the light,
Silent failures now take flight.
A row in Settings shows the clue,
Four tongues whisper what to do,
Debugging carrots for me and you!


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (2 errors, 1 warning)

Check name Status Explanation Resolution
Cmux Swift Actor Isolation ❌ Error The new enums AuthManagerError and AuthSignInError lack explicit Sendable conformance but are used in @Published on @MainActor AuthManager, violating Swift 6 actor isolation rules. Add Sendable conformance to both enums: enum AuthManagerError: LocalizedError, Equatable, Sendable and enum AuthSignInError: Equatable, Sendable in Sources/Auth/AuthManagerErrors.swift
Cmux Swift @Concurrent ❌ Error applySignInResult performs file I/O (await tokenStore.setTokens) on @MainActor without @concurrent. Violates rule on file-heavy async from UI isolation. Add @concurrent: @concurrent func applySignInResult(_ result: SignInResult) async. Or extract token writes to nonisolated with @MainActor hop for UI updates.
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (12 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: surfacing sign-in errors in the Account settings UI, which is the primary objective of the PR.
Linked Issues check ✅ Passed The PR comprehensively addresses all coding objectives from issue #3617: adds @Published lastSignInError to AuthManager, sets it on failure paths, renders localized error messages in AuthSettingsRow, prevents duplicate sign-in attempts, improves session lifecycle handling, and documents changes in CHANGELOG.md.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the requirements in issue #3617: error state tracking, UI display, session hardening, refactoring error types to a new file, and test coverage. No unrelated changes detected.
Cmux Swift Blocking Runtime ✅ Passed PR introduces no new blocking/timing synchronization primitives in production code. Pre-existing blocking patterns remain unchanged. All changes improve async/await patterns.
Cmux No Hacky Sleeps ✅ Passed PR contains only Swift files and Xcode/localization configs. Check targets non-Swift runtime code only. Swift changes covered by separate swift-blocking-runtime rule.
Cmux Swift Concurrency ✅ Passed No legacy async patterns. DispatchQueue.main.sync allowed for AppKit. No completion handlers or fire-and-forget Tasks. One @Published added to existing ObservableObject is not material expansion.
Cmux Swift File And Package Boundaries ✅ Passed AuthManagerErrors (63L) and AuthSettingsRow (96L) have single clear responsibilities. AuthManager.swift additions stay under 250L threshold. No responsibility mixing. Code properly extracted.
Cmux Swift Logging ✅ Passed PR passes swift-logging.md check. No NSLog/print/debugPrint/dump added. AuthManager properly uses Logger with privacy annotations. New files contain no logging.
Cmux Swiftui State Layout ✅ Passed AuthManager is legacy ObservableObject. Property added to pre-existing state. AuthSettingsRow in non-lazy VStack. No problematic GeometryReader or render mutations.
Cmux Architecture Rethink ✅ Passed Single-owner error surface with clear invariants. No timing patches, competing observers, or architectural debt. Proper async/await ordering for token persistence. Correctly fixes #3617.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed New AuthSettingsRow is a SwiftUI view within existing Settings window (cmux.settings). No standalone windows created. Settings already registered in cmuxAuxiliaryWindowIdentifiers.
Description check ✅ Passed Pull request description is comprehensive and addresses all required template sections with relevant details.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-3617-sign-in-error-surface

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

The workflow guard rejects growth in already-large Swift files, so the new sign-in error model and account settings row live in focused sub-500-line files instead of increasing AuthManager.swift and cmuxApp.swift.

Constraint: CI enforces .github/swift-file-length-budget.tsv.

Rejected: Refresh the Swift length budget | this change can stay within the existing budget by splitting focused code.

Confidence: high

Scope-risk: narrow

Tested: python3 scripts/swift_file_length_budget.py --budget .github/swift-file-length-budget.tsv

Tested: git diff --check

Tested: python3 -m json.tool Resources/Localizable.xcstrings

Not-tested: Local unit/UI tests by instruction.
@greptile-apps

greptile-apps Bot commented May 6, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR surfaces sign-in failures in the Settings > Account row by adding lastSignInError state to AuthManager and rendering the localized generic message in the extracted AuthSettingsRow component. It also hardens the browser and credential sign-in paths against stale callbacks, concurrent sign-out, and timed-out sessions using a mutation-generation guard.

  • Error visibility: lastSignInError is set on web-auth, session-start, and credential failures, cleared on success/sign-out/new attempt, and shown via AuthSignInError.localizedMessage (always the generic localized copy, never internal diagnostic strings).
  • Concurrency hardening: applySignInResult is now async and awaits token storage before checking mutation generation; signInWithCredential absorbs AuthMutationSupersededError internally; timeOutBrowserSignInAttempt uses beginAuthMutation(.signInCancellation) to prevent stale callbacks from authenticating.
  • Localization: settings.account.error.signInFailed is added with translations across all 19 supported locales (ar, bs, da, de, en, es, fr, it, ja, ko, nb, pl, pt-BR, ru, th, tr, uk, zh-Hans, zh-Hant).

Confidence Score: 5/5

Safe to merge. Auth state transitions are correctly guarded by mutation generations, token cleanup is handled by keepAuthMutationIfCurrent, and all previous review findings have been addressed.

All seven previously flagged issues have been resolved. The mutation-generation approach correctly handles concurrent sign-out and timeout cases, confirmed by the new test suite. Localization is now comprehensive across all 19 supported locales.

No files require special attention.

Important Files Changed

Filename Overview
Sources/Auth/AuthManager.swift Adds lastSignInError tracking, credential sign-in injection, mutation-generation guards in applySignInResult/signInWithCredential, timeOutBrowserSignInAttempt, and error suppression for canceledLogin; concurrency model is sound given @mainactor isolation.
Sources/Auth/AuthManagerErrors.swift New file extracting AuthManagerError and AuthSignInError; localizedMessage always returns the generic user copy regardless of associated value, keeping diagnostic details out of the UI.
Sources/Settings/AuthSettingsRow.swift Extracted from cmuxApp.swift; adds error text row below Sign In button and top-alignment HStack; uses @ObservedObject consistently with existing ObservableObject AuthManager.
cmuxTests/AuthManagerSignInErrorTests.swift Seven new tests covering invalid callback, stale callback, concurrent sign-out races, timeout supersession, and stale callback failure; actor-based test helpers are correctly structured.
Resources/Localizable.xcstrings Adds settings.account.error.signInFailed with translations for all 19 supported locales; addresses previously flagged incomplete coverage.

Sequence Diagram

sequenceDiagram
    participant UI as AuthSettingsRow
    participant AM as AuthManager
    participant TS as TokenStore

    Note over UI,TS: Browser sign-in happy path
    UI->>AM: beginSignIn()
    AM->>AM: "lastSignInError = nil, beginAuthMutation(G1)"
    AM->>AM: ASWebAuthenticationSession.start()
    AM-->>UI: "isLoading = true"
    AM->>AM: handleCallbackURL(url)
    AM->>TS: setTokens(access, refresh)
    AM->>AM: keepAuthMutationIfCurrent(G1) → true
    AM-->>UI: "isAuthenticated = true, lastSignInError = nil"

    Note over UI,TS: Browser sign-in timeout path
    UI->>AM: beginSignInAndAwait(timeout)
    AM->>AM: waitForSignInSettled(timeout) → false
    AM->>AM: timeOutBrowserSignInAttempt()
    AM->>AM: beginAuthMutation(.signInCancellation, G2)
    AM-->>UI: "isLoading = false, lastSignInError = .message(...)"

    Note over UI,TS: Credential sign-in superseded by signOut
    UI->>AM: signInWithCredential(email, pwd)
    AM->>AM: "beginAuthMutation(G1), isLoading = true"
    AM->>AM: credentialSignIn(email, pwd) [awaiting]
    UI->>AM: signOut()
    AM->>AM: beginAuthMutation(.signOut, G2)
    AM->>AM: "cancelBrowserSignInForSignOut() → isLoading = false"
    AM->>TS: clearTokens()
    AM-->>UI: "isAuthenticated = false"
    AM->>TS: setTokens(G1 result) [G1 completes]
    AM->>AM: keepAuthMutationIfCurrent(G1) → false, clearSessionState()
    AM-->>UI: tokens cleared, no error shown
Loading

Reviews (41): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

Comment thread Sources/Auth/AuthManager.swift
Comment thread Sources/Auth/AuthManager.swift Outdated
Comment thread Sources/Auth/AuthManager.swift
Comment thread Sources/Auth/AuthManager.swift
@psh4607

psh4607 commented May 6, 2026

Copy link
Copy Markdown
Contributor

Sharing diagnostic data from local verification of the same fix shape on a separate branch — should help triage what comes after this PR lands.

On a reload.sh --tag <branch> Debug build, the surfaced error after Sign In… is consistently AuthManagerError.invalidCallback (rendered as "로그인 콜백이 잘못되었습니다." in ko-KR locale), not the generic web auth-session failure. The Swift side received a cmux-dev://auth-callback redirect — so it's neither a canceledLogin, sandbox/TCC, nor a first-request network failure.

The specific failure shape in web/app/handler/after-sign-in/page.tsx:

  • getUser({ or: "return-null" }) returns a user.
  • user.createSession() succeeds for refresh, but session.getTokens() returns an accessToken that's missing/empty.
  • Line 102's gate if (refreshToken && accessToken) is false → accessCookie stays at its raw cookie value (potentially JSON-encoded [refreshToken, ""]) instead of being rebuilt.
  • Line 114's emit gate refreshToken && accessCookie still passes (both are truthy strings, even though accessCookie payload is malformed).
  • OpenNativeClient renders the deep link, the user clicks "Return to cmux".
  • Swift AuthCallbackRouter.decodeAccessToken sees array[1] === "" and returns nil → handleCallbackURL throws .invalidCallback.

After this PR lands the visibility fix, users will see "로그인에 실패했습니다. 다시 시도하세요." but the sign-in still won't complete because the deep link itself is malformed. I'm opening a separate web-only PR against web/app/handler/after-sign-in/page.tsx to tighten both emit gates (the L114 gate and the L133 fallback) to require non-empty accessToken before emitting OpenNativeClient, so the page falls through to the existing redirect("/") retry path instead of handing the native app a payload Swift can't decode.

Will link the follow-up PR here once it's open.

ASWebAuthenticationSession reports user-dismissed sheets as canceledLogin. That path should end loading without presenting a failure banner, while real web-auth errors still surface a visible Settings error.

Constraint: AuthManager.swift must stay within the Swift file length budget.

Rejected: Surface canceledLogin as a generic failure | normal user dismissal is not an actionable sign-in failure.

Confidence: medium

Scope-risk: narrow

Tested: python3 scripts/swift_file_length_budget.py --budget .github/swift-file-length-budget.tsv

Tested: git diff --check

Not-tested: Local unit/UI tests by instruction.
Comment thread Sources/Auth/AuthManagerErrors.swift Outdated
Generic sign-in failures should be visible without exposing platform NSError descriptions to users. The original message payload still travels in AuthSignInError for diagnostics and mapping, while the user-facing string stays localized and stable.

Constraint: Settings copy must use localized strings and avoid leaking OAuth/session implementation details.

Rejected: Append NSError.localizedDescription to the generic string | produces developer-facing hybrid text in the Account settings UI.

Confidence: high

Scope-risk: narrow

Tested: git diff --check; python3 scripts/swift_file_length_budget.py --budget .github/swift-file-length-budget.tsv

Not-tested: Local tests/build omitted per instruction to avoid local test runs and direct xcodebuild.

Copy link
Copy Markdown
Contributor

Acknowledged the diagnostic about the malformed web callback path. This PR is intentionally scoped to the native visible-error surface for #3617: the invalid callback is now shown instead of being swallowed, and the separate web-side token/deep-link emission fix can land independently without changing the native error UX in this branch.

Comment thread Sources/Auth/AuthManager.swift
Comment thread Sources/Auth/AuthManager.swift Outdated
Comment thread Sources/Auth/AuthManagerErrors.swift Outdated
coderabbitai[bot]
coderabbitai Bot previously requested changes May 6, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CHANGELOG.md`:
- Around line 7-8: Add a single blank line immediately after the "### Fixed"
heading in CHANGELOG.md so the heading is separated from the following list
(fixing MD022 / blanks-around-headings); ensure the file contains "### Fixed"
followed by an empty line before the "- Surface Settings > Sign In..." list
entry.

In `@Sources/Auth/AuthManager.swift`:
- Around line 207-213: When session.start() returns false, don't assign an empty
string to lastSignInError; instead capture a meaningful message so the error
state retains context for debugging. Update the failure branch where
webAuthSession = session and session.start() is false (the block that currently
calls Self.authLogger.error("auth.webauth session.start returned false") and
sets lastSignInError = .message("")) to set lastSignInError =
.message("auth.webauth session.start returned false") or a similar descriptive
message that mirrors the logged text (referencing webAuthSession,
session.start(), Self.authLogger.error and lastSignInError) so the stored error
payload is informative.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: b055e2f3-b634-461b-9525-b151ee7e6010

📥 Commits

Reviewing files that changed from the base of the PR and between 2ba1949 and 13f41d5.

📒 Files selected for processing (8)
  • CHANGELOG.md
  • GhosttyTabs.xcodeproj/project.pbxproj
  • Resources/Localizable.xcstrings
  • Sources/Auth/AuthManager.swift
  • Sources/Auth/AuthManagerErrors.swift
  • Sources/Settings/AuthSettingsRow.swift
  • Sources/cmuxApp.swift
  • cmuxTests/AuthManagerSignInErrorTests.swift
💤 Files with no reviewable changes (1)
  • Sources/cmuxApp.swift

Comment thread CHANGELOG.md
Comment thread Sources/Auth/AuthManager.swift Outdated
The native sign-in fix is unchanged; hosted macOS CI failed while installing Zig from ziglang.org, and CircleCI cannot be rerun from this workspace without a CircleCI token.

Constraint: User requires CI green before the final tagged reload and local launch.

Rejected: Change app code without CI logs | no branch-specific failure evidence was available.

Rejected: Modify CI installer immediately | a no-op retry preserves PR scope before adding workflow hardening.

Confidence: medium

Scope-risk: narrow

Tested: No code changes; GitHub/Vercel/review checks were passing before retry.

Not-tested: CircleCI step logs unavailable via public API; local tests/builds omitted per instruction.
Review feedback showed that callback handling could clear the loading state while an ASWebAuthenticationSession was still active. The callback path now only owns loading state for out-of-band callbacks, while the browser-session completion remains responsible for in-flight sessions. The session.start failure path also records a useful diagnostic payload, and the changelog heading spacing matches the markdown rule.\n\nConstraint: Do not run local tests or direct xcodebuild for this branch.\nConfidence: high\nScope-risk: narrow\nDirective: Keep web-auth-session state ownership in one place; callback helpers should not make the Sign In button appear idle while a session is still in flight.\nTested: git diff --check; python3 -m json.tool Resources/Localizable.xcstrings; python3 scripts/swift_file_length_budget.py --budget .github/swift-file-length-budget.tsv\nNot-tested: Local unit tests and app build per user instruction; CI will verify after push.
@lawrencecchen
lawrencecchen dismissed coderabbitai[bot]’s stale review May 6, 2026 17:22

Addressed by ab73452: the changelog spacing and session.start diagnostic payload comments are fixed, CodeRabbit's current status is passing, and the inline review threads are resolved.

The required GitHub checks and review feedback were clean on ab73452, but Vercel and CircleCI left optional commit statuses pending without starting jobs or exposing failure logs. This empty commit refreshes those external contexts so the PR can reach an observable terminal state without changing product code.\n\nConstraint: No direct xcodebuild or local tests per user instruction.\nRejected: Patch CI config without logs | no evidence of a repository-side failure.\nConfidence: medium\nScope-risk: narrow\nDirective: Do not treat this as product behavior; it is an external CI/status retry only.\nTested: Required PR checks were green before this retry; no file changes in this commit.\nNot-tested: Local tests/build intentionally not run.
coderabbitai[bot]
coderabbitai Bot previously requested changes May 6, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Sources/Auth/AuthManager.swift`:
- Around line 207-212: When session.start() returns false in AuthManager (the
block that sets webAuthSession, lastSignInError and isLoading), short-circuit
the awaited sign-in path instead of only flipping isLoading: make beginSignIn()
return a started/failed result (e.g., Bool or an enum) or have it throw on
synchronous failure, and have callers of beginSignInAndAwait() check that result
and return immediately when start failed; alternatively, have
beginSignInAndAwait() detect the synchronous failure by checking
webAuthSession/lastSignInError right after beginSignIn() and return the failure
immediately so awaiting callers are not left waiting for an observed $isLoading
change. Ensure references: webAuthSession, session.start(), lastSignInError,
isLoading, beginSignIn(), and beginSignInAndAwait().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: bb98641e-5f6c-4803-aed5-a7fc89d4c689

📥 Commits

Reviewing files that changed from the base of the PR and between 13f41d5 and 9aeb58f.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • Sources/Auth/AuthManager.swift

Comment thread Sources/Auth/AuthManager.swift Outdated
ASWebAuthenticationSession.start() can fail synchronously, leaving beginSignInAndAwait() to subscribe after isLoading has already returned to false. The awaited path now returns immediately in that settled state instead of waiting for a publisher transition that already happened.\n\nConstraint: No direct xcodebuild or local tests per user instruction.\nConfidence: high\nScope-risk: narrow\nDirective: Awaited auth helpers must handle synchronous settle paths as well as publisher-delivered transitions.\nTested: git diff --check; python3 scripts/swift_file_length_budget.py --budget .github/swift-file-length-budget.tsv\nNot-tested: Local unit tests/build intentionally not run.
Comment thread Sources/Auth/AuthManager.swift Outdated

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7ecf7d6. Configure here.

Comment thread Sources/Auth/AuthManager.swift Outdated
Comment thread Sources/Auth/AuthManager.swift
…-3617-sign-in-error-surface

# Conflicts:
#	Sources/cmuxApp.swift
#	cmux.xcodeproj/project.pbxproj
@psh4607

psh4607 commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

On current main, HostBrowserSignInFlow.lastFailure already records display-safe sign-in failures, but that state is not exposed through the macOS AccountFlow or rendered by AccountIdentityCard in Settings.

I am not looking to replace the broader work in this PR. Would it be okay if I opened a narrowly scoped follow-up PR against the current architecture that only wires this existing failure state into the macOS Settings UI, with localization and behavior-level coverage?

@lawrencecchen lawrencecchen added the stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening. label Sep 23, 2026
@github-project-automation github-project-automation Bot moved this from Todo to Done in cmux backlog Sep 23, 2026

This branch was successfully deployed

1 active deployment
Preview – cmux — ba351999 Deployed May 31, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Settings → Sign In… opens auth sheet that closes immediately (no page rendered)

4 participants