vault backup: 2026-07-30 17:01:43

This commit is contained in:
2026-07-30 17:01:43 -04:00
parent 4c8db1e7ce
commit ad91a431cf
2 changed files with 1148 additions and 0 deletions
@@ -0,0 +1,478 @@
## Resume executif
Le CTO souhaite supprimer Mogador afin que les donnees sauvegardees dans Louise puissent alimenter les sites plus directement.
L'objectif est legitime: le flux actuel est lourd, lent et difficile a maintenir.
Flux actuel simplifie:
```text
Louise
-> export SQL complet toutes les 3h
-> rsync vers serveurs internes
-> import MySQL
-> API Mogador
-> Laravel Sync
-> Directus
-> sites web / fournisseurs
```
Le probleme principal n'est pas seulement Mogador. Le vrai probleme est que le systeme depend de plusieurs couches qui ne donnent pas assez de garanties de fiabilite, d'observabilite et de publication rapide.
Supprimer Mogador est possible, mais il faut remplacer ce que Mogador fournit aujourd'hui:
- une API officielle au-dessus de l'export Louise;
- une logique metier implicite;
- une structure de donnees consommee par Laravel;
- un point de controle en cas d'audit;
- une maniere standard d'obtenir produits, programmations, series, collections, images, videos, presses et droits.
La recommandation est de ne pas passer directement a "Louise save -> site". C'est trop risque si le fournisseur ne garantit pas les evenements, les retries, l'audit et le replay.
La meilleure cible serait:
```text
Louise full snapshot JSON officiel + events optionnels
-> Sync Engine interne
-> validation / diff / rapports
-> JSON statiques par plateforme
-> buckets/CDN
-> sites web
```
Il faut retirer Mogador seulement apres une periode de double-run ou les sorties Mogador et les nouvelles sorties Louise sont comparees et validees.
## Contexte
Louise est la source de verite fonctionnelle. Toutes les 3 heures, Louise produit `export_mogador.sql`, un export SQL complet qui commence par des `TRUNCATE`, puis reinsere toutes les donnees.
Aujourd'hui, l'equipe consomme ces donnees via l'API Mogador. Cette API parle a une base MySQL reconstruite a partir de l'export SQL.
Mogador est donc une couche intermediaire entre Louise et notre systeme de publication.
Le CTO souhaite supprimer cette couche pour accelerer la publication et simplifier le systeme.
## Pourquoi supprimer Mogador
Les raisons sont bonnes:
- reduire le nombre de couches;
- publier plus vite;
- eviter les imports SQL lourds;
- eviter trois serveurs avec le meme code;
- reduire les points de panne;
- faciliter une mise a jour rapide des sites;
- reprendre le controle de la publication.
Mais supprimer Mogador cree aussi des risques si aucun remplacement fiable n'est prevu.
## Ce que Mogador fait aujourd'hui
Mogador n'est pas seulement une base de donnees. Dans le flux actuel, c'est aussi:
- une API officielle;
- une couche contractuelle/audit;
- une abstraction au-dessus de la structure SQL Louise;
- une facon stable pour Laravel de recuperer les donnees;
- un point d'acces pour appliquer les regles metier exposees par l'API.
Si on retire Mogador, il faut savoir qui reprend ces responsabilites.
## Options possibles
## Option 1: Louise envoie des webhooks a chaque sauvegarde
Principe:
```text
Louise save
-> webhook
-> ingestion interne
-> validation
-> JSON site / bucket / CDN
```
### Avantages
- Publication beaucoup plus rapide.
- Flux presque temps reel.
- Plus besoin d'attendre l'export SQL toutes les 3h.
- Moins de couches techniques.
### Risques
- Forte dependance au fournisseur Louise.
- Risque de pertes d'evenements.
- Risque de doublons.
- Risque d'evenements hors ordre.
- Risque de payload incomplet.
- Difficile a auditer si le fournisseur ne fournit pas de journal/replay.
- Si un webhook echoue, il faut pouvoir rejouer.
### Conditions minimales
Cette option n'est acceptable que si Louise fournit:
- schema JSON versionne;
- signature HMAC des payloads;
- cle d'idempotence par evenement;
- numero de sequence global ou par entite;
- retries automatiques;
- endpoint de replay;
- endpoint de full snapshot;
- documentation claire;
- environnement staging;
- SLA ou garanties operationnelles.
### Evaluation
Webhook seul: non recommande.
Webhook + full snapshot: interessant.
## Option 2: Louise publie un snapshot JSON complet
Principe:
```text
Louise
-> full snapshot JSON
-> ingestion interne
-> diff avec snapshot precedent
-> JSON site / bucket / CDN
```
### Avantages
- Remplace le SQL par un format plus simple.
- Supprime la base MySQL Mogador locale.
- Supprime l'API Mogador.
- Reste compatible avec un fonctionnement par snapshots.
- Plus fiable qu'un webhook seul.
- Permet de fabriquer notre propre incremental en comparant deux snapshots.
### Risques
- Pas temps reel si le snapshot reste toutes les 3h.
- Louise doit fournir toutes les donnees necessaires.
- Il faut valider que le JSON contient les memes informations que l'API Mogador.
- Le fichier peut etre volumineux.
### Evaluation
Option tres interessante et probablement la plus realiste si Louise accepte de produire un format officiel complet.
## Option 3: Louise expose une API officielle moderne
Principe:
```text
Sync Engine interne
-> API Louise
-> snapshots internes
-> validation
-> JSON site / bucket / CDN
```
### Avantages
- Plus besoin de SQL.
- Plus besoin de Mogador.
- On garde le controle du moment ou on synchronise.
- Plus facile a auditer qu'un webhook direct.
- Peut etre plus proche du temps reel si l'API offre les bons endpoints.
### Risques
- Disponibilite de Louise.
- Performance API.
- Endpoints incomplets.
- Changements de contrat API.
- Depend toujours fortement du fournisseur.
### Endpoints necessaires
Il faudrait au minimum:
```text
GET /products?updated_since=...
GET /programs?platform=tfo&from=...&to=...
GET /collections/{id}/full
GET /products/{id}/full
GET /media?product_id=...
GET /snapshot/full
GET /events/replay?since=...
```
### Evaluation
Bonne option si Louise peut s'engager sur une vraie API produit, versionnee et documentee.
## Option 4: Garder le SQL Louise mais supprimer l'API Mogador
Principe:
```text
Louise SQL
-> import MySQL
-> Laravel lit directement les tables
-> Sync Engine interne
-> JSON site / bucket / CDN
```
### Avantages
- Supprime l'API Mogador.
- Plus rapide potentiellement.
- Plus de controle sur les requetes.
- Plus facile de construire le modele attendu par les sites.
### Risques
- Contourne l'API officielle.
- Risque contractuel ou audit.
- Si Louise change la structure SQL, notre code casse.
- Il faut reimplementer la logique que l'API Mogador fournit.
### Evaluation
Techniquement tentant, mais risque contractuel et operationnel important. A eviter si l'obligation d'utiliser l'API Mogador reste valide.
## Option 5: Double-run et retrait progressif de Mogador
Principe:
```text
Flux actuel:
Louise SQL -> Mogador API -> Laravel -> sortie actuelle
Nouveau flux en parallele:
Louise nouvelle sortie -> Sync Engine v2 -> JSON statiques
Comparaison:
sortie actuelle vs sortie v2
```
### Avantages
- Transition securisee.
- Permet de mesurer les ecarts avant de couper.
- Permet de prouver que la nouvelle source remplace Mogador correctement.
- Reduit le risque de regression.
- Permet d'avancer progressivement.
### Risques
- Demande une periode ou deux flux coexistent.
- Demande de construire des rapports de comparaison.
### Evaluation
Option recommandee si le retrait de Mogador est un objectif serieux.
## Recommandation
Ne pas supprimer Mogador en une seule etape.
La trajectoire recommandee:
```text
1. Stabiliser et observer le flux actuel.
2. Construire une sortie JSON statique interne.
3. Demander a Louise un snapshot JSON complet ou une API moderne.
4. Faire tourner le nouveau flux en parallele de Mogador.
5. Comparer les resultats pendant plusieurs cycles.
6. Retirer Mogador seulement quand les ecarts sont compris et acceptes.
```
La meilleure architecture cible:
```text
Louise
-> full snapshot JSON officiel
-> events optionnels pour accelerer certains changements
-> Sync Engine interne
-> validation et rapports
-> JSON statiques par plateforme
-> buckets/CDN
-> sites web
```
Cette approche combine:
- fiabilite du snapshot complet;
- possibilite de publication plus rapide via events;
- controle interne;
- audit;
- rollback;
- suppression progressive de Mogador;
- reduction ou retrait de Directus comme moteur de publication.
## Ce qu'il faut demander a Louise
Avant de prendre une decision, il faut demander au fournisseur Louise s'il peut fournir:
### Donnees
- un full snapshot JSON complet;
- un schema documente et versionne;
- les produits;
- les programmations par plateforme et date;
- les series/saisons;
- les collections;
- les episodes;
- les droits;
- les images;
- les videos;
- les transcriptions;
- les presses FR/EN;
- les categories pedagogiques IDELLO;
- les dates de modification;
- les suppressions.
### API ou events
- endpoint de full snapshot;
- endpoint de diff ou updated_since;
- webhook optionnel;
- replay d'evenements;
- statut d'export;
- journal/audit des changements.
### Fiabilite
- retries;
- idempotency key;
- sequence number;
- signature HMAC;
- environnement staging;
- SLA;
- monitoring cote fournisseur;
- documentation des erreurs.
## Position sur les webhooks
Un webhook peut etre utile, mais ne doit pas etre la seule source de verite.
Bonne utilisation:
```text
Louise webhook: "un produit ou programme a change"
Notre systeme: recupere/valide les donnees, puis publie
```
Mauvaise utilisation:
```text
Louise webhook -> site directement
```
Le site ne devrait pas dependre directement d'un webhook fournisseur.
## Publication web proposee
Comme l'app Laravel ne peut pas etre exposee a Internet, la publication devrait se faire par JSON statiques.
```text
Laravel interne
-> genere JSON
-> publie vers S3/CDN/bucket
-> sites lisent les fichiers JSON
```
Exemples:
```text
/tfo/manifest.json
/tfo/today.json
/tfo/latest.json
/tfo/schedule/2026-08-08.json
/tfo/products/GP123456.json
/tfo/collections/0123456/full.json
```
Cela evite d'exposer Laravel tout en donnant aux sites une source rapide, stable et cacheable.
## Permissions fournisseurs
Si Directus est retire, les permissions peuvent etre gerees au niveau bucket ou CDN.
Option simple:
```text
bucket-tfo
bucket-idello
bucket-onfr
```
Option plus centralisee:
```text
publication/tfo/
publication/idello/
publication/onfr/
```
Chaque fournisseur ou site a acces seulement a son bucket ou prefixe.
## Edition d'urgence sans Directus
Si Directus est retire, il faut une alternative interne.
Proposition:
```text
mini CMS interne Laravel
```
Fonctions:
- rechercher produit/collection/programme;
- voir donnees source;
- voir JSON publie;
- ajouter override temporaire;
- indiquer raison;
- date d'expiration;
- audit trail;
- republication controlee.
Les corrections ne doivent pas etre faites directement dans les JSON publies. Elles doivent etre stockees comme overrides et reappliquees a chaque generation.
## Critere de decision
Mogador peut etre retire seulement si une nouvelle source fournit au moins:
- toutes les donnees necessaires;
- une logique equivalente ou documentee;
- une preuve d'audit;
- un mode full snapshot;
- un mode replay;
- des garanties contre la perte d'evenements;
- un contrat de schema stable;
- une facon de comparer l'ancien flux et le nouveau.
Sans ces garanties, supprimer Mogador risque de rendre le systeme plus fragile, meme s'il semble plus simple sur papier.
## Conclusion
Supprimer Mogador est une bonne direction strategique, mais pas sous forme de webhook direct vers les sites.
La recommandation est:
```text
Ne pas aller vers "Louise save -> site".
Aller vers "Louise snapshot/API officielle -> Sync Engine interne -> JSON statiques -> buckets/CDN".
```
Mogador devrait etre retire progressivement, apres une periode de double-run et de comparaison.
Cette strategie donne:
- moins de dependance a Mogador;
- une publication plus rapide;
- moins de dependance a Directus;
- un meilleur controle interne;
- des rapports proactifs;
- une meilleure fiabilite;
- un chemin de migration prudent.
@@ -0,0 +1,670 @@
## Objectif
Ce document resume une proposition de refonte de la synchronisation Mogador afin de rendre le systeme plus fiable, plus simple a maintenir et plus rapide a publier vers les sites TFO, IDELLO, ONFR et Linear.
Le but n'est pas de jeter toute la connaissance metier existante. Le code actuel contient plusieurs regles importantes qui doivent etre conservees. Par contre, l'architecture actuelle est devenue lourde parce que la synchronisation, Directus, les permissions, la publication web, les rapports et les corrections d'urgence sont trop melanges.
## Contexte actuel
Louise est la vraie source de verite.
Toutes les 3 heures, Louise produit un fichier SQL complet, `export_mogador.sql`. Ce fichier n'est jamais incremental. Il commence par des `TRUNCATE`, puis reinsere toutes les donnees.
Le flux actuel ressemble a ceci:
```text
Louise
-> export_mogador.sql complet
-> rsync vers serveur Linux
-> import dans une base MySQL structuree avec mogador.sql
-> API Mogador officielle qui parle a cette base
-> application Laravel interne
-> synchronisation vers Directus
-> sites web / fournisseurs consomment Directus ou redistribuent dans leurs propres bases
```
Aujourd'hui, il y a trois serveurs avec une copie du meme code:
```text
P1: TFO + Linear
P2: IDELLO
P3: ONFR
```
Cette separation existe surtout parce qu'un seul serveur prendrait trop de temps a synchroniser toutes les plateformes. L'export, le transfert, l'import SQL et la synchronisation prennent environ 1 heure par cycle.
## Contraintes importantes
- La source officielle reste le fichier SQL exporte par Louise.
- L'equipe dev peut regarder la base Mogador, mais la consommation officielle des donnees doit passer par l'API Mogador.
- L'API Mogador doit rester dans le flux pour rester conforme aux attentes contractuelles et eviter de contourner une logique API qui pourrait changer.
- L'app Laravel ne doit pas etre exposee a Internet selon les contraintes Infra actuelles.
- Les fournisseurs ont besoin d'un acces read-only aux donnees publiees.
- L'equipe interne doit pouvoir faire des corrections d'urgence sans attendre le prochain export Louise.
- Les sites veulent des donnees organisees dans le sens utilisateur: collection -> saisons -> episodes -> programmations.
- Louise expose souvent les donnees dans le sens inverse: episode -> programmation -> serie -> collection.
- Directus est utile pour les permissions et l'edition, mais devient problematique comme moteur relationnel/publication.
## Problemes actuels
### 1. Architecture lourde
Le meme code est deploye sur plusieurs serveurs, chaque serveur etant responsable d'une plateforme. Cela rend les mises a jour, les migrations, les alertes et le debugging plus compliques.
### 2. Directus est force dans un role trop large
Directus sert aujourd'hui a:
- donner un acces read-only aux fournisseurs;
- permettre des corrections d'urgence par l'equipe interne;
- exposer les donnees aux sites;
- representer des relations complexes entre produits, programmations, series et collections.
Le probleme est surtout le dernier point. Les relations entre `products`, `programmations`, `series` et `collections` sont difficiles a maintenir dans Directus. Certaines relations ne peuvent pas etre creees proprement a cause de contraintes FK ou du modele de donnees.
### 3. Le modele attendu par les sites est different du modele Louise
Terminologie metier:
```text
Collection = serie pour le public
Serie = saison
Episode = episode
```
Les sites veulent souvent:
```json
{
"collection": {},
"seasons": [
{
"serie": {},
"episodes": [
{
"product": {},
"programmations": [],
"media": {},
"images": []
}
]
}
]
}
```
Mais les donnees Louise/Mogador sont souvent disponibles depuis l'episode, puis il faut remonter vers la serie/saison et la collection.
Exemple de difficulte: `is_original` est disponible sur les episodes, mais pas directement sur la collection. Si le site veut afficher cette information au niveau collection, il faut definir une regle de remontee.
### 4. Peu d'observabilite proactive
Aujourd'hui, l'equipe est souvent reactive. Les problemes sont decouverts quand la production ou les sites signalent une erreur.
Exemples de problemes deja rencontres:
- supervisor down;
- worker queue down;
- migration Laravel oubliee lors d'un changement de serveur;
- programmation attendue absente du site;
- synchro incomplete;
- donnees manquantes dans Directus.
### 5. Besoin de programmation future
Une demande recurrente est de pouvoir afficher des informations comme:
```text
Prochain episode le 8 aout
```
Aujourd'hui, se limiter a la programmation du jour evite de ralentir la sync, mais limite les usages des sites.
## Decision recommandee
La recommandation principale est de ne plus utiliser Directus comme moteur principal de publication web.
L'application Laravel devrait rester interne et produire des JSON statiques prets a consommer par les sites.
Architecture cible:
```text
Louise SQL full export
-> import MySQL Mogador
-> API Mogador officielle
-> Laravel interne: Sync Engine v2
-> donnees internes / snapshots / rapports
-> generation de JSON statiques
-> publication vers buckets S3/CDN par plateforme
-> sites web consomment les JSON
```
Laravel ne serait pas expose a Internet. Les sites ne parlent pas a Laravel. Ils lisent des fichiers JSON statiques publies dans un bucket ou CDN.
## Role futur de Directus
Deux options sont possibles.
### Option 1: retirer Directus progressivement
Si les sites consomment les JSON statiques et si les permissions fournisseurs sont gerees par bucket ou prefixe, Directus n'est plus necessaire dans la chaine de publication.
Les permissions peuvent etre gerees par:
```text
bucket-tfo
bucket-idello
bucket-onfr
```
Ou par un seul bucket avec prefixes:
```text
publication/tfo/
publication/idello/
publication/onfr/
```
Chaque fournisseur ou site a acces seulement a son bucket ou son prefixe.
### Option 2: garder Directus uniquement temporairement
Directus peut rester pendant une periode de transition pour:
- consultation interne;
- edition d'urgence;
- acces read-only fournisseur existant.
Mais il ne devrait plus etre responsable de composer le JSON relationnel final utilise par les sites.
## Edition d'urgence
Si Directus est retire, il faut remplacer son role d'edition d'urgence.
La proposition est de creer un mini CMS interne dans Laravel, non expose a Internet.
Fonctions minimales:
- rechercher un produit, programme, collection ou serie;
- voir les donnees venant de Mogador;
- voir le JSON actuellement publie;
- ajouter une correction temporaire;
- mettre une raison;
- mettre une date d'expiration;
- republier les JSON concernes;
- garder un historique complet.
Exemple de table:
```text
manual_overrides
- id
- platform
- entity_type: product | program | collection | serie
- entity_key: product_key | program_key | biznumber
- field_path
- value_json
- reason
- active_from
- active_until
- created_by
- approved_by
- created_at
- updated_at
```
Exemple d'override:
```json
{
"platform": "tfo",
"entity_type": "collection",
"entity_key": "0123456",
"field_path": "is_original",
"value_json": true,
"reason": "Correction urgente demandee par programmation",
"active_until": "2026-08-02T23:59:59"
}
```
Important: il ne faut pas modifier les JSON publies directement a la main. Les overrides doivent etre appliques dans le pipeline de generation, sinon ils seront perdus ou impossibles a auditer.
## Fabrication d'un incremental a partir d'un full export
Louise ne fournit pas d'incremental. Chaque export est complet.
La solution est de sauvegarder des snapshots internes et de comparer les snapshots entre eux.
Exemple:
```text
09h00: export Louise complet
-> import MySQL
-> extraction via API Mogador
-> snapshot_09h00
12h00: export Louise complet
-> import MySQL
-> extraction via API Mogador
-> snapshot_12h00
Diff snapshot_09h00 -> snapshot_12h00:
-> programmes ajoutes
-> programmes retires
-> produits modifies
-> images modifiees
-> dates de programmation modifiees
-> erreurs ou anomalies
```
On ne demande donc pas a Louise de changer son fonctionnement. On fabrique notre propre diff a partir des donnees extraites apres chaque full export.
Cela permet:
- de savoir ce qui a change;
- de generer un `latest.json`;
- de limiter certaines publications;
- de produire un rapport clair;
- de conserver un historique.
## Donnees internes proposees
Le terme "canonical" veut simplement dire: donnees internes propres, normalisees et controlees par nous.
Il n'est pas obligatoire d'utiliser le mot `canonical` dans le code. L'idee est d'avoir une couche interne avant la publication.
Exemples de tables:
```text
sync_runs
sync_run_items
sync_anomalies
products
programs
collections
series
episodes
media
publication_snapshots
manual_overrides
deleted_programs
```
Avec une colonne `platform`:
```text
tfo
idello
onfr
linear
```
Cela evite de dupliquer toute la logique dans des tables separees comme `tfo_products`, `idello_products`, `onfr_products`, etc., sauf si une contrainte technique oblige a garder cette separation.
## JSON statiques proposes
Au lieu d'un seul gros JSON, il faut publier plusieurs fichiers specialises.
Exemple pour TFO:
```text
/tfo/manifest.json
/tfo/today.json
/tfo/latest.json
/tfo/schedule/index.json
/tfo/schedule/2026-07-30.json
/tfo/schedule/2026-07-31.json
/tfo/collections/index.json
/tfo/collections/0123456/full.json
/tfo/products/GP123456.json
/tfo/search/index.json
```
Pour 8 000 produits TFO et 22 000 produits IDELLO, ce volume de fichiers JSON n'est pas un probleme pour un bucket S3/CDN. C'est meme preferable a un gros fichier unique.
### manifest.json
Le manifest indique quelle version est publiee.
```json
{
"platform": "tfo",
"published_at": "2026-07-30T09:50:00",
"run_id": "20260730-0900",
"base_path": "/tfo/runs/20260730-0900"
}
```
### today.json
Contient ce qui doit etre en ligne aujourd'hui.
```json
{
"date": "2026-07-30",
"programs": []
}
```
### latest.json
Contient les nouveautes et changements depuis la derniere publication.
```json
{
"run_id": "20260730-0900",
"added": [],
"updated": [],
"removed": []
}
```
### schedule/YYYY-MM-DD.json
Contient la programmation d'une date precise.
```json
{
"date": "2026-08-08",
"programs": [
{
"program_key": 123,
"product_key": 456,
"begin": "2026-08-08T06:00:00",
"end": "2026-08-08T06:24:00",
"title": "..."
}
]
}
```
### products/{id}.json
Contient le detail d'un produit.
```json
{
"product": {},
"programmations": {
"current": [],
"upcoming": [],
"next": {
"date": "2026-08-08",
"begin": "2026-08-08T06:00:00"
}
},
"media": {},
"images": []
}
```
### collections/{biznumber}/full.json
Contient le modele attendu par les sites.
```json
{
"collection": {
"biznumber": "0123456",
"title": "...",
"is_original": true,
"next_programmation": {
"date": "2026-08-08",
"begin": "2026-08-08T06:00:00"
}
},
"seasons": [
{
"serie": {},
"episodes": [
{
"product": {},
"programmations": [],
"media": {},
"images": []
}
]
}
]
}
```
## Programmations futures
Pour afficher des messages comme "prochain episode le 8 aout", il faut extraire une fenetre future de programmation.
Proposition configurable:
```env
TFO_SCHEDULE_DAYS_AHEAD=14
IDELLO_SCHEDULE_DAYS_AHEAD=30
ONFR_SCHEDULE_DAYS_AHEAD=14
LINEAR_SCHEDULE_DAYS_BEHIND=7
LINEAR_SCHEDULE_DAYS_AHEAD=15
```
Les programmations futures sont publiees dans:
```text
/tfo/schedule/2026-08-08.json
```
Et resumees dans les JSON produit/collection:
```json
{
"next_programmation": {
"date": "2026-08-08",
"begin": "2026-08-08T06:00:00"
}
}
```
Cela evite aux sites de parcourir toute la grille future pour afficher une information simple.
## Search et Algolia
Un fichier comme:
```text
/tfo/search/index.json
```
peut servir a alimenter Algolia, Meilisearch, Typesense ou un autre moteur de recherche.
Il peut contenir seulement les champs utiles a la recherche:
```json
[
{
"objectID": "GP123456",
"type": "product",
"title": "...",
"slug": "...",
"image": "...",
"collection_biznumber": "0123456"
}
]
```
Si les sites ont besoin d'une vraie recherche rapide sur 8 000 a 22 000 items, un moteur dedie comme Algolia reste preferable a un gros fichier recherche charge cote client.
## Publication atomique
Il faut eviter qu'un site lise une publication incomplete.
Principe:
```text
/tfo/runs/20260730-0900/...
/tfo/runs/20260730-1200/...
/tfo/manifest.json
```
Le site lit d'abord:
```text
/tfo/manifest.json
```
Puis utilise le `base_path` indique.
Si la generation du run `20260730-1200` echoue, `manifest.json` continue de pointer vers `20260730-0900`.
Ainsi, une sync ratee ne casse pas le site.
## Rapport et alertes
Le rapport est une piece centrale de la v2.
Il doit comparer:
```text
ce que le fichier Louise/Mogador contient
vs
ce que Laravel a traite
vs
ce qui a ete publie en JSON
vs
eventuellement ce qui reste dans Directus pendant la transition
```
Exemple de rapport:
```text
Plateforme: TFO
Run: 20260730-0900
Export SQL recu: oui
Import MySQL: succes
API Mogador: OK
Programmes attendus aujourd'hui: 1230
Programmes publies: 1229
Produits attendus: 8142
Produits publies: 8139
Ecarts:
- 1 programme absent du JSON final
- 2 produits sans video JWP
- 5 images manquantes
- 1 produit ignore car type extrait
Publication:
- statut: publie avec avertissements
- manifest pointe vers: /tfo/runs/20260730-0900
```
Alertes a mettre en place:
- export SQL non recu;
- fichier SQL trop petit ou checksum identique de facon suspecte;
- import MySQL echoue;
- API Mogador ne repond pas;
- workers down;
- queue bloquee;
- sync trop longue;
- ecart entre attendu et publie;
- programme prevu a 6h absent de la publication avant 6h;
- video JWP manquante;
- image ou transcription manquante;
- override actif proche expiration.
## Fichier SQL hors Laravel
Le fait que `export_mogador.sql` soit hors du repertoire Laravel n'est pas un probleme.
Le script d'import peut ecrire un fichier de statut dans un chemin connu:
```json
{
"export_received_at": "2026-07-30T09:01:00",
"import_started_at": "2026-07-30T09:35:00",
"import_finished_at": "2026-07-30T09:48:00",
"sql_file_size": 306184192,
"checksum": "abc123",
"status": "success"
}
```
Laravel lit ce statut pour produire son rapport.
Chemins configurables:
```env
MOGADOR_EXPORT_PATH=/data/mogador/export_mogador.sql
MOGADOR_IMPORT_STATUS_PATH=/data/mogador/import-status.json
MOGADOR_IMPORT_LOG_PATH=/var/log/mogador-import.log
```
## Plan de migration propose
### Phase 1: Observabilite
Objectif: savoir ce qui se passe avant de tout changer.
- Ajouter `sync_runs`.
- Ajouter `sync_run_items`.
- Ajouter `sync_anomalies`.
- Generer un rapport par plateforme.
- Alerter sur les ecarts critiques.
- Garder Directus tel quel.
### Phase 2: Publication JSON en parallele
Objectif: produire les JSON sans encore remplacer Directus.
- Generer `/manifest.json`.
- Generer `/today.json`.
- Generer `/schedule/YYYY-MM-DD.json`.
- Generer quelques `/products/{id}.json`.
- Generer quelques `/collections/{id}/full.json`.
- Comparer JSON vs Directus.
### Phase 3: Premier site pilote
Objectif: faire consommer les JSON par un site ou une section limitee.
- Choisir une plateforme simple, probablement ONFR ou une portion TFO.
- Publier dans un bucket/prefix dedie.
- Valider performance, structure JSON, cache et rollback.
### Phase 4: Mini CMS interne
Objectif: remplacer l'edition d'urgence Directus.
- Ajouter `manual_overrides`.
- Ajouter interface interne Laravel.
- Ajouter audit trail.
- Ajouter expiration automatique.
- Ajouter rapport des overrides actifs.
### Phase 5: Reduction ou retrait de Directus
Objectif: retirer Directus de la publication si les JSON remplissent le besoin.
- Garder Directus seulement pendant transition.
- Migrer les usages fournisseurs vers buckets/CDN.
- Retirer progressivement les dependances Directus.
## Position finale
La proposition recommandee est:
```text
Laravel interne + snapshots + diff maison + JSON statiques + buckets/CDN + rapports + mini CMS d'urgence
```
Directus peut etre garde temporairement, mais ne devrait plus etre le moteur principal de publication web.
Cette approche respecte les contraintes:
- Louise reste source de verite.
- L'API Mogador officielle reste utilisee.
- Laravel n'est pas expose a Internet.
- Les sites recoivent des donnees simples et rapides.
- Les fournisseurs peuvent etre isoles par bucket ou prefixe.
- L'equipe interne garde la capacite de corriger en urgence.
- Les erreurs deviennent visibles avant que la production les signale.