Source:
src/api/v1/user/doc.md— edit there, not here (this copy is regenerated).
User
Table: user
PRD
Business problem
TODO — fill in.
User stories
TODO — fill in.
Success criteria
TODO — fill in.
How it works
High-level overview — enough to understand the feature without reading the code.
Summary
The User feature owns end-user identity: registration, email verification (OTP),
login, password reset, and which workspaces a user can enter. A user is not tied
to one workspace — login resolves the user's workspaces and issues a JWT scoped to a
chosen workspace (the workspace_id + session_version baked into the token).
Flow
Steps
- Register (
POST /user/auth/register) creates the user as unverified and emails a one-time code via the OTP system. - Verify (
POST /user/otp/verify) checks the OTP; on success the email is marked verified, a welcome email is queued, and access + refresh JWTs are issued. - Login (
POST /user/auth/login) validates the password, then loads the user's workspaces. One workspace → it's auto-pinned and workspace-scoped tokens are returned. Zero or several → the workspace list is returned to choose from. - Select workspace (
POST /user/auth/select-workspace) pins the chosen workspace and returns tokens carrying thatworkspace_id. (POST /user/auth/workspacescreates a new workspace + subdomain and seeds it.) - Password reset is the same OTP shape:
forgot-password→ emailed code →reset-password. Refresh/logout rotate tokens; bumpingsession_versioninvalidates every previously issued token for that user.
Key components
- Controllers —
auth/user-auth.controller.ts(register/login/refresh/logout/ select-workspace/create-workspace),otp/otp.controller.ts(verify/resend),user-object-template.controller.ts(read-only CRM template suggestions). - Services (facade
auth/user-auth.service.tsdelegating toservices/) —login.service.ts(login + workspace pinning),registration.service.ts,auth-token.service.ts(token pair / refresh / logout),account-lookup.service.ts,auth-token-payload.factory.ts(single JWT-payload source),email-verification.service.ts(OTP → tokens),password-reset.service.ts,otp/otp.service.ts(issue/verify codes). Workspace provisioning now lives in the top-levelworkspace/module, not here. - Data —
usertable;user_workspaceslinks users → workspaces (one user, many workspaces);session_versiononuseris the token-invalidation lever. - Events / side effects — OTP + welcome emails go through the mailer queue; JWTs
embed
workspace_id+session_versionso every request is workspace-scoped.
FRD
Per-field functional requirements (auto-listed from the entity):
- id —
number/ PK, auto-increment - name —
string/ — - email —
string/ —, unique - slug —
string/ —, nullable, unique - email_verified_at —
Date \| null/ timestamp, nullable - password —
string/ — - image —
string/ —, nullable - is_block —
boolean/ — - is_active —
boolean/ — - social_token —
string/ —, nullable, len 100 - social_type —
SocialType/ enum, nullable, enum - profile —
string/ —, nullable - created_at —
Date/ timestamp - updated_at —
Date/ timestamp - session_version —
number/ integer
HLD
Frontend
TODO — fill in.
API
TODO — fill in.
Database changes
TODO — fill in.
LLD
Tables
| Field | TS type | DB type | Nullable | Default | Notes |
|---|---|---|---|---|---|
id | number | PK | no | — | auto-increment |
name | string | — | no | — | |
email | string | — | no | — | unique |
slug | string | — | yes | — | unique |
email_verified_at | Date | null | timestamp | yes | — | |
password | string | — | no | — | |
image | string | — | yes | — | |
is_block | boolean | — | no | false | |
is_active | boolean | — | no | false | |
social_token | string | — | yes | — | len 100 |
social_type | SocialType | enum | yes | — | enum |
profile | string | — | yes | — | |
created_at | Date | timestamp | no | () => 'CURRENT_TIMESTAMP | |
updated_at | Date | timestamp | no | () => 'CURRENT_TIMESTAMP | |
session_version | number | integer | no | 0 |
Services
TODO — fill in.
Validators
TODO — fill in.
API endpoints
GET /api/v1/user/auth/check-subdomainGET /api/v1/user/object-templatesGET /api/v1/user/object-templates/{slug}GET /api/v1/user/pricingPOST /api/v1/user/auth/forgot-passwordPOST /api/v1/user/auth/loginPOST /api/v1/user/auth/logoutPOST /api/v1/user/auth/refreshPOST /api/v1/user/auth/registerPOST /api/v1/user/auth/reset-passwordPOST /api/v1/user/auth/select-workspacePOST /api/v1/user/auth/workspacesPOST /api/v1/user/otp/resendPOST /api/v1/user/otp/verify
API
Each link opens that endpoint in the API Explorer.
GET /api/v1/user/auth/check-subdomainGET /api/v1/user/object-templatesGET /api/v1/user/object-templates/{slug}GET /api/v1/user/pricingPOST /api/v1/user/auth/forgot-passwordPOST /api/v1/user/auth/loginPOST /api/v1/user/auth/logoutPOST /api/v1/user/auth/refreshPOST /api/v1/user/auth/registerPOST /api/v1/user/auth/reset-passwordPOST /api/v1/user/auth/select-workspacePOST /api/v1/user/auth/workspacesPOST /api/v1/user/otp/resendPOST /api/v1/user/otp/verify
ERD
- user (this model)
- tenants — via
tenants(one-to-many)