# 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(
      '<script type="module"',
      '<link rel="modulepreload" href="/js/vendor-react-core-[hash].js" crossorigin>\n    <script type="module"'
    );
  }
}
```

### Correction 3: Cache Busting et Headers No-Cache
**Fichier:** `config/incus/apache/veza-web.conf` ou configuration Apache

**Ajouter des headers no-cache pour les chunks JS:**
```apache
<LocationMatch "^/js/.*\.js$">
  Header set Cache-Control "no-cache, no-store, must-revalidate"
  Header set Pragma "no-cache"
  Header set Expires "0"
</LocationMatch>
```

### Correction 4: Vérifier l'Ordre dans le HTML Généré
**Action:** Vérifier que le chunk React est bien chargé avant zustand dans le HTML final.

---

## 📊 MATRICE DE COMPARAISON

| Aspect | Bare Metal | Incus | Problème |
|--------|------------|-------|----------|
| Protocole | HTTP | HTTPS | ⚠️ Différence |
| CORS Origins | localhost:5173 | 10.10.10.6 | ❌ Manquant/incorrect |
| URLs API | localhost:8080 | /api/v1 (relative) | ✅ Correct |
| React.Children | ✅ OK | ❌ Erreur | ❌ Cache/ordre |
| Service Worker | Dev mode (désactivé) | Production (actif) | ⚠️ Cache |
| Headers CORS | Direct backend | Via HAProxy | ⚠️ Peut être modifié |

---

## 🎯 CAUSE RACINE PRINCIPALE - IDENTIFIÉE

**CAUSE RACINE CONFIRMÉE:** 
Le problème vient de **l'erreur React.Children** qui empêche l'application de se charger.

**ANALYSE:**
1. ✅ **CORS fonctionne:** Headers présents, origine autorisée, requêtes API réussissent
2. ✅ **API fonctionne:** Backend répond correctement via HAProxy
3. ✅ **Frontend accessible:** HTML et JS chunks sont servis
4. ❌ **Application ne charge pas:** Erreur React.Children au runtime

**DIFFÉRENCE CLÉ BARE METAL vs INCUS:**
- **Bare metal:** Mode dev (Vite), pas de cache, chunks chargés dynamiquement
- **Incus:** Mode production (build), cache navigateur, Service Worker actif, chunks pré-compilés

**HYPOTHÈSE:** 
L'erreur React.Children est causée par:
1. **Cache navigateur** avec d'anciens chunks qui ont un ordre de chargement différent
2. **Service Worker** qui peut servir d'anciens assets malgré le bypass configuré
3. **Ordre de chargement des chunks** qui peut être différent entre builds

**PRIORITÉ:** Corriger React.Children (cache + Service Worker + ordre de chargement).

---

## 🔍 DÉCOUVERTES CRITIQUES DE L'AUDIT

### Découverte 1: CORS Fonctionne ✅
**Conclusion:** CORS n'est **PAS** la cause du problème.

**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`

### Découverte 2: Frontend 503 Intermittent ⚠️
**Problème:** HAProxy retourne parfois 503 pour le frontend.

**Logs HAProxy:**
```
web_frontend/<NOSRV> 503
```

**Cause:** Container web perd son IP statique, HAProxy ne peut pas le joindre.

**Impact:** Empêche le chargement de l'application.

### Découverte 3: Erreur React.Children ❌
**Problème:** L'application ne se charge pas à cause de l'erreur React.

**Symptôme:**
```
Uncaught TypeError: Cannot set properties of undefined (setting 'Children')
at react.production.min.js:20:1
```

**Causes identifiées:**
1. Cache navigateur avec anciens chunks
2. Service Worker qui sert d'anciens assets
3. Ordre de chargement des chunks peut être incorrect

**Différence clé Bare Metal vs Incus:**
- **Bare metal:** Mode dev (Vite), pas de cache, pas de Service Worker
- **Incus:** Mode production (build), cache navigateur, Service Worker actif

---

## 📝 PLAN DE REMÉDIATION DÉTAILLÉ

### Phase 1 - CORRECTION FRONTEND 503 (P0)

#### Étape 1.1: Stabiliser Réseau Container Web
**Problème:** Container web perd son IP statique.

**Solution:** Vérifier et corriger la configuration réseau persistante.

**Actions:**
1. Vérifier que le script `/usr/local/bin/setup-network.sh` existe
2. Vérifier que le service `veza-network-setup.service` est activé
3. Tester un redémarrage du container pour vérifier la persistance
4. Si nécessaire, améliorer le script de setup réseau

#### Étape 1.2: Vérifier Apache
**Actions:**
1. Vérifier qu'Apache écoute sur le bon port
2. Vérifier les logs Apache pour erreurs
3. Redémarrer Apache si nécessaire

---

### Phase 2 - CORRECTION REACT.CHILDREN (P0)

#### Étape 2.1: Désactiver Service Worker (IMMÉDIAT)
**Fichier:** `apps/web/src/main.tsx`

**Action:**
1. Commenter l'enregistrement du Service Worker
2. Rebuild: `./config/incus/build-native.sh web`
3. Redéployer: `./config/incus/deploy-service-native.sh web`

**Code:**
```typescript
// TEMPORAIRE: Désactiver Service Worker pour éviter les problèmes de cache
// if ('serviceWorker' in navigator) {
//   navigator.serviceWorker.register('/sw.js')
// }
```

### Étape 2: Vérifier et Forcer l'Ordre de Chargement React
**Fichier:** `apps/web/vite.config.ts`

