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 files

Replaces 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
- alert(`Erreur : ${err.message || 'Création impossible'}`);
140
  } finally {
141
  setLoading(false);
142
  }
@@ -154,7 +156,7 @@ export default function OnboardingWizard() {
154
  skip: false,
155
  }));
156
  } catch {
157
- alert('La connexion Facebook a été annulée ou a échoué.');
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 |