Skip to content

fix: recover cleanly when the stored session is dead#72

Merged
finalerock44 merged 1 commit into
devfrom
fix/login-dead-session-recovery
Jul 10, 2026
Merged

fix: recover cleanly when the stored session is dead#72
finalerock44 merged 1 commit into
devfrom
fix/login-dead-session-recovery

Conversation

@riglar

@riglar riglar commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Companion to devicecloud-dev/dcd#1084, which fixed the root cause of Invalid Refresh Token: Already Used (the login handoff put the CLI in the browser's refresh-token family). This PR fixes the CLI's recovery path for sessions that are already broken — including every session minted before that fix deployed.

Before

From the customer report: a run fails with Failed to refresh session: Invalid Refresh Token: Already Used. Run dcd login again. — but dcd login then says Already logged in as … Sign out and log in again? defaulting to No, so pressing enter keeps the dead session. Every subsequent command fails with the same refresh error.

After

  • CliAuthGateway.refresh throws a typed SessionRefreshError whose definitive flag distinguishes a GoTrue 4xx token rejection (revoked / already used — only a re-login fixes it) from transient failures (network, 5xx) where the token may still be good.
  • On a definitive rejection, resolveAuth drops the dead session from the config while keeping env/api_url/org, so the next command reports a clean Not authenticated… run dcd login and dcd login goes straight in with no prompt.
  • dcd login skips the "Already logged in" confirm entirely when the stored session is expired (prints "Your session for has expired — signing in again." and proceeds), and the confirm for a live session now defaults to Yes — running dcd login deliberately almost always means "log me in".

Also refreshes the login-flow comments and CLAUDE.md for the new handoff contract (access token as identity proof; the api mints the CLI a dedicated session).

Testing

  • pnpm lint / pnpm typecheck clean; full pnpm test suite passes (154 tests against the mock API).
  • New unit tests: dropStoredSession removes only the session (idempotent, keeps env/org), SessionRefreshError flag semantics.
  • Verified end-to-end against prod GoTrue with an isolated DCD_CONFIG_DIR:
    1. expired session + garbage refresh token → dcd list fails with the refresh error and drops the session (env/org preserved);
    2. next dcd list → clean Not authenticated message;
    3. dcd login → no dead-end prompt, straight to the sign-in URL.

🤖 Generated with Claude Code


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.

Companion to devicecloud-dev/dcd#1084 (which fixes the root cause of
"Invalid Refresh Token: Already Used" by minting the CLI its own session
at login). This fixes the recovery path for sessions that are already
broken:

- CliAuthGateway.refresh now throws a typed SessionRefreshError whose
  `definitive` flag distinguishes a GoTrue 4xx token rejection from
  transient failures (network, 5xx).
- On a definitive rejection, resolveAuth drops the dead session from the
  config (keeping env/api_url/org), so subsequent commands report a clean
  "Not authenticated" instead of failing the same refresh every time.
- `dcd login` no longer dead-ends users whose session has expired: the
  "Already logged in… Sign out and log in again?" confirm is skipped for
  expired sessions (it proceeds straight to sign-in), and defaults to Yes
  for live ones — running `dcd login` deliberately almost always means
  "log me in".

Also updates the login-flow comments and CLAUDE.md for the new handoff
contract (access token as identity proof; api mints a dedicated session).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@riglar riglar requested review from a team and finalerock44 July 9, 2026 10:04

@finalerock44 finalerock44 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@finalerock44 finalerock44 merged commit 7fd7748 into dev Jul 10, 2026
10 checks passed
@finalerock44 finalerock44 deleted the fix/login-dead-session-recovery branch July 10, 2026 14:55
@finalerock44 finalerock44 mentioned this pull request Jul 10, 2026
14 tasks
finalerock44 added a commit that referenced this pull request Jul 10, 2026
Promote from dev to stable:

* fix: recover cleanly when the stored session is dead (#72) — `dcd login`
  now mints a dedicated Supabase session for the CLI rather than reusing the
  browser's refresh-token family, and a dead stored session recovers instead
  of hard-failing.
* deps: bump the minor-and-patch group (9 updates) (#71) and
  eslint-plugin-unicorn 68 -> 69 (#70).

Carries only the source delta — package.json version, CHANGELOG.md and the
release-please manifests stay as release-please left them on production.

Release-As: 5.1.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants