Password Reset

Feature Owner: scorevi (Sean Patrick Caintic)
Module: Auth & Security
Priority: P0
Sprint #12: Fully Implemented
Date: 2026-06-29


EXECUTIVE SUMMARY

What is this feature?
A 3-step password reset flow (REQUEST → RESET → SUCCESS) built with Zod-validated schemas, Clerk SDK integration, and 38 mapped Clerk error codes. The UI is a 610-line self-contained page at /forgot-password.

Why does it matter?
Forgetting a password is the most common support request. Without self-service reset, every lockout requires manual admin intervention. This blocks users and wastes support time.

What's the MVP scope?
Forgot password page with email input, 6-digit verification code entry, new password with strength requirements (8+ chars, uppercase, lowercase, digit, special), password confirmation, resend cooldown (60s), and auto-redirect to sign-in after success (3s delay).


1. USER PAIN POINT & SOLUTION

Current State (Without Feature)

User forgets password → locked out → must contact support/admin → admin manually resets via Clerk dashboard → user waits for response. This can take hours or days.

Pain Point

Emotional: Frustration and helplessness when locked out of the platform.
Functional: No self-service recovery. Complete dependency on admin intervention.
Business Impact: Support tickets for password resets waste admin time. User churn from lockout frustration.

Future State (With Feature)

User enters email → receives 6-digit code via Clerk → enters code + new password → redirected to sign-in. Entire flow takes <2 minutes.

Marketing Hook

"Locked out? Reset your password in under 2 minutes. No admin needed."


2. 4D FRAMEWORK MAPPING

Diagnose

N/A — auth infrastructure.

Design

N/A — auth infrastructure.

Develop

N/A — auth infrastructure.

Deliver

N/A — auth infrastructure.


3. USER FLOWS

Entry Point

User clicks "Forgot Password?" on the sign-in page, navigates to /forgot-password.

Success Criteria

User receives verification code, sets new password, and is redirected to sign-in to log in with new credentials.

Main Flow (Happy Path)

  1. User navigates to /forgot-password (public route, no auth required).

  2. Step 1 — REQUEST: User enters email and submits. Clerk sends 6-digit verification code. UI transitions to step 2.

  3. Step 2 — RESET: User enters 6-digit code, new password, and confirms password. Form validates via resetPasswordSchema (Zod). On success, Clerk resets password.

  4. Step 3 — SUCCESS: Confirmation message shown. Auto-redirect to /sign-in after 3 seconds.

Edge Cases

  • Already signed in: Page checks useAuth().isSignedIn → redirects to /redirect-check instead of showing reset form.

  • Resend code: User can request a new code after 60-second cooldown (countdown timer shown).

  • Invalid code: Clerk returns error → mapped to user-friendly message via 38-code mapping.

  • Password mismatch: resetPasswordSchema.refine catches password !== confirmPassword → error on confirmPassword field.

  • Weak password: Zod passwordField enforces: min 8 chars, max 128 chars, uppercase, lowercase, digit, special character.

Decision Points

  • IF useAuth().isSignedIn → redirect to /redirect-check.

  • IF resend clicked within 60s cooldown → button disabled, countdown shown.

  • IF code is 6 digits matching /^\d+$/ regex → proceed to Clerk verification.

  • ELSE → Zod validation error shown inline.


4. INFORMATION ARCHITECTURE

Primary Information (Always visible)

  • Step 1: Email input field.

  • Step 2: Verification code input (6 digits), new password field, confirm password field, password requirements checklist.

  • Step 3: Success message with countdown.

Secondary Information

  • Resend code button with cooldown timer.

  • Password strength requirements checklist with real-time validation.

Actions

Primary CTA: "Send Code" → "Reset Password" → auto-redirect.
Secondary Actions: "Resend Code" (after 60s cooldown), "Back to Sign In" link.


5. WIREFRAMES

[Excluded — existing UI: app/(main)/forgot-password/page.tsx (610 lines)]

6. WIREFLOWS

Excluded.

7. PROTOTYPE

[Excluded — existing implementation]


8. BACKEND SCHEMA

