Brainstorm: New Identity Schema -- Signup, Onboarding & Auth
Date: 2026-03-10
Status: Ready for planning
Feature flag: ENABLE_NEW_IDENTITY_AUTH / VITE_ENABLE_NEW_IDENTITY_AUTH
What We're Building
A complete signup, onboarding, and authentication system for the new identity schema that supports all user types (doctors, practitioners, facility owners, facility managers, staff, vendors) with progressive onboarding and tenant-level subscription management.
Core User Flows
-
Self-Registration -- All roles can self-register via phone + password + name + role selection. OTP verification via SMS. After verification, user lands on Connect (networking) page.
-
Invite-to-Join -- Existing users accept an invite to add a membership to another tenant. New users receive an invite link that leads to signup with auto-linking to the inviting tenant/facility.
-
Progressive Onboarding -- No blocking wizard. All users get Connect access after signup. Premium features (CMS, Growth, Hospital Management) require sales-assisted onboarding -- users express interest through the app, and the sales team handles tenant/facility setup.
-
Authentication -- Phone + password login, profile selection (multi-tenant), token refresh, 2FA, password reset. Social login deferred.
Why This Approach
Unified Signup + Role-Driven Progressive Shell was chosen because:
- Lowest barrier to entry -- One simple form for all user types. No branching wizard that increases drop-off.
- Connect-first philosophy -- The Connect app (professional networking) works with just a user account. No tenant, facility, or subscription required. Users get value immediately.
- Connect-first, sales-assisted upgrade -- All users start with Connect. Premium features (CMS, Growth, Hospital Management) are unlocked through a sales-assisted onboarding process, not self-service. This keeps signup simple and ensures proper tenant/facility setup by the sales team.
- Invite compatibility -- The "User only" minimum setup means invites are clean: existing users just get a membership added, new users sign up minimally and get auto-linked.
Key Decisions
1. Signup Form
- Fields: Phone number, password, full name, role selection
- Role options: Doctor/Practitioner, Facility Owner/Manager, Vendor, Staff
- Verification: 6-digit OTP via SMS (same as legacy)
- Outcome: Creates
Identity::Userrecord only. No tenant, no facility, no practitioner. - Note: Role selection at signup is for UX targeting and analytics. The actual
UserMembershiprole is set when the user joins or creates a tenant (owner, admin, staff, practitioner).
2. Post-Signup Landing
- All users land on the Connect page after signup + verification
- Connect works without a tenant or facility (cross-tenant networking feature)
- The role selected during signup is stored on the user record for analytics and progressive prompt targeting
3. Premium Feature Access (Sales-Assisted)
- Premium features (CMS, Growth, Hospital Management) are not self-service. Users cannot create tenants or facilities themselves.
- User expresses interest: An in-app mechanism (e.g., "Upgrade" button, contact form, or interest expression) notifies the Kulcare sales team.
- Sales team onboards: Sales creates the Tenant, Organization, Facility, and assigns the user's UserMembership with the appropriate role (owner, admin, staff, practitioner).
- User gains access: Once the sales team completes setup, the user sees the new tenant/facility in their profile list and can switch to it.
- Invite flow still applies: After initial sales-assisted setup, the facility owner/admin can invite additional staff, practitioners, etc. using the invite system.
4. Connect-Only Onboarding (Self-Service)
- After signup, users can optionally complete their professional profile for Connect (networking)
- Doctors/Practitioners: Set up practitioner profile (specialties, qualifications, bio) for discoverability
- Vendors: Set up vendor profile in
identity.vendorstable (services offered, availability) - All users: Basic profile completion (photo, bio, location) for networking
- This is voluntary and prompted contextually, not a blocking wizard
5. Vendor Model
- Vendors are freelance professionals (yoga instructors, lamaze instructors, massage therapists, etc.)
- Separate profile type using the
identity.vendorstable (not a UserMembership role) - Vendors get a User account + Vendor profile record. No mandatory tenant or UserMembership.
- Vendors can work across multiple facilities or independently
- Facility-vendor linkage (which facilities use which vendors) is a separate association, not built in this scope
6. Invite Flow (Dual Path)
- Existing Kulcare user: Admin enters invitee's phone/email. System finds existing user, creates a pending
UserMembership. User sees invite notification and accepts. - New user: Admin enters invitee's phone/email. System sends invite link. Invitee clicks link, goes through signup (phone/password), and on verification the invite auto-links them to the tenant/facility with the correct role.
7. Subscription & Feature Flags
- Scope: Tenant-level subscriptions. All facilities under a tenant share the same plan.
- Port now: Subscription status, feature flags, and plan-based gating must be included in the new auth system for full parity with legacy.
- Implementation: The
@kulcare/auth-identitypackage needs subscription state, feature flag management, and permission checks similar to legacy@kulcare/auth. - Backend: Tenant model already has
plan_tierandfeature_flags(JSONB). Wire these into the auth session/profile response.
8. Authentication (Existing + Gaps)
- Already built: Login (phone+password), profile switching, token refresh, logout, 2FA, password reset (backend + frontend pages)
- To build: Signup page, OTP verification page, progressive onboarding prompts, invite acceptance flow, subscription/feature flag integration
- Deferred: Social login (Google/Facebook OAuth)
9. Feature Flag Gating
- All new auth flows gated behind
ENABLE_NEW_IDENTITY_AUTH/VITE_ENABLE_NEW_IDENTITY_AUTH - Legacy auth continues to work in parallel when flag is off
- Gradual rollout: flag can be enabled per-environment (staging first, then production)
Existing Code Inventory
Backend (already built)
backend/domains/identity/controllers/sessions_controller.rb-- Login, refresh, logoutbackend/domains/identity/controllers/registrations_controller.rb-- Signup endpoint, verifybackend/domains/identity/controllers/profiles_controller.rb-- List profiles, switch profilebackend/domains/identity/services/sessions/-- Authentication organizer, token managementbackend/domains/identity/services/users/-- Registration, verification, profile orchestrationbackend/domains/identity/services/two_factor/-- Complete 2FAbackend/domains/identity/services/passwords/-- Password resetbackend/parts/identity/models/identity/-- User, Tenant, UserMembership, Organization, Facility, Practitioner, etc.
Frontend (already built)
frontend/packages/auth-identity/-- Zustand store, hooks (useAuth, useProfile, usePermissions)frontend/apps/shell/src/services/identityAuthService.ts-- API service layerfrontend/apps/shell/src/pages/SignInPage.tsx-- Login pagefrontend/apps/shell/src/pages/SelectProfilePage.tsx-- Profile selectionfrontend/apps/shell/src/pages/ForgotPasswordPage.tsx-- Password reset startfrontend/apps/shell/src/pages/VerifyResetCodePage.tsx-- Reset code verificationfrontend/apps/shell/src/pages/ResetPasswordPage.tsx-- New password entry
What needs building
- Frontend: SignUpPage, VerifyOtpPage, invite acceptance page/flow, subscription/feature flag state in auth-identity package, "express interest in premium" mechanism (button/form)
- Backend: Invite system (create invite, accept invite, auto-link), subscription data in profile/session responses, route mounting for identity domain, role validation alignment (
[owner, admin, staff, practitioner]), sales-side tooling for tenant/facility creation and user assignment - Integration: Wire subscription/feature flags into auth-identity store, update CMS/Growth apps to read from new auth when flag is on
Resolved Decisions
- Role naming: Canonical set is
[owner, admin, staff, practitioner]. The UserMembership model validation needs updating from[owner, admin, member, viewer]. - Vendor model: Vendor is a separate profile type using
identity.vendorstable, not a UserMembership role.
Open Questions
-
Progressive prompt UX -- How should progressive prompts appear? Options: banner at top of page, modal on first access to gated feature, dedicated setup page, or inline card on dashboard.
-
Invite system scope -- How elaborate is the invite system for v1? Simple phone/email invite with link, or full invite management (pending, accepted, expired, revoked)?
-
Data migration -- When the flag is flipped for existing users, how do legacy accounts get migrated to the new identity schema? Is this a separate concern or part of this work?
-
Route mounting -- The identity domain routes are currently commented out in
config/routes.rb. Need to confirm the mounting strategy (direct mount vs. domain engine).
Technical Notes
- The new backend uses Services pattern (not Interactors) in
backend/domains/identity/ - Serialization uses Blueprints (not ActiveModel Serializers)
- Auth state package follows Pattern 1 Architecture: state in
@kulcare/auth-identity, API logic in shell app'sidentityAuthService.ts - The
Identity::Usermodel hashas_secure_passwordand supports both email and phone login - Multi-tenancy is through
UserMembershiplinking users to tenants with roles