# 🔍 FLUX DÉTAILLÉ : Création d'un Fail avec Modération

## Scénario 1 : Contenu Approprié ✅

### Utilisateur crée un fail
```json
POST http://localhost:3000/api/fails
Authorization: Bearer <token>
{
  "title": "J'ai raté mon examen de maths",
  "description": "J'ai oublié de réviser et j'ai eu 5/20. Je me sens nul."
}
```

### Backend : failsController.js (ligne 44-108)

**Étape 1 : Validation basique**
```javascript
// Vérifier longueur titre (max 200)
// Vérifier longueur description (max 2000)
// ✅ OK
```

**Étape 2 : Modération OpenAI**
```javascript
const moderationResult = await moderationService.moderateFail({
  title: "J'ai raté mon examen de maths",
  description: "J'ai oublié de réviser et j'ai eu 5/20. Je me sens nul."
});
```

### Backend : moderationService.js (ligne 21-60)

**Étape 2.1 : Appel API OpenAI**
```javascript
POST https://api.openai.com/v1/moderations
Headers: {
  "Authorization": "Bearer sk-proj-xxx",
  "Content-Type": "application/json"
}
Body: {
  "input": "J'ai raté mon examen de maths\nJ'ai oublié de réviser et j'ai eu 5/20. Je me sens nul."
}
```

**Étape 2.2 : Réponse OpenAI (100ms)**
```json
{
  "id": "modr-xxx",
  "model": "text-moderation-007",
  "results": [
    {
      "flagged": false,
      "categories": {
        "hate": false,
        "harassment": false,
        "sexual": false,
        "violence": false,
        "self-harm": false
      },
      "category_scores": {
        "hate": 0.00001,
        "harassment": 0.00002,
        "sexual": 0.00001,
        "violence": 0.00003,
        "self-harm": 0.12345  // Un peu élevé ("je me sens nul") mais pas flaggé
      }
    }
  ]
}
```

**Étape 2.3 : Retour à failsController**
```javascript
moderationResult = {
  flagged: false,  // ✅ Contenu OK
  categories: { hate: false, harassment: false, ... },
  categoryScores: { hate: 0.00001, ... },
  bypass: false
}
```

### Backend : failsController.js (suite)

**Étape 3 : Vérification flagged**
```javascript
if (moderationResult.flagged && !moderationResult.bypass) {
  // ❌ BLOQUER
}
// ✅ flagged = false → CONTINUER
```

**Étape 4 : Création en base**
```sql
INSERT INTO fails (
  id, user_id, title, description, category, 
  is_anonyme, allow_comments, created_at, updated_at
) VALUES (
  'uuid-xxx',
  'user-123',
  'J''ai raté mon examen de maths',
  'J''ai oublié de réviser et j''ai eu 5/20. Je me sens nul.',
  'Général',
  0,
  1,
  NOW(),
  NOW()
);
```

**Étape 5 : Récompense points**
```sql
-- +10 points pour création fail
UPDATE user_points 
SET points_total = points_total + 10
WHERE user_id = 'user-123';
```

**Étape 6 : Réponse utilisateur**
```json
HTTP 201 Created
{
  "success": true,
  "fail": {
    "id": "uuid-xxx",
    "title": "J'ai raté mon examen de maths",
    "description": "J'ai oublié de réviser et j'ai eu 5/20. Je me sens nul.",
    "authorId": "user-123",
    "authorName": "Taaazzz",
    "reactions": { courage: 0, empathy: 0, laugh: 0, support: 0 },
    "commentsCount": 0,
    "createdAt": "2024-12-28T15:30:00.000Z"
  }
}
```

**Frontend : Affiche le fail** ✅

---

## Scénario 2 : Contenu Inapproprié ❌

### Utilisateur crée un fail avec haine

```json
POST http://localhost:3000/api/fails
{
  "title": "Je déteste tout le monde",
  "description": "Vous êtes tous des idiots, je vous méprise. Allez vous faire voir."
}
```

### Backend : failsController.js

**Étape 1 : Validation basique** → ✅ OK

**Étape 2 : Modération OpenAI**
```javascript
const moderationResult = await moderationService.moderateFail({
  title: "Je déteste tout le monde",
  description: "Vous êtes tous des idiots, je vous méprise. Allez vous faire voir."
});
```

### Backend : moderationService.js

**Appel API OpenAI**
```
Input: "Je déteste tout le monde\nVous êtes tous des idiots, je vous méprise. Allez vous faire voir."
```

**Réponse OpenAI (100ms)**
```json
{
  "results": [
    {
      "flagged": true,  // ⚠️ CONTENU DÉTECTÉ
      "categories": {
        "hate": true,           // ⚠️ Discours haineux
        "harassment": true,     // ⚠️ Harcèlement
        "sexual": false,
        "violence": false,
        "self-harm": false
      },
      "category_scores": {
        "hate": 0.89234,         // 89% de probabilité
        "harassment": 0.92156,   // 92% de probabilité
        "sexual": 0.00012,
        "violence": 0.03456,
        "self-harm": 0.00089
      }
    }
  ]
}
```

**Retour à failsController**
```javascript
moderationResult = {
  flagged: true,  // ❌ BLOQUÉ !
  categories: { hate: true, harassment: true, sexual: false, ... },
  categoryScores: { hate: 0.89, harassment: 0.92, ... },
  bypass: false
}
```

### Backend : failsController.js (ligne 80-108)

