386 lines
24 KiB
Markdown
386 lines
24 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.
|
|
|
|
---
|
|
|
|
### FTD-20 — `GET /simulations/:id` manquant dans le backend
|
|
**Priorité :** 🔴 Critique (bloque RapportPage — Sprint 3 étape 15)
|
|
**Statut :** Ouvert — session backend requise
|
|
**Estimation de session :** 2h (backend)
|
|
**Description :** Le backend n'expose pas de route de lecture pour récupérer une simulation et son rapport après correction. `POST /corrections/ee` retourne le rapport dans sa réponse mais celui-ci n'est pas persisté côté frontend entre les navigations. `RapportPage` appelle `GET /simulations/:id` via `getReport()` + `useRapport()` — la route retourne 404 côté backend.
|
|
|
|
**Contexte frontend :** `src/entities/report/api.ts` — `getReport(id)`, `src/features/simulations/hooks/useRapport.ts`, `src/features/simulations/pages/RapportPage.tsx` sont implémentés et typechecked. Ils fonctionneront dès que le backend expose la route.
|
|
|
|
**À faire (session backend) :**
|
|
- Ajouter `GET /simulations/:id` dans `expria-backend/src/routes/simulations.ts`
|
|
- Retourner : `id`, `tache`, `mode`, `score`, `nclc`, `feedback_court`, `criteres`, `erreurs`, `modele`, `idees`, `exercices`
|
|
- Appliquer `authMiddleware` + vérifier que la simulation appartient à l'utilisateur connecté
|
|
- Retourner `SIMULATION_NOT_FOUND` (404) si la simulation n'existe pas ou appartient à un autre utilisateur
|
|
|
|
**Condition de résolution :** après implémentation backend + test manuel RapportPage complet (Free, Standard, Premium).
|
|
|
|
---
|
|
|
|
## 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-14 — Anti-FOUC thème : script inline manquant dans `<head>`
|
|
**Priorité :** 🟡 Important
|
|
**Statut :** Ouvert — à faire avant déploiement production
|
|
**Estimation de session :** 30 min
|
|
**Description :** Le `ThemeProvider` applique la classe `.dark` sur `<html>` après l'hydratation React (`useEffect`). Entre le premier paint du navigateur et l'exécution de React, la page s'affiche brièvement en mode clair même si l'utilisateur a choisi le mode sombre — c'est le FOUC (Flash Of Unstyled Content).
|
|
|
|
**Fix :** ajouter un script inline bloquant dans le `<head>` de `index.html` qui lit `localStorage.getItem('expria-theme')` (et `prefers-color-scheme` en fallback) et applique `.dark` sur `document.documentElement` avant le premier paint. Ce script doit être minifié et inliné (non-async, non-defer) pour garantir l'exécution avant le CSS.
|
|
|
|
```html
|
|
<script>
|
|
(function(){var t=localStorage.getItem('expria-theme');
|
|
if(t==='dark'||(t!=='light'&&matchMedia('(prefers-color-scheme:dark)').matches))
|
|
document.documentElement.classList.add('dark')})()
|
|
</script>
|
|
```
|
|
|
|
**Impact actuel :** visible uniquement pour les utilisateurs en mode sombre — bref flash de fond clair au chargement. Acceptable en dev, indésirable en production.
|
|
|
|
**Condition de résolution :** avant la première mise en production (Sprint 1 ou avant).
|
|
|
|
---
|
|
|
|
### FTD-15 — Option `'system'` manquante dans ThemeProvider
|
|
**Priorité :** 🟢 Mineur
|
|
**Statut :** Reporté — après MVP
|
|
**Estimation de session :** 2h
|
|
**Description :** Le `ThemeProvider` est bi-state (`'light' | 'dark'`). L'option `'system'` (qui suit `prefers-color-scheme` en temps réel via `MediaQueryList.addEventListener`) a été volontairement différée (décision Sprint 0.5).
|
|
|
|
**À faire :**
|
|
- Étendre le type `Theme` à `'light' | 'dark' | 'system'`
|
|
- Dans `ThemeProvider`, si `theme === 'system'` : écouter `matchMedia('(prefers-color-scheme: dark)')` et appliquer/retirer `.dark` dynamiquement
|
|
- `ThemeToggle` : cycle light → dark → system (ou un sélecteur 3 états)
|
|
- Mettre à jour `getInitialTheme()` pour retourner `'system'` si aucune préférence stockée
|
|
|
|
**Condition de résolution :** après MVP — confort utilisateur, pas bloquant.
|
|
|
|
---
|
|
|
|
### FTD-17 — Clé `['plan']` dupliquée entre features
|
|
**Priorité :** 🟢 Mineur
|
|
**Statut :** Ouvert — accepté par design (Sprint 3)
|
|
**Estimation de session :** 30 min
|
|
**Description :** La queryKey TanStack Query `['plan']` est écrite littéralement dans deux endroits : `features/dashboard/hooks/usePlan.ts` (via `PLAN_QUERY_KEY`) et `features/simulations/pages/SimulationPage.tsx` (inline). TanStack Query partage bien le cache par clé identique, donc la déduplication fonctionne en pratique. Mais toute faute de frappe dans l'une des occurrences briserait silencieusement la mise en cache partagée.
|
|
|
|
**À faire :**
|
|
- Déplacer `PLAN_QUERY_KEY` vers `src/entities/user/api.ts` (ou un nouveau `src/entities/user/query-keys.ts`)
|
|
- Importer `PLAN_QUERY_KEY` dans `usePlan.ts` et `SimulationPage.tsx` depuis ce fichier partagé
|
|
- Supprimer la constante locale dans `usePlan.ts`
|
|
|
|
**Condition de résolution :** avant l'ajout d'une troisième feature qui consomme `['plan']` (T2 Live page, rapport page).
|
|
|
|
---
|
|
|
|
### FTD-18 — SimulationForm utilise encore shadcn Button
|
|
**Priorité :** 🟢 Mineur
|
|
**Statut :** Ouvert
|
|
**Estimation de session :** 30 min
|
|
**Description :** `src/features/simulations/components/SimulationForm.tsx` importe `Button` depuis `@/shared/components/ui/button` (shadcn). Depuis Sprint 0.5 bis, la primitive canonique est `@/shared/ui/Button`. SimulationForm a été volontairement exclu de l'étape D1 pour respecter la règle max 3 fichiers par étape.
|
|
|
|
**À faire :**
|
|
- Remplacer l'import shadcn par `@/shared/ui/Button`
|
|
- Adapter `variant` si nécessaire (`"outline"` → `"secondary"`)
|
|
|
|
**Condition de résolution :** session dédiée — à grouper avec d'autres migrations shadcn → shared/ui si elles surviennent.
|
|
|
|
---
|
|
|
|
### FTD-19 — Token `--shadow-focus` absent de `src/index.css`
|
|
**Priorité :** 🟢 Mineur
|
|
**Statut :** Ouvert
|
|
**Estimation de session :** 15 min
|
|
**Description :** `DESIGN_SYSTEM.md` spécifie un token `--shadow-focus` pour les états focus des composants interactifs. Ce token n'a jamais été ajouté à `src/index.css`. En attendant, le focus est rendu via `ring-2 ring-expria/20` (token Direction H valide), utilisé dans `Button`, `Card`, `MobileHeader`. Le rendu visuel est correct mais ne correspond pas au token documenté.
|
|
|
|
**À faire :**
|
|
- Ajouter `--shadow-focus` dans `@theme {}` de `src/index.css` (valeur à aligner avec `DESIGN_SYSTEM.md`)
|
|
- Remplacer `ring-2 ring-expria/20` par `shadow-focus` dans les composants concernés
|
|
|
|
**Condition de résolution :** session design system dédiée (peut être groupée avec FTD-15 ou une refonte de tokens).
|
|
|
|
---
|
|
|
|
## 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.
|
|
|
|
---
|
|
|
|
### FTD-21 — Persistance session simulation
|
|
**Priorité :** 🔴 Critique
|
|
**Statut :** Partiellement résolu — `/simulation/ee` ✅ (2026-04-21)
|
|
|
|
**Pages concernées par ordre de priorité :**
|
|
|
|
✅ **`/simulation/ee`** (résolu 2026-04-21)
|
|
- Autosave contenu toutes les 30 s (`useAutosave`)
|
|
- Save on `beforeunload`
|
|
- Reprise au refresh via `localStorage` (`expria_simulation_id`) + `GET /simulations/:id`
|
|
- `PATCH /simulations/:id/contenu` + `PATCH /simulations/:id/sujet` (Option C)
|
|
- `getById` tolère `rapport=null` (Option A)
|
|
- `RapportPage` redirige vers `/simulation/ee` si simulation en cours
|
|
|
|
🟡 **`/simulation/eo`** (Sprint 4 — ouvert)
|
|
- Identique EE + état audio/enregistrement
|
|
|
|
🟡 **`/examen`** (Sprint 7 — ouvert)
|
|
- Autosave critique — timer inarrêtable + 3 tâches
|
|
- Crash pendant examen = perte totale
|
|
|
|
🟢 **`/sujets`** (inclus dans la résolution EE)
|
|
- `localStorage simulation_id` suffit
|
|
- Pas d'autosave (pas de données saisies)
|
|
|
|
❌ **Pas nécessaire :** `/dashboard`, `/rapport/:id`, `/historique`, `/progression`
|
|
|
|
**Résolution EE livrée (2026-04-21) :**
|
|
|
|
Backend :
|
|
- `simulationController.create` persiste `sujet_id` à la création
|
|
- `getById` retourne `SimulationState` (tolère `rapport=null` pour resume)
|
|
- `autosaveContenu` + `updateSujet` controllers (refuse si `rapport !== null`)
|
|
- Routes `PATCH /simulations/:id/contenu` + `PATCH /simulations/:id/sujet`
|
|
- CORS : `allowMethods` étendu à PATCH/PUT/DELETE
|
|
|
|
Frontend :
|
|
- `useAutosave` : debounce 30 s + `beforeunload` flush + dedup par contenu
|
|
- `SimulationForm` : hydrate `initialContenu`, affiche "Sauvegardé à HH:MM"
|
|
- `SimulationFlowProvider` : hydratation au montage depuis `localStorage` → restaure step `task-selected` si rapport null, nettoie sinon
|
|
- `getReport` délègue à `getSimulationState` et throw `REPORT_NOT_READY` si rapport null
|
|
|
|
**Condition de résolution complète :** intégration EO (Sprint 4) + examen (Sprint 7).
|
|
|
|
---
|
|
|
|
## 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-11 | `@theme` Tailwind 4 non défini — palette et typographie absentes | 2026-04-18 | Résolu au Sprint 0.5 (design system). Palette Direction H complète (canvas/surface/ink/expria/deep/semantic) + typo Plus Jakarta Sans définis dans `src/index.css` via `@theme {}` et `.dark {}`. shadcn/ui remappé sur ces tokens. Règle L ajoutée dans `DEVELOPMENT_PRINCIPLES.md` pour garantir l'usage exclusif des tokens. |
|
|
| 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. |
|
|
| FTD-16 | `VITE_MAINTENANCE_MODE` non lu dans le code — la variable d'env était dans `env.ts` mais jamais consommée | 2026-04-18 | Résolu au Sprint 1 étape 6. Ajout de `isMaintenanceMode` dans `src/shared/config/env.ts` et garde dans `src/app/main.tsx` : `isMaintenanceMode ? <MaintenancePage /> : <Providers />`. `MaintenancePage` est statique (aucun provider requis), tokens Direction H exclusivement. |
|
|
| FTD-22 | Code orphelin suite à la refonte UX `/sujets` (2026-04-21) — composant `SujetSelector` et helper `selectSujet` plus référencés après bascule dropdown → page dédiée | 2026-04-21 | Résolu **partiellement**. Supprimé : `src/features/simulations/components/SujetSelector.tsx` + helper `selectSujet` de `useSimulation.ts` (les tests `useSimulation.test.tsx` adaptés en utilisant `changeSubject` + `setStep('task-selected')` via `useSimulationFlow`). **Conservés intentionnellement** : le step `'choosing-subject'` (utilisé par `SimulationFlowProvider.selectTask` pour les tâches avec catalogue et par `SimulationPage` pour naviguer vers `/sujets`) et le helper `goToSubjectPicker` (bouton "Changer de sujet" dans `SimulationForm`). |
|
|
|
|
---
|
|
|
|
## 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 |
|
|
| 1.3 | 2026-04-18 | FTD-11 résolu (design system Sprint 0.5) ; ajout FTD-14 (anti-FOUC), FTD-15 (option 'system' thème) |
|
|
| 1.4 | 2026-04-18 | FTD-16 résolu (VITE_MAINTENANCE_MODE implémenté — Sprint 1 étape 6) |
|
|
| 1.5 | 2026-04-19 | Ajout FTD-17 (clé ['plan'] dupliquée entre features — Sprint 3 étape 14) |
|
|
| 1.6 | 2026-04-20 | Ajout FTD-18 (SimulationForm shadcn Button — Sprint 0.5 bis D2) ; ajout FTD-19 (token --shadow-focus manquant — Sprint 0.5 bis D2) |
|
|
| 1.7 | 2026-04-20 | Ajout FTD-20 🔴 (GET /simulations/:id manquant backend — bloque RapportPage Sprint 3 étape 15) |
|
|
| 1.8 | 2026-04-20 | Ajout FTD-21 🔴 (persistance session simulation — prod + sujet perdus au refresh, session dédiée après G1-G5) |
|
|
| 1.9 | 2026-04-21 | FTD-22 résolu partiellement (nettoyage code orphelin refonte `/sujets` — `SujetSelector` + `selectSujet` supprimés ; `choosing-subject` + `goToSubjectPicker` conservés) |
|
|
| 1.10 | 2026-04-21 | FTD-21 résolu partiellement pour `/simulation/ee` (autosave 30 s + `beforeunload` + reprise via `localStorage` + `PATCH /:id/contenu` + `PATCH /:id/sujet` + `getById` tolère `rapport=null`) ; EO + examen restent ouverts |
|