Skip to content

fix: 2FA recovery codes display, sync rate limit, taste strip gap, btn-danger#302

Merged
SimplicityGuy merged 3 commits intomainfrom
fix/2fa-recovery-and-sync
Apr 14, 2026
Merged

fix: 2FA recovery codes display, sync rate limit, taste strip gap, btn-danger#302
SimplicityGuy merged 3 commits intomainfrom
fix/2fa-recovery-and-sync

Conversation

@SimplicityGuy
Copy link
Copy Markdown
Owner

Summary

Batch fix for several reported issues with 2FA setup, sync, button styling, and the explore UI.

  • Recovery codes were blanksettings.js read recovery_codes from the /api/auth/2fa/confirm response, but the backend only returns {message} there. The plaintext codes are returned by /api/auth/2fa/setup and were already cached in _setupData. Now reads from the correct field. Also fixes Copy Codes which was copying an empty string.
  • Disable 2FA button misaligned — the .btn-danger class used by settings.js was never defined in tailwind.input.css. Added a definition matching the other btn-* variants so it picks up flex centering from btn-base.
  • Sync rate limit too aggressive — slowapi 2/10minute10/minute, Redis cooldown 600s60s. Frontend now reads the 429 message body from the backend instead of showing a generic "Please try again later" alert.
  • Empty box between stats and collection table — the #tasteStrip wrapper was leaving a blank gap when the taste fingerprint API timed out / was unavailable. Added #tasteStrip:empty { display: none; }.
  • Brevo password reset link wrapping — removed dead X-Mailin-Track* headers. The Brevo SDK rejects standard email headers (per its own signature: "Standard email headers are not supported"), so per-message click-tracking control is impossible via the v3 transactional API. Click tracking must be turned off in the Brevo dashboard (Senders, Domains & IPs → sending domain → Tracking, or Account Settings → Tracking).
  • Test mocks fixedsettings.test.js now mirrors the real API contract (setup returns otpauth_uri + recovery_codes; confirm returns {message}). The previous mocks lied about the contract and let the recovery-codes bug ship.

Not in scope

  • NLQ pieces missing in UI — this turned out to be a configuration issue, not a bug. The Search/Ask toggle requires both NLQ_ENABLED=true and NLQ_API_KEY to be set on the API service. Set both env vars and the toggle appears.

Test plan

  • vitest run — 955 / 955 passing
  • uv run pytest tests/api/test_sync.py tests/api/test_notifications.py tests/api/test_auth.py tests/api/test_auth_router.py — 110 / 110 passing
  • After merge: rebuild explore Docker image so the css-builder stage regenerates tailwind.css with the new .btn-danger class
  • After merge: manually verify in browser
    • 2FA setup → confirm → recovery codes display + Copy Codes works
    • Disable 2FA button shows red with centered icon + text
    • Sync trigger shows backend message text on 429 (and works again after 60s)
    • Empty box between stats and collection table is gone
    • Password reset email link is no longer wrapped (after disabling tracking in Brevo dashboard)

🤖 Generated with Claude Code

…n-danger

- Recovery codes were read from /api/auth/2fa/confirm response which only
  returns {message}; now read from cached _setupData.recovery_codes returned
  by /api/auth/2fa/setup. Also fixes Copy Codes copying empty string.
- Defined .btn-danger Tailwind component class so the Disable 2FA button
  picks up flex centering from btn-base. The class was used by settings.js
  but never defined.
- Loosened sync rate limit from 2/10minute to 10/minute and cooldown from
  600s to 60s. Frontend now reads 429 message body instead of showing a
  generic "Please try again later" alert.
- Hide #tasteStrip when empty so taste-fingerprint timeouts/unavailability
  no longer leave a blank gap between the stats cards and the collection
  table.
- Removed dead X-Mailin-Track headers from password reset email; Brevo's
  v3 transactional API rejects standard email headers per the SDK's own
  signature ("Standard email headers are not supported"), so per-message
  click tracking control is impossible. Click tracking has to be disabled
  in the Brevo dashboard. Added comment explaining why.
- Settings test mocks now match real API contract (setup returns
  otpauth_uri + recovery_codes; confirm returns {message}). The wrong
  mocks let the recovery codes bug ship.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 14, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

SimplicityGuy and others added 2 commits April 13, 2026 20:29
Clearing the inline `style="display: none;"` to '' should fall back to the
Tailwind `flex` class via the cascade, but in some browsers the layout
doesn't update until something else triggers a reflow. Setting display
explicitly to 'flex' is unambiguous and removes the dependency on cascade
ordering for elements with both inline-style hide and class-based show.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 5 tests for the branches introduced by the sync 429 handling:
- 503 returns the service-unavailable message
- 429 with empty body falls back to the default cooldown message
- generic non-ok with body.detail surfaces the detail text
- generic non-ok with body.message surfaces the message text
- ok:true success path schedules the four pane reloads via setTimeout

Closes the codecov gap on PR #302.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

E2E Coverage (webkit)

Totals Coverage
Statements: 47.64% ( 1241 / 2605 )
Lines: 47.64% ( 1241 / 2605 )

StandWithUkraine

@github-actions
Copy link
Copy Markdown
Contributor

E2E Coverage (chromium)

Totals Coverage
Statements: 47.64% ( 1241 / 2605 )
Lines: 47.64% ( 1241 / 2605 )

StandWithUkraine

@github-actions
Copy link
Copy Markdown
Contributor

E2E Coverage (firefox)

Totals Coverage
Statements: 47.64% ( 1241 / 2605 )
Lines: 47.64% ( 1241 / 2605 )

StandWithUkraine

@github-actions
Copy link
Copy Markdown
Contributor

E2E Coverage (webkit - iPad Pro 11)

Totals Coverage
Statements: 47.64% ( 1241 / 2605 )
Lines: 47.64% ( 1241 / 2605 )

StandWithUkraine

@github-actions
Copy link
Copy Markdown
Contributor

E2E Coverage (webkit - iPhone 15)

Totals Coverage
Statements: 47.64% ( 1241 / 2605 )
Lines: 47.64% ( 1241 / 2605 )

StandWithUkraine

@SimplicityGuy SimplicityGuy merged commit 3070826 into main Apr 14, 2026
57 checks passed
@SimplicityGuy SimplicityGuy deleted the fix/2fa-recovery-and-sync branch April 14, 2026 04:03
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.

1 participant