Database Tables

No dedicated tables. All logic uses Clerk's built-in password reset API.


9. API ENDPOINTS

No custom API endpoints. All operations use Clerk SDK client-side:

  • useSignIn() — for email code verification.

  • useAuth() — to check signed-in state.

  • useClerk().setActive() — for session management after reset.


10. DATA REQUIREMENTS

Frontend Needs

  • requestResetCodeSchema: { email: string (min 1, email format, max 255) }

  • resetPasswordSchema: { code: string (6 digits), password: string (min 8, max 128, uppercase + lowercase + digit + special), confirmPassword: string (min 1) } with .refine for password match.

  • PASSWORD_REQUIREMENTS array for UI checklist.

API Calls Frontend Will Make

All through Clerk SDK — no custom API calls.

Caching Strategy

N/A.


11. PERFORMANCE CONSIDERATIONS

Database Optimization

N/A — Clerk-managed.

API Response Time

Clerk API latency for code generation/verification. No custom backend involved.


12. SECURITY & AUTHORIZATION

Who can access this feature?

Anyone. Public route. Signed-in users are redirected away.

Authorization Logic

  • middleware.ts: /forgot-password(.*) is a public route.

  • Client-side guard: useAuth().isSignedIn check redirects to /redirect-check.

Data Validation

  • Zod schemas (requestResetCodeSchema, resetPasswordSchema in lib/schemas/password-reset.schema.ts, 96 lines) validate all inputs before Clerk API calls.

  • Password strength: 5 requirements (length, uppercase, lowercase, digit, special).

  • Code format: exactly 6 digits, numeric only.


13. ERROR HANDLING

Error

Response

Invalid email format

Zod: "Please enter a valid email address"

Code not 6 digits

Zod: "Code must be exactly 6 digits"

Code contains non-digits

Zod: "Code must contain only numbers"

Password too weak

Zod: specific requirement failure message

Password mismatch

Zod: "Passwords do not match", path: ["confirmPassword"]

Clerk API error (any of 38 codes)

Mapped to user-friendly message (e.g., "Invalid verification code", "Code has expired")


14. TESTING CHECKLIST

Happy Path
□ Enter valid email → receive code → enter 6-digit code + strong password → password reset → redirected to sign-in.
□ After success, auto-redirects in 3 seconds.
□ Signed-in user visits /forgot-password → redirected to /redirect-check.

Edge Cases
□ Enter invalid email format → Zod error shown.
□ Enter code with letters → Zod error shown.
□ Enter weak password (missing uppercase) → Zod error shown inline.
□ Passwords don't match → Zod error on confirmPassword field.
□ Clerk returns error for expired code → user-friendly message shown.
□ Resend code before 60s cooldown → button disabled.
□ After 60s, resend button enabled with fresh countdown.


15. OPEN QUESTIONS

  • Should there be a rate limit on code requests per email (beyond Clerk's built-in)?

  • Should the success page show the email the code was sent to for confirmation?


16. OUT OF SCOPE (v1.1+)

  • SMS-based password reset.

  • Magic link sign-in as alternative to password reset.

  • Admin-initiated password reset from admin panel.


17. SUCCESS METRICS

  • <2 minutes average time to complete password reset.

  • <5% error rate from invalid input (Zod catches most errors client-side).

  • 0 admin intervention required for password resets.


18. DEPENDENCIES

This feature depends on:

  • Clerk SDK: useSignIn(), useAuth(), useClerk().setActive().

  • lib/schemas/password-reset.schema.ts (96 lines): Zod schemas and PASSWORD_REQUIREMENTS.

  • middleware.ts: public route entry for /forgot-password(.*).

These features depend on this:

  • None directly. Self-contained auth flow.


19. TIMELINE & OWNERSHIP

  • Implemented: Sprint 0 (foundational).

  • Owner: scorevi (Sean Patrick Caintic)


Document Version

1.0 - Initial version - 2026-06-29 08:043 UTC

1.1 (Current Version) - Added Document Version section and update author to have full name - 2026-06-29 08:38 UTC


Was this article helpful?