Kulcare Docs
GeneralBrainstorms

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

  1. 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.

  2. 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.

  3. 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.

  4. 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::User record only. No tenant, no facility, no practitioner.
  • Note: Role selection at signup is for UX targeting and analytics. The actual UserMembership role 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.vendors table (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.vendors table (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-identity package needs subscription state, feature flag management, and permission checks similar to legacy @kulcare/auth.
  • Backend: Tenant model already has plan_tier and feature_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, logout
  • backend/domains/identity/controllers/registrations_controller.rb -- Signup endpoint, verify
  • backend/domains/identity/controllers/profiles_controller.rb -- List profiles, switch profile
  • backend/domains/identity/services/sessions/ -- Authentication organizer, token management
  • backend/domains/identity/services/users/ -- Registration, verification, profile orchestration
  • backend/domains/identity/services/two_factor/ -- Complete 2FA
  • backend/domains/identity/services/passwords/ -- Password reset
  • backend/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 layer
  • frontend/apps/shell/src/pages/SignInPage.tsx -- Login page
  • frontend/apps/shell/src/pages/SelectProfilePage.tsx -- Profile selection
  • frontend/apps/shell/src/pages/ForgotPasswordPage.tsx -- Password reset start
  • frontend/apps/shell/src/pages/VerifyResetCodePage.tsx -- Reset code verification
  • frontend/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.vendors table, not a UserMembership role.

Open Questions

  1. 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.

  2. 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)?

  3. 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?

  4. 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's identityAuthService.ts
  • The Identity::User model has has_secure_password and supports both email and phone login
  • Multi-tenancy is through UserMembership linking users to tenants with roles

On this page