CognxSafeTrack Claude Sonnet 4.6 commited on
Commit ·
e1ca6ab
1
Parent(s): 53e72e6
fix(wizard): replace alert() with toast + add tech debt audit doc
Browse filesReplaces native alert() calls in OnboardingWizard with useToast().
Adds docs/audit_dette_technique_10052026.md with 10 identified debt
items (2 critical: token expiry monitoring, Redis singleton).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
apps/admin/src/pages/OnboardingWizard.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
| 8 |
import { useAuth } from '../lib/auth';
|
| 9 |
import { api } from '../lib/api';
|
| 10 |
import { initMetaSDK, launchEmbeddedSignup } from '../lib/meta-signup';
|
|
|
|
| 11 |
|
| 12 |
// ─── Modes ───────────────────────────────────────────────────────────────────
|
| 13 |
|
|
@@ -61,6 +62,7 @@ export default function OnboardingWizard() {
|
|
| 61 |
const [showPass, setShowPass] = useState(false);
|
| 62 |
const { token } = useAuth();
|
| 63 |
const navigate = useNavigate();
|
|
|
|
| 64 |
|
| 65 |
const [org, setOrg] = useState({
|
| 66 |
name: '',
|
|
@@ -136,7 +138,7 @@ export default function OnboardingWizard() {
|
|
| 136 |
navigate('/clients');
|
| 137 |
} catch (err: any) {
|
| 138 |
console.error(err);
|
| 139 |
-
|
| 140 |
} finally {
|
| 141 |
setLoading(false);
|
| 142 |
}
|
|
@@ -154,7 +156,7 @@ export default function OnboardingWizard() {
|
|
| 154 |
skip: false,
|
| 155 |
}));
|
| 156 |
} catch {
|
| 157 |
-
|
| 158 |
}
|
| 159 |
};
|
| 160 |
|
|
|
|
| 8 |
import { useAuth } from '../lib/auth';
|
| 9 |
import { api } from '../lib/api';
|
| 10 |
import { initMetaSDK, launchEmbeddedSignup } from '../lib/meta-signup';
|
| 11 |
+
import { useToast } from '../hooks/useToast';
|
| 12 |
|
| 13 |
// ─── Modes ───────────────────────────────────────────────────────────────────
|
| 14 |
|
|
|
|
| 62 |
const [showPass, setShowPass] = useState(false);
|
| 63 |
const { token } = useAuth();
|
| 64 |
const navigate = useNavigate();
|
| 65 |
+
const toast = useToast();
|
| 66 |
|
| 67 |
const [org, setOrg] = useState({
|
| 68 |
name: '',
|
|
|
|
| 138 |
navigate('/clients');
|
| 139 |
} catch (err: any) {
|
| 140 |
console.error(err);
|
| 141 |
+
toast.error(err.message || 'Création impossible');
|
| 142 |
} finally {
|
| 143 |
setLoading(false);
|
| 144 |
}
|
|
|
|
| 156 |
skip: false,
|
| 157 |
}));
|
| 158 |
} catch {
|
| 159 |
+
toast.error('La connexion Facebook a été annulée ou a échoué.');
|
| 160 |
}
|
| 161 |
};
|
| 162 |
|
docs/audit_dette_technique_10052026.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Audit Dette Technique — 10 mai 2026
|
| 2 |
+
|
| 3 |
+
Périmètre : `apps/api`, `apps/admin`, `apps/whatsapp-worker`, `packages/`.
|
| 4 |
+
TypeScript : **0 erreur** sur les 3 apps. Migrations à jour.
|
| 5 |
+
|
| 6 |
+
---
|
| 7 |
+
|
| 8 |
+
## 🔴 Critique — Risque opérationnel immédiat
|
| 9 |
+
|
| 10 |
+
### 1. Expiration silencieuse du token Meta (60 jours)
|
| 11 |
+
|
| 12 |
+
**Problème :** Les System User Tokens Meta expirent après 60 jours. Aucun champ `tokenIssuedAt` en base, aucun monitoring, aucune alerte. Quand le token expire, tous les envois WhatsApp échouent silencieusement pour l'organisation concernée — le bot s'arrête sans notification.
|
| 13 |
+
|
| 14 |
+
**Risque :** Interruption de service invisible pour tous les clients actifs.
|
| 15 |
+
|
| 16 |
+
**Correction :** Ajouter `systemUserTokenIssuedAt DateTime?` sur `Organization`. Créer un cron job (BullMQ `CronJob`) qui tourne chaque semaine et alerte via email/log si `now() > issuedAt + 50 jours`.
|
| 17 |
+
|
| 18 |
+
---
|
| 19 |
+
|
| 20 |
+
### 2. Prolifération des connexions Redis (16+ instances)
|
| 21 |
+
|
| 22 |
+
**Problème :** Chaque fichier qui utilise Redis crée sa propre instance `new Redis(...)` :
|
| 23 |
+
|
| 24 |
+
```
|
| 25 |
+
apps/whatsapp-worker/src/services/whatsapp-logic.ts
|
| 26 |
+
apps/whatsapp-worker/src/services/normalization.ts
|
| 27 |
+
apps/whatsapp-worker/src/services/organization.ts
|
| 28 |
+
apps/whatsapp-worker/src/services/ai.ts
|
| 29 |
+
apps/whatsapp-worker/src/scheduler.ts
|
| 30 |
+
apps/whatsapp-worker/src/handlers/*.ts (×8 handlers)
|
| 31 |
+
apps/api/src/services/organization.ts
|
| 32 |
+
apps/api/src/services/normalization.ts
|
| 33 |
+
apps/api/src/services/queue.ts
|
| 34 |
+
```
|
| 35 |
+
|
| 36 |
+
**Risque :** Sur un plan Redis Cloud Standard (max 30 connexions), le worker seul peut saturer le pool. En pic de charge, nouvelles connexions refusées → jobs BullMQ échouent en masse.
|
| 37 |
+
|
| 38 |
+
**Correction :** Créer `apps/whatsapp-worker/src/lib/redis.ts` et `apps/api/src/lib/redis.ts` — singletons exportés, importés partout. Un seul `new Redis()` par process.
|
| 39 |
+
|
| 40 |
+
---
|
| 41 |
+
|
| 42 |
+
## 🟡 Important — Qualité & maintenabilité
|
| 43 |
+
|
| 44 |
+
### 3. Pas de rate limiting sur l'API
|
| 45 |
+
|
| 46 |
+
**Problème :** Seulement 2 mentions de rate limiting dans tout le codebase. Les routes publiques (auth, webhook) ne sont pas protégées contre le flooding.
|
| 47 |
+
|
| 48 |
+
**Correction :** Ajouter `@fastify/rate-limit` sur les routes sensibles :
|
| 49 |
+
- `POST /v1/auth/login` → 10 req/min par IP
|
| 50 |
+
- `POST /v1/auth/forgot-password` → 3 req/min par IP
|
| 51 |
+
- `POST /webhook` → déjà protégé par `WHATSAPP_VERIFY_TOKEN`, mais un throttle reste utile
|
| 52 |
+
|
| 53 |
+
---
|
| 54 |
+
|
| 55 |
+
### 4. `alert()` dans le wizard (régresssion de cette session)
|
| 56 |
+
|
| 57 |
+
**Problème :** Le nouveau `OnboardingWizard.tsx` utilise `alert()` natif pour les erreurs (lignes 139 et 157) au lieu du système de toast.
|
| 58 |
+
|
| 59 |
+
**Fichier :** `apps/admin/src/pages/OnboardingWizard.tsx:139`
|
| 60 |
+
|
| 61 |
+
**Correction :** Remplacer par `useToast()` — déjà disponible dans l'app.
|
| 62 |
+
|
| 63 |
+
---
|
| 64 |
+
|
| 65 |
+
### 5. `WhatsAppConnectButton.tsx` — code mort
|
| 66 |
+
|
| 67 |
+
**Problème :** `apps/admin/src/components/WhatsAppConnectButton.tsx` n'est importé nulle part. La connexion WhatsApp est maintenant gérée dans `ClientsManagementView.tsx` et `OnboardingWizard.tsx`.
|
| 68 |
+
|
| 69 |
+
**Correction :** Supprimer le fichier.
|
| 70 |
+
|
| 71 |
+
---
|
| 72 |
+
|
| 73 |
+
### 6. 26 blocs `catch` silencieux
|
| 74 |
+
|
| 75 |
+
**Problème :** 26 blocs `catch {}` ou `catch (e) {}` avalent des erreurs sans les loguer. Certains sont intentionnels (fallbacks Meta API non-fatals), la majorité ne l'est pas.
|
| 76 |
+
|
| 77 |
+
**Correction :** Passer en revue. Les blocs intentionnels doivent avoir un commentaire `/* non-fatal: raison */`. Les autres doivent loguer au minimum avec `logger.warn`.
|
| 78 |
+
|
| 79 |
+
---
|
| 80 |
+
|
| 81 |
+
### 7. 179 `console.*` dans le frontend admin
|
| 82 |
+
|
| 83 |
+
**Problème :** Toutes les pages admin utilisent `console.error/log` directement. En production, ces erreurs sont invisibles sauf si Sentry ou un équivalent est branché.
|
| 84 |
+
|
| 85 |
+
**Impact actuel :** Faible (admin utilisé uniquement par le super admin). Impact futur : élevé dès qu'on active le self-service client.
|
| 86 |
+
|
| 87 |
+
**Correction :** À faire avant le self-service client — centraliser dans un logger frontend ou brancher Sentry.
|
| 88 |
+
|
| 89 |
+
---
|
| 90 |
+
|
| 91 |
+
### 8. Scripts de migration one-off toujours présents
|
| 92 |
+
|
| 93 |
+
**Fichiers :**
|
| 94 |
+
- `apps/api/src/scripts/fix-types.ts` — script de refactoring TypeScript one-shot
|
| 95 |
+
- `apps/api/src/scripts/purge-any.ts` — idem
|
| 96 |
+
- `apps/api/src/scripts/migrate-json-to-sql.ts` — migration de données déjà appliquée
|
| 97 |
+
- `packages/database/sync-days.ts` — outil de sync ponctuel
|
| 98 |
+
|
| 99 |
+
**Correction :** Archiver dans `scripts/archive/` ou supprimer. Ils polluent le répertoire et peuvent induire en erreur sur ce qui est "actif".
|
| 100 |
+
|
| 101 |
+
---
|
| 102 |
+
|
| 103 |
+
## ⚪ Mineur — À surveiller
|
| 104 |
+
|
| 105 |
+
### 9. `as any` sur les réponses JSON Meta API
|
| 106 |
+
|
| 107 |
+
**Localisation :** `apps/api/src/services/organization.ts` (×6 occurrences)
|
| 108 |
+
|
| 109 |
+
**Contexte :** Meta ne publie pas de SDK TypeScript officiel pour son Graph API. Les `as any` sur `.json()` sont acceptables ici mais fragiles si Meta change sa structure de réponse.
|
| 110 |
+
|
| 111 |
+
**Recommandation :** Définir des interfaces locales pour les réponses Meta attendues (ex: `WabaStatusResponse`, `BusinessVerificationResponse`). Pas urgent mais facilite le debugging.
|
| 112 |
+
|
| 113 |
+
---
|
| 114 |
+
|
| 115 |
+
### 10. Token Meta — absence de date d'émission
|
| 116 |
+
|
| 117 |
+
Complément du point #1. Le champ `systemUserTokenIssuedAt` n'existe pas en base. Même sans le cron d'alerte, stocker cette date dès maintenant permettrait de calculer l'ancienneté du token dans le dashboard Meta Status.
|
| 118 |
+
|
| 119 |
+
---
|
| 120 |
+
|
| 121 |
+
## Récapitulatif priorités
|
| 122 |
+
|
| 123 |
+
| # | Sévérité | Effort | Priorité |
|
| 124 |
+
|---|----------|--------|----------|
|
| 125 |
+
| 1. Expiration token Meta | 🔴 Critique | Moyen | **P0 — avant prochain client** |
|
| 126 |
+
| 2. Redis singleton | 🔴 Critique | Faible | **P0 — avant scaling** |
|
| 127 |
+
| 3. Rate limiting | 🟡 Important | Faible | P1 |
|
| 128 |
+
| 4. `alert()` wizard | 🟡 Important | Très faible | P1 — quick win |
|
| 129 |
+
| 5. Code mort WhatsAppConnectButton | 🟡 Important | Très faible | P1 — quick win |
|
| 130 |
+
| 6. Catch silencieux | 🟡 Important | Moyen | P2 |
|
| 131 |
+
| 7. Console frontend | 🟡 Important | Élevé | P2 — avant self-service |
|
| 132 |
+
| 8. Scripts one-off | ⚪ Mineur | Très faible | P3 |
|
| 133 |
+
| 9. Types réponses Meta | ⚪ Mineur | Moyen | P3 |
|
| 134 |
+
| 10. Date émission token | ⚪ Mineur | Faible | Couplé à #1 |
|