# 🎓 Infrastructure Lessons (La Plomberie) Ce fichier archive les échecs et solutions liées à la **stabilité technique** du système. Les règles ici doivent être respectées lors de toute modification structurelle. - **[ARCHI] Détachement Gateway** : Ne JAMAIS laisser une gateway (Hugging Face / Meta) attendre > 20s. Répondre `200 OK` immédiatement et déléguer au worker. - **[DB] Séquençage des Opérations** : Ne JAMAIS envoyer de message WhatsApp avant d'avoir persisté la progression dans Prisma. La DB est la seule source de vérité. - **[CACHING] Verrous d'Idempotence** : Utiliser des locks Redis avec un TTL minimal de 300s (5 min) pour protéger les appels LLM longs et éviter les retries en boucle. - **[MEDIA] Vision Base64** : Gemini échoue par URL ; toujours convertir les photos d'utilisateurs en Base64. - **[STT] Whisper Auto-Validation** : Si l'indice de confiance est <= 80%, intercepter le flux et basculer en `PENDING_REVIEW` pour validation humaine sans crash. - **[NON-BLOQUANT] Processus FFMPEG** : Les conversions audio doivent tourner dans des sous-processus. - **[AI] OpenAI Zod Schemas** : Pour les Structured Outputs, OpenAI exige que TOUS les champs d'un schéma soient obligatoires OU explicitement `.nullable().optional()`. Les `.optional()` seuls sur les sous-objets provoquent une erreur. - **[QUEUES] Payload Sync** : S'assurer que les noms de champs dans `whatsappQueue.add` (producteur) matchent exactement le destructuring dans le worker (consommateur). Préférer `currentDay` partout pour la consistance. - **[DB] Enrollment ID** : Toujours passer l'ID d'inscription (`enrollmentId`) au job de feedback pour permettre la persistance des réponses sans crash Prisma. - **[JSON] Null Safety & Expansion** : Toujours vérifier la présence de données (Null Safety) lors de l'extension des schémas JSON, sous peine de briser le pipeline des jours précédents (Utiliser des guards `currentDay >= X`). - **[FLOW] Re-validation Window** : Ne jamais bloquer une analyse entrante sous prétexte que le statut est COMPLETED si le délai depuis la dernière validation est inférieur à 5 minutes (cas de correction immédiate par l'utilisateur) ou si un nouvel élément multimédia est présent. - **[FLOW] Day 7 Card Blockage** : Risque de blocage lors du choix de carte. Toujours valider que l'entrée textuelle courte (ex: "WhatsApp") déclenche la même logique que l'audio en baissant le seuil de `minWordCount`. - **[UX] Card Interaction (Hook)** : L'interaction par cartes/boutons ne doit jamais être bloquante. Elle doit servir de "hook" : le Coach valide le choix et relance immédiatement sur le "pourquoi" pour enrichir l'analyse. - **[UX] Anti-False Validation (Card Click)** : Un clic sur une carte/bouton ne doit JAMAIS valider une étape (`COMPLETED`). Il doit servir de point d'entrée ("hook") pour une explication riche. Forcer le statut à `PENDING` après un choix par bouton pour obliger l'utilisateur à donner son explication audio/texte. - **[FLOW] Validation Subordonnée** : Le passage en `COMPLETED` est strictement réservé au feedback positif de l'IA sur une réponse de fond. L'UI d'attente ("Analyse de votre réponse...") doit être envoyée, mais le statut ne doit bouger que sur confirmation IA. ## 🛡️ Règle d'Or de l'Intégrité **Les correctifs techniques ne doivent JAMAIS impacter la logique de personnalisation du prompt `generatePersonalizedLesson` ou des feedbacks.** Toute simplification technique qui réduit la spécificité de l'IA est un échec. ## 📅 Historique des Apprentissages - [24/03/2026] | Gemini 404 | Utiliser `gemini-1.5-pro-latest` au lieu de `gemini-1.5-pro` sur l'API `v1beta`. - [24/03/2026] | Missing dayNumber | `currentDay` vs `dayNumber` mismatch dans le job payload. Toujours vérifier le destructuring. - [30/04/2026] | tsx en production | Ne jamais utiliser `--import tsx` en PM2 pour production. tsx est une devDependency. Compiler tous les packages/apps avec tsc et pointer PM2 vers `dist/index.js`. - [30/04/2026] | @repo/database non compilé | Tout package workspace consommé en production doit : (1) avoir `noEmit: false` dans son tsconfig, (2) pointer `main` vers `./dist/index.js`, (3) être compilé dans le Dockerfile avant les apps qui en dépendent. - [30/04/2026] | Imports .js dans tsconfig node | Les imports `'./foo.js'` dans un fichier `.ts` requièrent `moduleResolution: node16`. Avec `moduleResolution: node`, utiliser des imports sans extension : `'./foo'`. - [30/04/2026] | Fastify plugin versioning | Avant de modifier la version de Fastify ou d'un plugin @fastify, auditer TOUS les plugins avec `grep "fastify:.*\.x"` dans leur index.js. Le numéro de version majeur varie par plugin — ne pas supposer que X.x = Fastify v4 ou v5. - [30/04/2026] | addContentTypeParser Fastify v5 | La signature callback `(req, body, done) => void` est remplacée par `async (req: FastifyRequest, body: Buffer) => unknown`. Retourner la valeur parsée, ne pas appeler done(). - [30/04/2026] | Fire-and-forget Fastify v5 | Pattern correct : `setImmediate(async () => { ... })` D'ABORD, puis `return reply.code(200).send(...)`. Ne jamais laisser reply.send() sans return dans un handler async Fastify v5.