# DTMC (Digital Team Member Card) Flow Documentation

## Overview

The DTMC feature allows existing Scandic Friends members to link their employee
status to their account by authenticating with Microsoft Entra ID.
This provides employees access to additional benefits.

## Current Implementation Architecture

### Separate Auth Configuration Approach

We use a completely separate auth configuration to avoid session conflicts between:

- **Curity**: `auth.ts`
  - Regular user authentication.
- **DTMC Auth**: `auth.dtmc.ts`
  - Short-lived (10min) session specifically for employee verification.

### Key Files & Responsibilities

#### Flow Handlers

- `app/[lang]/(live)/(public)/dtmc/route.ts`
  - Microsoft auth initiation.
- `app/api/web/auth/dtmc/route.ts`
  - Employee linking callback handler with API integration.

#### Core Authentication

- `auth.dtmc.ts`
  - Microsoft Entra ID provider configuration, JWT/session callbacks.
- `app/api/web/auth/[...nextauth]/route.ts`
  - Routes Microsoft requests to DTMC handlers.

#### API Integration

- `packages/trpc/lib/api/endpoints.ts`
  - API endpoint definitions including TeamMemberCard.
- `server/routers/user/output.ts`
  - Profile schema with employmentDetails.
- `utils/user.ts`
  - Employment utility functions.

#### UI Components

- `apps/scandic-web/components/MyPages/DigitalTeamMemberCard/index.tsx`
  - Main card component.
- `apps/scandic-web/components/MyPages/DigitalTeamMemberCard/Alert/index.tsx`
  - Banner shown on the overview page for employee's who have just linked their account.

#### Configuration

- `constants/routes/dtmc.ts` - Route definitions
- `components/DigitalTeamMemberCard/EmployeeBenefits/CallToActions/index.tsx`
  - "Link Employment" buttons used within the Employee Benefits page
    (a Contentstack "content page") to initiate the linking process.

## Technical Flow

### 1. User Journey

```
User (Curity authenticated) → Employee Benefits page → "Link Employment" button →
Microsoft Auth → Employee ID extraction → API linking → Success redirect
```

### 2. Detailed Technical Sequence

```mermaid
sequenceDiagram
    participant U as User
    participant C as Curity Session
    participant D as DTMC Route
    participant M as Microsoft Auth
    participant J as JWT Callback
    participant S as Session Callback
    participant H as DTMC Handler
    participant A as Employee API

    U->>C: Already authenticated (Curity)
    U->>D: Click "Link Employment" → /[lang]/dtmc
    D->>M: signIn("microsoft-entra-id")
    M->>U: Microsoft login prompt
    U->>M: Authenticate with corporate credentials
    M->>J: Profile with user.employeeid
    J->>J: Store employeeId directly in token
    J->>S: Expose as session.employeeId
    S->>H: Callback to /api/web/auth/dtmc
    H->>H: Validate both Curity + DTMC sessions
    H->>A: Call linkEmployeeToUser(employeeId)
    A->>H: Success response
    H->>U: Redirect to overview with success banner
```

### 3. Code Implementation Details

#### DTMC Auth Configuration (`auth.dtmc.ts`)

```typescript
// Separate session cookie to avoid conflicts
cookies: {
  sessionToken: {
    name: "dtmc.session-token",
  },
}

// Short-lived session for security
session: {
  strategy: "jwt",
  maxAge: 10 * 60, // 10 minutes
}

// Storage of employeeId
jwt({ account, profile, token }) {
  if (account?.provider === "microsoft-entra-id") {
    const employeeId = profile["user.employeeid"]
    return {
      access_token: "", // Empty to save cookie size
      loginType: "dtmc",
      employeeId,
    }
  }
}
```

#### Route Routing (`[...nextauth]/route.ts`)

Routes Microsoft requests to DTMC handlers by checking if the pathname contains "microsoft-entra-id".

#### Auth Initiation (`/dtmc/route.ts`)

```typescript
// Starts Microsoft signin with callback redirect
const redirectUrl = await signIn(
  "microsoft-entra-id",
  {
    redirectTo: `${env.PUBLIC_URL}${dtmcApiCallback}`,
    redirect: false,
  },
  {
    prompt: "login",
  }
)
```

#### Callback Handler (`/api/web/auth/dtmc/route.ts`)

```typescript
// Validates dual sessions and processes linking
const dtmcSession = await dtmcAuth() // Microsoft session
const session = await auth() // Curity session

// Both sessions required for security
if (!isValidSession(session) || !isValidSession(dtmcSession)) {
  // Redirect to error page
}

const employeeId = dtmcSession.employeeId
await linkEmployeeToUser(employeeId, accessToken)
```

## Routes & URLs

### User-Facing Routes

- `/[lang]/dtmc` - Microsoft auth initiation
- `/[lang]/link-employment-error` - Error handling page
- `/[lang]/employee-benefits` - Employee benefits overview

### API Routes

- `/api/web/auth/dtmc` - Employee linking callback handler
- `/api/web/auth/[...nextauth]` - NextAuth routing (handles Microsoft provider)

## API Integration Details

### TeamMemberCard Endpoint

```typescript
// Added to packages/trpc/lib/api/endpoints.ts
export namespace v2 {
  export namespace Profile {
    export function teamMemberCard(employeeId: string) {
      return `${profile}/${employeeId}/TeamMemberCard`
    }
  }
}
```

### Profile Schema Extension

```typescript
// Added to server/routers/user/output.ts
export const employmentDetailsSchema = z
  .object({
    employeeId: z.string(),
    location: z.string(),
    country: z.string(),
    retired: z.boolean(),
  })
  .optional()
```

### Employee Utility Functions

```typescript
// Added to utils/user.ts
export function isEmployeeLinked(user: User): boolean
export function getEmployeeInfo(user: User)
export function canUseEmployeeBenefits(user: User): boolean
```

### Status Code Handling

- **200/202**: Success → Continue to overview page
- **400/404**: Client errors → "unable_to_verify_employee_id" error page
- **500**: Server error → Default error message
- **Network errors**: → Default error message

## Digital Team Member Card Behavior

```typescript
// Current implementation
const hasEmploymentData = isEmployeeLinked(user)

if (!hasEmploymentData) {
  return null
}
return <DigitalTeamMemberCardClient user={user} />
```

## Testing Checklist

### Happy Path

- [x] User has valid Curity session
- [x] Microsoft auth extracts employee ID successfully
- [x] Both sessions validated in callback handler
- [x] Employee linking API call succeeds
- [x] User redirected to overview with success banner
- [x] Original Curity session remains functional
- [x] Digital Team Member Card displays with employment data

### Error Scenarios

- [x] Missing Curity session during flow
- [x] Microsoft auth failure/cancellation
- [x] Missing employee ID in Microsoft profile
- [x] Employee API failure scenarios
- [x] DTMC session expiration
- [x] Status code mapping (400/404/500/network errors)

### Security Validation

- [x] No employee ID in browser network logs
- [x] No employee ID in URL parameters
- [x] Dual session architecture working
- [x] Proper session validation in callback
- [x] Short-lived DTMC session (10 minutes) for security

### UI/UX Validation

- [x] Card shows real data when employment details exist
- [x] Proper fallbacks for missing employment data fields
