Skip to content

feat: password-reset rate limiting, ARIA labels, form label associations, keyboard navigation#830

Open
jasmine874 wants to merge 1 commit into
Ethereal-Future:mainfrom
jasmine874:feat/issues-735-736-737-738
Open

feat: password-reset rate limiting, ARIA labels, form label associations, keyboard navigation#830
jasmine874 wants to merge 1 commit into
Ethereal-Future:mainfrom
jasmine874:feat/issues-735-736-737-738

Conversation

@jasmine874

Copy link
Copy Markdown
Contributor

Summary

  • Closes Add rate limiting to password-reset endpoint #735 — Added POST /auth/password-reset with per-IP (10 req/hr) and per-email (3 req/hr) rate limits, a 200ms minimum response delay to prevent timing-based enumeration, previous-token invalidation, 15-min token TTL, and an identical response body regardless of whether the email is registered. Also adds /auth/password-reset/confirm to complete the flow.
  • Closes Add ARIA labels to all icon-only buttons #736 — Added aria-label to the icon-only ✕ remove-contact button in AddressBook.jsx. Confirmed all other icon-only buttons (QR close, copy, notification bell, settings gear) already carried labels.
  • Closes Ensure all form fields have associated label elements #737 — Updated FormField.jsx to use React useId + cloneElement to automatically inject id into child inputs and wire htmlFor on the wrapping <label>, fixing label associations for every FormField usage (KYCForm, NotificationPreferences, etc.). Also added explicit id/aria-label to all unlabeled inputs in AdvancedSearch, AddressBook, and the account-label edit field in AccountDashboardPage.
  • Closes Add keyboard navigation to SearchableSelect component #738 — Rewrote SearchableSelect.jsx with the ARIA combobox pattern: role="combobox", aria-expanded, aria-controls, aria-activedescendant, role="listbox", role="option". Keyboard support: ArrowDown/ArrowUp to move highlight, Home/End for first/last, Enter to select, Escape to dismiss, Tab to close. Visual highlight tracks active index.

Test plan

  • POST /auth/password-reset with the same email 4+ times within an hour returns 429 after the 3rd call, but the response body matches the success body
  • 11+ requests from the same IP within an hour result in 429
  • Timing: even for unknown emails the response takes ≥200ms
  • FormField-wrapped inputs are announced with their label in a screen reader or axe audit
  • SearchableSelect can be fully operated with keyboard alone (open → navigate → select → close)
  • AddressBook remove buttons announce "Remove [name]" to a screen reader

🤖 Generated with Claude Code

… keyboard nav

- Issue 735: Add POST /auth/password-reset with per-IP (10/hr) and per-email (3/hr) rate limiting, 200ms minimum delay to prevent timing enumeration, token invalidation and 15-min TTL, identical response for registered/unregistered emails. Adds /auth/password-reset/confirm endpoint.
- Issue 736: Add aria-label to icon-only ✕ remove-contact button in AddressBook.
- Issue 737: Fix FormField to auto-associate <label htmlFor> with child input using useId + cloneElement; add explicit id/aria-label to all unlabeled inputs in AdvancedSearch, AddressBook, and AccountDashboardPage.
- Issue 738: Implement ARIA combobox keyboard navigation in SearchableSelect — ArrowDown/Up/Home/End/Enter/Escape/Tab, aria-expanded, aria-controls, aria-activedescendant, role=listbox/option, visual highlight tracking.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@drips-wave

drips-wave Bot commented Jun 27, 2026

Copy link
Copy Markdown

@jasmine874 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant