NeahNew/AUDIT_API_N8N_CONNECTION.md
2026-01-08 09:34:10 +01:00

20 KiB

🔍 Audit Développeur Senior - Connexion API Next.js ↔️ N8N (Missions)

Date: $(date)
Auteur: Audit Développeur Senior
Objectif: Vérifier et documenter la connexion entre Next.js et N8N pour la gestion des missions


📋 Table des Matières

  1. Architecture Globale
  2. Flux de Communication
  3. Endpoints API
  4. Configuration Requise
  5. Sécurité
  6. Points Critiques à Vérifier
  7. Problèmes Potentiels et Solutions
  8. Tests et Validation
  9. Recommandations

🏗️ Architecture Globale

Vue d'ensemble

┌─────────────┐         ┌─────────────┐         ┌─────────────┐
│   Next.js   │────────▶│     N8N     │────────▶│  Intégrations│
│   (API)     │         │  (Workflow) │         │  (Gitea, etc)│
└─────────────┘         └─────────────┘         └─────────────┘
      │                         │
      │                         │
      └─────────────────────────┘
            (Callback)

Composants Principaux

  1. Next.js API Routes

    • POST /api/missions - Création de mission
    • POST /api/missions/mission-created - Callback de N8N
    • GET /api/missions - Liste des missions
  2. Service N8N (lib/services/n8n-service.ts)

    • Envoi de données vers N8N
    • Gestion des webhooks
    • Gestion des erreurs
  3. N8N Workflows

    • Webhook de réception: /webhook/mission-created
    • Création des intégrations externes
    • Callback vers Next.js

🔄 Flux de Communication

1. Création d'une Mission (Next.js → N8N → Next.js)

┌─────────────────────────────────────────────────────────────────┐
│ ÉTAPE 1: Création Mission dans Next.js                          │
└─────────────────────────────────────────────────────────────────┘
POST /api/missions
  ↓
1. Validation des données
2. Création en base de données (Prisma)
3. Upload des fichiers (logo, attachments) vers Minio
4. Vérification des fichiers
  ↓
┌─────────────────────────────────────────────────────────────────┐
│ ÉTAPE 2: Envoi vers N8N                                         │
└─────────────────────────────────────────────────────────────────┘
POST https://brain.slm-lab.net/webhook/mission-created
Headers:
  - Content-Type: application/json
  - x-api-key: {N8N_API_KEY}
Body:
  {
    missionId: "uuid",
    name: "...",
    oddScope: [...],
    services: [...],
    config: {
      N8N_API_KEY: "...",
      MISSION_API_URL: "https://api.slm-lab.net/api"
    },
    ...
  }
  ↓
┌─────────────────────────────────────────────────────────────────┐
│ ÉTAPE 3: Traitement N8N                                         │
└─────────────────────────────────────────────────────────────────┘
N8N Workflow:
  1. Réception webhook
  2. Création Gitea repository (si service "Gite")
  3. Création Leantime project (si service "Leantime")
  4. Création Outline collection (si service "Documentation")
  5. Création RocketChat channel (si service "RocketChat")
  6. Préparation des données de callback
  ↓
┌─────────────────────────────────────────────────────────────────┐
│ ÉTAPE 4: Callback N8N → Next.js                                  │
└─────────────────────────────────────────────────────────────────┘
POST {MISSION_API_URL}/api/missions/mission-created
Headers:
  - Content-Type: application/json
  - x-api-key: {N8N_API_KEY} (depuis config.N8N_API_KEY)
Body:
  {
    missionId: "uuid",
    gitRepoUrl: "...",
    leantimeProjectId: "...",
    documentationCollectionId: "...",
    rocketchatChannelId: "..."
  }
  ↓
┌─────────────────────────────────────────────────────────────────┐
│ ÉTAPE 5: Mise à jour Mission dans Next.js                       │
└─────────────────────────────────────────────────────────────────┘
Validation API key
Recherche mission par missionId
Mise à jour des champs d'intégration:
  - giteaRepositoryUrl
  - leantimeProjectId
  - outlineCollectionId
  - rocketChatChannelId

