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
- Architecture Globale
- Flux de Communication
- Endpoints API
- Configuration Requise
- Sécurité
- Points Critiques à Vérifier
- Problèmes Potentiels et Solutions
- Tests et Validation
- Recommandations
🏗️ Architecture Globale
Vue d'ensemble
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Next.js │────────▶│ N8N │────────▶│ Intégrations│
│ (API) │ │ (Workflow) │ │ (Gitea, etc)│
└─────────────┘ └─────────────┘ └─────────────┘
│ │
│ │
└─────────────────────────┘
(Callback)
Composants Principaux
-
Next.js API Routes
POST /api/missions- Création de missionPOST /api/missions/mission-created- Callback de N8NGET /api/missions- Liste des missions
-
Service N8N (
lib/services/n8n-service.ts)- Envoi de données vers N8N
- Gestion des webhooks
- Gestion des erreurs
-
N8N Workflows
- Webhook de réception:
/webhook/mission-created - Création des intégrations externes
- Callback vers Next.js
- Webhook de réception:
🔄 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
- ✅
missionIdinclus dans les données envoyées à N8N - ✅
config.N8N_API_KEYetconfig.MISSION_API_URLinclus
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 manquante400- Champs requis manquants404- Mission non trouvée500- Erreur serveur
Points critiques:
- ✅ Validation stricte de l'API key
- ✅ Recherche par
missionId(préféré) ouname + creatorId(fallback) - ✅ Conversion
leantimeProjectIdde 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
missionIddans le body - ✅ Inclure tous les IDs d'intégration créés
🔒 Sécurité
1. Authentification API Key
Mécanisme:
- N8N envoie
x-api-keyheader - 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:
- Next.js lit
process.env.N8N_API_KEY - Next.js envoie à N8N dans
config.N8N_API_KEY - N8N stocke temporairement dans le workflow
- N8N renvoie dans header
x-api-keylors du callback
Risque: Si N8N_API_KEY est undefined au moment de l'envoi:
- N8N reçoit
undefinedou 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 quename + 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_KEYest défini dans l'environnementN8N_API_KEYa la même valeur partout (dev, staging, prod)NEXT_PUBLIC_API_URLpointe 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
missionIddans le body - Tous les IDs d'intégration sont inclus dans le callback
3. Flux de Données
missionIdest envoyé à N8N lors de la créationmissionIdest renvoyé par N8N dans le callback- Les IDs d'intégration sont correctement mappés:
gitRepoUrl→giteaRepositoryUrlleantimeProjectId→leantimeProjectId(string)documentationCollectionId→outlineCollectionIdrocketchatChannelId→rocketChatChannelId
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:
N8N_API_KEYnon défini dans l'environnementN8N_API_KEYdifférent entre Next.js et N8N- N8N envoie une clé vide ou
undefined
Solutions:
- Vérifier que
N8N_API_KEYest défini:echo $N8N_API_KEY - Vérifier la valeur dans N8N:
- Ouvrir l'exécution du workflow
- Vérifier
config.N8N_API_KEYdans "Process Mission Data"
- 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:
missionIdnon envoyé par N8NmissionIdincorrect- Mission supprimée entre temps
Solutions:
- Vérifier que N8N envoie
missionId:{ "missionId": "{{ $node['Process Mission Data'].json.missionId }}" } - Vérifier que Next.js envoie
missionIdà N8N:config: { missionId: mission.id // ✅ Inclus dans n8nData } - Utiliser le fallback
name + creatorIdsimissionIdmanquant
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:
- Ajouter
N8N_API_KEYà.env.localou variables d'environnement - Redémarrer l'application
- 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:
- Ouvrir le workflow dans N8N
- Activer le toggle "Active" (devrait être vert)
- 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. sontnull
Causes possibles:
- N8N ne rappelle pas
/api/missions/mission-created - N8N rappelle mais avec des IDs manquants
- Erreur lors de la mise à jour en base
Solutions:
- Vérifier les logs N8N (Executions)
- Vérifier que le node "Save Mission To API" s'exécute
- Vérifier les logs Next.js pour "Mission Created Webhook Received"
- 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/500avec erreur workflow: Webhook actif - ❌
404avec "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:
- ✅
200avecsuccess: 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
- Créer une mission via le frontend
- Vérifier les logs Next.js:
- ✅ "Mission created successfully"
- ✅ "Starting N8N workflow"
- ✅ "N8N workflow result { success: true }"
- Vérifier les logs N8N (Executions):
- ✅ Workflow exécuté avec succès
- ✅ Node "Save Mission To API" exécuté
- 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
correlationIdpour 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_KEYdéfini et identique partoutNEXT_PUBLIC_API_URLpointe 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
missionIdinclus dans le callback
Code Next.js
missionIdenvoyé à 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_*.mddans le projet
Document créé le: $(date)
Dernière mise à jour: $(date)
Version: 1.0