**Action:**
1. Vérifier que `vendor-react-core` est bien créé
2. Vérifier l'ordre dans le HTML généré
3. Ajouter un preload explicite si nécessaire

**Test:**
```bash
curl -k -s https://10.10.10.6/ | grep -E "(script|modulepreload)" | head -15
```

### Étape 3: Ajouter Headers No-Cache pour JS
**Fichier:** `config/incus/apache/veza-web.conf`

**Action:**
1. Ajouter des headers no-cache pour `/js/*.js`
2. Redéployer le frontend

### Étape 4: Instructions Cache Navigateur
**Action:**
1. Documenter la procédure complète de vidage de cache
2. Fournir un script de test

### Étape 5: Test et Validation
**Action:**
1. Tester dans le navigateur avec cache vidé
2. Vérifier que l'application charge
3. Vérifier qu'il n'y a plus d'erreur React.Children

---

## 🔧 CORRECTIONS IMMÉDIATES À APPLIQUER

### Correction 1: Désactiver Service Worker
**Priorité:** P0 - IMMÉDIAT

### Correction 2: Headers No-Cache
**Priorité:** P0 - IMMÉDIAT

### Correction 3: Vérifier Ordre Chunks
**Priorité:** P1 - IMPORTANT

---

## 📊 RÉSUMÉ FINAL

**CAUSE RACINE:** Erreur React.Children due au cache navigateur et Service Worker

**CORS:** ✅ Fonctionne correctement - Pas de problème CORS

**SOLUTION:** 
1. Désactiver Service Worker
2. Ajouter headers no-cache
3. Vider le cache navigateur
4. Tester

---

## 🎯 CAUSE RACINE FINALE - CONFIRMÉE

### Problème Principal: Erreur React.Children
**Statut:** ❌ **BLOQUANT**

**Cause:** 
1. **Cache navigateur** avec d'anciens chunks JS qui ont un ordre de chargement différent
2. **Service Worker** qui peut servir d'anciens assets malgré le bypass configuré
3. **Ordre de chargement** des chunks peut être différent entre builds

**Pourquoi ça fonctionne en bare metal:**
- Mode dev (Vite) - pas de build pré-compilé
- Pas de cache navigateur (première visite)
- Pas de Service Worker actif en mode dev
- Chunks chargés dynamiquement par Vite

**Pourquoi ça ne fonctionne pas en Incus:**
- Mode production (build pré-compilé)
- Cache navigateur avec anciens chunks
- Service Worker actif qui peut servir d'anciens assets
- Chunks pré-compilés avec un ordre fixe

### Problème Secondaire: Frontend 503 Intermittent
**Statut:** ⚠️ **INTERMITTENT**

**Cause:** Container web perd son IP statique, HAProxy ne peut pas le joindre.

**Impact:** Empêche le chargement de l'application quand le problème survient.

---

## 📋 PLAN D'ACTION PRIORITAIRE

### Action 1: Stabiliser Réseau Web Container (IMMÉDIAT)
**Fichier:** `config/incus/deploy-service-native.sh`

**Vérifier:**
- Script réseau existe et est exécutable
- Service systemd activé
- IP configurée correctement

**Test:**
```bash
incus exec veza-web -- /usr/local/bin/setup-network.sh
incus exec veza-web -- systemctl status veza-network-setup.service
```

### Action 2: Désactiver Service Worker (IMMÉDIAT)
**Fichier:** `apps/web/src/main.tsx`

**Modification:**
```typescript
// TEMPORAIRE: Désactiver Service Worker pour éviter les problèmes de cache
// 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);
//     });
// }
```

### Action 3: Ajouter Headers No-Cache (IMMÉDIAT)
**Fichier:** `config/incus/apache/veza-web.conf`

**Ajouter:**
```apache
<LocationMatch "^/js/.*\.js$">
  Header set Cache-Control "no-cache, no-store, must-revalidate"
  Header set Pragma "no-cache"
  Header set Expires "0"
</LocationMatch>
```

### Action 4: Rebuild et Redéployer
```bash
cd /home/senke/git/talas/veza
./config/incus/build-native.sh web
./config/incus/deploy-service-native.sh web
```

### Action 5: Instructions Cache Navigateur
**Pour l'utilisateur:**
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)

---

## 📊 MATRICE DE COMPARAISON FINALE

| Aspect | Bare Metal | Incus | Problème |
|--------|------------|-------|----------|
| **Protocole** | HTTP | HTTPS | ✅ Différence normale |
| **CORS** | localhost:5173 | https://10.10.10.6 | ✅ Fonctionne |
| **API** | localhost:8080 | /api/v1 (relative) | ✅ Fonctionne |
| **Frontend** | Vite dev | Apache (build) | ⚠️ 503 intermittent |
| **Service Worker** | Désactivé (dev) | Actif (prod) | ❌ Cache problèmes |
| **Cache navigateur** | Pas de cache | Cache actif | ❌ Anciens chunks |
| **React.Children** | ✅ OK | ❌ Erreur | ❌ BLOQUANT |

---

## ✅ CONCLUSION

**CAUSE RACINE PRINCIPALE:** Erreur React.Children due au cache navigateur et Service Worker

**CAUSE RACINE SECONDAIRE:** Frontend 503 intermittent (réseau container web)

**CORS:** ✅ **FONCTIONNE** - Pas de problème CORS

**SOLUTION:**
1. Désactiver Service Worker
2. Ajouter headers no-cache pour JS
3. Stabiliser réseau container web
4. Vider cache navigateur
5. Tester

---

**Fin du rapport d'audit**
