Skip to content

PRD: Authentication & account verification

ModuleUser Management (CORE-01)PRD IDPRD-AUTH-001
StatusShippedOwnerIdentity squad
Date2026-05-25Versionv1.0
Packages@nx/identity · apps/clientURDAUTH

TL;DR

Lets every user prove ownership of their account and recover access on their own. People sign up and sign in with a username, email, or phone plus a password, verify their email and phone via one-time codes, and reset a forgotten password end-to-end - no support ticket required. The outcome: identifiers the rest of the platform can trust, and a self-service recovery path that keeps owners and staff out of lockout.

1. Context & Problem

User Management is the platform foundation - every other module trusts the identity and scope it issues. Sign-up and password-credential sign-in exist, but accounts cannot prove ownership of an email or phone, and a user who forgets their password has no self-service recovery path. Without verification, an email or phone identifier is just an unproven string; without a reset flow, a forgotten password means a hard lockout that only manual intervention can clear.

This increment closes those gaps on top of the existing sign-up / sign-in / password-hashing primitives: it adds OTP-driven email and phone verification, a forgot-password reset flow, identifier linking, and the client screens that consume them - delivering the verification and recovery requirements the AUTH feature lists as Must.

2. Goals & Non-Goals

Goals

  • Sign-up that creates account, profile, identifiers, and default settings in one all-or-nothing operation, with the Owner role auto-assigned.
  • Sign-in with any verified identifier (username / email / phone) + password, returning a scoped session token (roles, organization, merchant scope).
  • Change password with the current password verified first; passwords always stored hashed.
  • Verify email via OTP - request code → submit code → identifier marked verified.
  • Verify phone via OTP using the same request/submit flow.
  • Reset a forgotten password end-to-end - request reset → verify code → set a new hashed password.
  • Link a verified email or phone to an already-authenticated account.
  • Mail configurations and HTML templates seeded from the database so verification / reset mails are configurable, not hardcoded.
  • Client screens for identifier verification and password reset.

Non-Goals

  • OAuth / OAuth2 third-party login flow - scheme defined, login flow not built (URD-AUTH-014).
  • Two-factor enforcement - credential scheme exists, enforcement not built (URD-AUTH-013).
  • Session management and remote revocation - session tokens are stateless.
  • User invitation via email or phone.
  • Login-history / audit logging.

3. Success Metrics

MetricTarget / signal
Verification completionShare of email/phone identifiers that reach verified state via OTP trends up
Self-service recoveryForgotten passwords resolved via the reset flow, not manual support
Sign-in integrityZero successful sign-ins on unverified or deactivated/blocked identifiers
Credential safety100% of stored passwords hashed; zero plain-text storage
OTP reliabilityOTP delivery success rate; expired/max-attempt errors handled gracefully

4. Personas & Use Cases

PersonaGoal in this feature
OwnerSign up, secure the account, verify email/phone, recover a lost password
Employee / CashierSign in with own credentials, change or reset their password
CustomerVerify an identifier and recover access to their account

Core scenarios: sign up (account + profile + identifiers + settings, Owner role) → verify email/phone via OTP → sign in with a verified identifier for a scoped token → change password, or - if forgotten - request a reset, verify the code, and set a new one → optionally link an additional verified email or phone.

5. User Stories

  • As a new user, I want to sign up with a username and password in one step, so my account, profile, identifiers, and default settings are created together.
  • As a user, I want to verify my email via a one-time code, so the platform trusts that identifier and I can sign in with it.
  • As a user, I want to verify my phone via the same OTP flow, so my phone becomes a usable, trusted identifier.
  • As a user, I want to sign in with any verified identifier plus my password, so I receive a session token carrying my roles and scope.
  • As a user, I want to change my password after confirming my current one, so I can rotate credentials safely.
  • As a user who forgot my password, I want to request a reset, verify a code, and set a new password, so I can recover access without support.
  • As an authenticated user, I want to link a verified email or phone to my account, so I have more ways to sign in and recover.

6. Functional Requirements

