DOC
Accueil/ Projets/ MJY Task Platform/ Actions manuelles - Sprint 04

Actions manuelles - Sprint 04

Ce document liste tout ce que tu dois exécuter toi-même (Claude ne peut pas le faire à ta place : accès à ta console Supabase, à ton dashboard Netlify/Hostinger, installation de paquets, tests visuels).

Ordre conseillé : 1 → 2 → 3 → 4 → 5.


1. Variables d'environnement (⚠️ obligatoire, sinon l'auth ne démarre plus)

Depuis le Sprint 04, le serveur refuse de démarrer sans SUPABASE_JWT_SECRET (plus de valeur par défaut 'secret'), et la clé Anthropic a été renommée (VITE_ANTHROPIC_API_KEYANTHROPIC_API_KEY).

a) En local - fichier .env

Vérifie/complète (voir .env.example) :

VITE_SUPABASE_URL=https://TON-projet.supabase.co
VITE_SUPABASE_ANON_KEY=eyJ...            # clé "anon public"
SUPABASE_SERVICE_ROLE_KEY=eyJ...          # clé "service_role" (secrète)
SUPABASE_JWT_SECRET=xxxxxxxx              # Supabase > Settings > API > JWT Secret
ANTHROPIC_API_KEY=sk-ant-...              # (facultatif : sans elle, l'import IA passe en mode démo)

b) Sur Netlify - Site settings → Environment variables

Ajoute/renomme les mêmes clés. Important : si tu avais VITE_ANTHROPIC_API_KEY, crée ANTHROPIC_API_KEY (l'ancienne n'est plus lue).

c) Sur Hostinger (si tu utilises server.js / Node)

Renseigne les mêmes variables dans la configuration Node de l'hébergement.

Où trouver le JWT Secret : Supabase → Settings → API → JWT Settings → JWT Secret.


2. TS4.8 - Migration Supabase (hachage des PIN) - SQL Editor

Oui : tout se fait dans Supabase → SQL Editor → New query. La migration est en 3 étapes (pour éviter toute coupure : on ne supprime les PIN en clair qu'après avoir vérifié que la connexion marche).

🟢 ÉTAPE 1 - À lancer maintenant (crée le hash + la fonction de vérification)

⚠️ Chez Supabase, pgcrypto est installé dans le schéma extensions (pas public). Le search_path doit donc inclure extensions, sinon : ERROR: function crypt(text, text) does not exist.

-- 1a. Extension de cryptographie (bcrypt) - souvent dans le schéma "extensions"
create extension if not exists pgcrypto;

-- 1b. Rendre crypt()/gen_salt() visibles quel que soit leur schéma (public OU extensions)
set search_path = public, extensions;

-- 1c. Colonne de hash
alter table public.members add column if not exists pin_hash text;

-- 1d. Hacher les PIN en clair existants
update public.members
set pin_hash = crypt(pin, gen_salt('bf'))
where pin is not null and pin_hash is null;

-- 1e. Fonction d'authentification sécurisée (compare le hash, contourne le RLS)
--     Le search_path inclut "extensions" pour retrouver crypt() à l'exécution.
create or replace function public.verify_member_pin(
  p_email text,
  p_pin text,
  p_project_id text default null
)
returns setof public.members
language sql
security definer
set search_path = public, extensions
as $$
  select *
  from public.members
  where lower(email) = lower(p_email)
    and pin_hash is not null
    and pin_hash = crypt(p_pin, pin_hash)
    and (p_project_id is null or project_id = p_project_id);
$$;

-- 1f. Réserver l'exécution au backend (clé service_role) UNIQUEMENT.
--     Par défaut Postgres autorise PUBLIC : sans ce revoke, la clé anon publique
--     pourrait brute-forcer les PIN (10 000 combinaisons) directement via RPC.
revoke all on function public.verify_member_pin(text, text, text) from public;
grant execute on function public.verify_member_pin(text, text, text) to service_role;

Si l'erreur persiste, vérifie le schéma réel de pgcrypto puis remplace extensions en conséquence :

select extname, extnamespace::regnamespace as schema from pg_extension where extname = 'pgcrypto';

🟡 ÉTAPE 2 - Déployer le code

Le code serveur (server.js et netlify/functions/auth.js) appelle déjà verify_member_pin avec un repli automatique sur l'ancienne méthode tant que l'ÉTAPE 1 n'est pas faite. ➡️ Redéploie/relance simplement l'application après l'ÉTAPE 1, puis teste une connexion (manager ET collaborateur).

🔴 ÉTAPE 3 - Seulement après avoir confirmé que la connexion fonctionne

-- Supprime définitivement les PIN en clair
alter table members drop column pin;

⛔ Ne lance l'ÉTAPE 3 que si la connexion marche avec les hash. Une fois pin supprimée, le repli en clair n'existe plus (comportement voulu : plus aucun PIN lisible en base).

♻️ Si tu ré-exécutes seed-db.js plus tard

Le script insère encore des PIN en clair. Après un seed, re-lance l'étape de hachage pour (re)générer les hash :

set search_path = public, extensions;
update public.members set pin_hash = crypt(pin, gen_salt('bf')) where pin is not null and pin_hash is null;

(Idéalement, à terme : adapter seed-db.js pour écrire directement pin_hash. Non bloquant.)


3. TS4.24 - Activer ESLint (qualité de code)

La config est déjà prête (.eslintrc.cjs) et le script lint ajouté à package.json. Il te reste une installation :

npm install -D eslint@8 eslint-plugin-react eslint-plugin-react-hooks
npm run lint

Le plugin react-hooks signale les setState pendant le rendu - exactement la classe de bug de l'« Error #310 ».


4. Vérifications manuelles de l'application (TS4.3, TS4.6, TS4.19)

a) Lancer l'app en développement avec l'API

Dans deux terminaux (le proxy /api de Vite pointe vers server.js) :

# Terminal 1 - API (nécessite les variables du §1)
npm start
# Terminal 2 - Frontend
npm run dev

Alternative tout-en-un : netlify dev (si la CLI Netlify est installée).

b) Scénarios à cliquer

  • TS4.19 (proxy dev) : sur l'écran de connexion, choisis un compte et saisis son PIN → la connexion aboutit (pas d'erreur /api/...).
  • TS4.3 (Error #310) : connecte-toi en manager, clique « 👤 Mes tâches assignées » puis « 🗝️ Manager » plusieurs fois → aucun plantage, aucune erreur rouge dans la console (F12).
  • TS4.6 (notes) : ouvre une tâche, ajoute une note, recharge la page (F5) → la date/heure de la note reste correcte (plus de « Invalid Date »).

5. (Recommandé, optionnel) Secret du Super Manager

Le PIN Super Manager 9999 est encore codé en dur dans server.js et netlify/functions/auth.js. Il n'est pas exposé au client (contrairement aux anciens PIN), mais reste un secret dans le code. 👉 Dis-le-moi si tu veux que je le déplace vers une variable d'environnement SUPER_MANAGER_PIN.


Récapitulatif express

# Action Bloquant ?
1 Configurer SUPABASE_JWT_SECRET + ANTHROPIC_API_KEY .env, Netlify, Hostinger ✅ Oui
2 Migration SQL ÉTAPE 1 (hash + fonction) Supabase SQL Editor ✅ Oui (sécurité)
2 Migration SQL ÉTAPE 3 (drop pin) Supabase SQL Editor après vérif
3 npm install -D eslint... + npm run lint Terminal local ⬜ Non
4 Tests manuels (login, rôles, notes) Navigateur ⬜ recommandé
5 Déplacer PIN 9999 en env (me le demander) ⬜ optionnel