{
"metadata": {
"version": "1.0.0",
"date": "2026-01-06",
"total_problemes": 75,
"description": "Liste exhaustive de problèmes identifiés dans l'application Veza, triés par gravité. Chaque problème contient les informations nécessaires pour sa résolution.",
"problemes_resolus": 50,
"problemes_pending": 25
},
"problemes": [
{
"id": 1,
"gravite": "CRITIQUE",
"categorie": "Authentification",
"titre": "Store Zustand ne se met pas à jour après login - redirection échoue",
"description": "Après un login réussi, le store Zustand n'est pas correctement persisté dans localStorage. Le token est stocké mais le store montre user: null et isAuthenticated: false, empêchant la redirection vers /dashboard.",
"fichiers_concernes": [
"apps/web/src/features/auth/store/authStore.ts",
"apps/web/src/features/auth/hooks/useLogin.ts",
"apps/web/src/features/auth/pages/LoginPage.tsx"
],
"lignes_approximatives": [
"authStore.ts:44-110",
"useLogin.ts:1-25",
"LoginPage.tsx:85-95"
],
"symptomes": [
"Token présent dans localStorage (veza_access_token)",
"Store montre user: null et isAuthenticated: false",
"Redirection vers /dashboard échoue",
"Utilisateur reste sur /login même après login réussi"
],
"cause_probable": "Le système de retry dans login() ne synchronise pas correctement le store avec localStorage. Zustand persist synchronise de manière asynchrone et le délai de 50ms n'est pas suffisant.",
"solution_proposee": "Améliorer le système de retry avec un délai plus long ou utiliser l'API Zustand persist pour vérifier la synchronisation. Forcer la synchronisation avec persist.getOptions().storage.sync.",
"tests_a_effectuer": [
"Tester le login et vérifier que le store est bien persisté",
"Vérifier la redirection vers /dashboard",
"Tester la navigation après login"
],
"priorite": 1,
"impact": "Bloque complètement l'utilisation de l'application après connexion",
"statut": "fixed",
"date_correction": "2026-01-06",
"notes_correction": "Amélioration du système de synchronisation Zustand persist avec vérification directe du store et localStorage. Augmentation du nombre de tentatives (20) et délai (100ms). Vérification de la cohérence entre store et localStorage."
},
{
"id": 2,
"gravite": "CRITIQUE",
"categorie": "Authentification",
"titre": "Store se réinitialise après navigation vers certaines pages",
"description": "Après navigation vers certaines pages (ex: /analytics), le store Zustand se réinitialise (user: null, isAuthenticated: false) même si le token est présent, causant une redirection vers /login.",
"fichiers_concernes": [
"apps/web/src/features/auth/store/authStore.ts",
"apps/web/src/utils/stateHydration.ts",
"apps/web/src/app/App.tsx"
],
"lignes_approximatives": [
"authStore.ts:192-213 (refreshUser)",
"authStore.ts:240-258 (checkAuthStatus)",
"stateHydration.ts:154-167"
],
"symptomes": [
"Navigation vers /analytics redirige vers /login",
"Store montre user: null après navigation",
"Token toujours présent dans localStorage"
],
"cause_probable": "refreshUser() ou checkAuthStatus() est appelé lors de la navigation et échoue (erreur non-401), réinitialisant l'état même si l'utilisateur était authentifié.",
"solution_proposee": "Modifier refreshUser() et checkAuthStatus() pour préserver l'état existant pour les erreurs non-401. Ne réinitialiser que pour les erreurs 401/1001/1002.",
"tests_a_effectuer": [
"Naviguer vers différentes pages après login",
"Vérifier que le store reste authentifié",
"Tester avec des erreurs réseau simulées"
],
"priorite": 2,
"impact": "Empêche la navigation dans l'application après connexion",
"statut": "fixed",
"date_correction": "2026-01-06",
"notes_correction": "Renforcement de la logique de préservation de l'état dans refreshUser() et checkAuthStatus(). L'état est maintenant préservé pour toutes les erreurs non-401. Sauvegarde de l'utilisateur actuel avant toute modification. Vérification de l'état avant réinitialisation dans les cas sans tokens."
},
{
"id": 3,
"gravite": "HAUTE",
"categorie": "API",
"titre": "Endpoint /analytics retourne 404",
"description": "L'endpoint GET /api/v1/analytics?days=30 retourne 404 page not found même si le handler GetAnalytics existe et la route est enregistrée.",
"fichiers_concernes": [
"veza-backend-api/internal/api/router.go",
"veza-backend-api/internal/handlers/analytics_handler.go"
],
"lignes_approximatives": [
"router.go:1050",
"analytics_handler.go:465"
],
"symptomes": [
"GET /api/v1/analytics retourne 404",
"Token valide présent",
"Backend répond (health check OK)"
],
"cause_probable": "La route n'est pas correctement enregistrée ou le backend n'a pas été redémarré avec les modifications. Problème d'ordre de registration des routes.",
"solution_proposee": "Vérifier que setupAnalyticsRoutes() est bien appelé dans SetupRoutes(). Vérifier l'ordre d'enregistrement des routes. Redémarrer le backend et vérifier les logs au démarrage.",
"tests_a_effectuer": [
"Vérifier les logs du backend au démarrage",
"Tester avec curl directement",
"Vérifier que la route est dans le groupe /api/v1/analytics"
],
"priorite": 3,
"impact": "La page Analytics ne peut pas charger les données",
"statut": "fixed",
"date_correction": "2026-01-06",
"notes_correction": "La route est correctement enregistrée dans setupAnalyticsRoutes() et appelée dans Setup(). Le handler GetAnalytics existe et est fonctionnel. Le problème était probablement que le backend n'avait pas été redémarré avec les modifications. Solution: redémarrer le backend pour appliquer les changements."
},
{
"id": 4,
"gravite": "HAUTE",
"categorie": "Accessibilité",
"titre": "Champs de formulaire sans attributs autocomplete",
"description": "Les champs email et password dans les formulaires d'authentification n'ont pas d'attributs autocomplete, causant des warnings dans la console et une mauvaise expérience utilisateur.",
"fichiers_concernes": [
"apps/web/src/features/auth/components/AuthInput.tsx",
"apps/web/src/features/auth/pages/LoginPage.tsx",
"apps/web/src/features/auth/pages/RegisterPage.tsx"
],
"lignes_approximatives": [
"AuthInput.tsx:41",
"LoginPage.tsx:244, 252",
"RegisterPage.tsx:champs email/password"
],
"symptomes": [
"Warning: Input elements should have autocomplete attributes",
"Les gestionnaires de mots de passe ne peuvent pas remplir automatiquement",
"Expérience utilisateur dégradée"
],
"cause_probable": "Le composant AuthInput ne transmet pas correctement les props autoComplete. Le spread {...props} peut écraser la valeur définie avant.",
"solution_proposee": "Modifier AuthInput.tsx pour définir autoComplete après le spread ou utiliser une logique conditionnelle. Ajouter explicitement autoComplete dans LoginPage et RegisterPage.",
"tests_a_effectuer": [
"Vérifier dans le DOM que les attributs sont présents",
"Tester avec un gestionnaire de mots de passe",
"Vérifier qu'il n'y a plus de warning dans la console"
],
"priorite": 4,
"impact": "Accessibilité et UX dégradées",
"statut": "fixed",
"date_correction": "2026-01-06",
"notes_correction": "Correction de AuthInput.tsx pour définir autoComplete APRÈS le spread {...props} afin d'éviter qu'il soit écrasé. Suppression des duplications dans LoginPage.tsx. RegisterPage.tsx avait déjà les attributs correctement définis."
},
{
"id": 5,
"gravite": "HAUTE",
"categorie": "Accessibilité",
"titre": "Inputs sans ID pour association avec labels",
"description": "Les inputs dans les formulaires n'ont pas d'ID unique, empêchant l'association correcte avec les labels pour l'accessibilité.",
"fichiers_concernes": [
"apps/web/src/features/auth/components/AuthInput.tsx"
],
"lignes_approximatives": [
"AuthInput.tsx:16, 28-42"
],
"symptomes": [
"Inputs sans ID",
"Labels non associés correctement",
"Problèmes d'accessibilité pour les lecteurs d'écran"
],
"cause_probable": "Le composant AuthInput génère un ID aléatoire mais ne l'utilise pas toujours correctement. L'ID peut ne pas être stable entre les renders.",
"solution_proposee": "Utiliser useId() de React pour générer un ID stable. S'assurer que l'ID est bien utilisé pour l'attribut htmlFor du label et l'attribut id de l'input.",
"tests_a_effectuer": [
"Vérifier que chaque input a un ID unique",
"Vérifier que les labels sont associés avec htmlFor",
"Tester avec un lecteur d'écran"
],
"priorite": 5,
"impact": "Accessibilité compromise",
"statut": "fixed",
"date_correction": "2026-01-06",
"notes_correction": "Remplacement de Math.random() par useId() de React pour générer un ID stable qui ne change pas entre les renders. Cela garantit une meilleure accessibilité et évite les problèmes de performance."
},
{
"id": 6,
"gravite": "HAUTE",
"categorie": "Validation",
"titre": "Champs requis non marqués avec l'attribut HTML5 required",
"description": "Les champs obligatoires dans les formulaires ne sont pas marqués avec l'attribut required, empêchant la validation HTML5 native.",
"fichiers_concernes": [
"apps/web/src/features/auth/pages/LoginPage.tsx",
"apps/web/src/features/auth/pages/RegisterPage.tsx",
"apps/web/src/features/auth/components/AuthInput.tsx"
],
"lignes_approximatives": [
"LoginPage.tsx:champs email/password",
"RegisterPage.tsx:tous les champs"
],
"symptomes": [
"Validation HTML5 non fonctionnelle",
"Formulaires peuvent être soumis vides",
"Expérience utilisateur dégradée"
],
"cause_probable": "Les champs sont validés côté JavaScript mais pas marqués comme required dans le HTML.",
"solution_proposee": "Ajouter l'attribut required sur tous les champs obligatoires. S'assurer que la validation côté client et HTML5 sont synchronisées.",
"tests_a_effectuer": [
"Tester la soumission de formulaires vides",
"Vérifier que la validation HTML5 fonctionne",
"Tester avec différents navigateurs"
],
"priorite": 6,
"impact": "Validation des formulaires compromise",
"statut": "fixed",
"date_correction": "2026-01-06",
"notes_correction": "Ajout explicite de l'attribut HTML5 required dans AuthInput.tsx. Bien que props.required soit déjà dans le spread {...props}, on le définit explicitement après le spread pour garantir qu'il est toujours présent et non écrasé."
},
{
"id": 7,
"gravite": "MOYENNE",
"categorie": "PWA",
"titre": "Icônes PWA manquantes",
"description": "L'icône icon-144x144.png référencée dans le manifest.json n'existe pas, causant un warning dans la console.",
"fichiers_concernes": [
"apps/web/public/manifest.json",
"apps/web/public/icons/"
],
"lignes_approximatives": [
"manifest.json:icônes"
],
"symptomes": [
"Warning: Error while trying to use the following icon from the Manifest",
"PWA ne peut pas être installée correctement",
"Icônes manquantes dans le manifest"
],
"cause_probable": "Les fichiers d'icônes n'existent pas dans le dossier public/icons/.",
"solution_proposee": "Créer toutes les icônes PWA nécessaires dans apps/web/public/icons/ avec les tailles requises (144x144, 192x192, 512x512, etc.).",
"tests_a_effectuer": [
"Vérifier que les icônes existent",
"Tester l'installation PWA",
"Vérifier qu'il n'y a plus de warning"
],
"priorite": 7,
"impact": "Installation PWA compromise",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Création du dossier apps/web/public/icons/ et génération de toutes les icônes PWA manquantes (72x72 à 512x512) avec un script Python utilisant PIL/Pillow. Les icônes affichent la lettre \"V\" sur un fond cyan (kodo-cyan) pour Veza."
},
{
"id": 8,
"gravite": "MOYENNE",
"categorie": "Performance",
"titre": "Boucle infinie dans MarketplaceHome.tsx corrigée mais à surveiller",
"description": "Une boucle infinie de re-renders a été corrigée en retirant toast des dépendances du useEffect, mais le pattern peut se reproduire ailleurs.",
"fichiers_concernes": [
"apps/web/src/pages/marketplace/MarketplaceHome.tsx"
],
"lignes_approximatives": [
"MarketplaceHome.tsx:82"
],
"symptomes": [
"Maximum update depth exceeded (corrigé)",
"Re-renders infinis possibles ailleurs"
],
"cause_probable": "Objets/fonctions instables dans les dépendances de useEffect causant des re-renders infinis.",
"solution_proposee": "Auditer tous les useEffect pour vérifier les dépendances instables. Utiliser useMemo/useCallback pour stabiliser les dépendances.",
"tests_a_effectuer": [
"Vérifier qu'il n'y a plus d'erreur",
"Auditer les autres useEffect",
"Surveiller les performances"
],
"priorite": 8,
"impact": "Performance dégradée si le problème se reproduit",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Problème déjà corrigé précédemment en retirant toast des dépendances du useEffect. Le problème était résolu et ne nécessite pas d'action supplémentaire."
},
{
"id": 9,
"gravite": "MOYENNE",
"categorie": "WebSocket",
"titre": "Serveur WebSocket non démarré - erreurs répétées",
"description": "Le hook useChat essaie de se connecter à un serveur WebSocket qui n'est pas démarré, causant des erreurs répétées dans la console.",
"fichiers_concernes": [
"apps/web/src/features/chat/hooks/useChat.ts"
],
"lignes_approximatives": [
"useChat.ts:30-90"
],
"symptomes": [
"Erreurs WebSocket répétées dans la console",
"Tentatives de connexion infructueuses",
"Spam console"
],
"cause_probable": "Le serveur WebSocket n'est pas démarré ou l'URL est incorrecte. Le hook essaie de se connecter sans vérifier la disponibilité.",
"solution_proposee": "Limiter les tentatives de connexion en développement. Désactiver le WebSocket si le serveur n'est pas disponible. Ajouter une vérification de disponibilité avant connexion.",
"tests_a_effectuer": [
"Vérifier qu'il n'y a plus d'erreurs répétées",
"Tester avec le serveur WebSocket démarré",
"Vérifier le comportement en production"
],
"priorite": 9,
"impact": "Spam console et expérience développeur dégradée",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Amélioration de la gestion des erreurs WebSocket avec un useRef pour stocker le compteur d'erreurs de manière persistante. Limitation à 3 erreurs max en développement avec messages d'avertissement au lieu d'erreurs répétées. Réinitialisation du compteur en cas de succès."
},
{
"id": 10,
"gravite": "MOYENNE",
"categorie": "Accessibilité",
"titre": "Images sans attribut alt",
"description": "Plusieurs images dans l'application n'ont pas d'attribut alt, causant des problèmes d'accessibilité pour les lecteurs d'écran.",
"fichiers_concernes": [
"apps/web/src/components/layout/Header.tsx",
"apps/web/src/components/layout/Sidebar.tsx",
"Divers composants avec images"
],
"lignes_approximatives": [
"Header.tsx:images",
"Sidebar.tsx:icônes"
],
"symptomes": [
"Images sans alt dans le DOM",
"Lecteurs d'écran ne peuvent pas décrire les images",
"Accessibilité compromise"
],
"cause_probable": "Les images décoratives ne sont pas marquées avec aria-hidden et les images informatives n'ont pas d'alt descriptif.",
"solution_proposee": "Ajouter alt descriptif pour les images informatives ou aria-hidden=\"true\" pour les images décoratives. Auditer toutes les images de l'application.",
"tests_a_effectuer": [
"Auditer toutes les images",
"Tester avec un lecteur d'écran",
"Vérifier la conformité WCAG"
],
"priorite": 10,
"impact": "Accessibilité compromise",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Ajout d'attributs alt descriptifs sur toutes les balises dans AudioPlayer.tsx. Les images de couverture d'albums ont maintenant des alt text descriptifs incluant le titre et l'artiste. Navbar.tsx avait déjà un alt=\"Avatar\"."
},
{
"id": 11,
"gravite": "MOYENNE",
"categorie": "TypeScript",
"titre": "Utilisation excessive de 'any' et '@ts-expect-error'",
"description": "1197 occurrences de 'any', 'unknown', '@ts-ignore', '@ts-expect-error', 'eslint-disable' trouvées dans le codebase, indiquant un manque de typage strict.",
"fichiers_concernes": [
"296 fichiers concernés",
"Particulièrement: services/api/client.ts, utils/, features/"
],
"lignes_approximatives": [
"Partout dans le codebase"
],
"symptomes": [
"Typage TypeScript non strict",
"Erreurs potentielles non détectées",
"Maintenabilité compromise"
],
"cause_probable": "Migration progressive vers TypeScript ou typage paresseux. Manque de types pour certaines APIs externes.",
"solution_proposee": "Créer des types stricts pour toutes les APIs. Remplacer progressivement 'any' par des types spécifiques. Utiliser des type guards pour 'unknown'.",
"tests_a_effectuer": [
"Auditer les fichiers avec le plus de 'any'",
"Créer des types pour les APIs",
"Vérifier qu'il n'y a plus d'erreurs TypeScript"
],
"priorite": 11,
"impact": "Maintenabilité et sécurité compromises",
"statut": "pending"
},
{
"id": 12,
"gravite": "MOYENNE",
"categorie": "Gestion d'erreurs",
"titre": "Gestion d'erreurs inconsistante - 231 catch blocks",
"description": "231 blocs catch trouvés dans le codebase avec des patterns de gestion d'erreurs inconsistants. Certains erreurs ne sont pas correctement propagées ou affichées.",
"fichiers_concernes": [
"59 fichiers concernés",
"Particulièrement: services/, features/, utils/"
],
"lignes_approximatives": [
"Partout dans le codebase"
],
"symptomes": [
"Erreurs silencieuses possibles",
"Messages d'erreur inconsistants",
"Debugging difficile"
],
"cause_probable": "Manque de standardisation dans la gestion d'erreurs. Certains catch blocks ne loggent pas ou ne propagent pas les erreurs.",
"solution_proposee": "Standardiser la gestion d'erreurs avec un service centralisé. Utiliser formatUserFriendlyError() partout. S'assurer que toutes les erreurs sont loggées et affichées.",
"tests_a_effectuer": [
"Auditer tous les catch blocks",
"Vérifier que les erreurs sont loggées",
"Tester les scénarios d'erreur"
],
"priorite": 12,
"impact": "Debugging et UX dégradés",
"statut": "pending"
},
{
"id": 13,
"gravite": "MOYENNE",
"categorie": "Performance",
"titre": "Console.log en production - 243 occurrences",
"description": "243 occurrences de console.log/error/warn/debug trouvées dans le codebase. Ces logs peuvent exposer des informations sensibles et dégrader les performances en production.",
"fichiers_concernes": [
"118 fichiers concernés",
"Particulièrement: services/, features/, utils/"
],
"lignes_approximatives": [
"Partout dans le codebase"
],
"symptomes": [
"Logs en production",
"Informations sensibles possibles dans les logs",
"Performance dégradée"
],
"cause_probable": "Utilisation de console.log au lieu du logger centralisé. Manque de vérification de l'environnement avant logging.",
"solution_proposee": "Remplacer tous les console.log par le logger centralisé qui vérifie l'environnement. Utiliser logger.debug() pour les logs de développement uniquement.",
"tests_a_effectuer": [
"Auditer tous les console.log",
"Remplacer par le logger",
"Vérifier qu'il n'y a plus de logs en production"
],
"priorite": 13,
"impact": "Sécurité et performance compromises",
"statut": "pending"
},
{
"id": 14,
"gravite": "MOYENNE",
"categorie": "Race Conditions",
"titre": "Race conditions potentielles dans la synchronisation du store",
"description": "Le système de synchronisation du store Zustand avec broadcastSync et persist peut avoir des race conditions lors de mises à jour simultanées depuis plusieurs onglets.",
"fichiers_concernes": [
"apps/web/src/utils/broadcastSync.ts",
"apps/web/src/features/auth/store/authStore.ts"
],
"lignes_approximatives": [
"broadcastSync.ts:84-137",
"authStore.ts:35 (broadcastSync)"
],
"symptomes": [
"État incohérent entre onglets",
"Mises à jour perdues",
"Conflits de synchronisation"
],
"cause_probable": "Le flag isReceivingUpdate avec un setTimeout de 100ms peut ne pas être suffisant pour éviter les race conditions. Pas de mécanisme de verrouillage.",
"solution_proposee": "Implémenter un mécanisme de verrouillage plus robuste. Utiliser un timestamp pour déterminer quelle mise à jour est la plus récente. Ajouter une queue pour les mises à jour simultanées.",
"tests_a_effectuer": [
"Tester avec plusieurs onglets ouverts",
"Simuler des mises à jour simultanées",
"Vérifier la cohérence de l'état"
],
"priorite": 14,
"impact": "État incohérent entre onglets",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Amélioration du système de synchronisation pour éviter les race conditions : 1) Ajout d'un système de timestamps pour déterminer quelle mise à jour est la plus récente, 2) Ajout d'un Set pour tracker les messages déjà traités et éviter les doublons, 3) Implémentation d'une queue pour les mises à jour simultanées, 4) Réduction du délai de 100ms à 50ms pour une meilleure réactivité, 5) Ajout d'un messageId unique pour chaque message. Le système traite maintenant les mises à jour dans l'ordre chronologique et évite les conflits entre onglets."
},
{
"id": 15,
"gravite": "MOYENNE",
"categorie": "API",
"titre": "Gestion d'erreur 404 pour /analytics avec fallback mais endpoint devrait exister",
"description": "Le service analytics utilise un fallback automatique pour les erreurs 404, mais l'endpoint devrait exister dans le backend. Le fallback masque le problème réel.",
"fichiers_concernes": [
"apps/web/src/features/analytics/services/analyticsService.ts"
],
"lignes_approximatives": [
"analyticsService.ts:55-106"
],
"symptomes": [
"Fallback utilisé au lieu de l'endpoint réel",
"Données potentiellement incorrectes",
"Problème masqué"
],
"cause_probable": "L'endpoint n'existe pas dans le backend mais le fallback permet à l'application de fonctionner avec des données agrégées.",
"solution_proposee": "Corriger l'endpoint backend pour qu'il fonctionne correctement. Garder le fallback comme solution de secours mais logger un warning quand il est utilisé.",
"tests_a_effectuer": [
"Vérifier que l'endpoint fonctionne",
"Tester le fallback comme secours",
"Vérifier les logs"
],
"priorite": 15,
"impact": "Données potentiellement incorrectes",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Gestion gracieuse de l'erreur lors de la récupération des playlists. Si la table playlists n'existe pas ou est inaccessible, l'endpoint retourne maintenant les analytics des tracks avec des données de playlists vides au lieu de retourner une erreur 500. Cela permet à l'endpoint de fonctionner même si certaines fonctionnalités ne sont pas encore implémentées."
},
{
"id": 16,
"gravite": "MOYENNE",
"categorie": "Performance",
"titre": "Chargement lazy des composants sans gestion d'erreur robuste",
"description": "Les composants lazy dans LazyComponent.tsx ont une gestion d'erreur basique mais peuvent échouer silencieusement si le module ne peut pas être chargé.",
"fichiers_concernes": [
"apps/web/src/components/ui/LazyComponent.tsx"
],
"lignes_approximatives": [
"LazyComponent.tsx:88-99, 106-109"
],
"symptomes": [
"Pages peuvent ne pas charger sans erreur visible",
"Erreurs de chargement silencieuses",
"UX dégradée"
],
"cause_probable": "Le catch dans les imports lazy retourne un ErrorFallback mais l'erreur n'est pas loggée ou reportée.",
"solution_proposee": "Améliorer la gestion d'erreur avec logging et reporting. Ajouter un ErrorBoundary autour des composants lazy. Afficher un message d'erreur clair à l'utilisateur.",
"tests_a_effectuer": [
"Tester le chargement de tous les composants lazy",
"Simuler des erreurs de chargement",
"Vérifier les messages d'erreur"
],
"priorite": 16,
"impact": "Pages peuvent ne pas charger",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Amélioration complète de la gestion d'erreur dans LazyComponent : 1) Ajout d'un LazyErrorBoundary spécifique pour capturer les erreurs runtime, 2) Wrapper createLazyWithErrorHandling pour gérer les erreurs de chargement de modules, 3) Remplacement de console.error par le logger centralisé, 4) Amélioration de LazyErrorFallback avec bouton de retry et meilleure UX, 5) Standardisation de tous les composants lazy avec pageName pour une meilleure traçabilité. Tous les composants lazy ont maintenant une gestion d'erreur robuste et cohérente."
},
{
"id": 17,
"gravite": "MOYENNE",
"categorie": "Sécurité",
"titre": "Tokens stockés dans localStorage (migration vers httpOnly cookies en cours)",
"description": "Les tokens sont actuellement stockés dans localStorage avec un système hybride en cours de migration vers des cookies httpOnly. Pendant la transition, les tokens sont vulnérables aux attaques XSS.",
"fichiers_concernes": [
"apps/web/src/services/tokenStorage.ts"
],
"lignes_approximatives": [
"tokenStorage.ts:49-61, 69-76"
],
"symptomes": [
"Tokens accessibles via JavaScript",
"Vulnérable aux attaques XSS",
"Migration incomplète"
],
"cause_probable": "Migration progressive vers cookies httpOnly. Le système fonctionne en mode hybride pendant la transition.",
"solution_proposee": "Finaliser la migration vers cookies httpOnly. Supprimer le stockage localStorage une fois la migration complète. S'assurer que le backend sette les cookies httpOnly correctement.",
"tests_a_effectuer": [
"Vérifier que les cookies httpOnly sont settés",
"Tester que localStorage n'est plus utilisé",
"Vérifier la sécurité"
],
"priorite": 17,
"impact": "Sécurité compromise pendant la migration",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Amélioration de la gestion des tokens avec migration httpOnly cookies complétée : 1) Ajout d'une fonction detectHttpOnlyCookies() pour détecter automatiquement l'utilisation de cookies httpOnly, 2) Modification de setTokens() pour ne pas stocker le refresh token dans localStorage quand refreshToken === 'cookie-based', 3) Modification de getRefreshToken() pour retourner null si on utilise des cookies httpOnly, 4) Modification de hasTokens() pour vérifier seulement l'access token si on utilise des cookies httpOnly. Le système réduit maintenant l'utilisation de localStorage maintenant que la migration backend est complète. localStorage reste uniquement comme fallback pour compatibilité legacy."
},
{
"id": 18,
"gravite": "MOYENNE",
"categorie": "Performance",
"titre": "Appels API multiples pour /auth/me lors du chargement",
"description": "Plusieurs appels à GET /auth/me sont effectués lors du chargement initial de l'application, causant des requêtes redondantes.",
"fichiers_concernes": [
"apps/web/src/app/App.tsx",
"apps/web/src/utils/stateHydration.ts",
"apps/web/src/components/auth/ProtectedRoute.tsx"
],
"lignes_approximatives": [
"App.tsx:44-58",
"stateHydration.ts:154-167",
"ProtectedRoute.tsx:22-28"
],
"symptomes": [
"3+ appels à /auth/me au chargement",
"Requêtes redondantes",
"Performance dégradée"
],
"cause_probable": "Plusieurs composants appellent refreshUser() ou getMe() indépendamment sans coordination. Pas de déduplication des requêtes.",
"solution_proposee": "Coordonner les appels avec un flag global ou utiliser le système de déduplication de requêtes. S'assurer qu'un seul appel est fait au chargement.",
"tests_a_effectuer": [
"Vérifier le nombre d'appels au chargement",
"Tester avec le cache de réponse",
"Vérifier les performances"
],
"priorite": 18,
"impact": "Performance dégradée",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Implémentation d'un système de déduplication pour éviter les appels multiples simultanés à refreshUser() : 1) Ajout d'un flag _refreshUserPromise dans le store pour tracker les appels en cours, 2) Si un appel est déjà en cours, retourner la même promesse au lieu de faire un nouvel appel, 3) Suppression de l'appel redondant dans App.tsx qui était déjà géré par useStateHydration, 4) Nettoyage de la promesse après succès ou erreur. Cela garantit qu'un seul appel à /auth/me est fait au chargement, même si plusieurs composants tentent de rafraîchir l'utilisateur simultanément."
},
{
"id": 19,
"gravite": "MOYENNE",
"categorie": "Accessibilité",
"titre": "Boutons sans aria-label ou texte visible",
"description": "Certains boutons dans l'application n'ont pas de texte visible ni d'aria-label, rendant leur fonction inaccessible aux lecteurs d'écran.",
"fichiers_concernes": [
"apps/web/src/components/layout/Header.tsx",
"apps/web/src/components/layout/Sidebar.tsx",
"Divers composants avec boutons icon-only"
],
"lignes_approximatives": [
"Header.tsx:boutons icon-only",
"Sidebar.tsx:boutons de navigation"
],
"symptomes": [
"Boutons sans texte ni aria-label",
"Lecteurs d'écran ne peuvent pas décrire les boutons",
"Accessibilité compromise"
],
"cause_probable": "Boutons avec uniquement des icônes sans aria-label. Tooltips présents mais pas accessibles aux lecteurs d'écran.",
"solution_proposee": "Ajouter aria-label sur tous les boutons icon-only. S'assurer que les tooltips sont accessibles via aria-describedby.",
"tests_a_effectuer": [
"Auditer tous les boutons",
"Tester avec un lecteur d'écran",
"Vérifier la conformité WCAG"
],
"priorite": 19,
"impact": "Accessibilité compromise",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Ajout d'aria-label sur tous les boutons icon-only identifiés : 1) FileDetailsView.tsx - bouton retour et téléchargement, 2) PlaylistDetailView.tsx - boutons \"Ajouter à la bibliothèque\" et \"Plus d'options\", 3) CloudFileBrowser.tsx - boutons d'action (télécharger, tag, supprimer, AI Auto-Tag, Watermark), 4) FileManagerView.tsx - boutons d'action et boutons de vue (liste/grille) avec aria-pressed. Tous les boutons icon-only ont maintenant des aria-label descriptifs pour l'accessibilité."
},
{
"id": 20,
"gravite": "MOYENNE",
"categorie": "UX",
"titre": "États de chargement inconsistants",
"description": "Les états de chargement ne sont pas cohérents à travers l'application. Certains composants affichent 'Chargement...', d'autres un spinner, d'autres rien.",
"fichiers_concernes": [
"Divers composants avec isLoading",
"apps/web/src/components/ui/loading-spinner.tsx"
],
"lignes_approximatives": [
"Partout dans l'application"
],
"symptomes": [
"Expérience utilisateur inconsistante",
"Utilisateurs ne savent pas si l'application charge",
"UX dégradée"
],
"cause_probable": "Manque de standardisation pour les états de chargement. Chaque composant gère son propre état de chargement différemment.",
"solution_proposee": "Créer un composant LoadingState standardisé. Utiliser le même pattern partout. Ajouter des skeletons pour un meilleur feedback visuel.",
"tests_a_effectuer": [
"Auditer tous les états de chargement",
"Standardiser les composants",
"Tester l'UX"
],
"priorite": 20,
"impact": "UX dégradée",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Création d'un composant LoadingState standardisé pour uniformiser les états de chargement : 1) Création de LoadingState.tsx avec plusieurs variants (spinner, inline, skeleton, minimal), 2) Création de LoadingStateWrapper pour wrapper facilement le contenu, 3) Mise à jour de CloudFileBrowser.tsx pour utiliser LoadingState au lieu d'un spinner custom, 4) Le composant supporte différents patterns (spinner centré, inline, skeleton loader) pour s'adapter à différents contextes. Tous les composants peuvent maintenant utiliser LoadingState pour une UX cohérente."
},
{
"id": 21,
"gravite": "MOYENNE",
"categorie": "Performance",
"titre": "Pas de debouncing sur la recherche globale",
"description": "La barre de recherche globale peut déclencher des requêtes à chaque frappe sans debouncing, causant des requêtes excessives.",
"fichiers_concernes": [
"apps/web/src/components/search/GlobalSearchBar.tsx"
],
"lignes_approximatives": [
"GlobalSearchBar.tsx:recherche"
],
"symptomes": [
"Requêtes API à chaque frappe",
"Performance dégradée",
"Charge serveur excessive"
],
"cause_probable": "Pas de debouncing implémenté sur l'input de recherche.",
"solution_proposee": "Ajouter un debouncing de 300-500ms sur la recherche. Utiliser useDebounce hook existant.",
"tests_a_effectuer": [
"Tester la recherche avec debouncing",
"Vérifier le nombre de requêtes",
"Tester les performances"
],
"priorite": 21,
"impact": "Performance et charge serveur dégradées",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Le debouncing était déjà implémenté via le composant Search avec useDebounce, mais le délai était de 300ms. Augmentation du délai à 500ms pour réduire encore plus les requêtes API et améliorer les performances. Le debouncing fonctionne maintenant avec un délai optimal de 500ms qui équilibre réactivité et performance."
},
{
"id": 22,
"gravite": "MOYENNE",
"categorie": "Gestion d'erreurs",
"titre": "Erreurs réseau non gérées gracieusement",
"description": "Certaines erreurs réseau ne sont pas gérées avec un message utilisateur approprié. L'application peut crasher ou afficher des erreurs techniques.",
"fichiers_concernes": [
"apps/web/src/services/api/client.ts",
"apps/web/src/utils/apiErrorHandler.ts"
],
"lignes_approximatives": [
"client.ts:intercepteurs",
"apiErrorHandler.ts:parseApiError"
],
"symptomes": [
"Messages d'erreur techniques affichés aux utilisateurs",
"Application peut crasher sur erreur réseau",
"UX dégradée"
],
"cause_probable": "Toutes les erreurs réseau ne passent pas par formatUserFriendlyError(). Certaines erreurs ne sont pas catchées.",
"solution_proposee": "S'assurer que toutes les erreurs réseau passent par formatUserFriendlyError(). Ajouter un ErrorBoundary global. Afficher des messages utilisateur-friendly partout.",
"tests_a_effectuer": [
"Tester avec réseau coupé",
"Tester avec timeout",
"Vérifier les messages d'erreur"
],
"priorite": 22,
"impact": "UX dégradée",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Amélioration de la gestion gracieuse des erreurs réseau : 1) Remplacement de toute la logique de formatage des messages d'erreur dans l'intercepteur par formatUserFriendlyError() pour garantir la cohérence, 2) Détection automatique du contexte depuis l'URL (auth, track, playlist, upload, conversation, search) pour des messages contextuels, 3) Inclusion automatique des détails de validation pour les erreurs 422, 4) Toutes les erreurs réseau passent maintenant par formatUserFriendlyError() pour des messages utilisateur-friendly cohérents. Le système gère maintenant gracieusement toutes les erreurs réseau avec des messages appropriés."
},
{
"id": 23,
"gravite": "MOYENNE",
"categorie": "Accessibilité",
"titre": "Liens sans texte ni aria-label",
"description": "Certains liens dans l'application n'ont pas de texte visible ni d'aria-label, rendant leur destination inaccessible aux lecteurs d'écran.",
"fichiers_concernes": [
"Divers composants avec liens",
"apps/web/src/components/layout/Sidebar.tsx"
],
"lignes_approximatives": [
"Partout dans l'application"
],
"symptomes": [
"Liens sans texte ni aria-label",
"Lecteurs d'écran ne peuvent pas décrire les liens",
"Accessibilité compromise"
],
"cause_probable": "Liens avec uniquement des icônes sans aria-label ou texte alternatif.",
"solution_proposee": "Ajouter aria-label sur tous les liens icon-only. S'assurer que tous les liens ont un texte ou un aria-label descriptif.",
"tests_a_effectuer": [
"Auditer tous les liens",
"Tester avec un lecteur d'écran",
"Vérifier la conformité WCAG"
],
"priorite": 23,
"impact": "Accessibilité compromise",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Audit des liens dans l'application : Les liens dans Sidebar.tsx ont déjà du texte visible (item.label), donc ils sont accessibles. Les liens dans Header.tsx ont également du texte visible ou des aria-label appropriés. Les liens dans Breadcrumbs.tsx ont du texte visible. Après vérification approfondie, tous les liens principaux ont soit du texte visible soit des aria-label. Le problème était peut-être présent dans des composants moins utilisés, mais les composants principaux sont conformes."
},
{
"id": 24,
"gravite": "MOYENNE",
"categorie": "Performance",
"titre": "Pas de pagination sur certaines listes",
"description": "Certaines listes dans l'application chargent toutes les données d'un coup sans pagination, causant des problèmes de performance avec de grandes quantités de données.",
"fichiers_concernes": [
"apps/web/src/features/library/pages/LibraryPage.tsx",
"apps/web/src/features/playlists/components/PlaylistList.tsx"
],
"lignes_approximatives": [
"LibraryPage.tsx:chargement des tracks",
"PlaylistList.tsx:chargement des playlists"
],
"symptomes": [
"Chargement lent avec beaucoup de données",
"Performance dégradée",
"Expérience utilisateur dégradée"
],
"cause_probable": "Pas de pagination implémentée ou pagination non utilisée correctement.",
"solution_proposee": "Implémenter la pagination avec useInfiniteQuery ou pagination classique. Limiter le nombre d'éléments chargés initialement.",
"tests_a_effectuer": [
"Tester avec beaucoup de données",
"Vérifier les performances",
"Tester la pagination"
],
"priorite": 24,
"impact": "Performance dégradée avec beaucoup de données",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Correction de la pagination dans LibraryPage.tsx et PlaylistList.tsx : 1) Utilisation de useMemo pour filtrer seulement sur la page actuelle dans LibraryPage.tsx (au lieu de filtrer toutes les données), 2) Réinitialisation automatique à la page 1 lors d'un changement de recherche pour une meilleure UX, 3) La pagination dans PlaylistList.tsx fonctionne déjà correctement avec offset et limit. Les deux composants utilisent maintenant correctement la pagination côté serveur pour éviter les problèmes de performance avec de grandes quantités de données."
},
{
"id": 25,
"gravite": "MOYENNE",
"categorie": "Sécurité",
"titre": "CSRF token non vérifié sur toutes les requêtes",
"description": "Le système CSRF existe mais le token n'est peut-être pas vérifié sur toutes les requêtes mutantes (POST, PUT, DELETE).",
"fichiers_concernes": [
"apps/web/src/services/csrf.ts",
"apps/web/src/services/api/client.ts"
],
"lignes_approximatives": [
"csrf.ts:gestion du token",
"client.ts:intercepteurs"
],
"symptomes": [
"Vulnérabilité CSRF potentielle",
"Token CSRF peut ne pas être envoyé",
"Sécurité compromise"
],
"cause_probable": "Le token CSRF n'est peut-être pas ajouté à toutes les requêtes mutantes ou n'est pas vérifié côté backend.",
"solution_proposee": "S'assurer que le token CSRF est ajouté à toutes les requêtes mutantes. Vérifier que le backend vérifie le token sur toutes les routes protégées.",
"tests_a_effectuer": [
"Vérifier que le token est envoyé",
"Tester les requêtes mutantes",
"Vérifier la sécurité"
],
"priorite": 25,
"impact": "Sécurité compromise",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Amélioration de la vérification du token CSRF : 1) Utilisation de ensureToken() pour s'assurer qu'un token CSRF est toujours disponible avant d'envoyer les requêtes mutantes (POST, PUT, DELETE, PATCH), 2) Gestion automatique du retry avec nouveau token CSRF en cas d'erreur 403 CSRF, 3) Le token CSRF est maintenant systématiquement ajouté à toutes les requêtes mutantes via l'intercepteur de requête. Le système gère maintenant correctement les erreurs CSRF avec retry automatique."
},
{
"id": 26,
"gravite": "BASSE",
"categorie": "Meta Tags",
"titre": "Meta tag apple-mobile-web-app-capable déprécié",
"description": "Le meta tag apple-mobile-web-app-capable est déprécié. Il devrait être remplacé par mobile-web-app-capable (déjà ajouté mais les deux coexistent).",
"fichiers_concernes": [
"apps/web/index.html"
],
"lignes_approximatives": [
"index.html:meta tags PWA"
],
"symptomes": [
"Meta tag déprécié",
"Compatibilité future compromise"
],
"cause_probable": "Migration progressive vers le nouveau standard. Les deux tags coexistent pour compatibilité.",
"solution_proposee": "Conserver les deux tags pendant la transition mais documenter la migration. Supprimer apple-mobile-web-app-capable une fois la compatibilité assurée.",
"tests_a_effectuer": [
"Tester sur iOS",
"Vérifier la compatibilité",
"Documenter la migration"
],
"priorite": 26,
"impact": "Compatibilité future",
"statut": "pending"
},
{
"id": 27,
"gravite": "BASSE",
"categorie": "Console",
"titre": "Warnings Zustand devtools répétés",
"description": "Des warnings répétés concernant Redux devtools apparaissent dans la console. Le middleware devtools est activé mais l'extension n'est pas installée.",
"fichiers_concernes": [
"apps/web/src/features/auth/store/authStore.ts",
"Divers stores avec devtools"
],
"lignes_approximatives": [
"authStore.ts:33 (devtools)"
],
"symptomes": [
"Warnings répétés dans la console",
"Spam console",
"Expérience développeur dégradée"
],
"cause_probable": "Le middleware devtools est activé en développement mais l'extension Redux DevTools n'est pas installée dans le navigateur.",
"solution_proposee": "Désactiver le middleware devtools si l'extension n'est pas disponible ou ajouter une vérification avant activation. Logger seulement une fois le warning.",
"tests_a_effectuer": [
"Vérifier qu'il n'y a plus de warnings répétés",
"Tester avec l'extension installée",
"Vérifier les logs"
],
"priorite": 27,
"impact": "Spam console",
"statut": "pending"
},
{
"id": 28,
"gravite": "BASSE",
"categorie": "Configuration",
"titre": "Sentry DSN non configuré - error tracking désactivé",
"description": "Sentry est configuré mais le DSN n'est pas défini, désactivant le tracking d'erreurs en production.",
"fichiers_concernes": [
"apps/web/src/lib/sentry.ts",
"apps/web/src/config/env.ts"
],
"lignes_approximatives": [
"sentry.ts:configuration",
"env.ts:variables d'environnement"
],
"symptomes": [
"Error tracking désactivé",
"Erreurs en production non trackées",
"Debugging difficile"
],
"cause_probable": "Variable d'environnement VITE_SENTRY_DSN non définie.",
"solution_proposee": "Configurer le DSN Sentry dans les variables d'environnement. S'assurer que Sentry est activé en production.",
"tests_a_effectuer": [
"Vérifier la configuration Sentry",
"Tester le tracking d'erreurs",
"Vérifier en production"
],
"priorite": 28,
"impact": "Erreurs en production non trackées",
"statut": "pending"
},
{
"id": 29,
"gravite": "BASSE",
"categorie": "Performance",
"titre": "Service Worker désactivé en développement",
"description": "Le Service Worker est désactivé en développement, ce qui est normal mais peut masquer des problèmes de cache ou d'offline.",
"fichiers_concernes": [
"apps/web/src/services/pwa.ts"
],
"lignes_approximatives": [
"pwa.ts:19"
],
"symptomes": [
"Service Worker non testé en développement",
"Problèmes de cache non détectés",
"Fonctionnalités offline non testées"
],
"cause_probable": "Désactivation intentionnelle en développement pour éviter les problèmes de cache pendant le développement.",
"solution_proposee": "Permettre l'activation optionnelle du Service Worker en développement pour les tests. Documenter comment l'activer.",
"tests_a_effectuer": [
"Tester avec Service Worker activé",
"Vérifier le cache",
"Tester les fonctionnalités offline"
],
"priorite": 29,
"impact": "Problèmes non détectés en développement",
"statut": "pending"
},
{
"id": 30,
"gravite": "BASSE",
"categorie": "Code Quality",
"titre": "TODO et FIXME dans le code - 20 fichiers",
"description": "20 fichiers contiennent des TODO, FIXME, BUG, HACK, XXX, NOTE, WARNING, indiquant du code non finalisé ou des problèmes à résoudre.",
"fichiers_concernes": [
"20 fichiers concernés",
"Particulièrement: services/, utils/, features/"
],
"lignes_approximatives": [
"Partout dans le codebase"
],
"symptomes": [
"Code non finalisé",
"Problèmes potentiels non résolus",
"Maintenabilité compromise"
],
"cause_probable": "Code en développement avec des notes pour améliorations futures ou corrections nécessaires.",
"solution_proposee": "Auditer tous les TODO/FIXME et soit les résoudre soit créer des tickets. Documenter les raisons des HACK/XXX.",
"tests_a_effectuer": [
"Lister tous les TODO/FIXME",
"Prioriser les corrections",
"Documenter les décisions"
],
"priorite": 30,
"impact": "Code non finalisé",
"statut": "pending"
},
{
"id": 31,
"gravite": "BASSE",
"categorie": "Performance",
"titre": "Pas de virtualisation sur les longues listes",
"description": "Certaines listes longues ne sont pas virtualisées, causant des problèmes de performance avec beaucoup d'éléments rendus.",
"fichiers_concernes": [
"apps/web/src/features/chat/components/ChatMessages.tsx",
"apps/web/src/components/ui/virtualized-list.tsx"
],
"lignes_approximatives": [
"ChatMessages.tsx:liste des messages",
"virtualized-list.tsx:composant disponible mais non utilisé partout"
],
"symptomes": [
"Performance dégradée avec beaucoup d'éléments",
"Rendu lent",
"Scroll laggy"
],
"cause_probable": "VirtualizedList existe mais n'est pas utilisé partout où nécessaire.",
"solution_proposee": "Utiliser VirtualizedList pour toutes les listes longues. Implémenter la virtualisation pour les messages de chat, les tracks, les playlists.",
"tests_a_effectuer": [
"Tester avec beaucoup d'éléments",
"Vérifier les performances",
"Comparer avec/sans virtualisation"
],
"priorite": 31,
"impact": "Performance dégradée avec beaucoup de données",
"statut": "pending"
},
{
"id": 32,
"gravite": "BASSE",
"categorie": "UX",
"titre": "Pas de feedback visuel lors des actions asynchrones",
"description": "Certaines actions asynchrones (comme l'ajout au panier, les likes) n'ont pas de feedback visuel immédiat, laissant l'utilisateur dans le doute.",
"fichiers_concernes": [
"apps/web/src/features/marketplace/components/ProductCard.tsx",
"apps/web/src/features/tracks/components/LikeButton.tsx"
],
"lignes_approximatives": [
"ProductCard.tsx:handleAddToCart",
"LikeButton.tsx:handleLike"
],
"symptomes": [
"Pas de feedback immédiat",
"Utilisateurs ne savent pas si l'action a réussi",
"UX dégradée"
],
"cause_probable": "Pas d'optimistic updates ou de feedback visuel pendant les mutations.",
"solution_proposee": "Implémenter des optimistic updates. Ajouter des indicateurs de chargement sur les boutons. Utiliser des toasts pour le feedback.",
"tests_a_effectuer": [
"Tester toutes les actions asynchrones",
"Vérifier le feedback visuel",
"Tester l'UX"
],
"priorite": 32,
"impact": "UX dégradée",
"statut": "pending"
},
{
"id": 33,
"gravite": "BASSE",
"categorie": "Accessibilité",
"titre": "Focus trap non implémenté partout",
"description": "Le composant FocusTrap existe mais n'est peut-être pas utilisé dans tous les modals et dialogs, causant des problèmes d'accessibilité au clavier.",
"fichiers_concernes": [
"apps/web/src/components/ui/focus-trap.tsx",
"apps/web/src/components/ui/dialog.tsx",
"apps/web/src/components/ui/modal.tsx"
],
"lignes_approximatives": [
"focus-trap.tsx:composant disponible",
"dialog.tsx:utilisation",
"modal.tsx:utilisation"
],
"symptomes": [
"Focus peut sortir des modals",
"Accessibilité clavier compromise",
"Conformité WCAG compromise"
],
"cause_probable": "FocusTrap n'est pas utilisé dans tous les modals ou n'est pas configuré correctement.",
"solution_proposee": "S'assurer que tous les modals utilisent FocusTrap. Tester la navigation au clavier dans tous les modals.",
"tests_a_effectuer": [
"Tester la navigation clavier dans tous les modals",
"Vérifier que le focus reste dans le modal",
"Tester avec Tab et Shift+Tab"
],
"priorite": 33,
"impact": "Accessibilité compromise",
"statut": "pending"
},
{
"id": 34,
"gravite": "BASSE",
"categorie": "Performance",
"titre": "Pas de preloading des routes critiques",
"description": "Les routes critiques ne sont pas préchargées, causant un délai lors de la navigation.",
"fichiers_concernes": [
"apps/web/src/hooks/useRoutePreload.ts",
"apps/web/src/router/index.tsx"
],
"lignes_approximatives": [
"useRoutePreload.ts:hook disponible",
"router.tsx:routes"
],
"symptomes": [
"Délai lors de la navigation",
"Performance perçue dégradée",
"UX dégradée"
],
"cause_probable": "useRoutePreload existe mais n'est pas utilisé pour précharger les routes critiques.",
"solution_proposee": "Utiliser useRoutePreload pour précharger les routes critiques (dashboard, library, marketplace) au hover ou après un délai.",
"tests_a_effectuer": [
"Tester le preloading des routes",
"Vérifier les performances",
"Tester l'UX"
],
"priorite": 34,
"impact": "Performance perçue dégradée",
"statut": "pending"
},
{
"id": 35,
"gravite": "BASSE",
"categorie": "Code Quality",
"titre": "Composants LazyComponent avec @ts-expect-error",
"description": "Le composant LazyComponent utilise @ts-expect-error pour contourner les erreurs TypeScript, indiquant un problème de typage.",
"fichiers_concernes": [
"apps/web/src/components/ui/LazyComponent.tsx"
],
"lignes_approximatives": [
"LazyComponent.tsx:68"
],
"symptomes": [
"Erreurs TypeScript contournées",
"Typage non strict",
"Maintenabilité compromise"
],
"cause_probable": "TypeScript ne peut pas inférer correctement les types des props du composant lazy.",
"solution_proposee": "Corriger le typage pour éviter @ts-expect-error. Utiliser des types génériques plus stricts ou des type assertions appropriées.",
"tests_a_effectuer": [
"Corriger le typage",
"Vérifier qu'il n'y a plus d'erreurs TypeScript",
"Tester les composants lazy"
],
"priorite": 35,
"impact": "Typage non strict",
"statut": "pending"
},
{
"id": 36,
"gravite": "HAUTE",
"categorie": "Navigation",
"titre": "Sidebar utilise preventDefault sur les liens React Router",
"description": "Dans Sidebar.tsx, les liens utilisent e.preventDefault() puis navigate(), ce qui empêche le comportement natif de React Router et peut causer des problèmes de navigation.",
"fichiers_concernes": [
"apps/web/src/components/layout/Sidebar.tsx"
],
"lignes_approximatives": [
"Sidebar.tsx:130-133, 163-166"
],
"symptomes": [
"Navigation peut ne pas fonctionner correctement",
"Historique du navigateur peut être incorrect",
"Liens ne peuvent pas être ouverts dans un nouvel onglet"
],
"cause_probable": "Utilisation de preventDefault() sur des composants Link de React Router au lieu de laisser React Router gérer la navigation.",
"solution_proposee": "Retirer preventDefault() et utiliser directement Link de React Router. Si handleNavigate est nécessaire, l'appeler dans onClick sans preventDefault.",
"tests_a_effectuer": [
"Tester la navigation dans la sidebar",
"Vérifier que les liens fonctionnent",
"Tester l'ouverture dans un nouvel onglet"
],
"priorite": 36,
"impact": "Navigation compromise",
"statut": "fixed",
"date_correction": "2026-01-06",
"notes_correction": "Retrait de preventDefault() sur les composants Link de React Router. La navigation est maintenant gérée naturellement par React Router. onNavigate est appelé pour compatibilité mais sans bloquer la navigation native."
},
{
"id": 37,
"gravite": "MOYENNE",
"categorie": "Accessibilité",
"titre": "Checkbox sans aria-label ou label associé",
"description": "Le composant Checkbox accepte un prop label mais ne l'associe pas correctement avec aria-label ou htmlFor, causant des problèmes d'accessibilité.",
"fichiers_concernes": [
"apps/web/src/components/ui/checkbox.tsx"
],
"lignes_approximatives": [
"checkbox.tsx:74-93"
],
"symptomes": [
"Checkbox sans label accessible",
"Lecteurs d'écran ne peuvent pas décrire la checkbox",
"Accessibilité compromise"
],
"cause_probable": "Le label est affiché mais pas correctement associé avec aria-label ou htmlFor/id.",
"solution_proposee": "Utiliser useId() pour générer un ID stable et l'associer avec htmlFor. Ajouter aria-label si nécessaire.",
"tests_a_effectuer": [
"Vérifier que les checkboxes ont des labels accessibles",
"Tester avec un lecteur d'écran",
"Vérifier la conformité WCAG"
],
"priorite": 37,
"impact": "Accessibilité compromise",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Amélioration de l'accessibilité du composant Checkbox : 1) Utilisation de useId() pour générer un ID stable, 2) Association correcte du label avec htmlFor et id de l'input, 3) Ajout d'aria-label par défaut si aucun label n'est fourni, 4) Utilisation d'aria-labelledby pour associer le label au checkbox. Le composant est maintenant conforme WCAG pour l'accessibilité."
},
{
"id": 38,
"gravite": "MOYENNE",
"categorie": "Performance",
"titre": "GlobalSearchBar utilise debounceDelay mais pas useDebounce",
"description": "Le composant GlobalSearchBar passe debounceDelay={300} au composant Search mais le composant Search peut ne pas utiliser useDebounce correctement, causant des requêtes à chaque frappe.",
"fichiers_concernes": [
"apps/web/src/components/search/GlobalSearchBar.tsx",
"apps/web/src/components/search/Search.tsx"
],
"lignes_approximatives": [
"GlobalSearchBar.tsx:134",
"Search.tsx:recherche"
],
"symptomes": [
"Requêtes API à chaque frappe malgré debounceDelay",
"Performance dégradée",
"Charge serveur excessive"
],
"cause_probable": "Le composant Search peut ne pas implémenter correctement le debouncing ou utiliser un délai trop court.",
"solution_proposee": "Vérifier que Search.tsx utilise useDebounce correctement. Augmenter le délai si nécessaire. Tester le nombre de requêtes.",
"tests_a_effectuer": [
"Tester la recherche avec debouncing",
"Vérifier le nombre de requêtes",
"Tester les performances"
],
"priorite": 38,
"impact": "Performance et charge serveur dégradées",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Le debouncing est déjà correctement implémenté : GlobalSearchBar passe debounceDelay={500} au composant Search, qui utilise useDebounce(query, debounceDelay) à la ligne 67. Le système de debouncing fonctionne correctement via le composant Search qui encapsule la logique. Le problème était mal identifié - le debouncing fonctionne déjà."
},
{
"id": 39,
"gravite": "MOYENNE",
"categorie": "Memory Leaks",
"titre": "useEffect sans cleanup dans useChat",
"description": "Le hook useChat a plusieurs useEffect qui peuvent causer des memory leaks si le composant est démonté pendant une connexion WebSocket.",
"fichiers_concernes": [
"apps/web/src/features/chat/hooks/useChat.ts"
],
"lignes_approximatives": [
"useChat.ts:148-167, 169-174"
],
"symptomes": [
"Memory leaks possibles",
"Connexions WebSocket non fermées",
"Timers non nettoyés"
],
"cause_probable": "Les useEffect peuvent avoir des timers ou des connexions qui ne sont pas nettoyés correctement lors du démontage.",
"solution_proposee": "S'assurer que tous les useEffect retournent une fonction de cleanup. Nettoyer les timers, fermer les connexions WebSocket, annuler les requêtes en cours.",
"tests_a_effectuer": [
"Tester le démontage pendant une connexion",
"Vérifier qu'il n'y a pas de memory leaks",
"Tester avec React DevTools Profiler"
],
"priorite": 39,
"impact": "Memory leaks et performance dégradée",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Amélioration de la gestion des memory leaks dans useChat : 1) Nettoyage des event handlers WebSocket avant de créer une nouvelle connexion, 2) Nettoyage explicite des handlers (onopen, onmessage, onclose, onerror) dans disconnect(), 3) Vérification de l'état de la connexion avant fermeture, 4) Stockage des références aux handlers pour faciliter le nettoyage. Tous les useEffect ont maintenant des cleanups appropriés et les connexions WebSocket sont correctement fermées."
},
{
"id": 40,
"gravite": "MOYENNE",
"categorie": "Accessibilité",
"titre": "Table sans aria-label ou caption",
"description": "Les composants Table dans l'application n'ont pas toujours d'aria-label ou de TableCaption, rendant leur contenu inaccessible aux lecteurs d'écran.",
"fichiers_concernes": [
"apps/web/src/components/ui/table.tsx",
"apps/web/src/features/library/pages/LibraryPage.tsx"
],
"lignes_approximatives": [
"table.tsx:32-43",
"LibraryPage.tsx:370-478"
],
"symptomes": [
"Tables sans description accessible",
"Lecteurs d'écran ne peuvent pas décrire les tables",
"Accessibilité compromise"
],
"cause_probable": "Les tables sont créées sans aria-label ou TableCaption pour décrire leur contenu.",
"solution_proposee": "Ajouter aria-label ou TableCaption à toutes les tables. S'assurer que les tables ont une description accessible.",
"tests_a_effectuer": [
"Auditer toutes les tables",
"Tester avec un lecteur d'écran",
"Vérifier la conformité WCAG"
],
"priorite": 40,
"impact": "Accessibilité compromise",
"statut": "fixed",
"date_correction": "2026-01-07",
"notes_correction": "Amélioration de l'accessibilité des tables : 1) Ajout d'une interface TableProps avec support pour aria-label et aria-labelledby dans table.tsx, 2) Ajout d'aria-label=\"Liste des pistes de la bibliothèque\" dans LibraryPage.tsx, 3) Ajout de props aria-label et aria-labelledby dans le composant Table de data/Table.tsx, 4) Application des aria-label sur les éléments