#RequirementURD ref
FR-1Sign up with username + password; account, profile, identifiers, and default settings created in one all-or-nothing operation, Owner role assignedURD-AUTH-001..003
FR-2Sign in with any verified identifier (username / email / phone) + password; returns a session token carrying roles and organization / merchant scopeURD-AUTH-004..005
FR-3Passwords are securely hashed before storage and never stored in plain textURD-AUTH-006
FR-4Change password with the current password verified firstURD-AUTH-007
FR-5Verify email via OTP: request code → submit code → identifier marked verifiedURD-AUTH-008
FR-6Verify phone via OTP using the same request/submit flowURD-AUTH-009
FR-7Reset a forgotten password: request reset → verify code → set a new hashed passwordURD-AUTH-010
FR-8Link a verified email or phone to an already-authenticated accountURD-AUTH-011
FR-9Verified identifiers participate in the global uniqueness check (one verified email/phone per user)URD-AUTH-008..009
FR-10Mail configurations and HTML templates are seeded from the database, so verification / reset mails are configurableURD-AUTH-008..010

Full requirement text and acceptance criteria live in the User Management URD. This PRD references them rather than restating them.

7. Non-Functional Requirements

AreaRequirement
Data integritySign-up is atomic - if any step fails, nothing is created (account, profile, identifiers, settings)
Credential safetyPasswords hashed before storage; reset sets a hashed password; reset response never carries a session token
Tenancy & authzSession token carries roles and organization / merchant scope; all operations except sign-in / sign-up require authentication
OTP robustnessOTP codes expire and cap retry attempts; expired-code and max-attempt cases return explicit errors
StatelessnessSession tokens are stateless - permission changes take effect on next sign-in
ConfigurabilityMail content driven by DB-seeded configurations and HTML templates, not hardcoded strings
i18nUser-facing labels, statuses, and mail content are bilingual ({ en, vi })

8. UX & Flows

Key screens (in apps/client): a verify page that consumes the OTP request/submit endpoints, and a forgot-password / reset-password page that drives the reset flow.

9. Data & Domain

EntityRole
UserThe authenticated identity that owns credentials, identifiers, profile, and settings
CredentialThe hashed password secret used to authenticate
IdentifierA login value (username / email / phone), globally unique within its type, carrying a verified flag
OTP sessionShort-lived state backing verification and reset (request → submit, with expiry and attempt caps)
Mail configuration + templateDB-seeded mail config and HTML templates for verification / reset mails

Conceptual only - full schema and invariants in the identity domain model.

10. Dependencies & Assumptions

Depends on

  • User Account (URD-USR) - users, identifiers, and the verified lifecycle this feature drives.
  • Roles & Scoping (URD-ROLE) - sign-up assigns the Owner role; sign-in resolves roles and scope into the token.
  • User Configuration (URD-CFG) - default settings created during the atomic sign-up.
  • Mail delivery for OTP and reset codes; apps/client for the verify and reset screens.

Assumptions

  • An identifier (email/phone) is reachable so the OTP can be delivered.
  • Mail configurations and templates are seeded before verification / reset mails are sent.
  • Username is required and automatically considered verified; email and phone start unverified.

11. Risks & Open Questions

Risk / questionMitigation / status
Partial sign-up could leave orphaned account fragmentsSign-up is all-or-nothing; any failure rolls everything back
OTP brute-force / replayCodes expire and cap attempts; expired/max-attempt errors are explicit
Reset response leaking a session tokenSession token removed from the reset-password response
Email verification on sign-up currently disabled in codeKnown gap - fresh sign-up may need a separate verify flow before email sign-in; see developer docs
No 2FA enforcement / OAuth loginOut of scope this increment; credential scheme exists, enforcement/login flow planned

12. Release Plan & Launch Criteria

AspectPlan
PhaseP1 (foundation) - see URD feature catalog
RolloutAll users; no feature flag
MigrationSeed mail configurations and HTML templates; add optional verified fields to user schemas
Launch criteriaEmail + phone OTP verify end-to-end; forgot-password reset end-to-end; sign-in rejects unverified / deactivated identifiers; passwords stored hashed
MonitoringOTP delivery + verification success rate, reset-flow completion, sign-in failure reasons (unverified / bad password / blocked)

13. FAQ

Can I sign in with an unverified email or phone? No - sign-in requires a verified identifier. Username is automatically verified; email and phone must pass OTP first.

How does the OTP flow work? Request a code for your email or phone (a session token is returned), then submit the code; on success the identifier is marked verified. Codes expire and limit attempts.

What happens if I forget my password? Request a reset, verify the emailed/texted code, then set a new password - it is hashed before storage, and the reset response never returns a session token.

Where do the verification and reset mails come from? Mail configurations and HTML templates are seeded from the database, so content is configurable rather than hardcoded.

Is OAuth or two-factor supported? Not in this increment - both schemes are defined but their login flow / enforcement is planned, not built.

References

Proprietary and Confidential. Unauthorized copying, distribution, or use of this software is strictly prohibited.