Skip to content

[Auth] Повторная отправка OTP-кода (замена заглушки в ResendCodeControl) #67

@kapitulin24

Description

@kapitulin24

Контекст

На шаге ввода OTP после регистрации (SignupPage) и восстановления пароля (ForgotPasswordPage) отображается ResendCodeControl с таймером повторной отправки (RESEND_CODE_DELAY_MS = 60 с, ключ в localStorage). По истечении таймера кнопка «Отправить код» активна, но по клику вызывается заглушка: toast.warning('Функционал в разработке!') в src/features/otp-form/ui/ResendCodeControl.tsx.

Пользователь не может запросить новый код, если письмо не пришло или код истёк. API для resend на бэкенде ещё не реализован — задача в бэклог: согласовать контракт, реализовать бэк, затем подключить фронт. UI-таймер и черновик lastSentAt уже есть и должны быть синхронизированы с серверным rate limit.

Сценарий Страница Первичная отправка Подтверждение OTP
Регистрация SignupPage POST /auth/sign-up POST /auth/sign-up/confirm
Сброс пароля ForgotPasswordPage POST /auth/password/reset POST /auth/password/reset/verify

Технические требования

Бэкенд (блокер)

  • POST /auth/sign-up/resend — body: { email }
  • POST /auth/password/reset/resend — body: { email }
  • Альтернатива: идемпотентный повтор sign-up / password/reset с тем же email — зафиксировать в контракте
  • Rate limiting: не чаще 1 раза в N сек (согласовать с RESEND_CODE_DELAY_MS = 60000); при превышении — 429 или error с retryAfter
  • Безопасность: единые ответы без утечки существования email; лимиты по IP/email; инвалидация старого кода при выдаче нового

Фронтенд (после готовности API)

  • Локация: src/features/otp-form/ui/ResendCodeControl.tsx, src/entities/auth/api/http.ts, src/entities/auth/model/schemas.ts, SignupPage, ForgotPasswordPage
  • Инструменты: TanStack Query, Zod, sonner, LocalStorageDraft, useTimer
  • Логика:
    1. ResendCodeControl — проп onResend / mutation + email; убрать заглушку с toast
    2. AuthHttp.signupResend, AuthHttp.resetPasswordResend + хуки useResendSignupCode, useResendResetPasswordCode
    3. Подключить на /signup и /forgot-password (шаг otp)
    4. Успех: toast.success, обновить lastSentAt, restart() таймера
    5. 429 / retryAfter: синхронизировать таймер с сервером
    6. isPending — disabled кнопки
    7. До бэка (опционально): NEXT_PUBLIC_OTP_RESEND_ENABLED — скрыть кнопку вместо заглушки

Цель и критерии приемки (Definition of Done)

  • Бэкенд: эндпоинты resend задокументированы, rate limit согласован с фронтом
  • Signup: повторная отправка на шаге OTP работает, таймер сбрасывается
  • Forgot password: то же на шаге OTP
  • UX: нет toast «Функционал в разработке!»; countdown при cooldown
  • Ошибки: rate limit не сбрасывает таймер ошибочно; pending блокирует повторный клик
  • QA: первичная отправка → resend после cooldown → вход новым кодом

Зависимости

  1. Backend: контракт + реализация
  2. Frontend: HTTP + хуки + ResendCodeControl
  3. QA: оба флоу, спам-клики, истёкший draft

Важные указания

  • Безопасность: не логировать OTP; email из draft с TTL (DRAFT_TTL_MS)
  • Ошибки: skipGlobalValidationToast по аналогии с useSignupConfirm / useSendCode

Metadata

Metadata

Assignees

No one assigned

    Labels

    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions