User Management

Overview

The Refresh platform separates the concept of identity (how you log in) from user (who you are in the system). A single person can have multiple identities (work email, personal email) that all link to different internal user records. This design supports:

  • HRIS-provisioned work accounts

  • User-created personal accounts

  • Account linking for cross-company history

  • GDPR compliance with data portability

  • Privacy separation between work and personal data

Core Concepts

The Person Model

┌─────────────────────────────────────────────────────────────────┐
│                        THE PERSON (Taylor)                       │
├─────────────────────┬─────────────────────┬─────────────────────┤
│  users (personal)   │  users (work-acme)  │  users (work-newco) │
│  id: user-P         │  id: user-A         │  id: user-N         │
│  primary_user_id:   │  primary_user_id:   │  primary_user_id:   │
│  NULL (is primary)  │  user-P             │  user-P             │
├─────────────────────┼─────────────────────┼─────────────────────┤
│  user_identities:   │  user_identities:   │  user_identities:   │
[email protected][email protected][email protected]
│  (active)           │  (DELETED on leave) │  (active)           │
├─────────────────────┼─────────────────────┼─────────────────────┤
│  tenant_users:      │  tenant_users:      │  tenant_users:      │
│  (none)             │  acme (INACTIVE)    │  newco (ACTIVE)     │
├─────────────────────┼─────────────────────┼─────────────────────┤
│  DATA OWNED:        │  DATA OWNED:        │  DATA OWNED:        │
│  - therapy sessions │  - survey responses │  - survey responses │
│  - EAP usage        │  - backfill data    │  - backfill data    │
│  - personal reports │  - HRIS records     │  - HRIS records     │
└─────────────────────┴─────────────────────┴─────────────────────┘

Key Distinctions

Concept
What It Is
Where Stored

Identity

A way to authenticate (email + FusionAuth)

user_identities

User

An internal record for data ownership

users

Primary User

The "main" account (usually personal)

users.primary_user_id = NULL

Linked User

Work accounts linked to a primary

users.primary_user_id = <primary>

Why Multiple User Records?

User IDs are immutable references stored in:

  • S3 JSON files (backfill data)

  • Data warehouse tables

  • Audit logs

  • External integrations

Merging user records would break these references. Instead, we link users while preserving their original IDs.

Database Schema

users Table

Key Fields:

Field
Purpose

primary_user_id

NULL = this is a primary account; otherwise points to primary

is_anonymized

GDPR deletion flag - PII removed but record kept for FK integrity

user_identities Table

Key Fields:

Field
Purpose

fusionauth_id

NULL until user authenticates; set on first login

email

Unique across all identities

type

personal or work

tenant_id

Which tenant provisioned this identity (NULL for personal)

is_primary

User's preferred login method

User Lifecycle Flows

Flow 1: HRIS Creates Work Account

When a company onboards and HRIS sync runs:

At this point:

  • User exists in your system but hasn't logged in

  • FusionAuth doesn't know about them yet

  • They'll be linked on first authentication

Flow 2: User Authenticates with Work Email

When the user logs in for the first time:

Flow 3: User Creates Personal Account

When a user signs up with a personal email:

Personal Account Without Tenant Access

Users with only a personal account (no linked work accounts) see a limited experience:

Future Enhancement: Personal accounts may gain access to user-specific resources and memberships independent of employer tenants.

Flow 4: Linking Personal to Work Account

Account linking is user-initiated. The system does not automatically detect that a personal account holder has a work account—this is the user's responsibility based on employer instructions.

Two linking directions:

  1. Work → Personal: User logs in with work email, then links to personal account

  2. Personal → Work: User logs in with personal email, provides work email for verification

Key Points:

  • The personal account is always the primary (owns the data lifecycle)

  • Work accounts become children of the personal account

  • This maintains a clean tree structure: one primary with many linked work accounts

  • is_primary field on user_identities indicates the user's preferred login method

Flow 5: Employee Leaves Company

When HRIS sync shows termination:

Access After Termination

If user has personal account linked:

  • Can still log in with personal email

  • Can access personal data (therapy sessions, anonymous reports)

  • Cannot access terminated tenant's data

  • Can still access other active tenant memberships

If user only has work identity (no personal account):

  • Cannot log in at all

  • Loses all access to the system

  • Data is retained but inaccessible to the user

Future Enhancement: Terminated users without personal accounts may be offered a paid personal subscription to retain access to their data and history.

Flow 6: User Joins New Company

When a user's new employer also uses the platform:

Flow 7: GDPR Deletion Request

