# Type Sharing Strategy

This document explains how types are shared between the frontend and backend in the Mosaic Stack monorepo.

## Overview

All types that are used by both frontend and backend live in the `@mosaic/shared` package. This ensures:

- **Type safety** across the entire stack
- **Single source of truth** for data structures
- **Automatic type updates** when the API changes
- **Reduced duplication** and maintenance burden

## Package Structure

```
packages/shared/
├── src/
│   ├── types/
│   │   ├── index.ts              # Main export file
│   │   ├── enums.ts              # Shared enums (TaskStatus, etc.)
│   │   ├── database.types.ts     # Database entity types
│   │   └── auth.types.ts         # Authentication types (NEW)
│   ├── utils/
│   └── constants.ts
└── package.json
```

## Authentication Types

### Shared Types (`@mosaic/shared`)

These types are used by **both** frontend and backend:

#### `AuthUser`

The authenticated user object that's safe to expose to clients.

```typescript
interface AuthUser {
  readonly id: string;
  email: string;
  name: string;
  image?: string;
  emailVerified?: boolean;
}
```

#### `AuthSession`

Session data returned after successful authentication.

```typescript
interface AuthSession {
  user: AuthUser;
  session: {
    id: string;
    token: string;
    expiresAt: Date;
  };
}
```

#### `Session`, `Account`

Full database entity types for sessions and OAuth accounts.

#### `LoginRequest`, `LoginResponse`

Request/response payloads for authentication endpoints.

#### `OAuthProvider`

Supported OAuth providers: `"authentik" | "google" | "github"`

#### `OAuthCallbackParams`

Query parameters from OAuth callback redirects.

### Backend-Only Types

Types that are only used by the backend stay in `apps/api/src/auth/types/`:

#### `BetterAuthRequest`

Internal type for BetterAuth handler compatibility (extends web standard `Request`).

**Why backend-only?** This is an implementation detail of how NestJS integrates with BetterAuth. The frontend doesn't need to know about it.

## Usage Examples

### In the Backend (API)

```typescript
// apps/api/src/auth/auth.controller.ts
import { AuthUser } from "@mosaic/shared";

@Get("profile")
@UseGuards(AuthGuard)
getProfile(@CurrentUser() user: AuthUser) {
  return {
    id: user.id,
    email: user.email,
    name: user.name,
  };
}
```

### In the Frontend (Web)

```typescript
// apps/web/app/components/UserProfile.tsx
import type { AuthUser } from "@mosaic/shared";

export function UserProfile({ user }: { user: AuthUser }) {
  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
      {user.emailVerified && <Badge>Verified</Badge>}
    </div>
  );
}
```

### API Response Types

```typescript
// Both FE and BE can use this
import type { ApiResponse, AuthSession } from "@mosaic/shared";

// Backend returns this
const response: ApiResponse<AuthSession> = {
  success: true,
  data: {
    user: { id: "...", email: "...", name: "..." },
    session: { id: "...", token: "...", expiresAt: new Date() },
  },
};

// Frontend consumes this
async function login(email: string, password: string) {
  const response = await fetch("/api/auth/login", {
    method: "POST",
    body: JSON.stringify({ email, password }),
  });

  const data: ApiResponse<AuthSession> = await response.json();

  if (data.success) {
    // TypeScript knows data.data exists and is AuthSession
    saveSession(data.data);
  }
}
```

## Database Types

The `@mosaic/shared` package also exports database entity types that match the Prisma schema:

- `User` - Full user entity (includes all fields from DB)
- `Workspace`, `Task`, `Event`, `Project` - Other entities
- Enums: `TaskStatus`, `TaskPriority`, `ProjectStatus`, etc.

### Key Difference: `User` vs `AuthUser`

| Type       | Purpose                    | Fields                                    | Used By                 |
| ---------- | -------------------------- | ----------------------------------------- | ----------------------- |
| `User`     | Full database entity       | All DB fields including sensitive data    | Backend internal logic  |
| `AuthUser` | Safe client-exposed subset | Only public fields (no preferences, etc.) | API responses, Frontend |

**Example:**

```typescript
// Backend internal logic
import { User } from "@mosaic/shared";

async function updateUserPreferences(userId: string, prefs: User["preferences"]) {
  // Has access to all fields including preferences
}

// API response
import { AuthUser } from "@mosaic/shared";

function sanitizeUser(user: User): AuthUser {
  return {
    id: user.id,
    email: user.email,
    name: user.name,
    image: user.image,
    emailVerified: user.emailVerified,
  };
  // Preferences and other sensitive fields are excluded
}
```

## Adding New Shared Types

When adding new types that should be shared:

1. **Determine if it should be shared:**
   - ✅ API request/response payloads
   - ✅ Database entity shapes
   - ✅ Business domain types
   - ✅ Enums and constants
   - ❌ Backend-only implementation details
   - ❌ Frontend-only UI component props

2. **Add to the appropriate file:**
   - Database entities → `database.types.ts`
   - Auth-related → `auth.types.ts`
   - Enums → `enums.ts`
   - General API types → `index.ts`

3. **Export from `index.ts`:**

   ```typescript
   export * from "./your-new-types";
   ```

4. **Build the shared package:**

   ```bash
   cd packages/shared
   pnpm build
   ```

5. **Use in your apps:**
   ```typescript
   import { YourType } from "@mosaic/shared";
   ```

## Type Versioning

Since this is a monorepo, all packages use the same version of `@mosaic/shared`. When you:

1. **Change a shared type** - Both FE and BE automatically get the update
2. **Add a new field** - TypeScript will show errors where the field is missing
3. **Remove a field** - TypeScript will show errors where the field is still used

This ensures the frontend and backend never drift out of sync.

## Benefits

### Type Safety

```typescript
// If the backend changes AuthUser.name to AuthUser.displayName,
// the frontend will get TypeScript errors everywhere AuthUser is used.
// You'll fix all uses before deploying.
```

### Auto-Complete

```typescript
// Frontend developers get full autocomplete for API types
const user: AuthUser = await fetchUser();
user. // <-- IDE shows: id, email, name, image, emailVerified
```

### Refactoring

```typescript
// Rename a field? TypeScript finds all usages across FE and BE
// No need to grep or search manually
```

### Documentation

```typescript
// The types ARE the documentation
// Frontend developers see exactly what the API returns
```

## Current Shared Types

### Authentication (`auth.types.ts`)

- `AuthUser` - Authenticated user info
- `AuthSession` - Session data
- `Session` - Full session entity
- `Account` - OAuth account entity
- `LoginRequest`, `LoginResponse`
- `OAuthProvider`, `OAuthCallbackParams`

### Database Entities (`database.types.ts`)

- `User` - Full user entity
- `Workspace`, `WorkspaceMember`
- `Task`, `Event`, `Project`
- `ActivityLog`, `MemoryEmbedding`

### Enums (`enums.ts`)

- `TaskStatus`, `TaskPriority`
- `ProjectStatus`
- `WorkspaceMemberRole`
- `ActivityAction`, `EntityType`

### API Utilities (`index.ts`)

- `ApiResponse<T>` - Standard response wrapper
- `PaginatedResponse<T>` - Paginated data
- `HealthStatus` - Health check format

---

**Remember:** If a type is used by both frontend and backend, it belongs in `@mosaic/shared`. If it's only used by one side, keep it local to that application.
