v2

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

  1. The client calls POST /api/v1/auth/register.
  2. RegisterUserRequest validates syntax for email, username, password, and the basic profile fields.
  3. RegisterUserAction lowercases the email and username, then checks that neither is already taken, including soft-deleted users.
  4. Inside a database transaction, the users row is created.
  5. The password is not manually hashed in the action. Instead, the User model cast hashes it before persistence.
  6. After the transaction commits, UserRegistered is dispatched.
  7. The API returns Shape A with 201 Created and a UserResource.

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

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.