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 tablememberspour faire correspondre l'e-mail et le code PIN. En l'absence de données, la requête renvoyait systématiquement une erreur401 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 (
1052pour les managers,4011pour les collaborateurs) ainsi que les phases par défaut.
- Création d'un script de peuplement automatique :
2. Erreur 500 - Récursion infinie des politiques de sécurité (PostgREST error 42P17)
- Symptôme : L'accès à la table
projectsou le chargement de l'application échouait avec une erreur500 Internal Server Errordans la console réseau. Le détail du log Supabase indiquaitPostgREST: 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
projectsappelait unSELECTsurmembers, et la politique demembersappelait à son tour unSELECTsurmemberslui-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()etpublic.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.
- Mise à jour du schéma dans
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
POSTen erreur401 Unauthorizedvers/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 fonctionsaveS()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
saveSdanssrc/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 erreurs401de la console.
- Modification de la fonction
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 statut200 OK. - Le cache local était alors écrasé par cette liste vide.
- Un effet de synchronisation global dans
App.jsxréé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.
- Lors du chargement de l'application,
- 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 lesession_tokenau client Supabase avant de lancer la récupération des données.
- Bloqué l'exécution de
- Dans
src/App.jsx:- Sécurisé l'effet de synchronisation de
ws_listpour qu'il ne s'exécute que si l'utilisateur est connecté (sessionactif).
- Sécurisé l'effet de synchronisation de
- Dans
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 defineddansSuperManagerDashboard.jsx. - Cause : Le composant
SuperManagerDashboard.jsxhéritait d'une logique de groupement de tâches copier-coller deAdminDashboard.jsx:groupBy={pillarFilter === "all" ? "pillar" : "owner"}. Cependant, la variable d'étatpillarFiltern'était pas déclarée dansSuperManagerDashboard.jsx. - Résolution :
- Ajout de la déclaration de l'état manquant
const [pillarFilter, setPillarFilter] = useState("all");à la ligne 21 desrc/pages/SuperManagerDashboard.jsx.
- Ajout de la déclaration de l'état manquant
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 (...) }danssrc/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
useEffectconcernés avant la conditionif (!hydrated)danssrc/App.jsx.
- Déplacement des hooks
