# 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.