DOC
Accueil/ Projets/ MJY Task Platform/ Journal de Résolution des Incidents - Configuration Supabase & Hostinger

Journal de Résolution des Incidents - Configuration Supabase & Hostinger

Date : 6 juillet 2026

Ce document consigne les erreurs rencontrées lors du déploiement et de la configuration de la base de données Supabase, les causes identifiées et les actions menées pour les résoudre.


1. Dysfonctionnement de la connexion par PIN (Base vide)

  • Symptôme : Impossible de se connecter en tant que manager ou collaborateur avec les codes PIN. Seul le "Super Manager" (hardcodé) parvenait à se connecter.
  • Cause : La base de données Supabase était vide. Lors de la tentative de connexion, l'API backend (server.js) interrogeait la table members pour faire correspondre l'e-mail et le code PIN. En l'absence de données, la requête renvoyait systématiquement une erreur 401 Unauthorized ("Code PIN incorrect ou utilisateur introuvable").
  • Résolution :
    • Création d'un script de peuplement automatique : seed-db.js.
    • Exécution du script pour insérer les projets par défaut (Miyan Noodles et ENGWE France), les membres d'origine avec leurs adresses e-mails et codes PIN respectifs (1052 pour les managers, 4011 pour les collaborateurs) ainsi que les phases par défaut.

2. Erreur 500 - Récursion infinie des politiques de sécurité (PostgREST error 42P17)

  • Symptôme : L'accès à la table projects ou le chargement de l'application échouait avec une erreur 500 Internal Server Error dans la console réseau. Le détail du log Supabase indiquait PostgREST: error=42P17.
  • Cause : Les règles de sécurité au niveau des lignes (RLS - Row Level Security) de Supabase provoquaient une boucle infinie de requêtes. La politique de projects appelait un SELECT sur members, et la politique de members appelait à son tour un SELECT sur members lui-même.
  • Résolution :
    • Mise à jour du schéma dans docs/supabase_schema.sql.
    • Création de deux fonctions d'aide PostgreSQL avec l'option SECURITY DEFINER : public.is_project_manager() et public.is_project_member(). Cette option force les fonctions à s'exécuter avec les privilèges du propriétaire de la base de données, contournant ainsi le système RLS et cassant la récursion infinie.
    • Mise à jour des politiques RLS de toutes les tables pour utiliser ces deux fonctions sécurisées.

3. Erreur 401 sur la page d'authentification (Tentative de synchronisation anonyme)

  • Symptôme : Lors du premier affichage de la page de connexion, la console affichait plusieurs requêtes POST en erreur 401 Unauthorized vers /rest/v1/projects (et d'autres tables).
  • Cause : Le frontend chargeait les membres et projets publics via l'API backend publique (qui fonctionne correctement avec la clé d'administration globale). Une fois reçues, le code frontend appelait saveS() pour stocker ces informations localement. Cependant, la fonction saveS() essayait aussi de synchroniser immédiatement ces données vers Supabase en arrière-plan avec la clé anon. Comme aucun utilisateur n'était encore connecté à ce stade, les écritures RLS étaient rejetées avec une erreur 401.
  • Résolution :
    • Modification de la fonction saveS dans src/services/storage.js.
    • Ajout d'une condition pour n'envoyer de requêtes d'écriture à Supabase que si une session utilisateur active (session) est présente dans le cache ou le stockage local. Les écritures anonymes de démarrage sont désormais bloquées côté client, éliminant les erreurs 401 de la console.

4. Disparition des projets et membres sur la page de connexion (Écrasement du cache local)

  • Symptôme : Une fois la récursion RLS résolue, tous les projets et collaborateurs ont disparu de la page d'authentification (écran blanc/vide).
  • Cause :
    • Lors du chargement de l'application, pullFromSupabase() s'exécutait avant de charger le token de session et de l'appliquer au client Supabase. La requête était donc effectuée anonymement.
    • Parce que la RLS empêche les lectures anonymes, Supabase renvoyait légitimement une liste vide ([]) avec un statut 200 OK.
    • Le cache local était alors écrasé par cette liste vide.
    • Un effet de synchronisation global dans App.jsx réécrivait de force cette liste vide [] dans le stockage à chaque rendu, écrasant les données légitimes récupérées par la suite par l'API backend publique.
  • Résolution :
    • Dans src/services/storage.js :
      • Bloqué l'exécution de pullFromSupabase() si aucune session utilisateur n'est active.
      • Modifié hydrateFromCloud() pour charger et appliquer le session_token au client Supabase avant de lancer la récupération des données.
    • Dans src/App.jsx :
      • Sécurisé l'effet de synchronisation de ws_list pour qu'il ne s'exécute que si l'utilisateur est connecté (session actif).

5. Plantage sur le tableau de bord Super Manager (ReferenceError: pillarFilter is not defined)

  • Symptôme : Lors du clic sur le rôle "Super Manager", l'application plante avec un écran blanc et l'erreur console ReferenceError: pillarFilter is not defined dans SuperManagerDashboard.jsx.
  • Cause : Le composant SuperManagerDashboard.jsx héritait d'une logique de groupement de tâches copier-coller de AdminDashboard.jsx : groupBy={pillarFilter === "all" ? "pillar" : "owner"}. Cependant, la variable d'état pillarFilter n'était pas déclarée dans SuperManagerDashboard.jsx.
  • Résolution :

6. Erreur d'ordre des Hooks (Minified React Error #310)

  • Symptôme : Au chargement de l'application, celle-ci plante avec l'erreur Minified React error #310; visit https://reactjs.org/docs/error-decoder.html?invariant=310.
  • Cause : Les nouveaux hooks useEffect (pour l'expiration de session et la synchro après connexion) avaient été déclarés après la condition de retour anticipé if (!hydrated) { return (...) } dans src/App.jsx. En React, tous les hooks doivent être appelés inconditionnellement et dans le même ordre à chaque rendu.
  • Résolution :
    • Déplacement des hooks useEffect concernés avant la condition if (!hydrated) dans src/App.jsx.