# DEVELOPMENT_PRINCIPLES.md — Expria / Coach TCF Canada
> **Document de référence — Version 1.0**
> Ce document définit les règles que Claude Code doit lire et respecter
> à chaque session de développement, sans exception.
> Il est conçu pour un projet maintenu par un fondateur non-technique
> assisté par l'IA.
---
## INSTRUCTION OBLIGATOIRE POUR CLAUDE CODE
**Avant d'écrire la moindre ligne de code, tu dois :**
1. Lire ce fichier en entier
2. Lire ARCHITECTURE.md
3. Lire PLANS_TARIFAIRES.md
4. Annoncer : "Documents lus. Voici mon plan pour cette session."
5. Produire un plan détaillé et attendre la validation
**Tu ne passes à l'implémentation que quand Hermann dit "GO".**
---
## 1. Le cycle de travail obligatoire
Chaque modification, petite ou grande, suit ce cycle sans exception :
```
ÉTAPE 1 — ANALYSE
Lire les fichiers concernés
Identifier tous les fichiers qui seront impactés
Identifier les risques de régression
ÉTAPE 2 — PLAN
Produire un plan détaillé :
— Fichiers modifiés (liste exhaustive)
— Fichiers créés (liste exhaustive)
— Fichiers supprimés (liste exhaustive)
— Risques identifiés
— Étapes dans l'ordre
Attendre la validation de Hermann
ÉTAPE 3 — IMPLÉMENTATION
Exécuter le plan validé
Ne pas s'écarter du plan sans signaler le changement
Maximum 3 fichiers touchés par étape
ÉTAPE 4 — VÉRIFICATION
Lancer npm run test (backend)
Annoncer le résultat : "X tests passés, 0 échecs"
Si un test échoue : STOP — corriger avant de continuer
ÉTAPE 5 — RÉSUMÉ
Lister exactement ce qui a été modifié
Indiquer les tests manuels à rejouer (référence au Golden Dataset)
```
---
## 2. Règles absolues — ne jamais enfreindre
### Règle A — Plan avant code
Claude Code ne commence jamais à coder sans plan validé.
Même pour une modification "simple" d'une ligne.
La simplicité apparente est trompeuse dans un projet avec des permissions par plan.
### Règle B — Maximum 3 fichiers par étape
Si une tâche nécessite de modifier plus de 3 fichiers,
elle est découpée en plusieurs étapes avec validation intermédiaire.
Chaque étape est testée avant de passer à la suivante.
### Règle C — Tests verts avant de continuer
Après chaque étape d'implémentation :
`npm run test` doit retourner 0 échec.
Si un test échoue, on corrige avant de passer à l'étape suivante.
On ne livre jamais une étape avec des tests rouges.
### Règle D — Jamais de logique de plan en dur dans le code
Toutes les vérifications de permissions lisent depuis `lib/access.ts`.
Exemple interdit :
```typescript
// ❌ JAMAIS
if (user.plan === 'premium') { ... }
if (user.plan !== 'free') { ... }
```
Exemple correct :
```typescript
// ✅ TOUJOURS
const perms = getPlanPermissions(user.plan)
if (perms.exam_mode) { ... }
```
### Règle E — Jamais de clé privée dans le frontend
Les variables suivantes n'existent que dans le backend :
- `SUPABASE_SERVICE_ROLE_KEY`
- `GEMINI_API_KEY`
- `DEEPSEEK_API_KEY`
- `STRIPE_SECRET_KEY`
- `STRIPE_WEBHOOK_SECRET`
Le frontend n'a accès qu'à :
- `VITE_SUPABASE_ANON_KEY` (clé publique Supabase)
- `VITE_API_URL` (URL du backend)
### Règle F — Jamais de modification de la base de données sans migration SQL
Toute modification du schéma Supabase passe par un fichier de migration
dans `supabase/migrations/`.
Jamais de modification directe dans le dashboard Supabase sans fichier de migration correspondant.
### Règle G — Jamais de suppression de données utilisateur
Aucune opération `DELETE` sur les tables `productions` ou `profiles`
sauf dans les scripts de test explicitement balisés.
En cas de doute : archiver, ne pas supprimer.
### Règle H — Signaler tout écart par rapport au plan
Si pendant l'implémentation Claude Code réalise que le plan doit être modifié,
il STOP, signale le changement, explique pourquoi, et attend une nouvelle validation.
Il ne prend jamais de décision architecturale de sa propre initiative.
### Règle I — Pas de worktree Git
Claude Code ne crée jamais de worktree Git (`git worktree add`).
Toutes les modifications se font directement dans le dossier
du projet principal.
---
## 3. Structure du code — conventions
### Nommage des fichiers
```
frontend/src/
pages/ → PascalCase.tsx (Dashboard.tsx, Simulation.tsx)
components/ → PascalCase.tsx (RapportCard.tsx, PaywallModal.tsx)
hooks/ → camelCase.ts (useAuth.ts, usePlan.ts)
api/ → camelCase.ts (simulations.ts, corrections.ts)
lib/ → camelCase.ts (access.ts, supabase.ts)
types/ → camelCase.ts (plans.ts, simulation.ts)
backend/src/
routes/ → camelCase.ts (simulations.ts, stripe.ts)
controllers/ → camelCase.ts (simulationController.ts)
middleware/ → camelCase.ts (auth.ts, plan.ts)
lib/ → camelCase.ts (access.ts, deepseek.ts)
__tests__/ → camelCase.test.ts (canUserSimulate.test.ts)
```
### Nommage des variables et fonctions
```typescript
// Variables : camelCase
const userPlan = 'premium'
const simulationsUsed = 5
// Fonctions : camelCase, verbe en premier
function getUserPlan(userId: string) { }
function canUserSimulate(profile: Profile) { }
function updateUserPlan(userId: string, plan: Plan) { }
// Types et interfaces : PascalCase
type Plan = 'free' | 'standard' | 'premium'
interface UserProfile { }
interface SimulationResult { }
// Constantes globales : SCREAMING_SNAKE_CASE
const MAX_FREE_SIMULATIONS = 5
const PLANS = { free: {...}, standard: {...}, premium: {...} }
```
### Structure d'une route Hono (backend)
```typescript
// Pattern obligatoire pour toutes les routes
app.post('/simulations', authMiddleware, planMiddleware('simulation'), async (c) => {
// 1. Récupérer et valider les données entrantes
const body = await c.req.json()
// 2. Logique métier (déléguer au controller)
const result = await simulationController.create(body, c.get('user'))
// 3. Retourner la réponse
return c.json(result, 201)
})
```
### Structure d'un composant React (frontend)
```typescript
// Pattern obligatoire pour tous les composants
interface Props {
// Toujours typer les props
}
export function NomDuComposant({ prop1, prop2 }: Props) {
// 1. Hooks en premier
const { user } = useAuth()
const perms = usePlan()
// 2. Handlers
const handleClick = () => { }
// 3. Rendu conditionnel selon le plan
if (!perms.dashboard) return