Skip to content

fix(oauth): allow cancelLoginFlow to dismiss settled terminal error states (#7378) - #7384

Closed
yobushka wants to merge 179 commits into
lidge-jun:devfrom
yobushka:fix/oauth-error-lifecycle
Closed

yobushka wants to merge 179 commits into
lidge-jun:devfrom
yobushka:fix/oauth-error-lifecycle

Conversation

@yobushka

@yobushka yobushka commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes #7378.

When an interactive OAuth login attempt is interrupted, cancelled, or fails, loginState.get(provider) retains a settled state (done: true) with the terminal error message.

Previously, cancelLoginFlow(provider, flowId) contained the check:

if (!active && (!existing || existing.done)) return false;

Because of this guard, calling cancelLoginFlow (such as via POST /api/oauth/login/cancel from the dashboard modal close/cancel button) had no effect once the flow reached existing.done === true. As a consequence, getLoginStatus(provider) permanently returned error: st?.error on every poll, displaying a persistent red error banner in the dashboard UI and masking an otherwise healthy authenticated provider pool until the process was restarted.

Changes

  • In src/oauth/login-flow-state.ts, allow cancelLoginFlow to dismiss a settled (!active && existing) flow via dropLoginFlow(flowKey). This cleans up the latched terminal error from memory.
  • Added comprehensive unit test in tests/oauth/oauth-cancel-clears-transient-error.test.ts verifying that canceling after a settled terminal error successfully clears status.error and resets status.done.

Verification

  • Run bun test tests/oauth/oauth-cancel-clears-transient-error.test.ts (pass)
  • Run bun test tests/oauth/oauth-manual-code.test.ts (pass)

Review readiness checklist

This PR stays in draft until every box below is ticked. Tick all four boxes once the requirements are met:

  • Required local validation passed; commands, results, and any full-suite exception are documented.

  • I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).

  • I resolved all correct Codex and CodeRabbit findings.

  • My PR is ready for review.

Summary by CodeRabbit

  • Bug Fixes
    • Canceling an OAuth login now clears lingering error information and resets its status, even when the login flow has already completed. This prevents an old error from continuing to appear after cancellation and ensures the status reflects that the flow is no longer active.

lidge-jun and others added 30 commits August 25, 2026 19:10
merge dev into preview for the v2.33.0-preview.20260825 release (api-usage oracle fix)
…w-2340

[WRONG BRANCH] release: promote dev to preview for v2.34.0-preview.20260827
…w-2350

[WRONG BRANCH] promote dev onto preview for v2.35.0-preview
…w-23600829

[WRONG BRANCH] release: v2.36.0-preview.20260829
`preview` carries its own release-bump commits (`release: v2.36.0-preview.20260829`), which
are not on `dev`, so the promotion cannot fast-forward: `package.json` is the only conflicting
path. Resolved to the version this train publishes, `2.36.0-preview.20260830`, which moves the
`preview` channel forward from the 20260829 tip.

Every other path takes `dev` (`bb6a6fbdf`) unchanged.
…w-23600830

[WRONG BRANCH] promote dev onto preview for v2.36.0-preview.20260830
…w-23800831

[WRONG BRANCH] promote dev onto preview for v2.38.0-preview.20260831
[WRONG BRANCH] promote dev onto preview for v2.39.0-preview.20260901
…w-24000902

release: promote dev to preview for v2.40.0-preview.20260902
…rkflow call (lidge-jun#3262)

Both v2.40.0 release dispatches (33615174183 preview, 33615177849 main) died
at startup_failure: a workflow_call cannot grant its callee more than the
calling job holds, and dev-version-bump.yml's job declares contents+pull-
requests write. lidge-jun#3129 wired the call but never dispatched a release, so this
is its first live run. The caller job now declares exactly the callee's two
permissions; no other job in release.yml gains anything.

Co-authored-by: jun <jun@lidge.dev>
(cherry picked from commit 7ce0ba5)
…w-relfix

release: carry the release.yml permissions fix onto preview for v2.40.0-preview.20260902
Brings the reviewed dev head (81a1fc1) onto preview. The only conflict is
package.json's version, resolved to the preview channel's next version rather
than to either side: preview carried 2.40.0-preview.20260902 and dev carries
2.41.0, and neither is what this publish is.

The 37-commit delta since v2.40.0 is reviewed per-commit in
devlog/_plan/260903_muse_release_train/011_review_ledger.md.
…w-2410-v2

[WRONG BRANCH] release: v2.41.0-preview.20260903
…w-2410-v3

[WRONG BRANCH] release: refresh preview onto the audit-clean dev head for v2.41.0-preview.20260903
v2.41.0 published from main while this promotion was in flight, so the preview
line has to move past it: a 2.41.0-preview version is now BEHIND a released
one, which tests/release-version-line.test.ts refuses and npm would refuse
after it.

dev moved to 2.42.0 in lidge-jun#3354, the automatic post-release bump. Preview follows
the same line at 2.42.0-preview.20260903, which is the conflict resolution
here: neither side's value, because neither is what this publish is.

Also brings the three CI timing-flake fixes from lidge-jun#3351, which is what preview
CI failed on twice at 491ffcf.

Preflight: 2.42.0-preview.20260903 unpublished on npm, no v2.42.0* tag, no
GitHub release, and it moves preview forward from 2.40.0-preview.20260902.
…w-2410-v4

[WRONG BRANCH] release: v2.42.0-preview.20260903
…w-2420-badges

[WRONG BRANCH] release: promote dev onto preview for the main-account badge fix
…view

preview had diverged from main: it carried 28 merge commits main did not have,
while main carried 23 preview did not, so preview could not fast-forward.
The divergence was history only - the sole CONTENT difference between the two
branches was the package.json version line.

This merge takes main (48f8186, the v2.42.0 release commit) into preview and
resolves the tree to main's content, so preview now matches the released tree
exactly apart from its own prerelease version line.

The version could not stay at 2.42.0-preview.20260903: v2.42.0 has published,
and compareReleaseTags ranks that prerelease BEHIND its own stable release
(-1), which is what tests/release-version-line.test.ts fails on. preview opens
the next prerelease line at 2.43.0-preview.20260904, matching dev's 2.43.0.
…w-2430

[WRONG BRANCH] chore(release): promote main v2.42.0 onto preview and open 2.43.0-preview
lidge-jun and others added 16 commits October 10, 2026 17:57
[WRONG BRANCH] release: 2.84.0
…-2.86.0

[WRONG BRANCH] release: promote dev 494c50d to main as 2.86.0
…-2.87.0

release: promote dev de315e7 to main as 2.87.0
…-2.88.0

[WRONG BRANCH] release: promote dev 7761e04 to main as 2.88.0
…-2.89.0

release: promote dev 52c326b to main as 2.89.0
@github-actions github-actions Bot added the intake: hygiene-blocked Deterministic PR hygiene checks failed label Oct 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Deterministic hygiene checks failed.

  • unsponsored_surface — This changes an authentication, workflow, release-automation, or dependency surface. MAINTAINERS.md requires security review for these; ask a maintainer to apply maintainer-sponsored once they have reviewed it. Paths: src/oauth/login-flow-state.ts.

@github-actions github-actions Bot added the bug Something isn't working label Oct 19, 2026
@github-actions github-actions Bot changed the title fix(oauth): allow cancelLoginFlow to dismiss settled terminal error states (#7378) [WRONG BRANCH] fix(oauth): allow cancelLoginFlow to dismiss settled terminal error states (#7378) Oct 19, 2026
@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

⏳ DRAFT

  • hygiene: unsponsored_surface.

What to do

  • Fix unsponsored_surface — This changes an authentication, workflow, release-automation, or dependency surface. MAINTAINERS.md requires security review for these; ask a maintainer to apply maintainer-sponsored once they have reviewed it. Paths: src/oauth/login-flow-state.ts.
  • Tick all four boxes in the PR description once you're done (currently 0/4).

Review readiness checklist

  • ⬜ Required local validation passed; commands, results, and any full-suite exception are documented.
  • ⬜ I pushed my PR to a recent dev commit (at most 10 behind; a maintainer may still ask for the exact tip before merge).
  • ⬜ I resolved all correct Codex and CodeRabbit findings.
  • ⬜ My PR is ready for review.

0/4 boxes ticked.

This pull request was already a draft. Its draft status will be preserved after every issue above is resolved.
@yobushka Tick the boxes once required local validation has passed with commands, results, and any full-suite exception documented, your branch is on the latest dev commit, and every correct Codex and CodeRabbit finding is resolved.

@github-actions
github-actions Bot marked this pull request as draft October 19, 2026 13:35
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: lidge-jun/opencodex/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 831beb00-03ef-4949-a37a-295ea58b7e72
📥 Commits

Reviewing files that changed from the base of the PR and between dd2bdd2 and b304f12.

📒 Files selected for processing: 2
  • src/oauth/login-flow-state.ts
  • tests/oauth/oauth-cancel-clears-transient-error.test.ts
📝 Walkthrough

cancelLoginFlow now removes an existing login flow when no abort controller is active, including a completed flow with an error. A test checks that cancellation clears the error and resets the reported status.

Changes: OAuth cancellation

Layer / File(s) Summary
Clear flow state on cancellation
src/oauth/login-flow-state.ts, tests/oauth/oauth-cancel-clears-transient-error.test.ts
When no abort controller is active, cancelLoginFlow returns false only if no flow exists. Otherwise, it drops the flow and returns true. The test checks that cancelling a completed login error clears the error and sets done to false.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to b304f

No actionable issue remains from the supplied evidence; this change is mergeable after normal checks.

Pre-merge checks: Passed 5
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title accurately describes the main change: allowing cancelLoginFlow to dismiss settled OAuth terminal error states. The issue reference is relevant. The [WRONG BRANCH] prefix adds noise but does …
Linked Issues check Passed Issue #7378 requires cancellation to remove a settled login error so later OAuth status polling stops reporting stale failure state. In src/oauth/login-flow-state.ts:305-314, cancelLoginFlow now c…
Out of Scope Changes check Passed The whole-PR diff contains one targeted change in cancelLoginFlow and one focused regression test. Both changes support issue #7378 by clearing settled OAuth state and verifying the resulting status…
Docstring Coverage Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files.
Full details: Title check

Explanation

The title accurately describes the main change: allowing cancelLoginFlow to dismiss settled OAuth terminal error states. The issue reference is relevant. The [WRONG BRANCH] prefix adds noise but does not make the title unclear or unrelated.

Full details: Linked Issues check

Explanation

Issue #7378 requires cancellation to remove a settled login error so later OAuth status polling stops reporting stale failure state. In src/oauth/login-flow-state.ts:305-314, cancelLoginFlow now calls dropLoginFlow(flowKey) when an existing flow has no active abort controller, which removes the settled state. The added test at tests/oauth/oauth-cancel-clears-transient-error.test.ts:5-28 verifies that a settled error is visible before cancellation, that cancellation returns true, and that subsequent getLoginStatus has no error and reports done: false.

Full details: Out of Scope Changes check

Explanation

The whole-PR diff contains one targeted change in cancelLoginFlow and one focused regression test. Both changes support issue #7378 by clearing settled OAuth state and verifying the resulting status. No unrelated source, API, or test changes are present.

✨ Finishing Touches: 💡 1
🛠️ Fix failing CI checks: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@Ingwannu Ingwannu left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

[P2] Preserve the cancellation owner contract and successful outcomes — src/oauth/login-flow-state.ts:308–312.

The new !active branch drops any existing row, including a successful terminal flow and a stale pending flow whose controller has been replaced. Internal Codex cancellation interprets true as evidence that its actual live controller was cancelled; changing that boolean meaning allows a stale Codex flow to report a successful cancellation. The existing tests/codex-integration/codex-auth-cancel-ownership.test.ts covers that boundary. A completed code-login result/account receipt also needs to remain readable rather than disappearing on a later cancel.

The same issue already has Draft #7379 on dev, whose initial broad CI caught exactly this shared-caller regression. Its public-endpoint opt-in now preserves the internal boolean and successful outcome, and current-head CI is green. Please coordinate against that candidate; no code from this PR was carried into it.

Also retarget/rebase to dev (this PR currently targets main), register the new test in both layout maps, isolate/reset its global flow state, and update the owning flow contract. This is scoped static feedback at b304f12; no independent local run or merge approval of this new branch is claimed.

@yobushka
yobushka changed the base branch from main to dev October 19, 2026 13:43
@github-actions github-actions Bot changed the title [WRONG BRANCH] fix(oauth): allow cancelLoginFlow to dismiss settled terminal error states (#7378) fix(oauth): allow cancelLoginFlow to dismiss settled terminal error states (#7378) Oct 19, 2026
@yobushka

Copy link
Copy Markdown
Contributor Author

Closing in favor of Draft #7379 which already addresses #7378 on dev while preserving the internal cancellation contract.

@yobushka yobushka closed this Oct 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working intake: hygiene-blocked Deterministic PR hygiene checks failed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Transient OAuth login failure persists in getLoginStatus and masks active account in dashboard

4 participants