# Unified "Get Started" Flow ## Overview The unified get-started flow provides a single entry point for customer account creation and eligibility checking. It replaces separate `/signup` and `/migrate` pages with a streamlined flow at `/auth/get-started`. ## User Flows ### 1. Direct Account Creation (`/auth/get-started`) ``` /auth/get-started │ ├─→ Step 1: Enter email │ ├─→ Step 2: Verify email (6-digit OTP) │ └─→ Step 3: System checks accounts & routes: │ ├─→ Portal exists → "Go to login" ├─→ WHMCS exists (unmapped) → "Link account" (enter WHMCS password) ├─→ SF exists (unmapped) → "Complete account" (pre-filled form) └─→ Nothing exists → "Create account" (full form) ``` ### 2. Eligibility Check First (`/services/internet/check-availability`) For customers who want to check internet availability before creating an account: ``` /services/internet (public) │ └─→ Click "Check Availability" │ └─→ /services/internet/check-availability (dedicated page) │ ├─→ Step 1: Enter name, email, address (with Japan ZIP lookup) │ └─→ Step 2: Choose action: │ ├─→ "Send Request Only" │ └─→ SF Account + Case created → Success page │ └─→ Success page shows: │ ├─→ "Back to Internet Plans" → Return to /services/internet │ └─→ "Create Your Account Now" → /auth/get-started?email=xxx │ (standard OTP flow) │ └─→ "Continue to Create Account" ├─→ SF Account + Case created ├─→ Inline OTP verification (no redirect) └─→ On success → /auth/get-started?verified=true (skips email/OTP steps, goes to complete-account) ``` **Key difference from Phase 1:** The "Continue to Create Account" path now includes inline OTP verification directly on the eligibility page, rather than redirecting to `/auth/get-started` for OTP. ## Account Status Routing | Portal | WHMCS | Salesforce | Mapping | → Result | | ------ | ----- | ---------- | ------- | ------------------------------ | | ✓ | ✓ | ✓ | ✓ | Go to login | | ✓ | ✓ | - | ✓ | Go to login | | - | ✓ | ✓ | - | Link WHMCS account (migrate) | | - | ✓ | - | - | Link WHMCS account (migrate) | | - | - | ✓ | - | Complete account (pre-filled) | | - | - | - | - | Create new account (full form) | ## Frontend Structure ``` apps/portal/src/features/get-started/ ├── api/get-started.api.ts # API client functions ├── stores/get-started.store.ts # Zustand state management ├── components/ │ ├── GetStartedForm/ │ │ ├── GetStartedForm.tsx # Main form container │ │ └── steps/ │ │ ├── EmailStep.tsx # Email input │ │ ├── VerificationStep.tsx # OTP verification │ │ ├── AccountStatusStep.tsx# Route based on status │ │ ├── CompleteAccountStep.tsx # Full signup form │ │ └── SuccessStep.tsx # Success confirmation │ └── OtpInput/OtpInput.tsx # 6-digit code input ├── views/GetStartedView.tsx # Page view └── index.ts # Public exports ``` ## Eligibility Check Page **Location:** `apps/portal/src/features/services/views/PublicEligibilityCheck.tsx` **Route:** `/services/internet/check-availability` A dedicated page for guests to check internet availability. This approach provides: - Better mobile experience with proper form spacing - Clear user journey with bookmarkable URLs - Natural browser navigation (back button works) - Focused multi-step experience **Flow:** 1. Collects name, email, and address (with Japan ZIP code lookup) 2. Verifies email with 6-digit OTP 3. Creates SF Account + Eligibility Case immediately on verification 4. Shows success with options: "Create Account Now" or "Maybe Later" ## Backend Endpoints | Endpoint | Rate Limit | Purpose | | ----------------------------------------- | ---------- | --------------------------------------------- | | `POST /auth/get-started/send-code` | 5/5min | Send OTP to email | | `POST /auth/get-started/verify-code` | 10/5min | Verify OTP, return account status | | `POST /auth/get-started/quick-check` | 5/15min | Guest eligibility (creates SF Account + Case) | | `POST /auth/get-started/complete-account` | 5/15min | Complete SF-only account | | `POST /auth/get-started/maybe-later` | 3/10min | Create SF + Case (legacy) | ## Domain Schemas Location: `packages/domain/get-started/` Key schemas: - `sendVerificationCodeRequestSchema` - email only - `verifyCodeRequestSchema` - email + 6-digit code - `quickEligibilityRequestSchema` - sessionToken, name, address - `completeAccountRequestSchema` - sessionToken + password + profile fields - `accountStatusSchema` - `portal_exists | whmcs_unmapped | sf_unmapped | new_customer` ## OTP Security - **Storage**: Redis with key format `otp:{email}` - **TTL**: 10 minutes - **Max Attempts**: 3 per code - **Rate Limits**: 5 codes per 5 minutes ## Handoff from Eligibility Check ### Flow A: "Continue to Create Account" (Inline OTP) When a user clicks "Continue to Create Account": 1. Eligibility form is submitted (creates SF Account + Case) 2. OTP is sent and verified **inline on the same page** 3. On successful verification: - Session data stored in sessionStorage with timestamp: - `get-started-session-token` - `get-started-account-status` - `get-started-prefill` (JSON with name, address from SF) - `get-started-email` - `get-started-timestamp` (for staleness validation) - Redirect to: `/auth/get-started?verified=true` 4. GetStartedView detects `?verified=true` param and: - Reads session data from sessionStorage (validates timestamp < 5 min) - Clears sessionStorage immediately after reading - Sets session token, account status, and prefill data in Zustand store - Skips directly to `complete-account` step (no email/OTP required) - User only needs to add phone, DOB, and password ### Flow B: "Send Request Only" → Return Later When a user clicks "Send Request Only": 1. Eligibility form is submitted (creates SF Account + Case) 2. Success page is shown with two options: - **"Back to Internet Plans"** → Returns to `/services/internet` - **"Create Your Account Now"** → Redirects to `/auth/get-started?email=xxx&handoff=true` 3. If user returns later via success page CTA or SF email: - Standard flow: Email (pre-filled) → OTP → Account Status → Complete - Backend detects `sf_unmapped` status and returns prefill data ### Salesforce Email Link Format SF can send "finish your account" emails with this link format: ``` https://portal.example.com/auth/get-started?email={Account.PersonEmail} ``` - No handoff token needed (SF Account persists) - User verifies via standard OTP flow on get-started page - Backend detects `sf_unmapped` status and pre-fills form data ## Testing Checklist ### Manual Testing 1. **New customer flow**: Enter new email → Verify OTP → Full signup form 2. **SF-only flow**: Enter email with SF account → Verify → Pre-filled form (name, address pre-filled, add phone, DOB, password) 3. **WHMCS migration**: Enter email with WHMCS → Verify → Enter WHMCS password 4. **Eligibility check - Send Request Only**: - Click "Check Availability" → Fill form → Click "Send Request Only" - Verify success page shows "Back to Plans" and "Create Account" buttons - Click "Create Account" → Verify redirect to `/auth/get-started?email=xxx` - Complete standard OTP flow → Verify sf_unmapped prefill works 5. **Eligibility check - Continue to Create Account**: - Click "Check Availability" → Fill form → Click "Continue to Create Account" - Verify inline OTP step appears (no redirect) - Complete OTP → Verify redirect to `/auth/get-started?verified=true` - Verify CompleteAccountStep shows directly (skips email/OTP steps) - Verify form is pre-filled with name and address 6. **Return flow**: Customer returns, enters same email → Auto-links to SF account 7. **Mobile experience**: Test eligibility check page on mobile viewport 8. **Browser back button**: After OTP success, press back → Verify graceful handling 9. **Session timeout**: Wait 5+ minutes after OTP → Verify stale data is rejected ### Security Testing - Verify OTP expires after 10 minutes - Verify max 3 attempts per code - Verify rate limits on all endpoints - Verify email enumeration is prevented (same response until OTP verified) ## Routes | Route | Action | | --------------------------------------- | -------------------------------- | | `/auth/get-started` | Unified account creation page | | `/auth/signup` | Redirects to `/auth/get-started` | | `/auth/migrate` | Redirects to `/auth/get-started` | | `/services/internet/check-availability` | Guest eligibility check (public) | ## Environment Variables ```bash # OTP Configuration OTP_TTL_SECONDS=600 # 10 minutes OTP_MAX_ATTEMPTS=3 GET_STARTED_SESSION_TTL=3600 # 1 hour ```