# AUDIT COMPLET : BARE METAL vs INCUS **Date:** 2026-01-15 **Objectif:** Identifier pourquoi l'application fonctionne en bare metal mais pas via HAProxy dans Incus --- ## 📊 RÉSUMÉ EXÉCUTIF ### ✅ État Bare Metal - **Backend API:** ✅ Fonctionnel (http://localhost:8080) - **Frontend Dev:** ✅ Fonctionnel (http://localhost:5173) - **Application:** ✅ Charge correctement dans le navigateur - **API Calls:** ✅ Fonctionnent ### ❌ État Incus (via HAProxy) - **Backend API:** ⚠ Accessible mais peut avoir des problĂšmes CORS - **Frontend:** ✅ Accessible (https://10.10.10.6) - **Application:** ❌ Erreur React.Children dans le navigateur - **API Calls:** ⚠ Potentiels problĂšmes CORS --- ## 🔍 ANALYSE DÉTAILLÉE ### 1. CONFIGURATION URLS API #### Bare Metal ``` VITE_API_URL=http://localhost:8080/api/v1 VITE_WS_URL=ws://localhost:8081/ws VITE_STREAM_URL=ws://localhost:8082/stream VITE_UPLOAD_URL=http://localhost:8080/upload ``` #### Incus (Build) ``` VITE_API_URL=/api/v1 (URL relative) VITE_WS_URL=/ws (URL relative) VITE_STREAM_URL=/stream (URL relative) VITE_UPLOAD_URL=/upload (URL relative) ``` **✅ CORRECT:** Les URLs relatives sont correctes pour fonctionner via HAProxy. --- ### 2. CONFIGURATION CORS BACKEND #### Bare Metal ``` CORS_ALLOWED_ORIGINS=http://localhost:5173,http://127.0.0.1:5173 ``` #### Incus ``` CORS_ALLOWED_ORIGINS=http://10.10.10.1,http://10.10.10.6,https://10.10.10.6,http://localhost ``` **⚠ PROBLÈME IDENTIFIÉ:** - Le backend Incus n'a **PAS** `https://10.10.10.6` dans les origines CORS autorisĂ©es de maniĂšre explicite - `http://localhost` est prĂ©sent mais ne correspond pas Ă  l'origine rĂ©elle du navigateur (`https://10.10.10.6`) **Impact:** Les requĂȘtes API depuis le navigateur peuvent ĂȘtre bloquĂ©es par CORS. --- ### 3. PROTOCOLE ET HTTPS #### Bare Metal - **Protocole:** HTTP (http://) - **Pas de SSL/TLS** - **Pas de redirection HTTPS** #### Incus - **Protocole:** HTTPS (https://) via HAProxy - **Certificat auto-signĂ©** - **Redirection HTTP → HTTPS** **⚠ PROBLÈME POTENTIEL:** - Le navigateur accĂšde via `https://10.10.10.6` - Les requĂȘtes API sont faites vers `https://10.10.10.6/api/v1` (URL relative convertie) - Le backend doit accepter `https://10.10.10.6` dans CORS --- ### 4. ERREUR REACT.CHILDREN #### SymptĂŽmes ``` Uncaught TypeError: Cannot set properties of undefined (setting 'Children') at react.production.min.js:20:1 ``` #### Cause Probable 1. **Ordre de chargement des chunks:** React n'est pas chargĂ© avant zustand/react/shallow 2. **Cache navigateur:** Anciens chunks JS en cache 3. **Service Worker:** Cache des anciens assets #### Corrections AppliquĂ©es - ✅ React et Zustand sĂ©parĂ©s en chunks diffĂ©rents - ✅ Service Worker configurĂ© pour bypass JS chunks - ✅ VĂ©rification React.Children avant import zustand **⚠ PROBLÈME PERSISTANT:** - L'erreur persiste dans le navigateur via Incus - Peut ĂȘtre dĂ» au cache navigateur ou Ă  l'ordre de chargement --- ### 5. CONNECTIVITÉ RÉSEAU #### Bare Metal - Backend: `localhost:8080` (mĂȘme machine) - Pas de proxy - Pas de SSL #### Incus - Backend: `10.10.10.2:8080` (container sĂ©parĂ©) - HAProxy: `10.10.10.6` (proxy + SSL) - Frontend: `10.10.10.5:80` (Apache) **✅ CORRECT:** La connectivitĂ© rĂ©seau fonctionne (tests rĂ©ussis). --- ## 🎯 CAUSES RACINES IDENTIFIÉES ### P0 - CRITIQUES #### 1. **Erreur React.Children - CAUSE RACINE PRINCIPALE** ✅ IDENTIFIÉE **ProblĂšme:** L'erreur `Cannot set properties of undefined (setting 'Children')` persiste. **Analyse:** - ✅ CORS fonctionne correctement (headers prĂ©sents, `https://10.10.10.6` autorisĂ©) - ✅ API rĂ©pond correctement via HAProxy - ❌ L'application ne se charge pas Ă  cause de l'erreur React **Causes identifiĂ©es:** 1. **Cache navigateur:** Anciens chunks JS en cache 2. **Service Worker:** Peut servir d'anciens assets mĂȘme avec bypass configurĂ© 3. **Ordre de chargement:** React peut ne pas ĂȘtre chargĂ© avant zustand/react/shallow 4. **Build diffĂ©rent:** Le build Incus peut avoir un ordre de chunks diffĂ©rent du build bare metal **Preuve:** - Bare metal fonctionne (mode dev, pas de cache) - Incus ne fonctionne pas (production build, cache navigateur) **Impact:** ❌ **BLOQUANT** - L'application ne se charge pas du tout. #### 2. **Frontend 503 Intermittent** ⚠ SECONDAIRE **ProblĂšme:** HAProxy retourne parfois 503 pour le frontend. **Causes:** - Container web perd son IP statique - Apache ne rĂ©pond pas temporairement - HAProxy ne peut pas joindre le container **Impact:** ⚠ Intermittent, mais peut causer des erreurs de chargement. #### 3. **CORS - NON PROBLÉMATIQUE** ✅ VÉRIFIÉ **Statut:** ✅ **FONCTIONNE CORRECTEMENT** **Preuve:** - Headers CORS prĂ©sents: `Access-Control-Allow-Origin: https://10.10.10.6` - Preflight OPTIONS fonctionne - RequĂȘtes GET avec Origin fonctionnent - Backend accepte `https://10.10.10.6` dans `CORS_ALLOWED_ORIGINS` **Conclusion:** CORS n'est **PAS** la cause du problĂšme. ### P1 - IMPORTANTS #### 3. **Headers HTTP DiffĂ©rents** **ProblĂšme:** HAProxy peut modifier/ajouter des headers qui interfĂšrent avec CORS. **Impact:** Les headers CORS peuvent ĂȘtre incorrects. #### 4. **Configuration HAProxy pour CORS** **ProblĂšme:** HAProxy ne passe peut-ĂȘtre pas correctement les headers CORS du backend. **Impact:** Les rĂ©ponses CORS peuvent ĂȘtre incorrectes. --- ## 📋 PLAN DE REMÉDIATION DÉTAILLÉ ### Phase 1 - CORRECTION REACT.CHILDREN (P0) - PRIORITÉ ABSOLUE **STATUT CORS:** ✅ **FONCTIONNE** - Pas besoin de correction CORS. --- ### Phase 1 - CORRECTION REACT.CHILDREN (P0) #### Étape 1.1: DĂ©sactiver ComplĂštement le Service Worker **ProblĂšme:** Le Service Worker peut servir d'anciens assets mĂȘme avec bypass configurĂ©. **Solution:** DĂ©sactiver complĂštement le Service Worker pour Ă©liminer le cache. **Actions:** 1. Modifier `apps/web/src/main.tsx` pour ne pas enregistrer le Service Worker 2. Ou modifier `apps/web/public/sw.js` pour ne rien faire 3. Rebuild et redĂ©ployer **Code Ă  modifier:** ```typescript // Dans apps/web/src/main.tsx // Commenter ou supprimer l'enregistrement du Service Worker // if ('serviceWorker' in navigator) { // navigator.serviceWorker.register('/sw.js') // } ``` #### Étape 1.2: Forcer l'Ordre de Chargement des Chunks **ProblĂšme:** React peut ne pas ĂȘtre chargĂ© avant zustand/react/shallow. **Solution:** S'assurer que React est chargĂ© en premier via preload. **Actions:** 1. VĂ©rifier l'ordre dans le build: ```bash curl -k -s https://10.10.10.6/ | grep -E "(script|modulepreload)" | head -15 ``` 2. Ajouter un preload explicite pour le chunk React dans `index.html` 3. Ou modifier `vite.config.ts` pour forcer l'ordre via `manualChunks` #### Étape 1.3: Ajouter un Cache Busting **ProblĂšme:** Le navigateur peut avoir d'anciens chunks en cache. **Solution:** Ajouter un paramĂštre de version dans les URLs des chunks. **Actions:** 1. Modifier le build pour ajouter un hash de version 2. Ou forcer le rechargement via meta tags 3. Ajouter des headers no-cache pour les chunks JS #### Étape 1.4: Vider le Cache Navigateur (Instructions) **ProblĂšme:** Le navigateur peut avoir d'anciens chunks en cache. **Solution:** Instructions dĂ©taillĂ©es pour vider le cache. **Actions:** 1. Ouvrir DevTools (F12) 2. Application > Storage > Clear site data 3. Application > Service Workers > Unregister 4. Network > Disable cache (pendant les tests) 5. Hard refresh (Ctrl+Shift+R ou Cmd+Shift+R) --- ### Phase 3 - VALIDATION ET TESTS (P1) #### Étape 3.1: Tests Complets 1. Test CORS preflight 2. Test requĂȘtes API depuis navigateur 3. Test chargement de l'application 4. VĂ©rification des erreurs console #### Étape 3.2: Monitoring 1. Activer les logs HAProxy (✅ dĂ©jĂ  fait) 2. Monitorer les erreurs CORS 3. VĂ©rifier les logs backend --- ## 🔧 CORRECTIONS IMMÉDIATES ### Correction 1: DĂ©sactiver Service Worker **Fichier:** `apps/web/src/main.tsx` **Modification:** ```typescript // Commenter ou supprimer l'enregistrement du Service Worker // if ('serviceWorker' in navigator) { // navigator.serviceWorker.register('/sw.js') // .then((registration) => { // console.log('Service Worker registered:', registration); // }) // .catch((error) => { // console.error('Service Worker registration failed:', error); // }); // } ``` **Alternative:** Modifier `apps/web/public/sw.js` pour ne rien faire: ```javascript // Service Worker dĂ©sactivĂ© pour Ă©viter les problĂšmes de cache self.addEventListener('install', () => { self.skipWaiting(); }); self.addEventListener('activate', (event) => { event.waitUntil( caches.keys().then((cacheNames) => { return Promise.all( cacheNames.map((cacheName) => caches.delete(cacheName)) ); }).then(() => self.clients.claim()) ); }); // Ne pas intercepter de requĂȘtes self.addEventListener('fetch', () => { // Ne rien faire - laisser le navigateur gĂ©rer }); ``` ### Correction 2: Forcer l'Ordre de Chargement React **Fichier:** `apps/web/vite.config.ts` **VĂ©rifier que la configuration est correcte:** ```typescript manualChunks: (id) => { if (id.includes('node_modules')) { // React DOIT ĂȘtre chargĂ© en premier if (id.includes('react') || id.includes('react-dom')) { return 'vendor-react-core'; } // Zustand aprĂšs React if (id.includes('zustand')) { return 'vendor-zustand'; } // ... } } ``` **Ajouter un preload dans `index.html` (via plugin Vite):** ```typescript // Dans vite.config.ts, ajouter un plugin pour injecter preload { name: 'preload-react', transformIndexHtml(html) { return html.replace( '