# Fix - Création de salarié en mode Staff

## 🐛 Problème identifié

En mode staff, lors de la création d'un nouveau salarié, l'erreur `no_organization` apparaissait même après avoir sélectionné une organisation dans le menu déroulant.

### Cause racine

La fonction `resolveActiveOrg()` retourne `null` pour les utilisateurs staff (comportement attendu), mais l'API `/api/salaries` POST rejetait toute demande avec un `null`, même quand l'utilisateur staff fournissait un `employer_id` valide dans le body de la requête.

La logique de sécurité ne distinguait pas :
- **Utilisateurs clients** : doivent avoir une organisation associée via `organization_members`
- **Utilisateurs staff** : peuvent créer des salariés pour n'importe quelle organisation en fournissant un `employer_id`

## ✅ Solution implémentée

### Modifications dans `/app/api/salaries/route.ts`

La logique de sécurité a été réorganisée pour gérer les deux cas différemment :

#### 1. Vérification du statut staff en premier

```typescript
// 🔒 SÉCURITÉ : Vérifier si l'utilisateur est staff
let isStaff = false;
try {
  const { data: staffRow } = await sbAuth.from('staff_users').select('is_staff').eq('user_id', user.id).maybeSingle();
  isStaff = !!staffRow?.is_staff;
} catch {
  // Fallback sur metadata
  const userMeta = user?.user_metadata || {};
  const appMeta = user?.app_metadata || {};
  isStaff = Boolean((userMeta.is_staff === true || userMeta.role === 'staff') || (Array.isArray(appMeta.roles) && appMeta.roles.includes('staff')));
}
```

#### 2. Logique différenciée selon le type d'utilisateur

**Pour les utilisateurs STAFF :**
```typescript
if (isStaff) {
  // Accepter l'employer_id fourni dans la requête
  orgId = body.employer_id || null;
  
  if (!orgId) {
    return NextResponse.json(
      { ok: false, error: 'no_organization', message: 'Vous devez sélectionner une organisation' },
      { status: 400 }
    );
  }
  
  // Vérifier que l'organisation existe
  const { data: orgExists } = await sbAuth
    .from('organizations')
    .select('id')
    .eq('id', orgId)
    .maybeSingle();
  
  if (!orgExists) {
    return NextResponse.json(
      { ok: false, error: 'invalid_organization', message: 'Organisation introuvable' },
      { status: 404 }
    );
  }
}
```

**Pour les utilisateurs CLIENTS :**
```typescript
else {
  // Utiliser l'organisation associée à l'utilisateur
  const userOrgId = await resolveActiveOrg(sbAuth);
  
  if (!userOrgId) {
    return NextResponse.json(
      { ok: false, error: 'no_organization', message: 'Aucune organisation associée à votre compte' },
      { status: 403 }
    );
  }

  // 🔒 SÉCURITÉ CRITIQUE : Vérifier que l'employer_id fourni correspond à l'org de l'utilisateur
  if (body.employer_id && body.employer_id !== userOrgId) {
    return NextResponse.json(
      { ok: false, error: 'unauthorized_organization', message: 'Vous ne pouvez pas créer un salarié dans cette organisation' },
      { status: 403 }
    );
  }
  
  orgId = userOrgId;
}
```

#### 3. Logs améliorés

```typescript
console.log('✅ [SÉCURITÉ] Vérifications réussies');
console.log('   - Utilisateur:', user.email);
console.log('   - Type:', isStaff ? 'STAFF' : 'CLIENT');
console.log('   - Organisation:', orgId);
console.log('   - Email salarié validé:', body.email_salarie);
console.log('   - Rate limit:', `${rateLimitMap.get(user.id)?.count || 0}/${RATE_LIMIT_MAX}`);
```

## 🔒 Sécurité

### Garanties maintenues

1. **Utilisateurs clients** : Ne peuvent créer des salariés **QUE** dans leur propre organisation
2. **Utilisateurs staff** : Peuvent créer des salariés pour n'importe quelle organisation, mais :
   - Doivent obligatoirement sélectionner une organisation (pas de création sans org)
   - L'organisation doit exister dans la base de données
3. **Rate limiting** : Toujours en place (50 créations/heure par utilisateur)
4. **Authentification** : Requise pour tous les utilisateurs

### Erreurs possibles

| Code d'erreur | Status | Cas |
|---------------|--------|-----|
| `unauthorized` | 401 | Utilisateur non authentifié |
| `rate_limit_exceeded` | 429 | Limite de 50 créations/heure dépassée |
| `no_organization` | 400 (staff) / 403 (client) | Aucune organisation sélectionnée ou associée |
| `invalid_organization` | 404 | Organisation sélectionnée introuvable (staff) |
| `unauthorized_organization` | 403 | Tentative de créer un salarié dans une autre org (client) |

## 🧪 Tests à effectuer

### Test 1 : Staff - Création avec organisation valide
```bash
# En tant que staff, sélectionner une organisation et créer un salarié
✓ Devrait réussir
✓ Le salarié devrait être associé à l'organisation sélectionnée
```

### Test 2 : Staff - Création sans sélectionner d'organisation
```bash
# En tant que staff, ne pas sélectionner d'organisation
✗ Devrait échouer avec "no_organization" (400)
```

### Test 3 : Staff - Création avec organisation inexistante
```bash
# Manuellement envoyer un employer_id invalide
✗ Devrait échouer avec "invalid_organization" (404)
```

### Test 4 : Client - Création normale
```bash
# En tant que client, créer un salarié
✓ Devrait réussir
✓ Le salarié devrait être dans l'organisation du client
```

### Test 5 : Client - Tentative de création dans une autre org
```bash
# Manuellement envoyer un employer_id d'une autre organisation
✗ Devrait échouer avec "unauthorized_organization" (403)
```

## 📝 Fichiers modifiés

- `/app/api/salaries/route.ts` - Logique de sécurité réorganisée

## 📝 Fichiers non modifiés (déjà corrects)

- `/app/(app)/salaries/nouveau/page.tsx` - Frontend déjà correct
  - Charge la liste des organisations pour les staff
  - Envoie `employer_id` quand staff ET organisation sélectionnée
  - Validation client-side : `const orgOk = !isStaff || (isStaff && selectedOrg !== null);`

## ✨ Améliorations futures possibles

1. Ajouter un cache pour les vérifications staff (éviter une requête DB à chaque création)
2. Ajouter un audit log des créations de salariés par staff dans d'autres organisations
3. Permettre aux staff de créer des salariés dans plusieurs organisations en batch
