edtech / docs /multi-tenant-architecture.md
CognxSafeTrack
chore: finalize Sprint P2 & P3 optimizations, baseline prisma migrations, and update technical audit docs
cfbb685
# Documentation Technique : Architecture B2B SaaS Multi-Tenant
Cette documentation détaille la transition du système d'un produit "Single-Tenant" vers une plateforme B2B SaaS Multi-Tenant capable d'accueillir plusieurs organisations (écoles, entreprises) avec une isolation stricte et une configuration personnalisée.
---
## 🏛️ 1. Architecture des Données & Isolation
### Modèle de Données (Prisma)
Toutes les entités critiques (`Track`, `Lesson`, `User`, `Response`, `Enrollment`) sont désormais liées à une entité `Organization`.
- **Champ `organizationId`** : Présent et indexé sur chaque table pour garantir des performances de filtrage optimales.
- **Isolation Automatique** : Utilisation d'une extension Prisma (`packages/database/src/extension.ts`) qui injecte automatiquement la clause `where: { organizationId }` dans toutes les requêtes.
### Contexte Tenant
Le contexte est propagé via `AsyncLocalStorage` (`packages/database/src/context.ts`) :
- **API** : Le `tenantMiddleware` extrait l'ID depuis les headers (`x-organization-id`) ou le token auth.
- **Worker** : Le contexte est extrait des données du job BullMQ et injecté avant l'exécution du handler.
---
## ⚙️ 2. Worker WhatsApp (Engine)
Le worker a été totalement modularisé pour éviter le monolithisme.
### Dispatcher Central (`index.ts`)
Le worker agit comme un dispatcher léger qui délègue les tâches à des **JobHandlers** spécialisés.
### Handlers Spécialisés (`src/handlers/`)
- **InboundHandler** : Point d'entrée unique pour tous les messages texte/audio.
- **AdminHandler** : Commandes réservées à l'administration.
- **NudgeHandler** : Relances automatiques.
- **EnrollHandler** : Gestion des inscriptions aux parcours.
- **MediaHandler** : Traitement des images et vidéos.
---
## 🧠 3. Moteur d'IA & Pattern Strategy
Le service d'intelligence artificielle (`apps/api/src/services/ai/`) a été conçu pour la résilience.
### Provider Registry
L'IA n'est plus liée à un seul fournisseur. Le `ProviderRegistry` permet d'enregistrer plusieurs moteurs (Gemini, OpenAI, Mistral) avec leurs capacités :
- **Priority Failover** : Si le provider primaire (ex: Gemini) échoue, le système bascule automatiquement sur le secondaire (ex: OpenAI).
- **Capability Routing** : Les requêtes sont routées vers le meilleur modèle selon le besoin (Vision pour les images, Whisper pour l'audio, GPT-4o pour le texte complexe).
### Personnalisation Dynamique
Chaque organisation peut configurer son propre "Personality Studio". Les prompts sont compilés dynamiquement en fusionnant :
1. Le template de base du système.
2. La configuration spécifique de l'organisation (nom du bot, mission, ton).
---
## 👁️ 4. Observabilité & Debugging
### Logging Multi-Tenant
Le logger (`logger.ts`) est synchronisé avec le contexte `AsyncLocalStorage`.
- **Auto-Injection** : Chaque ligne de log (`info`, `error`) inclut automatiquement l' `organizationId` s'il est présent dans le contexte d'exécution.
- **Bénéfice** : Possibilité de filtrer les logs en temps réel par client dans les outils de monitoring (Cloudwatch, Datadog).
---
## 📡 5. Flux de Message (Pipeline)
Le flux de traitement est désormais unifié et asynchrone :
1. **Webhook API** : Reçoit le message, identifie l'organisation via le `phone_number_id`, et ajoute un job `handle-inbound` dans Redis (BullMQ).
2. **BullMQ** : Gère la file d'attente et la persistance des tâches.
3. **Worker** : Consomme le job, initialise le contexte tenant, normalise le texte (Wolof/FR), et appelle le handler approprié.
4. **WhatsApp Cloud API** : Envoi de la réponse finale via les services utilitaires (`whatsapp-cloud.ts`).
---
## 🧪 6. Stratégie de Test
Le projet utilise **Vitest** pour garantir la stabilité :
- **Tests Unitaires** : Validation de la normalisation du Wolof (`normalizeWolof.test.ts`).
- **Tests d'Intégration** : Simulation des flux métier via des mocks Prisma et BullMQ (`OnboardingHandler.test.ts`).
---
## 🛠️ Maintenance & Évolutions
- **Ajouter un Handler** : Créer une classe implémentant `JobHandler` dans `src/handlers/` et l'enregistrer dans `index.ts`.
- **Ajouter un Provider IA** : Créer une classe implémentant `LLMProvider` et l'ajouter au `ProviderRegistry`.
- **Migration DB** : Toujours utiliser `npx prisma migrate dev` pour maintenir l'intégrité du schéma multi-tenant.