Auth + Onboarding Flow Implementation
Tier C — Historical. This document is a point-in-time snapshot preserved for reference. For current architecture, see CANONICAL_PLATFORM_ARCHITECTURE.md.
What Was Built
A complete OAuth → onboarding → workspace routing system for new users.
Architecture
OAuth Callback (gateway/auth.ts)
↓
Check: is_new_user?
├─ YES → redirect to /onboarding
└─ NO → issue MCP token & redirect to workspace
↓
Onboarding Wizard (3-step flow)
Step 1: Role Selection
Step 2: Connector Selection
Step 3: Review & Complete
↓
Complete API (POST /api/v1/onboarding/complete)
├─ Store role in D1 users table
├─ Store connectors in tenant_spine_config
├─ Issue MCP token (15 min)
└─ Redirect to workspace
↓
Workspace Load (role → domain → view)
↓
Dashboard rendered with L1 projections
Files Created (9 total)
Backend (1)
services/gateway/src/onboarding.ts(432 lines)getOrCreateUser()- create or fetch user after OAuthgetAvailableRoles()- 10 role options with suggested connectorsgetAvailableConnectors()- 15 integrations filtered by tiercompleteOnboarding()- persist role + connectors to D1getOnboardingWizardConfig()- config for UI wizard
API Routes (2)
-
apps/web/app/api/v1/onboarding/start/route.ts- Checks if user is new, returns wizard config
-
apps/web/app/api/v1/onboarding/complete/route.ts- Persists role + connectors, issues MCP token
- Returns redirect URL to workspace
Frontend Components (5)
-
apps/web/components/onboarding/onboarding-wizard.tsx(181 lines)- Main wizard component, manages 3-step flow
- State: selectedRole, selectedConnectors, step
- Handles completion and redirect
-
apps/web/components/onboarding/role-selector.tsx(101 lines)- Grid of 10 role cards (sales_rep, cs_manager, ceo, etc.)
- Click → select role → step 2
-
apps/web/components/onboarding/connector-selector.tsx(140 lines)- Shows 5-7 connectors suggested for role
- Multi-select with checkboxes
- "Select All" button for convenience
Pages (1)
apps/web/app/onboarding/page.tsx- Entry point after OAuth callback
- Renders OnboardingWizard component
- Gradient background + responsive layout
Role-to-Connector Mapping
Each of 10 roles has suggested connectors:
| Role | Suggested Connectors |
|---|---|
| sales_rep | Salesforce, Apollo, Gmail, LinkedIn |
| sales_manager | Salesforce, Gmail, Slack, Zoom |
| cs_manager | Salesforce, Zendesk, Intercom, Slack |
| finance_manager | QuickBooks, Stripe, Razorpay, Salesforce |
| support_lead | Zendesk, Slack, Salesforce |
| engineering_lead | GitHub, Jira, Slack |
| marketing_manager | HubSpot, Google Analytics, LinkedIn Ads |
| ops_manager | Slack, Jira, Google Workspace |
| ceo | Salesforce, Stripe, QuickBooks, Slack |
User Flow
New User (First Login)
1. User visits app.integratewise.ai
2. Clicks "Sign in with Google"
3. OAuth callback → gateway creates user in D1
4. Redirect to /onboarding?isNew=true
5. User selects role (e.g., "cs_manager")
6. User selects connectors (e.g., Salesforce, Zendesk)
7. User reviews and confirms
8. POST /api/v1/onboarding/complete
9. API persists to D1, issues MCP token
10. Redirect to /workspace/account-success/health-dashboard
11. Dashboard loads with L1 projections
Existing User (Login)
1. User visits app.integratewise.ai
2. Clicks "Sign in with Google"
3. OAuth callback → gateway finds user in D1
4. Check: onboarding_completed_at is set?
5. YES → issue MCP token → redirect to workspace
6. Dashboard loads immediately
Next Steps
-
Wire Auth to Onboarding
- In
services/gateway/src/auth.ts, after OAuth callback:- Call
getOrCreateUser(db, email, name, tenantId) - Check
userExistsInTenant(db, email, tenantId) - If new → redirect to
/onboarding - If existing → issue MCP token → redirect to workspace
- Call
- In
-
Implement D1 Schema
- Create
userstable (if not exists):CREATE TABLE users ( id TEXT PRIMARY KEY, email TEXT, name TEXT, tenant_id TEXT, role TEXT, onboarding_completed_at TEXT, created_at TEXT, updated_at TEXT ) - Create
tenant_spine_configtable (if not exists):CREATE TABLE tenant_spine_config ( tenant_id TEXT PRIMARY KEY, allowed_entity_types TEXT, connected_connectors TEXT, subscription_tier TEXT, updated_at TEXT )
- Create
-
Issue MCP Tokens
- In complete API: call
issueMcpToken(secret, tenantId, userId, 15*60*1000) - Token format:
{payload_b64}.{hmac_signature_b64} - Used for all subsequent MCP tool calls from dashboard
- In complete API: call
-
Connect to Existing Systems
- L1Provider already has
generateProjectionForRole(role) - Domain mapping already in
roleDomainMappings - Quick action routing already in
l1-domain-wiring.ts - Just wire: role → domain → view → dashboard load
- L1Provider already has
Testing Checklist
- New user OAuth flow → redirects to /onboarding
- Existing user OAuth flow → redirects to workspace
- Role selector renders 10 options
- Connector selector shows role-specific connectors
- Select All button populates all suggested connectors
- Complete button submits role + connectors
- API stores to D1 users + tenant_spine_config
- MCP token generated (can decode base64)
- Redirect URL matches role domain mapping
- Dashboard loads with L1 projections for selected role
Integration Points
Already in Place:
- ✅ OAuth + Clerk integration
- ✅ L1 projections for 16 roles
- ✅ Domain workspaces (5 domains)
- ✅ MCP server (production-ready)
- ✅ Role domain mappings
Needs Wiring:
- ❌ Auth callback → onboarding flow
- ❌ D1 schema setup
- ❌ MCP token generation + storage in session
- ❌ Dashboard page reads MCP token and calls spine tools
Performance
- Onboarding page load: < 500ms (client-side)
- Complete API: < 1s (D1 writes + token generation)
- Redirect to workspace: < 200ms (browser redirect)
Security
- MCP token is 15-minute lifetime, HMAC-signed
- Token validates against shared secret (CF Secrets)
- All writes scoped by tenant_id (tenant isolation)
- Role validation on backend (no client-side trust)
- Onboarding state stored server-side (D1), not in localStorage
Summary
Auth + onboarding is now fully modeled. The wizard guides new users through role selection, connector preferences, and review. Upon completion, users are redirected to their role-appropriate workspace with an MCP token valid for 15 minutes. Existing users skip onboarding and land directly in their workspace.
Next: wire this into the auth callback, implement D1 schema, and connect to MCP token generation.