# ADR 002 — Découplage auth-client et api-client **Statut :** Accepté **Date :** 2026-04-17 **Décideur :** Hermann --- ## Contexte Le frontend doit : 1. Obtenir un token JWT auprès de Supabase (authentification). 2. Envoyer ce token au backend Hono sur chaque requête API (autorisation). L'approche initiale proposée était un seul fichier `api-client.ts` contenant un intercepteur qui appelle directement le SDK Supabase pour récupérer le token avant chaque requête. Cette approche couple fortement le client HTTP à Supabase. ## Options envisagées ### Option A — API client avec intercepteur Supabase intégré ```typescript // api-client.ts import { supabase } from './supabase' async function apiFetch(path: string) { const { data } = await supabase.auth.getSession() return fetch(`${API_URL}${path}`, { headers: { Authorization: `Bearer ${data.session?.access_token}` } }) } ``` - Avantages : code court, un seul fichier, familier aux développeurs juniors. - Inconvénients : couple définitivement l'HTTP layer à Supabase, rend impossible le test du client API sans mocker Supabase entier, bloque toute migration future d'auth (ex : passage à Auth0, Clerk, auth maison). ### Option B — Deux fichiers distincts ```typescript // auth-client.ts (connaît Supabase, rien d'autre) export async function getAccessToken(): Promise { ... } // api-client.ts (connaît HTTP, rien d'autre) export async function apiFetch(path: string, options: RequestOptions = {}): Promise { const token = options.token ?? await getAccessToken() // fetch avec Bearer token } ``` - Avantages : séparation des responsabilités claire (auth vs HTTP), chaque fichier testable indépendamment, migration d'auth = modifier un seul fichier, respecte le principe d'inversion de dépendance. - Inconvénients : deux fichiers au lieu d'un (impact négligeable). ## Décision **Option B** — deux fichiers séparés : - `src/shared/lib/auth-client.ts` : gère exclusivement Supabase Auth (login, logout, register, récupération du token, refresh de session). - `src/shared/lib/api-client.ts` : gère exclusivement les appels HTTP vers `api.expria.app` (fetch, retry, timeout, logging, parsing d'erreurs). L'api-client appelle `getAccessToken()` depuis l'auth-client, mais n'importe aucun type ni fonction Supabase directement. ## Conséquences **Positives :** - Un dev qui arrive comprend en 30 secondes : "ici l'auth, ici l'HTTP". - Le test de `api-client.ts` ne nécessite pas de mocker Supabase — on injecte un token factice. - Si Supabase est remplacé un jour (peu probable mais possible), seul `auth-client.ts` change. Aucun fichier feature n'est touché. - Cohérent avec la Règle 1 de `DEVELOPMENT_PRINCIPLES.md` : séparation stricte des responsabilités. **Négatives :** - Un fichier supplémentaire. Coût négligeable. **À revisiter si :** - Un besoin de couplage fort émerge (ex : un token custom généré par le backend plutôt que Supabase). Dans ce cas, la séparation reste valide — on change juste l'implémentation interne de `getAccessToken()`. ## Références - `DEVELOPMENT_PRINCIPLES.md` Règle 1 (séparation stricte) - `ARCHITECTURE.md` §10 Règle 1 (le frontend ne contient aucune logique métier)