Feature: Org Onboarding
Last updated: 2026-05-07
This document is the single source of truth for org onboarding. Requirements and acceptance criteria were consolidated here on 2026-05-04.
Overview
Org onboarding is a two-phase process:
- Phase 1 (AM-assisted) — Internal Account Manager sets up the Org in the admin portal
- Phase 2 (Client confirmation) — Client Admin completes setup via a guided wizard at
/onboarding(link delivered via invite email)
The result is an active Org with at least one Specialist assigned, Email channel configured, and a Client Admin who has confirmed the setup.
Actors
| Actor | Role | What They Do |
|---|---|---|
| Account Manager | Internal | Creates Org, assigns Specialists, sends invite |
| Client Admin | Client | Confirms setup, sets password, configures channels |
| Super Admin | Internal | Can view/edit any onboarding; can impersonate AM |
Phase 0: Validation Gate
Before the invite is sent, the system hard-blocks until all pass:
- All required company fields complete
- At least 1 Specialist assigned with complete profile (name, avatar, email, skill tags)
- AM's own profile complete
- Trial end date set (default: 30 days from invite send date)
Endpoint: GET /am/orgs/:orgId/phase0-status
Route note: AM-facing endpoints use the
/am/orgs/prefix internally (NestJS routing), but the frontend accesses them through/ops/clients/[id]/setup/*routes.
AM Wizard — 4 Steps
The AM wizard has 4 steps accessed from /ops/clients/new (step 1) and /ops/clients/[id]/setup/* (steps 2–4).
Phase 1: AM-Assisted Setup
Step 1.1 — Company Information
AM enters on behalf of the client:
Required: company legal name, subdomain (slug), industry, primary corporate email domain(s), admin email address (optional), company website, country/timezone
The AM wizard labels this field "Subdomain" in the UI. The code and DB call it
slug. After the client confirms in onboarding Step 2.2, the slug is immutable.
Optional: company logo, billing email, company size, secondary email domains
Slug rules:
- Format:
^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$(3–63 chars) - Validated in real-time via
GET /orgs/slug-check?slug=... - Reserved word list enforced (api, app, www, admin, etc.) — see
config/reserved-slugs.ts - Not reserved until client confirms in Step 2.2
Email domain rules:
- Personal domains blocked (gmail, yahoo, etc.) — see
config/blocked-email-domains.ts - Admin email must match an approved corporate domain
- No DNS verification required
Step 1.2 — Assign Specialists
AM selects 1+ Specialists from the platform pool. For each Specialist:
- Confidence Threshold set (integer 0–101; default 101 = Never autoreply)
- Optional: designate a primary Specialist
Specialist constraints:
- Specialist ↔ Org relationship is many-to-many via
OrgSpecialistAssignment - Specialist profile must be complete (name, avatar, email, skill tags)
- Specialist email format:
{firstname}`@`{HWORK_DOMAIN}(routing alias only; not a login) - Only SuperAdmin can create/modify Specialist personas. AMs assign existing ones.
Step 1.3 — Account Manager Profile
AM verifies their global profile (name, avatar, email). Shown to client during onboarding and in the portal. Not per-Org — shared profile.
Step 1.4 — Send Client Invitation
After Phase 0 validation passes:
- System sends welcome email to admin email with AM name/avatar, org name, workspace URL, and CTA
- Invitation token expires in 7 days; resending issues a fresh 7-day window
- Trial clock does NOT start until Phase 2 completion
- Org status:
pending_client_confirmation - Stale orgs (90+ days in
pending_client_confirmation) are auto-archived; restorable by Super Admin
Step 1.4 UX (as of PR #243):
- Send button is enabled as soon as company info, specialist, and AM profile gates pass. The
trialEndDateSetcheck is satisfied client-side (trial date is set on this very step). - "Copy Onboarding Link" button is available before and after sending — AM can share the link directly without waiting for the email.
- "Complete Setup" CTA appears for orgs already in
pending_client_confirmationstatus (re-entry after first send).
Phase 2: Client Confirmation
Client accesses the onboarding wizard via the invite email link (/onboarding route).
Step 2.1 — Account Verification
- Email OTP sent to the admin email on record
- Client Admin sets password
- Profile fields: full name, job title (optional), phone (optional)
Step 2.2 — Review & Confirm Company Information
Client sees AM-entered data pre-populated and can edit most fields. The slug is permanently reserved at the end of this step.
| Field | Client Can Change? |
|---|---|
| Company legal name | Yes |
| Slug | Yes (once, here only) — immutable after confirmation |
| Industry | Yes |
| Primary corporate email domain | No — AM-controlled |
| Admin email | Yes — must still match approved domain |
| Website, country, timezone | Yes |
Slug reservation uses a pessimistic write lock + server-side re-validation to prevent race conditions.
Step 2.3 — Meet Your Specialist
Read-only profile card(s) for each assigned Specialist. Client sees: name, avatar, email, skill tags, bio. Client does not see the Specialist Team composition (Experts + Agents behind the persona).
To request a different Specialist: use Settings post-onboarding (AM fulfills the request).
Step 2.4 — Set Up Channels
Email (default, always on):
- Specialist routing address pre-configured (
{firstname}`@`{HWORK_DOMAIN}) - Client can set a custom display name for outbound messages
- No technical setup from client
Email Whitelist:
- Pre-seeded from org's corporate domain(s) at completion
- Client Admin can add additional approved domains or specific addresses
- Non-whitelisted inbound email rejected at channel routing layer
WhatsApp (optional):
- Present but marked skippable
- Full Meta embedded signup flow: design deferred — tracked in issue #101
Coming Soon (shown as locked): Slack, Telegram, WeChat, Microsoft Teams
Step 2.5 — Optional Steps (Skippable)
| Step | Description |
|---|---|
| Invite teammates | Add Client Members by email (must match approved domain) |
| Billing & invoicing | Add payment method (required before trial end, not before completion) |
| Customize Specialist | Add welcome message or custom bio |
TrialBanner displays throughout portal: "Your trial ends in N days — add billing to continue."
Step 2.6 — Onboarding Complete
- Org status:
pending_client_confirmation→active - Trial clock starts (
org.trialStartedAt = now()) - Client Admin redirected to
/client/chat - AM receives email notification
- Welcome summary email sent to Client Admin (Specialist contact info, workspace URL, next steps)
- Onboarding wizard link becomes invalid (token
status = 'accepted')
API Endpoints
All onboarding endpoints are prefixed with /onboarding/:token/.
| Endpoint | Description |
|---|---|
POST /:token/verify-email | Send OTP to admin email |
POST /:token/confirm-otp | Verify OTP → session JWT |
POST /:token/set-credentials | Set password (+ optional 2FA) |
POST /:token/profile | Save name, title, phone |
GET /:token/org | Org details for wizard |
GET /:token/specialist | Assigned Specialist card |
POST /:token/confirm-slug | Finalize and reserve slug |
GET /:token/whitelist | List whitelist entries |
POST /:token/whitelist | Add email/domain to whitelist |
DELETE /:token/whitelist/:id | Remove whitelist entry |
POST /:token/invite-members | Invite multiple Client Members |
POST /:token/complete | Finalize onboarding (Step 2.6) |
AM-side endpoints are under /am/orgs/ (NestJS routing) — see docs/api/reference.md.
Status After Audit (2026-04-30)
| Status | Count |
|---|---|
| ✅ RESOLVED | 89 |
| ⚠️ PARTIAL | 5 |
| ❌ OPEN | 6 |
Open items: WhatsApp onboarding UX (issue #101), slug churn/rebrand/cross-env enforcement (AC-SLUG-04/05/06).