docs: ajout documentation de référence
This commit is contained in:
parent
1cb432401d
commit
b06970c9ae
8 changed files with 2954 additions and 46 deletions
422
docs/DEVELOPMENT_PRINCIPLES.md
Normal file
422
docs/DEVELOPMENT_PRINCIPLES.md
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
# 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.
|
||||
|
||||
---
|
||||
|
||||
## 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 <PaywallModal feature="dashboard" />
|
||||
|
||||
// 4. JSX
|
||||
return (
|
||||
<div>...</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Gestion des erreurs
|
||||
|
||||
### Backend — toujours retourner une erreur structurée
|
||||
```typescript
|
||||
// ✅ Format d'erreur standard
|
||||
return c.json({
|
||||
error: true,
|
||||
code: 'QUOTA_REACHED',
|
||||
message: 'Quota de simulations atteint pour ce plan',
|
||||
}, 403)
|
||||
|
||||
// ❌ Jamais
|
||||
return c.json({ error: 'error' }, 500)
|
||||
throw new Error('Something went wrong')
|
||||
```
|
||||
|
||||
### Codes d'erreur standardisés
|
||||
```
|
||||
AUTH_REQUIRED → 401 Pas de JWT ou JWT invalide
|
||||
PLAN_INSUFFICIENT → 403 Feature non disponible pour ce plan
|
||||
QUOTA_REACHED → 403 Quota de simulations épuisé
|
||||
INVALID_PLAN → 400 Valeur de plan inconnue
|
||||
SIMULATION_NOT_FOUND → 404 Simulation inexistante ou non accessible
|
||||
STRIPE_WEBHOOK_INVALID → 400 Signature webhook invalide
|
||||
INTERNAL_ERROR → 500 Erreur serveur inattendue
|
||||
```
|
||||
|
||||
### Frontend — toujours gérer les erreurs API
|
||||
```typescript
|
||||
// ✅ Pattern obligatoire pour tout appel API
|
||||
try {
|
||||
const result = await api.simulations.create(data)
|
||||
// succès
|
||||
} catch (error) {
|
||||
if (error.code === 'QUOTA_REACHED') {
|
||||
// afficher modal upgrade
|
||||
} else if (error.code === 'PLAN_INSUFFICIENT') {
|
||||
// afficher paywall
|
||||
} else {
|
||||
// afficher message d'erreur générique
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Sécurité — vérifications obligatoires
|
||||
|
||||
### Toute route backend qui touche à des données utilisateur doit :
|
||||
|
||||
```typescript
|
||||
// 1. Vérifier l'authentification
|
||||
app.use(authMiddleware) // vérifie le JWT Supabase
|
||||
|
||||
// 2. Vérifier le plan si nécessaire
|
||||
app.use(planMiddleware('exam_mode')) // vérifie la permission
|
||||
|
||||
// 3. Vérifier que la ressource appartient à l'utilisateur
|
||||
const simulation = await db.getSimulation(id)
|
||||
if (simulation.user_id !== currentUser.id) {
|
||||
return c.json({ error: true, code: 'AUTH_REQUIRED' }, 401)
|
||||
}
|
||||
```
|
||||
|
||||
### La vérification des permissions se fait TOUJOURS côté backend
|
||||
Le frontend peut masquer des boutons selon le plan — c'est de l'UX.
|
||||
Mais la vérification réelle se fait dans le middleware backend.
|
||||
Un utilisateur malveillant peut appeler l'API directement sans passer par le frontend.
|
||||
|
||||
---
|
||||
|
||||
## 6. Communication avec Hermann
|
||||
|
||||
### Format du plan (avant implémentation)
|
||||
```
|
||||
📋 PLAN — [nom de la tâche]
|
||||
|
||||
Fichiers modifiés :
|
||||
- src/routes/simulations.ts (ajouter la vérification de quota)
|
||||
- src/lib/access.ts (ajouter la fonction canUserSimulate)
|
||||
|
||||
Fichiers créés :
|
||||
- src/lib/__tests__/canUserSimulate.test.ts
|
||||
|
||||
Fichiers supprimés :
|
||||
- aucun
|
||||
|
||||
Risques identifiés :
|
||||
- La modification de access.ts peut affecter toutes les routes
|
||||
qui utilisent getPlanPermissions → vérifier après modification
|
||||
|
||||
Étapes :
|
||||
1. Créer la fonction canUserSimulate dans access.ts
|
||||
2. Écrire le test canUserSimulate.test.ts
|
||||
3. Ajouter la vérification dans la route POST /simulations
|
||||
|
||||
En attente de validation avant de commencer.
|
||||
```
|
||||
|
||||
### Format du résumé (après implémentation)
|
||||
```
|
||||
✅ RÉSUMÉ — [nom de la tâche]
|
||||
|
||||
Modifié :
|
||||
- src/routes/simulations.ts : ajout vérification quota ligne 42
|
||||
- src/lib/access.ts : ajout fonction canUserSimulate
|
||||
|
||||
Créé :
|
||||
- src/lib/__tests__/canUserSimulate.test.ts (7 tests)
|
||||
|
||||
Tests : 41/41 passés ✅
|
||||
|
||||
Tests manuels à rejouer :
|
||||
- Golden Dataset Groupe 2 (B2, B7) — quota Free
|
||||
- Golden Dataset Groupe 3 (C2) — illimité Standard
|
||||
```
|
||||
|
||||
### Quand Claude Code doit s'arrêter et demander
|
||||
- Un test automatisé échoue après modification
|
||||
- La tâche nécessite de modifier plus de 3 fichiers par étape
|
||||
- Une décision architecturale non documentée est requise
|
||||
- Une ambiguïté sur le comportement attendu selon un plan tarifaire
|
||||
- Une clé privée serait nécessaire côté frontend
|
||||
|
||||
---
|
||||
|
||||
## 7. Checklist de démarrage de session
|
||||
|
||||
Avant chaque session Claude Code, vérifier :
|
||||
|
||||
```
|
||||
[ ] Les 4 documents de référence ont été lus
|
||||
(DEVELOPMENT_PRINCIPLES.md, ARCHITECTURE.md,
|
||||
PLANS_TARIFAIRES.md, PARCOURS_UTILISATEURS.md)
|
||||
|
||||
[ ] L'environnement de test est dans l'état attendu
|
||||
(voir TEST_ENVIRONMENT.md — script de réinitialisation)
|
||||
|
||||
[ ] Les tests automatisés sont tous verts
|
||||
(npm run test → 0 échec)
|
||||
|
||||
[ ] Un commit Git propre existe avant de commencer
|
||||
(état de repli en cas de régression)
|
||||
|
||||
[ ] La tâche de la session est clairement définie
|
||||
(une seule tâche par session)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. Checklist de fin de session
|
||||
|
||||
Avant de clôturer chaque session Claude Code :
|
||||
|
||||
```
|
||||
[ ] Les tests automatisés sont tous verts
|
||||
(npm run test → 0 échec)
|
||||
|
||||
[ ] Le résumé de session a été produit
|
||||
(fichiers modifiés, tests passés)
|
||||
|
||||
[ ] Les tests manuels du Golden Dataset ont été rejoués
|
||||
(groupes concernés par les modifications)
|
||||
|
||||
[ ] Un commit Git a été fait avec un message clair
|
||||
Format : "feat: [description]" ou "fix: [description]"
|
||||
Exemples :
|
||||
"feat: ajout vérification quota simulations free"
|
||||
"fix: correction rapport flouté plan découverte"
|
||||
"refactor: extraction logique permissions dans access.ts"
|
||||
|
||||
[ ] DEVELOPMENT_PRINCIPLES.md et ARCHITECTURE.md
|
||||
sont à jour si une décision a changé
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. Messages d'erreur utilisateur — ton et format
|
||||
|
||||
Les messages affichés à l'utilisateur doivent être :
|
||||
- En français
|
||||
- Clairs et non techniques
|
||||
- Orientés action (que faire ensuite)
|
||||
- Non condescendants
|
||||
|
||||
```
|
||||
// ✅ Bons messages
|
||||
"Vous avez utilisé vos 5 simulations gratuites.
|
||||
Passez en Standard pour continuer votre préparation."
|
||||
|
||||
"Le mode Examen est réservé au plan Premium.
|
||||
Passez en Premium pour vous entraîner en conditions réelles."
|
||||
|
||||
"Une erreur est survenue. Veuillez réessayer dans quelques instants."
|
||||
|
||||
// ❌ Mauvais messages
|
||||
"Erreur 403 : quota_reached"
|
||||
"Vous n'êtes pas autorisé à effectuer cette action."
|
||||
"Internal server error"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. Ce que Claude Code ne doit jamais faire
|
||||
|
||||
```
|
||||
❌ Modifier lib/access.ts sans signaler que TOUTES les permissions sont impactées
|
||||
❌ Ajouter une dépendance npm sans demander la validation
|
||||
❌ Modifier le schéma Supabase directement dans le dashboard
|
||||
❌ Écrire une logique de plan en dur (if plan === 'premium')
|
||||
❌ Exposer une clé privée dans le frontend
|
||||
❌ Supprimer des données utilisateur (productions, profiles)
|
||||
❌ Modifier plus de 3 fichiers sans validation intermédiaire
|
||||
❌ Passer à l'étape suivante si un test est rouge
|
||||
❌ Prendre une décision architecturale sans la documenter
|
||||
❌ Coder sans plan validé, même pour "juste une petite modification"
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue