Feature: Org Onboarding
Last updated: 2026-06-06
This document is the single source of truth for org onboarding. Requirements and acceptance criteria were consolidated here on 2026-05-04.
Recent (2026-06-02): AM Setup Wizard slice 2 (#1319 — step 2
email_aliaspreview) and slice 3 (#1326 — OSA detail page Workspace section + Suspend/Restore, closes #1322) landed. Invite lifecycle locked in ADR-023 (#1286) — 7-day expiry, token rotation, user-initiated resend.Recent (2026-06-05/06):
- OTP verification now required before profile creation (#1949).
- Optional onboarding steps no longer block activation; step-6 escape hatch added (#1807).
- Waiting room flow rebuilt from first principles (#1904).
- Mic permission flow: user gesture required, mic-only recovery path (#2029); URL-deeplink + mic-required / camera-optional permissions (#2010).
- "Finish without invite" stranded-orgs banner safety net for AMs (#1698).
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, 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
Dedicated doc: the end-to-end AM Setup Wizard flow (step-by-step, with the
email_aliaspreview and the OSA Workspace Suspend/Restore surface) now lives in am-setup-wizard.md. The summary below is retained for the onboarding-flow context.
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, skill tags) — the Email field was dropped from the Specialist Create form in #1097 (ADR-0002 Phase 2)
- Per-OSA email alias is auto-generated as
{firstname}.{org-slug}@{HWORK_DOMAIN}at assignment time via theOrganizationsService.assignSpecialisthook (#1089). The alias is stored onOrgSpecialistAssignment.email_alias, not on the catalog Specialist. - The catalog Specialist no longer carries an
emailcolumn. - 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).
Expert onboarding email templates (#1554 / #1560)
See also: docs/features/expert-application.md — the full Tavus-driven application → interview → promote flow these emails fire on.
In parallel with client onboarding, Expert onboarding now uses 5 dedicated email templates rendered through Resend (#1554 / #1560). The 5 templates:
| Template key | Trigger | Audience |
|---|---|---|
expert.application_received | New marketing-lead Expert application submitted | Applicant |
expert.interview_scheduled | Interview slot booked via the application flow | Applicant |
expert.application_approved | SuperAdmin promotes the marketing lead to an Expert | New Expert |
expert.application_declined | SuperAdmin declines the marketing lead | Applicant |
expert.welcome | First successful login to /workspace | New Expert |
Templates live under api/src/email/templates/expert/ and are version-pinned;
copy changes go through PR review. AM/client-side onboarding emails are
unaffected — those still use the client templates documented in §1.4.
AM Wizard test coverage (#1562)
The 4-step structure is locked in by #1562, which aligned the wizard test cases to the 4-step flow (previously the test fixture asserted 5 steps, which was stale). Any future step-count change must update the test fixture in the same PR.
Phase 2: Client Confirmation
Client accesses the onboarding wizard via the invite email link (/onboarding route).
UX Update (PRs #267-271, 2026-05-10): The onboarding wizard was simplified from 6 steps to 3 steps. Steps 2.4 (Set Up Channels) and 2.5 (Optional Steps) were removed as dedicated wizard steps. Channels and Billing are now accessed post-onboarding from
/client/settings/*.
Step 2.1 — Account Verification
- No separate email-verification step (#3488): clicking the invite link
(emailed only to the admin) already proves email ownership, so the onboarding
session is bootstrapped from the token via
POST /:token/sessionwhen the wizard loads. The earlier emailed-OTP step re-verified the same address through the same channel and was removed as redundant double verification. - 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, skill tags, bio, and the resolved per-OSA contact alias ({firstname}.{org-slug}@{HWORK_DOMAIN}). Client does not see the Specialist composition (AI Agent + Experts behind the persona).
To request a different Specialist: use Settings post-onboarding (AM fulfills the request).
Step 2.3a — Agreements
Modal presents four documents in tabs: Terms of Service, Privacy Policy, Acceptable Use Policy, Data Processing Addendum. Each tab requires scroll-to-bottom before the corresponding accept checkbox is enabled (#1046 / #1048 / #1068).
- All four must be accepted before Step 2.4 unlocks.
- Acceptance writes to the legal acceptance ledger (org × user × document version × timestamp).
- A re-consent banner re-prompts when any document version is bumped post-acceptance.
Cross-reference: docs/legal/ and the TOS/Privacy/AUP/DPA source documents.
Step 2.4 — 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')
Post-Onboarding Configuration: Channels (Slack, WhatsApp, Email settings) and Billing are configured from
/client/settings/*after onboarding completion. These were previously Steps 2.4 and 2.5 of the wizard but were moved to post-onboarding to reduce friction.
API Endpoints
All onboarding endpoints are prefixed with /onboarding/:token/.
| Endpoint | Description |
|---|---|
POST /:token/session | Bootstrap session from token (#3488) → session JWT |
POST /:token/verify-email | Send OTP to admin email (legacy) |
POST /:token/confirm-otp | Verify OTP → session JWT (legacy) |
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-06-04)
The 2026-04-30 snapshot table previously shown here is superseded by the
weekly audit reports under docs/audits/. Open onboarding-area
items as of 2026-06-04: