Identity Registration Flow Guide
Purpose
This wiki explains what actually happens in Loreax during registration, email verification, and first-time onboarding. It is meant to save future work from reverse-engineering the flow from controllers, actions, and tests.
Current Status
- Registration is implemented
- Verification email issuance is implemented
- Email verification confirmation is implemented
- First-time onboarding is implemented
- MFA remains intentionally deferred as a rollout concern and is not part of the registration happy path today
Registration Flow At A Glance
flowchart TD
A["Client POST /api/v1/auth/register"] --> B["RegisterUserRequest validates payload"]
B --> C["RegisterUserAction checks email availability"]
C --> D["RegisterUserAction checks username availability"]
D --> E["DB transaction creates users row"]
E --> F["Password stored through hashed cast"]
F --> G["Transaction commits"]
G --> H["UserRegistered event dispatched after commit"]
H --> I["Client receives 201 with UserResource"]
I --> J["Client can request verification email"]
What Happens During Registration
- The client calls
POST /api/v1/auth/register. RegisterUserRequestvalidates syntax foremail,username,password, and the basic profile fields.RegisterUserActionlowercases the email and username, then checks that neither is already taken, including soft-deleted users.- Inside a database transaction, the
usersrow is created. - The password is not manually hashed in the action. Instead, the
Usermodel cast hashes it before persistence. - After the transaction commits,
UserRegisteredis dispatched. - The API returns Shape A with
201 Createdand aUserResource.
Registration Decision Path
flowchart TD
A["Registration request received"] --> B{"Payload valid?"}
B -- "No" --> C["Return 422 Shape B"]
B -- "Yes" --> D{"Email already used?"}
D -- "Yes" --> E["Throw EmailAlreadyRegisteredException"]
E --> F["Return 430 Shape C"]
D -- "No" --> G{"Username already used?"}
G -- "Yes" --> H["Throw UsernameUnavailableException"]
H --> I["Return 430 Shape C"]
G -- "No" --> J["Create user"]
J --> K["Dispatch UserRegistered after commit"]
K --> L["Return 201 Shape A"]
Verification Email Flow
Registration creates the account, but email verification is its own follow-up step.
flowchart TD
A["Authenticated user POST /api/v1/auth/email/verify/send"] --> B{"Already verified?"}
B -- "Yes" --> C["Return 200 already verified"]
B -- "No" --> D["SendVerificationEmailAction starts transaction"]
D --> E["Delete old unconsumed verification rows for this user+type"]
E --> F["Create fresh email_verifications row"]
F --> G["Queue VerifyEmailNotification after commit"]
G --> H["Return 202 Accepted"]
Email Confirmation Flow
flowchart TD
A["Client POST /api/v1/auth/email/verify/confirm"] --> B["Request validates token shape"]
B --> C["VerifyEmailAction finds unconsumed token"]
C --> D{"Token exists and not expired?"}
D -- "No" --> E["Throw EmailVerificationTokenInvalidException"]
E --> F["Return 430 Shape C"]
D -- "Yes" --> G["DB transaction marks token consumed"]
G --> H["Set user.email_verified_at if not already set"]
H --> I["Return 200 with UserResource"]
First-Time Onboarding Flow
This is separate from registration because the user account can exist before the creator-style profile is finalized.
flowchart TD
A["Authenticated user POST /api/v1/identity/me/onboarding/complete"] --> B["CompleteOnboardingRequest validates payload"]
B --> C{"User already has username?"}
C -- "Yes" --> D["Throw OnboardingAlreadyCompletedException"]
D --> E["Return 430 Shape C"]
C -- "No" --> F["Check username availability across users and handle_history cooldown"]
F --> G{"Username available?"}
G -- "No" --> H["Throw HandleUnavailableException"]
H --> I["Return 430 Shape C"]
G -- "Yes" --> J["Update user profile fields"]
J --> K["Dispatch OnboardingCompleted after commit"]
K --> L["Log onboarding_completed activity"]
L --> M["Return updated user"]
End-To-End Identity Journey
flowchart LR
A["Register account"] --> B["Receive user record"]
B --> C["Request verification email"]
C --> D["Receive verification link/token"]
D --> E["Confirm email"]
E --> F["Complete onboarding"]
F --> G["Ready for verified-user flows"]
Implemented Files Behind This Flow
- RegisterUserController.php
- RegisterUserAction.php
- VerifyEmailController.php
- SendVerificationEmailAction.php
- VerifyEmailAction.php
- CompleteOnboardingAction.php
- RegisterUserTest.php
- VerifyEmailTest.php
Important Notes
- Registration does not automatically verify the email.
- Registration does not automatically complete onboarding.
- Registration does not currently force MFA setup.
- Withdrawal and other sensitive flows still rely on verified identity, and MFA wiring is intentionally staged for later rollout.