# Handoff — diff exhaustif du schéma de production (issue #137)

**But** : brief complet pour une conversation Claude Code dédiée. Objectif du chantier :
savoir **exactement** ce qui diffère entre le schéma réel de la production et le schéma
qu'obtiennent nos migrations, puis produire les migrations de rattrapage nécessaires.

**Le prompt à coller est au §7.**

---

## 1. Pourquoi ce chantier existe

Le 06/08, la table `migrations` de la production a été « recalée » : les noms des migrations
manquantes y ont été **insérés sans être exécutés**, en supposant que les objets existaient
déjà (procédure `15_BASCULE_SERVEUR_VERS_GIT.md`, étape 5).

Le 08/08, au déploiement du staging, cette hypothèse s'est révélée fausse : la colonne
**`courses.category_id` n'existe ni en staging ni en production**, alors que la migration
`add_category_id_into_courses` est enregistrée comme appliquée. La migration de rattrapage
EA-001 a échoué dessus (`errno 1072`).

**Conséquence** : Laravel croit le schéma à jour, la réalité dit autre chose, et **on ne sait
pas ce qui manque d'autre**. Tant que ce diff n'est pas fait, chaque déploiement en production
est un pari.

## 2. ⚠️ Point d'attention CENTRAL sur la méthode

> **Comparer des NOMS de migrations ne prouve rien. Il faut comparer les OBJETS.**

C'est exactement l'erreur du 06/08 : un `comm` entre les noms de fichiers du disque et les
lignes de la table `migrations` a conclu « tout est là », alors que des colonnes manquaient.

La seule méthode fiable :

1. Construire un **schéma de référence** : `migrate:fresh` sur une base VIERGE locale, à partir
   des migrations de `development`. C'est ce que le code *croit* être le schéma.
2. Extraire le **schéma réel** de la production (structure seule, `mysqldump --no-data`, ou
   `information_schema`).
3. Comparer **objet par objet** : tables, puis pour chaque table les colonnes (nom, type,
   nullabilité, défaut), les index, les clés étrangères.
4. Ne conclure « conforme » **que** sur la base de cette comparaison — jamais sur le contenu de
   la table `migrations`.

Le livrable doit distinguer trois catégories, qui n'ont pas le même traitement :
- **Manquant en prod** (le code l'attend, la base ne l'a pas) → migration de rattrapage, idempotente ;
- **En trop en prod** (la base l'a, le code l'ignore) → colonne morte : décision explicite (garder/supprimer) ;
- **Divergent** (existe des deux côtés mais type/nullabilité/défaut différents) → **le plus dangereux**,
  car silencieux : à examiner un par un.

## 3. Accès et environnement

| Élément | Valeur |
|---|---|
| Serveur | `ssh ubuntu@57.129.1.122` (clé déjà en place ; sudo disponible) |
| Racine Laravel prod | `/var/www/api.efektiv-academie.com/e-learning-api` |
| Base prod | `elearning` — identifiants dans le `.env` de cette racine |
| Base staging | `elearning-staging` (**a divergé le 08/08** : migrations L1+L2 appliquées + conversion InnoDB → ne PAS la prendre comme référence de la prod) |
| PHP local | `/opt/homebrew/opt/php@8.2/bin/php` (8.2 obligatoire, cf. `09_ENVIRONNEMENT_LOCAL.md`) |
| Repo | `AAZTEKDEV/EFEKTIVACADEMIE-BACK`, branche `development` |

**Le diff est une opération EN LECTURE SEULE** : aucune écriture sur la prod, aucune fenêtre de
maintenance nécessaire, aucun impact utilisateur. Il peut tourner à n'importe quelle heure.

## 4. Pièges déjà connus (ne pas les redécouvrir)

1. **Le recalage trompeur** (§2) — le piège principal.
2. **Toute la prod est en MyISAM** (55 tables) : ce moteur ignore silencieusement les clés
   étrangères. Une FK « déclarée » dans une vieille migration peut donc **ne pas exister** en
   base sans que rien ne l'ait signalé. Le diff doit traiter les FK comme un sujet à part.
   Conversion prévue en issue #136 — **prérequis** aux migrations de rattrapage qui créent des FK.
3. **`courses.category_id` absent** des deux bases (déjà contourné par #135, qui ne crée les FK
   que sur les colonnes réellement présentes).
4. **Chemin d'URL inhabituel** : la racine web de l'API est le dossier *parent* de Laravel, d'où
   `…/e-learning-api/public/api/…`. Ne pas y toucher.
5. **Ne jamais lancer `git clean`** sur le serveur : 289 Mo de fichiers téléversés (certificats,
   avatars, ressources) sont non suivis et seraient supprimés.
6. **Ordre des opérations sur le serveur** : `git checkout` d'abord, `chown www-data` ensuite —
   l'inverse empêche git de travailler (erreur vécue le 08/08).
7. La prod contient des copies manuelles de l'équipe (`app-old-16-10/`, `app--13-05-2026/`…) :
   les ignorer, ne rien y supprimer.

## 5. Livrables attendus

1. **Rapport de diff** dans `docs/roadmap/` : tableau par table, avec les trois catégories du §2
   et une colonne « impact » (fonctionnalité concernée, sévérité).
2. **Migrations de rattrapage** pour les écarts qui comptent — **idempotentes**
   (`Schema::hasColumn` / `hasTable`), rejouables sur prod, staging et local, comme
   `2026_08_07_200001_ea001_rattrapage_schema`.
3. **Issues** pour ce qui relève d'une décision produit (colonnes mortes, divergences de type).
4. **Correctif de la procédure** `15_BASCULE_SERVEUR_VERS_GIT.md` : le recalage doit exiger une
   vérification objet par objet, pas une comparaison de noms.
5. Le tout **en PR** vers `development` (jamais de push direct), une PR par livrable cohérent.

## 6. Règles de travail du repo (rappel)

- **1 issue = 1 branche = 1 PR** ; tests dans la même PR (`14_REGLES_GIT.md`).
- **Branches empilées** : re-cibler sur `development` AVANT merge, puis **vérifier le contenu
  réellement présent** sur la cible (incident du 08/08, documenté dans `14_REGLES_GIT.md`).
- Doctrine de maintenance des tests : `17_DOCTRINE_TESTS.md`.
- Cycle des statuts d'issues : `recette/00_STATUTS_ISSUES.md`.
- Commits en français, signés `Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>`.

## 7. Prompt à coller dans la conversation dédiée

> Lis `docs/roadmap/18_HANDOFF_DIFF_SCHEMA_PROD.md` et exécute le chantier qu'il décrit : le diff
> exhaustif entre le schéma réel de la production et le schéma attendu par nos migrations
> (issue #137).
>
> Respecte impérativement le point d'attention du §2 : **comparer les objets, jamais les noms de
> migrations** — c'est précisément l'erreur qui a créé ce problème. Le diff est en lecture seule
> sur la prod ; aucune écriture sans mon accord explicite.
>
> Livre : le rapport de diff, les migrations de rattrapage idempotentes, les issues pour ce qui
> relève d'une décision, et le correctif de la procédure de recalage — le tout en PR vers
> `development`.
>
> Signale-moi tout écart dont la correction pourrait changer un comportement visible par les
> apprenants : je veux trancher moi-même.
