PRD: User account & configuration
| Module | User Management (CORE-01) | PRD ID | PRD-USR-001 |
| Status | Shipped | Owner | Identity squad |
| Date | 2026-05-27 | Version | v1.0 |
| Packages | @nx/identity · @nx/core | URD | USR · CFG |
TL;DR
Gives every person on KICKO a durable, soft-deletable account: one system-generated ID that can hold several identifiers (username, emails, phones), an editable profile with a locale preference, a controlled status lifecycle, and a default set of personal settings created automatically at registration. The result: a single trustworthy account record every other module can layer roles, employees, and customers on top of - and that the user can read and tune themselves.
1. Context & Problem
Every other module trusts the identity and scope issued by User Management, so the account itself - the durable record a person owns, with its identifiers, profile, status, and personal settings - must exist before roles, employees, or customers can be layered on top. Without a first-class account, there is no stable subject to attach a role to, no way to verify which email or phone actually belongs to a user, no per-user place to remember preferences such as language, and no guarantee that account data survives a "delete". This is a hard prerequisite for the rest of the platform.
This increment builds the USR (User Account) and CFG (User Configuration) feature areas on top of the identity foundation, sitting alongside authentication and feeding role and scope resolution.
2. Goals & Non-Goals
Goals
- A user account with a unique system-generated ID, soft-deletable and never physically removed.
- Multiple identifiers per user (username, emails, phones): username required and treated as verified; email/phone start unverified and require OTP.
- An editable profile (name, birthday, locale, contacts) with a language / locale preference.
- A status lifecycle (activate, deactivate, block, archive) gated against sign-in, with
ARCHIVEDterminal. - A default set of per-user configurations created automatically on registration, grouped and uniquely keyed by code per user.
- Users can read and update their own configurations (including a read path and a saved launchpad-tour flag).
Non-Goals
- Authentication, OTP delivery, and password flows themselves →
AUTHarea / Authentication. - Custom role creation and dynamic permission management → Permissions.
- User invitation, session management / remote revocation, login history / audit.
- Multi-organization access for a single user; MFA enforcement.
3. Success Metrics
| Metric | Target / signal |
|---|---|
| Account durability | Zero physical deletes; every removed account remains as a soft-deleted row |
| Identifier integrity | 100% of identifiers globally unique within their type; no verified duplicates |
| Verification correctness | Email/phone usable only after OTP verification; deactivated/blocked users cannot sign in |
| Config bootstrap | 100% of registrations create the default configuration set, grouped and keyed by code |
| Self-service | Users can read and update their own profile and configurations without operator help |
4. Personas & Use Cases
| Persona | Goal |
|---|---|
| Owner / end user | Own an account, edit their profile and locale, manage emails/phones, tune personal settings |
| Authorized operator | Change a user's status (activate, deactivate, block, archive) within their scope |
| Other modules | Rely on a stable, scoped account subject for roles, employees, and customers |
Core scenarios: a user registers → an account, profile, identifiers, and default configurations are created → the user edits their profile/locale, adds and OTP-verifies an email or phone, and reads/updates their settings → an authorized operator changes the user's status, which gates sign-in; account data is always preserved via soft-delete.
5. User Stories
- As a user, I want a single account that can hold a username plus several emails and phones, so I can sign in by whichever identifier I have.
- As a user, I want to add an email or phone and verify it via OTP, so the contact becomes a trusted login.
- As a user, I want to edit my profile and set my language / locale, so the product speaks to me correctly.
- As an authorized operator, I want to activate, deactivate, block, or archive a user, so access reflects the account's standing.
- As a user, I want my account preserved even when "deleted", so data is never silently lost.
- As a user, I want default settings created automatically and editable by me, so my preferences (including the launchpad tour) persist.
6. Functional Requirements
| # | Requirement | URD ref |
|---|---|---|
| FR-1 | Each user has a unique system-generated ID; account data is soft-deletable and never physically removed | URD-USR-001 · URD-USR-009 |
| FR-2 | A user can hold multiple identifiers (username, emails, phones), each globally unique within its type | URD-USR-002..003 |
| FR-3 | Username is required and treated as verified; email/phone identifiers start unverified and require OTP | URD-USR-004..005 |
| FR-4 | User can view and update their own profile (name, birthday, locale, contacts) | URD-USR-006 |
| FR-5 | User can set a language / locale preference | URD-USR-010 |
| FR-6 | Authorized users can change a user's status (activate, deactivate, block, archive); deactivated/blocked users cannot sign in | URD-USR-007..008 |
| FR-7 | ARCHIVED is a terminal status and cannot be reactivated | URD-USR-011 |
| FR-8 | A default set of configurations is created automatically when a user registers | URD-CFG-001 |
| FR-9 | Configurations are grouped and uniquely identified by code per user | URD-CFG-002 |
| FR-10 | User can view and update their own configurations (read path + saved launchpad-tour flag) | URD-CFG-003 |
Full requirement text and acceptance criteria live in the User Management URD. This PRD references them rather than restating them.
7. Non-Functional Requirements
| Area | Requirement |
|---|---|
| Data integrity | Identifier uniqueness is verify-aware (uniqueness enforced on verified identifiers); soft-delete preserves all account rows |
| Tenancy & authz | Account scope (organizer/merchant) is resolved per user; status/profile/config operations are permission-gated |
| Privacy | OTP re-requests for an already-existing identifier send silently - no account-enumeration leak |
| Consistency | Registration creates account, profile, identifiers, and default configurations together; partial creation is not allowed |
| i18n | User-facing labels/statuses are bilingual ({ en, vi }); locale preference drives presentation |
8. UX & Flows
Key screens (in apps/client): user profile editing, locale selection, identifier management, and the merchant-settings danger zone; the launchpad-tour flag is persisted as a user configuration.
9. Data & Domain
| Entity | Role |
|---|---|
User | The durable account - system-generated ID, status, soft-delete, organizer/merchant scope |
UserIdentifier | A login value (username / email / phone) with a verification flag; verify-aware uniqueness |
UserProfile | One-per-user personal info - name, birthday, locale, contacts |
UserConfiguration | A per-user key-value setting, grouped and uniquely keyed by code |
Conceptual only - full schema and invariants in the identity domain model.
10. Dependencies & Assumptions
Depends on
- Authentication (URD-AUTH) - registration, OTP delivery, and sign-in gating live in the
AUTHarea. - Roles & Scoping (URD-ROLE) - the account is the subject roles and organizer/merchant scope attach to.
@nx/core- shared models, scoping, and configuration plumbing.
Assumptions
- A user registers through the sign-up flow, which triggers account, profile, identifier, and default-configuration creation.
- OTP transport (email/SMS) exists for verifying email and phone identifiers.
11. Risks & Open Questions
| Risk / question | Mitigation / status |
|---|---|
| Duplicate identifiers across users | Uniqueness enforced per type on verified identifiers; table-level constraint reworked to a verify-aware check |
| Account enumeration via OTP requests | OTP re-request for an existing identifier sends silently |
| Half-created accounts on registration failure | Account + profile + identifiers + default configs created together; partial creation rejected |
| Re-activating an archived account | ARCHIVED is terminal by design; no reactivation path |
12. Release Plan & Launch Criteria
| Aspect | Plan |
|---|---|
| Phase | P1 (foundation) - see URD feature catalog |
| Rollout | All users; no feature flag |
| Migration | None for new accounts; default configurations seeded per user at registration |
| Launch criteria | Register → account/profile/identifiers/default-configs verified; OTP verification flips identifier state; status transitions gate sign-in; soft-delete preserves data |
| Monitoring | Registration success rate, OTP verification rate, identifier-uniqueness violations, config-bootstrap coverage |
13. FAQ
Can a user have more than one email or phone? Yes - a user holds multiple identifiers (username, emails, phones). Username is required and verified; emails and phones start unverified and need OTP.
What happens when an account is "deleted"? It is soft-deleted - the row is preserved and never physically removed.
Why can't a deactivated or blocked user sign in? Status gates sign-in: only active accounts authenticate; deactivated and blocked users are denied.
Is ARCHIVED reversible? No - ARCHIVED is a terminal status and cannot be reactivated.
Where do default settings come from? A default configuration set is created automatically at registration, grouped and uniquely keyed by code; the user can read and update their own configurations.
Does requesting an OTP for an existing email reveal that the account exists? No - re-requests for an already-existing identifier send silently to avoid enumeration leaks.
References
- URD: User Management - User Account · User Configuration
- Builds on: Authentication · Roles & Scoping
- Module: User Management - overview + traceability
- Developer: @nx/identity · domain model · @nx/core