docs: ajouter ONBOARDING, SECURITY, CHANGELOG, ADR 001-006
This commit is contained in:
parent
28c9c08d31
commit
52b8e9d011
9 changed files with 1380 additions and 0 deletions
78
docs/adr/002-auth-api-decoupling.md
Normal file
78
docs/adr/002-auth-api-decoupling.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# 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<string | null> { ... }
|
||||
|
||||
// api-client.ts (connaît HTTP, rien d'autre)
|
||||
export async function apiFetch<T>(path: string, options: RequestOptions = {}): Promise<T> {
|
||||
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)
|
||||
Loading…
Add table
Add a link
Reference in a new issue