**Étape 3 : Vérification flagged**
```javascript
if (moderationResult.flagged && !moderationResult.bypass) {
  // ❌ BLOQUER !
  
  const flaggedCategories = Object.entries(moderationResult.categories)
    .filter(([_, value]) => value)
    .map(([key]) => key);
  // flaggedCategories = ['hate', 'harassment']
  
  // Log dans system_logs
  await logSystem({
    level: 'warn',
    action: 'fail_blocked_moderation',
    message: 'Fail bloqué par modération automatique',
    details: {
      userId: 'user-123',
      title: 'Je déteste tout le monde',
      categories: ['hate', 'harassment']
    },
    userId: 'user-123'
  });
  
  // Retourner erreur 400
  return res.status(400).json({
    success: false,
    message: 'Contenu inapproprié détecté. Votre publication ne respecte pas nos règles de communauté.',
    moderationCategories: ['hate', 'harassment']
  });
}
```

**Base de données : system_logs**
```sql
INSERT INTO system_logs (
  level, action, message, details, user_id, created_at
) VALUES (
  'warn',
  'fail_blocked_moderation',
  'Fail bloqué par modération automatique',
  '{"userId":"user-123","title":"Je déteste tout le monde","categories":["hate","harassment"]}',
  'user-123',
  '2024-12-28 15:30:00'
);
```

**Réponse utilisateur**
```json
HTTP 400 Bad Request
{
  "success": false,
  "message": "Contenu inapproprié détecté. Votre publication ne respecte pas nos règles de communauté.",
  "moderationCategories": ["hate", "harassment"]
}
```

**Frontend : Toast d'erreur**
```
❌ Échec de création
Contenu inapproprié détecté. Votre publication ne respecte pas nos règles de communauté.
```

**Base de données : Rien créé** (fail bloqué avant insertion)

---

## Scénario 3 : API OpenAI Hors Ligne (Graceful Degradation)

### Backend : moderationService.js

**Appel API échoue**
```javascript
try {
  const response = await axios.post(...);
} catch (error) {
  console.error('❌ Erreur modération OpenAI:', error.message);
  // En cas d'erreur API, on laisse passer (éviter blocage)
  return { 
    flagged: false,  // ⚠️ BYPASS
    categories: {}, 
    error: true, 
    bypass: true     // Flag pour indiquer bypass
  };
}
```

**Retour à failsController**
```javascript
moderationResult = {
  flagged: false,
  categories: {},
  error: true,
  bypass: true  // API offline, on autorise par sécurité
}

if (moderationResult.flagged && !moderationResult.bypass) {
  // bypass = true → Condition false → CONTINUER
}
```

**Résultat** : Fail créé normalement (mode dégradé, modération manuelle uniquement)

---

## 🎚️ Réglages Possibles

### Ajuster la Sensibilité

Dans `moderationService.js`, tu peux modifier la logique :

**Actuel** :
```javascript
if (result.flagged) {
  // Bloque si OpenAI flag
}
```

**Plus strict** :
```javascript
// Bloquer si score hate > 50% même sans flag
const hateScore = result.category_scores.hate;
if (result.flagged || hateScore > 0.5) {
  // Bloque
}
```

**Plus permissif** :
```javascript
// Bloquer uniquement hate + harassment ensemble
const isHate = result.categories.hate;
const isHarassment = result.categories.harassment;
if (isHate && isHarassment) {
  // Bloque seulement si les 2 catégories
}
```

---

## 📊 Monitoring en Temps Réel

### Dashboard Admin (à venir)

Ajouter dans le panel admin une section "Modération" :

```sql
-- Fails bloqués aujourd'hui
SELECT COUNT(*) as blocked_today
FROM system_logs
WHERE DATE(created_at) = CURDATE()
  AND action = 'fail_blocked_moderation';

-- Top catégories flaggées
SELECT 
  JSON_EXTRACT(details, '$.categories') as categories,
  COUNT(*) as count
FROM system_logs
WHERE action IN ('fail_blocked_moderation', 'comment_blocked_moderation')
GROUP BY categories
ORDER BY count DESC
LIMIT 10;
```

---

## ⚡ Performances

| Opération | Temps |
|-----------|-------|
| Validation basique | ~1ms |
| Appel OpenAI API | ~100ms |
| Insertion base | ~5ms |
| **Total création fail** | **~110ms** |

Sans modération : ~10ms  
Avec modération : ~110ms  
**Overhead : +100ms** (acceptable)

---

## 🔐 Sécurité

### Que se passe-t-il si un utilisateur contourne ?

**Impossible de contourner** :
- La modération est **côté backend** (pas frontend)
- Impossible d'appeler directement la base de données
- JWT vérifié avant chaque requête
- Validation système avant tout insert

**Tentatives de contournement** :
- Modifier requête frontend → ❌ Backend valide quand même
- Appeler API directement → ❌ JWT requis
- Injecter SQL → ❌ Requêtes préparées (protection injection)

---

## 🎯 Prochaines Améliorations

1. **Blacklist complémentaire** (instant, avant OpenAI) :
   ```javascript
   const blacklist = ['connard', 'salope', ...];
   if (containsBlacklistWord(text)) return { flagged: true };
   ```

2. **Cache Redis** (éviter re-modérer même texte) :
   ```javascript
   const hash = crypto.createHash('md5').update(text).digest('hex');
   const cached = await redis.get(`moderation:${hash}`);
   if (cached) return JSON.parse(cached);
   ```

3. **Queue asynchrone** (modération différée si non urgent) :
   ```javascript
   await queue.add('moderate-fail', { failId, text });
   ```

---

**Conclusion** : La modération fonctionne en **temps réel**, **gratuitement**, avec **100ms de latence**, et **bloque efficacement** les contenus inappropriés avant qu'ils n'atteignent la base de données. 🚀