When a user requests data deletion, the system performs a cascading de-identification across all linked accounts.

Legal Context: De-identified data that can never be mapped back to an individual may be retained. All personally identifiable information (PII) must be deleted.

Data Retention After Deletion

Data Type
Action
Reason

PII (name, email, gender, demographics)

Deleted

Required by GDPR

user_identities rows

Deleted

Contains email (PII)

FusionAuth users

Deleted

Contains auth credentials

users record

Anonymized

Preserved for FK integrity

Survey responses (anonymized)

Retained

De-identified aggregate data

Derived analytics

Retained

Cannot be traced to individual

Deletion Scope

The deletion cascades to all linked accounts:

Important: Users cannot selectively delete only their personal account while retaining work accounts. Deletion affects the entire identity graph.

Querying Linked Users

Helper Functions

Query Patterns

Get all data for a person across all their accounts:

Get data for a specific tenant context:

Personal vs Work Data

Data Ownership Model

Data Type
Owned By
Example

Survey responses

Work user_id

Responses to company surveys

HRIS data

Work user_id

Job title, department, manager

Backfill data

Work user_id

Historical data from integrations

Therapy sessions

Personal user_id

EAP provider usage

Personal resources

Personal user_id

Wellness resources accessed

Anonymous reports

Personal user_id

Workplace concern reports

Account settings

Primary user_id

Timezone, preferences

Privacy Boundary

Tenant admins can see (for their employees):

  • Survey responses (aggregated or individual per survey settings)

  • Training completions

  • Resource usage (aggregated counts)

Tenant admins CANNOT see:

  • Personal account data

  • Anonymous reports content

  • EAP/therapy usage details

  • Data from other tenants

Route-Based Data Access

Identity Resolution Flow

Complete flow when a request arrives:

Account Linking UI

Settings Page

Users can manage their linked accounts from settings:

Linking Flow UI

Notification Routing

Notifications are sent to the appropriate email based on context. There is no dedicated notification_email field on the users table—instead, routing is determined by the identity associated with the action.

Routing Logic

Notification Context Examples

Notification Type
Context
Email Used

Survey reminder

work

Work email for that tenant

HRIS sync complete

work

Work email for that tenant

New team member

work

Work email for that tenant

Therapy session reminder

personal

Personal email

Anonymous report update

personal

Personal email

Account security alert

personal

Primary identity email

Password reset

(auth)

Identity email used to log in

Why Not a Dedicated Field?

  1. Context-aware routing - Work notifications should go to work email, personal to personal

  2. No synchronization issues - Email always comes from the identity source of truth

  3. Privacy separation - Ensures work-related notifications don't leak to personal email

  4. Simpler data model - One less field to maintain and keep in sync

Best Practices

For HRIS Sync

  1. Always create user_identities first - The identity links email to user

  2. Set tenant_id on work identities - Tracks which tenant provisioned the identity

  3. Leave fusionauth_id NULL - It gets set on first authentication

  4. Check for existing identities - Avoid duplicates

For Authentication

  1. Resolve by fusionauth_id first - Most efficient lookup

  2. Fall back to email lookup - For first-time authentication

  3. Create personal account if no match - Self-registration flow

  4. Never delete user records - Only anonymize

For Data Queries

  1. Always use the correct user_id - Personal vs work context matters

  2. Use helper functions - getWorkUserIdForTenant, getPersonalUserId

  3. Consider linked accounts - When showing "all my data"

  4. Respect privacy boundaries - Personal data is personal

For Notifications

  1. Always specify context - work or personal determines routing

  2. Include tenantId for work context - Ensures correct work email is used

  3. Handle missing identities gracefully - Fallback chain ensures delivery

  4. Never hardcode email addresses - Always resolve from identities

Future Improvements

Structured Name Fields in Employee Data

Currently, name and email are stored on the users table and are user-controlled. For HRIS integrations, we should add structured name fields to employee_data:

  • first_name - Structured first name from HRIS

  • middle_name - Optional middle name

  • last_name - Structured last name from HRIS

  • display_name - Full/display name when HRIS only provides combined name

  • preferred_name - Nickname or preferred name (e.g., "Mike" instead of "Michael")

This would allow:

  1. users.name and users.email remain user-controlled (their account/login identity)

  2. employee_data name fields are tenant/HRIS-controlled (organizational directory)

  3. UI displays with fallback logic: preferredNamefirstNamedisplayNameusers.name

This separation ensures users control their authentication identity while organizations can maintain their own employee records.


Last updated: December 2025

Last updated