Skip to content

DEF-004 — Post-Spotify consent returns to /rankings without auto-opening Export

Summary

After approving Spotify access (login + consent), the app redirected back to /rankings but landed on the standard Rankings view. The user had to click Export to Spotify a second time to reopen the export UI. Expected behavior is to auto-open the Export panel upon return so the user can continue the in-progress export without additional clicks.

Environment

  • App: Melodex (local dev)
  • Commit: 333d6ca
  • Browser: Firefox (desktop)
  • Device: Windows 11
  • Network: Spectrum (~450 up / 11 down)
  • Date/Time: 2025-11-10

Triage

  • Severity: Minor
  • Priority: High

Preconditions

  • Valid Spotify account.
  • User begins export from /rankings (some items selected, optional name/description entered).

Steps to Reproduce (original)

  1. On /rankings, click Export to Spotify.
  2. In Spotify, complete login and click Agree to grant scopes.
  3. Observe redirect back to the app at /rankings.

Expected Result

  • App resumes the export flow automatically: Export UI opens after OAuth with previous context (checked items, name/description) intact.

Actual Result

  • Page returns to /rankings showing the standard Rankings view.
  • User must click Export to Spotify again to proceed.

Impact

  • Increases friction in a critical conversion path.
  • Heightens risk of lost context (e.g., description text, selections).
  • Potentially increases abandonment if combined with separate export errors.

Attachments

  • Console breadcrumb: Local dev: overriding Amplify redirect URLs
  • Server trace showing /auth/session 200 followed by return to /rankings without auto-open (LINK)
  • Short screen capture of the double-click requirement (LINK)

Suspected Areas

  • Missing/ignored export intent on the OAuth round-trip (returnTo / state).
  • /rankings mount logic not consuming an intent flag to open Export.
  • Over-eager /auth/session gating causing re-auth loops in some statuses.
  • Filters not preserved in redirect, making the post-return view feel reset.

Diagnostics

  • Reproduced consistently with a personal Spotify account.
  • Observed /auth/session200 prior to the second manual click.
  • Verified redirect lands on /rankings without selection UI automatically opening.

Owner: Michael DeReus
Status: Resolved
Opened: 2025-11-10
Closed: 2025-12-12

Linked Items

  • Risks:
    • R-01: Onboarding/auth failures
    • R-02: Token refresh failures (silent 401s) break export mid-flow
    • R-12: Legal / Terms non-compliance (Spotify/Deezer API usage)
    • R-20: User confusion about export scope (filters vs. selection)
  • Related Tests: IT-001, IT-002, IT-010, UI-001, E2E-003, E2E-007, E2E-Export-OAuth-Resume (new)

Fix Reference


Root Cause

  1. Intent not persisted: The client initiated /auth/start without a durable export intent (e.g., returnTo=/rankings?export=1 or equivalent state). After OAuth, /rankings mounted with no signal to auto-open Export.
  2. Loop-prone gating: Client treated ambiguous /auth/session outcomes (e.g., 304, parse issues) as “not connected”, occasionally re-triggering /auth/start and preventing the resume path.
  3. Filter context not carried: Active genre/subgenre were not appended to returnTo, so the view appeared reset even when the user had filtered before export.

Changes

  • OAuth intent carry & resume
    • Build returnTo=/rankings?export=1 when sending the user to /auth/start; also drop a fallback sessionStorage intent flag to survive provider quirks.
    • On return to /rankings, consume export=1 or the intent flag and auto-open selection mode, seeding visible items.
    • After opening, clean ?export=1 from the URL (avoid sticky behavior on refresh).
  • Session check hardening
    • ensureSpotifyConnected() now uses cache:'no-store' and only redirects for 401/403 or explicit { connected:false }.
    • Ambiguous statuses (e.g., 304, 204, transient 5xx with parsable body) are treated as connected to prevent auth loops.
  • Filter persistence
    • Include current genre / subgenre in returnTo so the post-OAuth list matches the pre-OAuth view.
    • Rankings initial fetch reads filters from location.search instead of forcing defaults.
  • Minor QoL
    • Stabilized selection-mode open path and seeded default playlist name deterministically.

Verification

  1. Integration:
    • IT-Auth-OAuthResume (new): /auth/callback/auth/session {connected:true} → auto-open Export on /rankings?export=1 without a second click.
  2. E2E:
    • E2E-Export-OAuth-Resume (new): Start from /rankings?genre=pop&subgenre=any; after consent, Export opens automatically and the same filters are applied. No repeated /auth/start and no extra click is required.
  3. Manual:
    • Confirm no re-auth loop; confirm ?export=1 is removed post-open; confirm selections/name/description persist where applicable.

Verified in: 98fd350 on 2025-12-12
Verification Status: Pass