257 lines
14 KiB
Markdown
257 lines
14 KiB
Markdown
# TECH_DEBT.md — Expria Frontend
|
|
|
|
> **Document de référence — Version 1.2**
|
|
> Ce document recense les décisions techniques prises par pragmatisme qui devront être revisitées, les stubs temporaires, et les fonctionnalités reportées.
|
|
> À mettre à jour après chaque session de développement.
|
|
>
|
|
> Format : chaque entrée a un identifiant (FTD-XX pour **Frontend Tech Debt**, différent des `TD-XX` backend), une priorité, un statut.
|
|
> Priorités : 🔴 Critique (bloque la production) / 🟡 Important / 🟢 Mineur
|
|
|
|
---
|
|
|
|
## Politique de gestion de la dette
|
|
|
|
Pour éviter que ce document devienne un cimetière de dette ignorée (le piège classique documenté dans `ONBOARDING.md`) :
|
|
|
|
- **Maximum 15 FTD actives simultanément.** Au-delà, priorisation obligatoire avant d'en ajouter une nouvelle.
|
|
- **Chaque release production doit résoudre au moins 1 FTD de priorité ≥ 🟡.**
|
|
- **Toute FTD 🔴 doit être résolue dans la session suivante** ou bloquer la release.
|
|
- **Revue trimestrielle** du document (Hermann + futur dev).
|
|
- **Chaque FTD doit avoir une estimation de session** (1h, 1 jour, 3 jours) pour permettre la priorisation.
|
|
|
|
---
|
|
|
|
## 1. Dettes héritées de l'audit backend (2026-04-17)
|
|
|
|
### FTD-01 — Inconsistance des codes de validation côté backend
|
|
**Priorité :** 🟡 Important
|
|
**Statut :** Ouvert — dépend du backend
|
|
**Estimation de session :** 2h (backend uniquement)
|
|
**Description :** Le backend utilise deux codes d'erreur pour la même classe (corps de requête invalide) :
|
|
- `VALIDATION_ERROR` dans `routes/simulations.ts` et `routes/corrections.ts`
|
|
- `INVALID_BODY` dans `routes/plans.ts` et `routes/stripe.ts`
|
|
|
|
Le frontend gère les deux de la même manière (voir `ARCHITECTURE.md` §5), mais c'est une odeur de code qui devrait être unifiée.
|
|
|
|
**Action côté frontend :** aucune — on gère les deux codes.
|
|
**Action côté backend :** unifier sous `VALIDATION_ERROR` (plus explicite), session dédiée à ouvrir via **TD-15** dans `expria-backend/docs/TECH_DEBT.md`.
|
|
|
|
**Condition de résolution :** après résolution de TD-15 backend, simplifier le switch dans les handlers frontend pour ne traiter que `VALIDATION_ERROR`.
|
|
|
|
---
|
|
|
|
### FTD-02 — Header `X-API-Version` envoyé mais non vérifié
|
|
**Priorité :** 🟡 Important
|
|
**Statut :** Ouvert
|
|
**Estimation de session :** 1h (backend) + 30min (frontend)
|
|
**Description :** Le frontend envoie le header `X-API-Version: 1.0` sur toutes les requêtes API (cf. `ARCHITECTURE.md` §5). Le backend ne le vérifie pas actuellement — donc en pratique, aucune incompatibilité de version ne sera détectée automatiquement.
|
|
|
|
**Impact :** si le backend évolue de façon breaking (ex : format de réponse de `/plans/status` modifié), le frontend peut recevoir un payload incompatible sans message d'erreur clair. Symptôme : bugs silencieux en production après un déploiement backend.
|
|
|
|
**À faire :**
|
|
- Backend : ajouter un middleware qui lit `X-API-Version`, le log, et retourne `HTTP 426 Upgrade Required` avec code `API_VERSION_MISMATCH` si breaking change
|
|
- Frontend : gérer `API_VERSION_MISMATCH` dans `api-client.ts` → afficher un message "Une nouvelle version est disponible, veuillez rafraîchir la page"
|
|
|
|
**Condition de résolution :** avant l'arrivée d'un dev externe (qui pourrait modifier le backend sans coordination).
|
|
|
|
---
|
|
|
|
### FTD-03 — Quirk `status` dans le body des erreurs de simulations/corrections
|
|
**Priorité :** 🟢 Mineur
|
|
**Statut :** Ouvert — dépend du backend
|
|
**Estimation de session :** 1h (backend uniquement)
|
|
**Description :** Les routes `POST /simulations` et `POST /corrections/ee,eo` renvoient un champ `status` dans le body JSON d'erreur, qui duplique le code HTTP :
|
|
```json
|
|
{ "error": true, "code": "QUOTA_REACHED", "message": "...", "status": 403 }
|
|
```
|
|
Vient du pattern `c.json(result, result.status)` où `result` contient déjà `status`. C'est ignorable côté frontend (on ne lit pas ce champ), mais c'est du bruit.
|
|
|
|
**À faire côté backend :** nettoyer les objets d'erreur retournés par `simulationController` et `correctionController` pour ne pas contenir de champ `status`. Tracé dans **TD-16** à créer dans `expria-backend/docs/TECH_DEBT.md`.
|
|
|
|
**Condition de résolution :** session de nettoyage backend, non urgente.
|
|
|
|
---
|
|
|
|
## 2. Dettes frontend propres
|
|
|
|
### FTD-04 — Documents miroir sans automatisation de synchronisation
|
|
**Priorité :** 🟢 Mineur
|
|
**Statut :** Ouvert — accepté par design (voir ADR 004)
|
|
**Estimation de session :** 1 jour (mise en place monorepo)
|
|
**Description :** Les documents `PLANS_TARIFAIRES.md`, `PARCOURS_UTILISATEURS.md`, et le fichier de code `src/entities/user/access.ts` existent à l'identique dans les deux dépôts (frontend et backend). La synchronisation est manuelle — si un changement est fait dans un dépôt sans être répercuté dans l'autre, divergence silencieuse.
|
|
|
|
**Mitigation actuelle :**
|
|
- Règle G de `DEVELOPMENT_PRINCIPLES.md` (modifications simultanées dans le même commit logique)
|
|
- Commentaire `// SOURCE OF TRUTH:` en tête de `access.ts`
|
|
- Tests de parité dans `src/entities/user/__tests__/access.test.ts` (calqués sur les tests backend)
|
|
|
|
**À faire si la dette devient trop coûteuse :**
|
|
- Migrer vers un monorepo pnpm workspaces avec package partagé `@expria/types-and-access`
|
|
- OU ajouter un script CI qui vérifie que le hash SHA-256 de `access.ts` matche entre les deux dépôts
|
|
|
|
**Condition de résolution :** après 3+ mois de production stable, ou si une divergence silencieuse cause un bug.
|
|
|
|
---
|
|
|
|
### FTD-05 — Ancien scaffold frontend possiblement caduc
|
|
**Priorité :** 🟡 Important
|
|
**Statut :** Ouvert — diagnostic en cours (session Claude Code)
|
|
**Estimation de session :** variable selon diagnostic
|
|
**Description :** Un scaffold frontend a été créé au démarrage du projet (fin mars 2026 ou début avril 2026), avant que les décisions architecturales récentes (entities/features/shared, auth-client/api-client découplés, pas de Zustand, etc.) ne soient prises. Le contenu actuel de `D:\expria-frontend\` peut donc contenir des fichiers qui ne matchent plus l'architecture cible.
|
|
|
|
**À faire :** session Claude Code (première session frontend de la V2) qui fait un état des lieux complet et propose une stratégie (clean slate / refactor progressif / adaptation en place). Cf. prompt de session dans l'historique de conversation Claude AI du 2026-04-17.
|
|
|
|
**Condition de résolution :** fin du Sprint 0 (scaffold conforme à `ARCHITECTURE.md`).
|
|
|
|
---
|
|
|
|
### FTD-10 — Semgrep non intégré en CI
|
|
**Priorité :** 🟢 Mineur
|
|
**Statut :** Reporté — après MVP
|
|
**Estimation de session :** 2h
|
|
**Description :** `ARCHITECTURE.md` §CI mentionne `semgrep scan (via plugin)` dans le workflow CI cible. L'étape 10 du Sprint 0 n'a intégré que `lint`, `format:check`, `typecheck`, `test`, `npm audit --audit-level=high` — Semgrep a été volontairement différé pour respecter la règle de scope (max 2-3 fichiers par étape).
|
|
|
|
**Impact actuel :** `npm audit` couvre les vulnérabilités des dépendances npm, mais aucune analyse statique de sécurité (SAST) n'est faite sur le code custom du projet. Des patterns dangereux (`eval`, `innerHTML` sans DOMPurify, secrets en dur, etc.) passeraient inaperçus en CI.
|
|
|
|
**À faire :**
|
|
- Ajouter un step Semgrep au workflow `.github/workflows/ci.yml`
|
|
- Utiliser les rulesets `auto` + `r2c-security-audit` + `r2c-ci`
|
|
- Configurer la sortie pour bloquer sur sévérité ERROR uniquement
|
|
- Documenter dans SEC-08 de `SECURITY.md`
|
|
|
|
**Condition de résolution :** avant l'arrivée d'un dev externe (même raisonnement que FTD-02).
|
|
|
|
---
|
|
|
|
### FTD-11 — `@theme` Tailwind 4 non défini
|
|
**Priorité :** 🟢 Mineur
|
|
**Statut :** Ouvert — à faire dans session design system
|
|
**Estimation de session :** 1 jour (palette + typo + itérations design)
|
|
**Description :** `src/index.css` a été nettoyé à l'étape 11 du Sprint 0 et réduit à la seule ligne `@import 'tailwindcss';`. L'ADR 006 (§Configuration Tailwind 4) décrit le bloc `@theme { ... }` comme le mécanisme officiel de configuration Tailwind 4 (CSS-first) :
|
|
|
|
```css
|
|
@theme {
|
|
--color-primary: #1B4FD8;
|
|
--font-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
|
|
}
|
|
```
|
|
|
|
La palette brand Expria et la typographie ne sont pas encore décidées, donc `@theme` est volontairement absent pour ne pas poser de valeurs placeholder qu'il faudrait repasser plus tard.
|
|
|
|
**Impact actuel :** les composants utilisent les couleurs Tailwind par défaut (`bg-slate-*`, `text-gray-*`). Visuellement cohérent mais pas brand.
|
|
|
|
**À faire au Sprint 1 (design system) :**
|
|
- Définir la palette brand Expria (primary, secondary, neutrals, danger, success)
|
|
- Choisir + installer la typo (Plus Jakarta Sans ou autre) via `<link>` dans `index.html` ou `@import` dans `index.css`
|
|
- Ajouter le bloc `@theme` dans `src/index.css`
|
|
- Mettre à jour ADR 006 avec les valeurs retenues
|
|
|
|
**Condition de résolution :** Sprint 1 — session dédiée au design system.
|
|
|
|
---
|
|
|
|
## 3. Fonctionnalités reportées
|
|
|
|
### FTD-06 — AudioWorklet au lieu de ScriptProcessorNode (T2 Live)
|
|
**Priorité :** 🟢 Mineur
|
|
**Statut :** Reporté à après le lancement MVP
|
|
**Estimation de session :** 1 jour
|
|
**Description :** Hérité du backend (TD-09). Côté frontend, le traitement audio pour la T2 Live (capture PCM 16kHz) devra probablement utiliser `AudioWorklet` au lieu de `ScriptProcessorNode` qui est déprécié.
|
|
|
|
**Impact actuel :** fonctionne avec warnings dans la console. Peut poser problème sur certains navigateurs futurs.
|
|
|
|
**À faire :** session dédiée après le lancement MVP, pour migrer le pipeline audio vers AudioWorklet.
|
|
|
|
**Condition de résolution :** après 30 jours de production stable.
|
|
|
|
---
|
|
|
|
### FTD-07 — Sentry non intégré
|
|
**Priorité :** 🟡 Important
|
|
**Statut :** Planifié — après MVP
|
|
**Estimation de session :** 3h
|
|
**Description :** Le monitoring frontend (erreurs JS, performances, sessions) n'est pas encore en place. Sans Sentry (ou équivalent), les bugs en production ne remontent pas — on les découvre uniquement si un utilisateur prend la peine de les signaler.
|
|
|
|
**À faire :**
|
|
- Créer un compte Sentry (tier gratuit suffit pour démarrer)
|
|
- Ajouter `@sentry/react` au projet
|
|
- Intégrer dans `src/app/providers.tsx`
|
|
- Ajouter `VITE_SENTRY_DSN` dans les variables d'environnement
|
|
- Configurer le filtrage des données sensibles (JWT, emails)
|
|
- Mettre à jour SEC-11 dans `SECURITY.md`
|
|
|
|
**Condition de résolution :** avant la première vague d'utilisateurs post-MVP (30 jours après lancement).
|
|
|
|
---
|
|
|
|
### FTD-08 — Tests E2E non implémentés
|
|
**Priorité :** 🟢 Mineur
|
|
**Statut :** Reporté — accepté par design
|
|
**Estimation de session :** 2 jours (Playwright setup)
|
|
**Description :** Actuellement, les tests de bout en bout sont manuels (via `GOLDEN_DATASET.md`). Une automatisation avec Playwright permettrait de détecter les régressions UI sans effort humain.
|
|
|
|
**À faire :** session Playwright setup après MVP, pour automatiser au minimum les 10 scénarios du Groupe Z (smoke test).
|
|
|
|
**Condition de résolution :** quand la maintenance manuelle du Golden Dataset devient trop chronophage.
|
|
|
|
---
|
|
|
|
## 4. Tests à renforcer
|
|
|
|
### FTD-09 — Tests de la state machine T2 Live non implémentés
|
|
**Priorité :** 🟡 Important
|
|
**Statut :** Planifié — à créer au Sprint 2.5
|
|
**Estimation de session :** 3h
|
|
**Description :** La state machine T2 Live (`src/features/t2-live/state/t2-machine.ts`) n'existe pas encore. Quand elle sera créée, elle devra être testée de manière exhaustive (6+ tests couvrant les transitions d'états et les cas d'erreur).
|
|
|
|
**À faire au Sprint 2.5 (spike T2 Live) :**
|
|
- Créer `t2-machine.test.ts` avec tests des transitions : idle → connecting, connecting → listening, listening ↔ speaking, * → error, * → ended
|
|
- Tests des messages d'erreur (close code 4001, 4003, autre)
|
|
|
|
**Condition de résolution :** fin Sprint 2.5.
|
|
|
|
---
|
|
|
|
### FTD-12 — Tests automatisés manquants pour `api-client.ts`
|
|
**Priorité :** 🟡 Important
|
|
**Statut :** Ouvert — à faire avant intégration des features critiques
|
|
**Estimation de session :** 3h
|
|
**Description :** Le wrapper `apiFetch` dans `src/shared/lib/api-client.ts` (créé à l'étape 7b du Sprint 0) contient une logique critique non couverte par des tests automatisés : timeout via `AbortSignal.timeout`, retry avec backoff exponentiel, stratégie d'idempotence (retry `GET`/`HEAD`/`PUT`/`DELETE` uniquement), parsing des erreurs backend (`ApiError`) vs frontend (`ClientError`), construction des headers (`Authorization`, `X-API-Version`, `Content-Type`).
|
|
|
|
**Impact actuel :** toute régression sur ce fichier (oubli d'un header, mauvais parsing d'une erreur, boucle de retry infinie sur un edge case) passera inaperçue jusqu'aux tests manuels ou à un bug en production.
|
|
|
|
**À faire :**
|
|
- Créer `src/shared/lib/__tests__/api-client.test.ts`
|
|
- Mocker globalement `fetch` via `vi.fn()`
|
|
- Couvrir :
|
|
- Succès 2xx → retourne le payload parsé
|
|
- Erreur 4xx `ApiError` bien parsée → throw conforme
|
|
- Erreur 4xx body non-JSON → fallback `INTERNAL_ERROR`
|
|
- Erreur 5xx avec retry → max 2 retries puis throw
|
|
- Timeout → `ClientError` code `TIMEOUT`
|
|
- Erreur réseau (fetch reject) → `ClientError` code `NETWORK_ERROR` + retry
|
|
- Parsing succès JSON invalide → `ClientError` code `PARSE_ERROR`
|
|
- Retry désactivé sur POST/PATCH par défaut (non-idempotent)
|
|
- Bearer omis sur `/health`
|
|
- Bearer injecté avec token valide depuis `auth-client`
|
|
- Objectif : ≥ 10 tests, couverture complète des branches
|
|
|
|
**Condition de résolution :** avant l'intégration des hooks TanStack Query sur des features critiques (dashboard, simulations, auth).
|
|
|
|
---
|
|
|
|
## 5. Historique des résolutions
|
|
|
|
| ID | Description | Résolu le | Comment |
|
|
|---|---|---|---|
|
|
| FTD-13 | Incompatibilité Vitest 3 / Vite 8 (conflit de types `Plugin<any>` entre le Vite 8 top-level avec Rolldown et le Vite 7 pinné de Vitest 3.2.4 ; `npm run build` cassé) | 2026-04-17 | Résolu par upgrade Vitest `3.2.4 → 4.1.4` (et `@vitest/coverage-v8` idem) à l'étape 12-bis du Sprint 0. Vitest 4.x supporte nativement Vite 8 Rolldown. Correctif complémentaire : script `typecheck` passé de `tsc --noEmit -p tsconfig.app.json` à `tsc -b --noEmit` pour couvrir aussi `tsconfig.node.json` (d'où `vite.config.ts`) et éviter qu'un bug similaire échappe à la CI. |
|
|
|
|
---
|
|
|
|
## 6. Historique de ce document
|
|
|
|
| Version | Date | Changements |
|
|
|---|---|---|
|
|
| 1.0 | 2026-04-17 | Création initiale avec 9 FTD identifiées depuis l'audit backend et les décisions d'architecture |
|
|
| 1.1 | 2026-04-17 | Ajout FTD-10 (Semgrep CI), FTD-11 (`@theme` Tailwind 4), FTD-12 (tests `api-client`) suite à l'étape 11 du Sprint 0 |
|
|
| 1.2 | 2026-04-17 | Ajout FTD-13 résolu (incompatibilité Vitest 3 / Vite 8) suite à l'étape 12-bis du Sprint 0 |
|