🔌 Endpoints API

1. POST /api/missions

Fichier: app/api/missions/route.ts

Fonction: Créer une nouvelle mission et déclencher le workflow N8N

Authentification:

  • Session utilisateur requise (via getServerSession)
  • Vérification: checkAuth(request)

Body attendu:

{
  name: string;
  oddScope: string[];
  niveau?: string;
  intention?: string;
  missionType?: string;
  services?: string[];
  guardians?: Record<string, string>;
  volunteers?: string[];
  logo?: { data: string; name?: string; type?: string };
  attachments?: Array<{ data: string; name?: string; type?: string }>;
}

Réponse:

{
  "success": true,
  "mission": { ... },
  "message": "Mission created successfully with all integrations"
}

Points critiques:

  • Mission créée en base AVANT l'envoi à N8N
  • Fichiers uploadés et vérifiés AVANT l'envoi à N8N
  • missionId inclus dans les données envoyées à N8N
  • config.N8N_API_KEY et config.MISSION_API_URL inclus

2. POST /api/missions/mission-created

Fichier: app/api/missions/mission-created/route.ts

Fonction: Recevoir les IDs d'intégration de N8N et mettre à jour la mission

Authentification:

  • API Key via header x-api-key
  • PAS de session utilisateur requise (N8N n'a pas de session)

Headers requis:

x-api-key: {N8N_API_KEY}
Content-Type: application/json

Body attendu:

{
  missionId: string;  // ✅ Préféré (plus fiable)
  // OU (fallback pour compatibilité)
  name: string;
  creatorId: string;
  
  // IDs d'intégration (optionnels)
  gitRepoUrl?: string;
  leantimeProjectId?: string | number;
  documentationCollectionId?: string;
  rocketchatChannelId?: string;
}

Réponse succès:

{
  "success": true,
  "message": "Mission updated successfully",
  "mission": {
    "id": "...",
    "name": "...",
    "giteaRepositoryUrl": "...",
    "leantimeProjectId": "...",
    "outlineCollectionId": "...",
    "rocketChatChannelId": "..."
  }
}

Codes d'erreur:

  • 401 - API key invalide ou manquante
  • 400 - Champs requis manquants
  • 404 - Mission non trouvée
  • 500 - Erreur serveur

Points critiques:

  • Validation stricte de l'API key
  • Recherche par missionId (préféré) ou name + creatorId (fallback)
  • Conversion leantimeProjectId de number vers string si nécessaire
  • Mise à jour uniquement des champs fournis

⚙️ Configuration Requise

Variables d'Environnement

1. N8N_API_KEY (OBLIGATOIRE)

N8N_API_KEY=LwgeE1ntADD20OuWC88S3pR0EaO7FtO4

Usage:

  • Envoyé à N8N dans config.N8N_API_KEY
  • N8N l'utilise pour authentifier le callback
  • Vérifié côté serveur dans /api/missions/mission-created

Où configurer:

  • .env.local (développement)
  • Variables d'environnement production (CapRover, Vercel, Docker, etc.)

Vérification:

// Erreur si non défini
if (!process.env.N8N_API_KEY) {
  logger.error('N8N_API_KEY is not set in environment variables');
}

2. N8N_WEBHOOK_URL (Optionnel)

N8N_WEBHOOK_URL=https://brain.slm-lab.net/webhook/mission-created

Valeur par défaut: https://brain.slm-lab.net/webhook/mission-created

Usage: URL du webhook N8N pour la création de mission


3. NEXT_PUBLIC_API_URL (Recommandé)

NEXT_PUBLIC_API_URL=https://api.slm-lab.net/api

Usage:

  • Envoyé à N8N dans config.MISSION_API_URL
  • N8N l'utilise pour construire l'URL du callback
  • Format attendu: {MISSION_API_URL}/api/missions/mission-created

Valeur par défaut: https://api.slm-lab.net/api


4. N8N_ROLLBACK_WEBHOOK_URL (Optionnel)

N8N_ROLLBACK_WEBHOOK_URL=https://brain.slm-lab.net/webhook/mission-rollback

Usage: URL du webhook N8N pour le rollback de mission


Configuration N8N Workflow

Webhook de Réception

Path: mission-created
URL complète: https://brain.slm-lab.net/webhook/mission-created
Méthode: POST
Status: Doit être ACTIF (toggle vert dans N8N)


Node "Save Mission To API"

URL:

{{ $node['Process Mission Data'].json.config.MISSION_API_URL }}/api/missions/mission-created

Méthode: POST

Headers:

Content-Type: application/json
x-api-key: {{ $node['Process Mission Data'].json.config.N8N_API_KEY }}

Body:

{
  "missionId": "{{ $node['Process Mission Data'].json.missionId }}",
  "gitRepoUrl": "{{ $node['Create Git Repo'].json.url }}",
  "leantimeProjectId": "{{ $node['Create Leantime Project'].json.id }}",
  "documentationCollectionId": "{{ $node['Create Outline Collection'].json.id }}",
  "rocketchatChannelId": "{{ $node['Create RocketChat Channel'].json.id }}"
}

Points critiques:

  • Utiliser config.MISSION_API_URL (pas d'URL en dur)
  • Utiliser config.N8N_API_KEY (pas de clé en dur)
  • Inclure missionId dans le body
  • Inclure tous les IDs d'intégration créés

🔒 Sécurité

1. Authentification API Key

Mécanisme:

  • N8N envoie x-api-key header
  • Next.js compare avec process.env.N8N_API_KEY
  • Si différent → 401 Unauthorized

Code de validation (app/api/missions/mission-created/route.ts:42):

const apiKey = request.headers.get('x-api-key');
const expectedApiKey = process.env.N8N_API_KEY;

if (apiKey !== expectedApiKey) {
  logger.error('Invalid API key', {
    received: apiKey ? 'present' : 'missing',
    expected: expectedApiKey ? 'configured' : 'missing'
  });
  return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}

Points critiques:

  • Comparaison stricte (pas de hash, clé en clair)
  • Logging des tentatives invalides
  • Pas de fallback si clé manquante

2. Transmission de la Clé API

Flux:

  1. Next.js lit process.env.N8N_API_KEY
  2. Next.js envoie à N8N dans config.N8N_API_KEY
  3. N8N stocke temporairement dans le workflow
  4. N8N renvoie dans header x-api-key lors du callback

Risque: Si N8N_API_KEY est undefined au moment de l'envoi:

  • N8N reçoit undefined ou chaîne vide
  • N8N envoie chaîne vide dans le header
  • Next.js rejette avec 401

Solution: Vérifier que N8N_API_KEY est défini avant l'envoi à N8N


3. Validation des Données

Côté Next.js:

  • Validation des champs requis
  • Recherche de mission par missionId (plus sûr que name + creatorId)
  • Conversion de types (number → string pour leantimeProjectId)

Côté N8N:

  • ⚠️ Pas de validation visible dans le code Next.js
  • ⚠️ N8N doit valider les données avant création des intégrations

⚠️ Points Critiques à Vérifier

1. Configuration Environnement

  • N8N_API_KEY est défini dans l'environnement
  • N8N_API_KEY a la même valeur partout (dev, staging, prod)
  • NEXT_PUBLIC_API_URL pointe vers la bonne URL
  • Application redémarrée après modification des variables

2. Workflow N8N

  • Workflow est ACTIF (toggle vert)
  • Webhook path est correct: mission-created
  • Node "Save Mission To API" utilise config.MISSION_API_URL
  • Node "Save Mission To API" utilise config.N8N_API_KEY
  • Node "Save Mission To API" inclut missionId dans le body
  • Tous les IDs d'intégration sont inclus dans le callback

3. Flux de Données

  • missionId est envoyé à N8N lors de la création
  • missionId est renvoyé par N8N dans le callback
  • Les IDs d'intégration sont correctement mappés:
    • gitRepoUrlgiteaRepositoryUrl
    • leantimeProjectIdleantimeProjectId (string)
    • documentationCollectionIdoutlineCollectionId
    • rocketchatChannelIdrocketChatChannelId

4. Gestion d'Erreurs

  • Erreurs N8N sont loggées
  • Rollback en cas d'échec (si configuré)
  • Messages d'erreur clairs pour debugging
  • Pas de données sensibles dans les logs

🐛 Problèmes Potentiels et Solutions

Problème 1: 401 Unauthorized

Symptômes:

Invalid API key { received: 'present', expected: 'configured' }

Causes possibles:

  1. N8N_API_KEY non défini dans l'environnement
  2. N8N_API_KEY différent entre Next.js et N8N
  3. N8N envoie une clé vide ou undefined

Solutions:

  1. Vérifier que N8N_API_KEY est défini:
    echo $N8N_API_KEY
    
  2. Vérifier la valeur dans N8N:
    • Ouvrir l'exécution du workflow
    • Vérifier config.N8N_API_KEY dans "Process Mission Data"
  3. S'assurer que la même clé est utilisée partout

Problème 2: 404 Mission Not Found

Symptômes:

Mission not found { missionId: "...", name: "...", creatorId: "..." }

Causes possibles:

  1. missionId non envoyé par N8N
  2. missionId incorrect
  3. Mission supprimée entre temps

Solutions:

  1. Vérifier que N8N envoie missionId:
    {
      "missionId": "{{ $node['Process Mission Data'].json.missionId }}"
    }
    
  2. Vérifier que Next.js envoie missionId à N8N:
    config: {
      missionId: mission.id  // ✅ Inclus dans n8nData
    }
    
  3. Utiliser le fallback name + creatorId si missionId manquant

Problème 3: 500 Server Configuration Error

Symptômes:

N8N_API_KEY not configured in environment

Cause: process.env.N8N_API_KEY est undefined

Solution:

  1. Ajouter N8N_API_KEY à .env.local ou variables d'environnement
  2. Redémarrer l'application
  3. Vérifier avec un endpoint de test

Problème 4: 404 Webhook Not Registered

Symptômes:

404 Error: The requested webhook "mission-created" is not registered.
Hint: Click the 'Execute workflow' button on the canvas, then try again.

Cause: Workflow N8N n'est pas actif

Solution:

  1. Ouvrir le workflow dans N8N
  2. Activer le toggle "Active" (devrait être vert)
  3. Vérifier que le webhook node est actif

Problème 5: IDs d'Intégration Non Sauvegardés

Symptômes:

  • Mission créée mais giteaRepositoryUrl, leantimeProjectId, etc. sont null

Causes possibles:

  1. N8N ne rappelle pas /api/missions/mission-created
  2. N8N rappelle mais avec des IDs manquants
  3. Erreur lors de la mise à jour en base

Solutions:

  1. Vérifier les logs N8N (Executions)
  2. Vérifier que le node "Save Mission To API" s'exécute
  3. Vérifier les logs Next.js pour "Mission Created Webhook Received"
  4. Vérifier que tous les IDs sont inclus dans le body du callback

🧪 Tests et Validation

Test 1: Vérifier Configuration

Endpoint de test (à créer):

// app/api/test-n8n-config/route.ts
import { NextResponse } from 'next/server';

export async function GET() {
  return NextResponse.json({
    hasN8NApiKey: !!process.env.N8N_API_KEY,
    n8nApiKeyLength: process.env.N8N_API_KEY?.length || 0,
    n8nWebhookUrl: process.env.N8N_WEBHOOK_URL || 'https://brain.slm-lab.net/webhook/mission-created',
    missionApiUrl: process.env.NEXT_PUBLIC_API_URL || 'https://api.slm-lab.net/api'
  });
}

Usage: GET /api/test-n8n-config


Test 2: Tester Webhook N8N

curl -X POST https://brain.slm-lab.net/webhook/mission-created \
  -H "Content-Type: application/json" \
  -d '{"test": "data"}'

Résultats attendus:

  • 200/400/500 avec erreur workflow: Webhook actif
  • 404 avec "webhook not registered": Webhook inactif

Test 3: Tester Callback Endpoint

curl -X POST https://api.slm-lab.net/api/missions/mission-created \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_N8N_API_KEY" \
  -d '{
    "missionId": "test-mission-id",
    "gitRepoUrl": "https://git.example.com/repo",
    "leantimeProjectId": "123"
  }'

Résultats attendus:

  • 200 avec success: true: API key valide
  • 401: API key invalide
  • 404: Mission non trouvée (normal si missionId de test)

Test 4: Créer une Mission Complète

  1. Créer une mission via le frontend
  2. Vérifier les logs Next.js:
    • "Mission created successfully"
    • "Starting N8N workflow"
    • "N8N workflow result { success: true }"
  3. Vérifier les logs N8N (Executions):
    • Workflow exécuté avec succès
    • Node "Save Mission To API" exécuté
  4. Vérifier la base de données:
    • Mission a les IDs d'intégration sauvegardés

💡 Recommandations

1. Amélioration de la Sécurité

Problème actuel: Clé API en clair, comparaison simple

Recommandations:

  • Utiliser un système de tokens avec expiration
  • Implémenter un système de signature HMAC
  • Ajouter un rate limiting sur /api/missions/mission-created
  • Logging des tentatives d'accès invalides avec IP

2. Amélioration de la Robustesse

Problème actuel: Pas de retry automatique si N8N échoue

Recommandations:

  • Implémenter un système de retry avec backoff exponentiel
  • Queue de messages pour les callbacks manqués
  • Webhook de santé pour vérifier que N8N est accessible
  • Timeout configurable pour les appels N8N

3. Amélioration du Debugging

Problème actuel: Logs dispersés, pas de traçabilité complète

Recommandations:

  • Ajouter un correlationId pour tracer une mission de bout en bout
  • Logs structurés avec contexte complet
  • Dashboard de monitoring des intégrations
  • Alertes en cas d'échec répété

4. Amélioration de la Documentation

Recommandations:

  • Documenter le format exact attendu par N8N
  • Exemples de payloads complets
  • Diagrammes de séquence détaillés
  • Guide de troubleshooting avec cas réels

5. Tests Automatisés

Recommandations:

  • Tests unitaires pour N8nService
  • Tests d'intégration pour les endpoints API
  • Tests E2E avec mock N8N
  • Tests de charge pour vérifier la scalabilité

📝 Checklist de Vérification Rapide

Configuration

  • N8N_API_KEY défini et identique partout
  • NEXT_PUBLIC_API_URL pointe vers la bonne URL
  • Application redémarrée après modifications

N8N Workflow

  • Workflow actif (toggle vert)
  • Webhook path: mission-created
  • Node "Save Mission To API" configuré correctement
  • missionId inclus dans le callback

Code Next.js

  • missionId envoyé à N8N lors de la création
  • Validation API key fonctionnelle
  • Mapping des champs correct
  • Gestion d'erreurs appropriée

Tests

  • Test de création de mission réussi
  • IDs d'intégration sauvegardés en base
  • Logs sans erreurs critiques

🔗 Références

  • Service N8N: lib/services/n8n-service.ts
  • Endpoint création: app/api/missions/route.ts
  • Endpoint callback: app/api/missions/mission-created/route.ts
  • Documentation N8N: Voir fichiers N8N_*.md dans le projet

Document créé le: $(date)
Dernière mise à jour: $(date)
Version: 1.0