# 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 │ ├─→ Step 2: Verify email (6-digit OTP) │ └─→ Step 3: SF Account + Case created immediately │ ├─→ "Create Account Now" → Redirect to /auth/get-started │ (email pre-verified, goes to complete-account) │ └─→ "Maybe Later" → Return to /services/internet (SF Account created for agent to review) ``` ## 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 When a user clicks "Create Account Now" from the eligibility check page: 1. Email stored in sessionStorage: `get-started-email` 2. Verification flag stored: `get-started-verified=true` 3. Redirect to: `/auth/get-started?email={email}&verified=true` 4. GetStartedView detects handoff and: - Sets account status to `sf_unmapped` (SF Account was created during eligibility) - Skips to `complete-account` step - User only needs to add password + profile details When a user clicks "Maybe Later": - Returns to `/services/internet` plans page - SF Account already created during eligibility check (agent can review) - User can return anytime and use the same email to continue ## 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, just add password 3. **WHMCS migration**: Enter email with WHMCS → Verify → Enter WHMCS password 4. **Eligibility check**: Click "Check Availability" on plans page → Dedicated page → Enter details → OTP → "Create Account" or "Maybe Later" 5. **Return flow**: Customer returns, enters same email → Auto-links to SF account 6. **Mobile experience**: Test eligibility check page on mobile viewport ### 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 ```