From f95fa35c0da50054665375e41c0996a0d57a571a Mon Sep 17 00:00:00 2001 From: Amadou Date: Sat, 1 Aug 2026 15:51:54 -0400 Subject: [PATCH] vault backup: 2026-08-01 15:51:54 --- ... sites- proposition de publication JSON.md | 135 ++-- ...chitecture - Content Publication Engine.md | 594 ++++++++++-------- 2 files changed, 411 insertions(+), 318 deletions(-) diff --git a/20 Work/Ideas/Mogador/Consultation fournisseurs sites- proposition de publication JSON.md b/20 Work/Ideas/Mogador/Consultation fournisseurs sites- proposition de publication JSON.md index df3fcbe..08a8abb 100644 --- a/20 Work/Ideas/Mogador/Consultation fournisseurs sites- proposition de publication JSON.md +++ b/20 Work/Ideas/Mogador/Consultation fournisseurs sites- proposition de publication JSON.md @@ -1,17 +1,16 @@ - ## Objectif -Nous evaluons une nouvelle facon de fournir les donnees de programmation et de contenus aux sites web TFO, IDELLO, ONFR et lineaire. +Nous évaluons une nouvelle façon de fournir les données de programmation et de contenus aux sites web TFO, IDELLO, ONFR et linéaire. -L'objectif est de savoir si une publication sous forme de fichiers JSON versionnes peut bien repondre a vos besoins techniques et operationnels. +L'objectif est de savoir si une publication sous forme de fichiers JSON versionnés peut bien répondre à vos besoins techniques et opérationnels. -Ce document ne presente pas une decision finale. Il sert a recueillir vos commentaires avant de figer le format. +Ce document ne présente pas une décision finale. Il sert à recueillir vos commentaires avant de figer le format. -## Idee generale +## Idée générale -Aujourd'hui, les donnees sont disponibles via Directus ou via des mecanismes de synchronisation propres a chaque site. +Aujourd'hui, les données sont disponibles via Directus ou via des mécanismes de synchronisation propres à chaque site. -La proposition est de publier des fichiers JSON prets a consommer, organises par plateforme, par version et par publication. +La proposition est de publier des fichiers JSON prêts à consommer, organisés par plateforme, par version et par publication. Exemple: @@ -32,7 +31,7 @@ Les sites ne devraient pas coder un chemin de run en dur. Ils liraient d'abord: /tfo/v1/manifest.json ``` -Puis utiliseraient le `base_path` retourne par le manifest pour charger les fichiers du run actif. +Puis utiliseraient le `base_path` retourné par le manifest pour charger les fichiers du run actif. ## Exemple de manifest @@ -46,13 +45,43 @@ Puis utiliseraient le `base_path` retourne par le manifest pour charger les fich } ``` -Le `manifest.json` permet de changer de publication de facon atomique. Si une nouvelle generation echoue, le manifest continue de pointer vers le dernier run valide. +Le `manifest.json` permet de changer de publication de façon atomique. Si une nouvelle génération échoue, le manifest continue de pointer vers le dernier run valide. -## Types de fichiers proposes +## Runs complets et changements incrémentaux + +Chaque run publié doit être considéré comme une version complète des données disponibles pour une plateforme. + +Par contre, entre deux runs, tous les fichiers ne changent pas nécessairement. + +Exemple: + +```text +Run 1: +8 000 produits + +Run 2: +10 nouveaux produits +5 produits retirés +7 produits modifiés +``` + +Dans ce cas, le run 2 reste un run complet pour le site, mais seuls les fichiers réellement impactés devraient changer. + +Conséquence pour les sites: + +- il faut toujours lire le `manifest.json` pour connaître le run actif; +- il ne faut pas supposer que tous les fichiers changent à chaque run; +- un fichier produit inchangé peut être identique entre deux runs; +- un produit retiré ne devrait plus apparaître dans les indexes du nouveau run; +- `latest.json` peut aider à savoir ce qui a été ajouté, modifié ou retiré. + +Cette approche permet de publier plus vite et de réduire le risque de remplacer des données valides par des données incomplètes. + +## Types de fichiers proposés ### today.json -Contient les contenus ou programmations pertinents pour la journee courante. +Contient les contenus ou programmations pertinents pour la journée courante. ```json { @@ -66,7 +95,7 @@ Contient les contenus ou programmations pertinents pour la journee courante. ### latest.json -Contient les contenus ajoutes, modifies ou retires depuis la derniere publication. +Contient les contenus ajoutés, modifiés ou retirés depuis la dernière publication. ```json { @@ -81,7 +110,7 @@ Contient les contenus ajoutes, modifies ou retires depuis la derniere publicatio ### schedule/YYYY-MM-DD.json -Contient la programmation pour une date precise. +Contient la programmation pour une date précise. ```json { @@ -95,17 +124,17 @@ Contient la programmation pour une date precise. "product_key": "GP123456", "begin": "2026-08-08T06:00:00-04:00", "end": "2026-08-08T06:24:00-04:00", - "title": "Titre de l'episode" + "title": "Titre de l'épisode" } ] } ``` -La premiere version viserait une fenetre future jusqu'a J+10. +La première version viserait une fenêtre future jusqu'à J+10. ### products/{product_key}.json -Contient le detail d'un produit ou episode. +Contient le détail d'un produit ou épisode. ```json { @@ -115,7 +144,7 @@ Contient le detail d'un produit ou episode. "product": { "product_key": "GP123456", "biznumber": "0123456", - "title": "Titre de l'episode", + "title": "Titre de l'épisode", "description": "..." }, "programmations": { @@ -133,10 +162,10 @@ Contient le detail d'un produit ou episode. ### collections/{biznumber}/full.json -Contient une vue complete d'une collection, dans le sens attendu par les sites: +Contient une vue complète d'une collection, dans le sens attendu par les sites: ```text -collection -> saisons -> episodes +collection -> saisons -> épisodes ``` Exemple: @@ -169,7 +198,7 @@ Exemple: { "product": { "product_key": "GP123456", - "title": "Episode 1" + "title": "Épisode 1" }, "programmations": [], "media": {}, @@ -183,14 +212,14 @@ Exemple: ### search/index.json -Fichier optionnel pouvant servir a alimenter un moteur de recherche comme Algolia, Meilisearch, Typesense ou un index interne. +Fichier optionnel pouvant servir à alimenter un moteur de recherche comme Algolia, Meilisearch, Typesense ou un index interne. ```json [ { "objectID": "GP123456", "type": "product", - "title": "Titre de l'episode", + "title": "Titre de l'épisode", "slug": "titre-de-lepisode", "image": "https://...", "collection_biznumber": "0123456" @@ -198,7 +227,7 @@ Fichier optionnel pouvant servir a alimenter un moteur de recherche comme Algoli ] ``` -## Cache propose +## Cache proposé Le manifest aurait un cache court: @@ -207,7 +236,7 @@ Le manifest aurait un cache court: Cache-Control: public, max-age=60, stale-while-revalidate=120 ``` -Les fichiers d'un run seraient immuables et pourraient etre caches longtemps: +Les fichiers d'un run seraient immuables et pourraient être cachés longtemps: ```text /tfo/v1/runs/20260730-0900/* @@ -216,19 +245,19 @@ Cache-Control: public, max-age=31536000, immutable Logique: -- le site consulte regulierement `manifest.json`; +- le site consulte régulièrement `manifest.json`; - si `run_id` change, le site charge les fichiers du nouveau run; - les fichiers des runs ne changent jamais; -- un rollback peut etre fait en repointant le manifest vers un run precedent. +- un rollback peut être fait en repointant le manifest vers un run précédent. ## Points importants pour les sites -- Les JSON seraient versionnes dans le chemin: `/v1/`, puis eventuellement `/v2/`. -- Les changements cassants seraient publies dans une nouvelle version. +- Les JSON seraient versionnés dans le chemin: `/v1/`, puis éventuellement `/v2/`. +- Les changements cassants seraient publiés dans une nouvelle version. - Les dates seraient fournies avec timezone explicite. -- Les fichiers seraient separes pour eviter de telecharger un enorme JSON unique. -- Les sites pourraient consommer seulement les fichiers utiles a leurs pages. -- Les fournisseurs pourraient avoir acces uniquement a leur plateforme ou prefixe. +- Les fichiers seraient séparés pour éviter de télécharger un énorme JSON unique. +- Les sites pourraient consommer seulement les fichiers utiles à leurs pages. +- Les fournisseurs pourraient avoir accès uniquement à leur plateforme ou préfixe. ## Questions pour vous @@ -237,28 +266,28 @@ Merci de nous dire si cette approche fonctionnerait pour votre site, et de comme ### Consommation - Est-ce que votre site peut consommer des fichiers JSON statiques via HTTP/CDN? -- Est-ce que votre site peut lire un `manifest.json` avant de charger les donnees? +- Est-ce que votre site peut lire un `manifest.json` avant de charger les données? - Avez-vous besoin d'une API dynamique, ou des fichiers JSON suffisent? -- Avez-vous des contraintes sur le nombre de fichiers charges? +- Avez-vous des contraintes sur le nombre de fichiers chargés? -### Structure des donnees +### Structure des données -- Le modele `collection -> seasons -> episodes` convient-il a vos pages? -- Le fichier `products/{product_key}.json` contient-il le bon niveau de detail? +- Le modèle `collection -> seasons -> episodes` convient-il à vos pages? +- Le fichier `products/{product_key}.json` contient-il le bon niveau de détail? - Le fichier `collections/{biznumber}/full.json` est-il trop gros, trop petit ou correct? - Avez-vous besoin d'autres regroupements? - Quels champs sont obligatoires pour vos pages? ### Programmation -- La fenetre future J+10 est-elle suffisante? -- Avez-vous besoin de programmation passee? +- La fenêtre future J+10 est-elle suffisante? +- Avez-vous besoin de programmation passée? - Avez-vous besoin d'un fichier par date, par semaine ou par mois? -- Comment affichez-vous "prochain episode" aujourd'hui? +- Comment affichez-vous "prochain épisode" aujourd'hui? ### Media et images -- Quels champs media sont requis pour votre lecteur video? +- Quels champs media sont requis pour votre lecteur vidéo? - Avez-vous besoin de plusieurs formats d'image? - Avez-vous besoin de sous-titres, transcriptions, audio ou autres assets dans le JSON? @@ -266,24 +295,24 @@ Merci de nous dire si cette approche fonctionnerait pour votre site, et de comme - Utilisez-vous Algolia, Meilisearch, Typesense ou un autre moteur? - Un fichier `search/index.json` vous serait-il utile? -- Quels champs devraient etre inclus dans l'index? +- Quels champs devraient être inclus dans l'index? -### Cache et mise a jour +### Cache et mise à jour - Un cache court sur `manifest.json` vous convient-il? -- Quelle frequence de verification du manifest serait acceptable? +- Quelle fréquence de vérification du manifest serait acceptable? - Avez-vous besoin d'un webhook ou signal pour savoir qu'un nouveau run est disponible? -- Comment votre site ferait-il un rollback si necessaire? +- Comment votre site ferait-il un rollback si nécessaire? ### Migration -- Pouvez-vous tester cette approche en parallele de votre integration actuelle? +- Pouvez-vous tester cette approche en parallèle de votre intégration actuelle? - Quel serait le meilleur pilote pour vous: une page, une plateforme, une collection, une section? -- Quels risques voyez-vous dans une migration vers ce modele? +- Quels risques voyez-vous dans une migration vers ce modèle? ## Commentaires attendus -Pour nous aider a valider l'approche, merci de repondre avec: +Pour nous aider à valider l'approche, merci de répondre avec: - les fichiers que vous utiliseriez; - les champs manquants; @@ -291,15 +320,15 @@ Pour nous aider a valider l'approche, merci de repondre avec: - les contraintes de performance ou cache; - les impacts sur votre architecture; - les risques de migration; -- une estimation du travail cote site. +- une estimation du travail côté site. -## Decision recherchee +## Décision recherchée -Nous voulons confirmer si cette approche JSON peut devenir un contrat stable entre notre systeme de publication et les sites. +Nous voulons confirmer si cette approche JSON peut devenir un contrat stable entre notre système de publication et les sites. -La decision attendue n'est pas encore "on migre tout". La decision attendue est plutot: +La décision attendue n'est pas encore "on migre tout". La décision attendue est plutôt: ```text -Est-ce que ce modele JSON est techniquement viable pour les sites? -Si oui, quels ajustements sont necessaires avant un pilote? +Est-ce que ce modèle JSON est techniquement viable pour les sites? +Si oui, quels ajustements sont nécessaires avant un pilote? ``` \ No newline at end of file diff --git a/20 Work/Ideas/Mogador/Proposition d'architecture - Content Publication Engine.md b/20 Work/Ideas/Mogador/Proposition d'architecture - Content Publication Engine.md index a78f74e..291cb9f 100644 --- a/20 Work/Ideas/Mogador/Proposition d'architecture - Content Publication Engine.md +++ b/20 Work/Ideas/Mogador/Proposition d'architecture - Content Publication Engine.md @@ -1,28 +1,27 @@ - ## TL;DR -Le systeme actuel de synchro Louise/Mogador fonctionne, mais il est devenu trop fragile: trois serveurs avec le meme code, dependance forte a Directus, peu d'observabilite, corrections d'urgence difficiles a tracer, et trop de logique implicite dans une synchro construite rapidement. +Le système actuel de synchro Louise/Mogador fonctionne, mais il est devenu trop fragile: trois serveurs avec le même code, dépendance forte à Directus, peu d'observabilité, corrections d'urgence difficiles à tracer, et trop de logique implicite dans une synchro construite rapidement. -La recommandation est de ne pas tout recommencer en big bang, mais de construire un **Content Publication Engine** interne qui publie des JSON statiques versionnes vers un bucket/CDN. Les sites consommeraient ces JSON au lieu de consommer Directus directement. +La recommandation est de ne pas tout recommencer en big bang, mais de construire un **Content Publication Engine** interne qui publie des JSON statiques versionnés vers un bucket/CDN. Les sites consommeraient ces JSON au lieu de consommer Directus directement. -Le projet doit etre separe en deux chantiers: +Le projet doit être séparé en deux chantiers: -1. **Chantier interne, sous notre controle** +1. **Chantier interne, sous notre contrôle** - produire les JSON publics; - - gerer les runs atomiques et rollback; - - integrer JWP via un `Media Pipeline`; + - gérer les runs atomiques et rollback; + - intégrer JWP via un `Media Pipeline`; - offrir une `Publication Console` interne pour corrections d'urgence; - produire rapports et alertes. -2. **Chantier PCI, separe** +2. **Chantier PCI, séparé** - discuter avec PCI d'une API Louise/Mogador v2; - - demander du bulk, SSL fonctionnel, pagination, limites documentees; - - a long terme, demander des events/webhooks comme signal de changement. + - demander du bulk, SSL fonctionnel, pagination, limites documentées; + - à long terme, demander des events/webhooks comme signal de changement. Point important: le chantier interne ne doit pas attendre PCI. Il doit fonctionner avec le Mogador Toolkit actuel, puis remplacer son lecteur source par Louise API v2 si elle arrive. -Position recommandee: +Position recommandée: ```text Louise Export / Mogador Toolkit actuel @@ -34,31 +33,31 @@ Louise Export / Mogador Toolkit actuel -> Sites web ``` -Directus peut rester temporairement pendant la transition, mais ne devrait plus etre le moteur principal de publication web. +Directus peut rester temporairement pendant la transition, mais ne devrait plus être le moteur principal de publication web. ## Objectif -Ce document propose une refonte progressive de la synchronisation Louise/Mogador afin de rendre la publication vers TFO, IDELLO, ONFR et lineaire plus fiable, plus rapide a diagnostiquer et plus simple a consommer par les sites. +Ce document propose une refonte progressive de la synchronisation Louise/Mogador afin de rendre la publication vers TFO, IDELLO, ONFR et linéaire plus fiable, plus rapide à diagnostiquer et plus simple à consommer par les sites. -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 melange trop de responsabilites: +Le but n'est pas de jeter toute la connaissance métier existante. Le code actuel contient plusieurs règles importantes qui doivent être conservées. Par contre, l'architecture actuelle mélange trop de responsabilités: -- extraction des donnees officielles; +- extraction des données officielles; - synchronisation; - Directus; - permissions; -- edition d'urgence; +- édition d'urgence; - publication web; -- videos JWP; +- vidéos JWP; - rapports; - alertes. -La refonte doit separer ces responsabilites sans creer une usine a gaz. +La refonte doit séparer ces responsabilités sans créer une usine à gaz. ## Contexte actuel -Louise est la vraie source de verite. +Louise est la vraie source de vérité. -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. +Toutes les 3 heures, Louise produit un fichier SQL complet, `export_mogador.sql`. Ce fichier n'est jamais incrémental. Il commence par des `TRUNCATE`, puis réinsère toutes les données. Flux actuel: @@ -66,69 +65,69 @@ Flux actuel: 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 + -> import dans une base MySQL structurée avec mogador.sql + -> API Mogador officielle qui parle à 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: +Aujourd'hui, il y a trois serveurs avec une copie du même code: ```text -P1: TFO + lineaire +P1: TFO + linéaire P2: IDELLO P3: ONFR ``` -Cette separation existe 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 sur l'architecture actuelle. +Cette séparation existe parce qu'un seul serveur prendrait trop de temps à synchroniser toutes les plateformes. L'export, le transfert, l'import SQL et la synchronisation prennent environ 1 heure par cycle sur l'architecture actuelle. ## Contraintes importantes - La source officielle reste Louise. -- L'export Louise est un full export SQL, pas un incrementiel. -- L'equipe dev peut regarder la base, mais la consommation officielle devrait passer par l'API Mogador pour rester conforme aux attentes contractuelles. -- L'app interne ne doit pas etre exposee a Internet selon les contraintes Infra actuelles. -- Les fournisseurs ont besoin d'un acces read-only. -- Les edimestres et l'equipe interne doivent pouvoir faire des corrections d'urgence. -- Les sites veulent un modele oriente utilisateur: collection -> saisons -> episodes -> programmations. -- Louise/Mogador expose souvent les donnees dans le sens inverse: episode -> programmation -> serie -> collection. -- Directus est utile pour les permissions et l'edition, mais difficile comme moteur relationnel/publication. -- Les programmations futures sont demandees, avec une limite v1 proposee a J+10. -- Les videos JWP sont gerees dans une app AdonisJS existante et doivent etre integrees sans coupler toute la publication a JWP. +- L'export Louise est un full export SQL, pas un incrémentiel. +- L'équipe dev peut regarder la base, mais la consommation officielle devrait passer par l'API Mogador pour rester conforme aux attentes contractuelles. +- L'app interne ne doit pas être exposée à Internet selon les contraintes Infra actuelles. +- Les fournisseurs ont besoin d'un accès read-only. +- Les édimestres et l'équipe interne doivent pouvoir faire des corrections d'urgence. +- Les sites veulent un modèle orienté utilisateur: collection -> saisons -> épisodes -> programmations. +- Louise/Mogador expose souvent les données dans le sens inverse: épisode -> programmation -> serie -> collection. +- Directus est utile pour les permissions et l'édition, mais difficile comme moteur relationnel/publication. +- Les programmations futures sont demandées, avec une limite v1 proposée à J+10. +- Les vidéos JWP sont gérées dans une app AdonisJS existante et doivent être intégrées sans coupler toute la publication à JWP. -## Problemes actuels +## Problèmes actuels ### Architecture lourde -Le meme code est deploye sur plusieurs serveurs. Cela complique: +Le même code est déployé sur plusieurs serveurs. Cela complique: -- les mises a jour; +- les mises à jour; - les migrations; - les alertes; - le debugging; -- les reprises apres incident; -- la comprehension globale du systeme. +- les reprises après incident; +- la comprehension globale du système. -### Directus porte trop de responsabilites +### Directus porte trop de responsabilités Directus sert aujourd'hui a: -- donner un acces read-only aux fournisseurs; +- donner un accès read-only aux fournisseurs; - permettre des corrections d'urgence; -- exposer les donnees aux sites; -- representer des relations complexes entre produits, programmations, series et collections. +- exposer les données aux sites; +- représenter des relations complexes entre produits, programmations, series et collections. -Le probleme principal est le dernier point. Les relations entre produits, 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. +Le problème principal est le dernier point. Les relations entre produits, programmations, series et collections sont difficiles à maintenir dans Directus. Certaines relations ne peuvent pas être créées proprement à cause de contraintes FK ou du modèle de données. -### Le modele Louise ne correspond pas au modele des sites +### Le modèle Louise ne correspond pas au modèle des sites -Terminologie metier: +Terminologie métier: ```text Collection = serie pour le public Serie = saison -Episode = episode +Épisode = épisode ``` Les sites veulent souvent: @@ -157,28 +156,28 @@ Les sites veulent souvent: } ``` -Mais les donnees Louise/Mogador partent souvent de l'episode, puis il faut remonter vers la serie/saison et la collection. +Mais les données Louise/Mogador partent souvent de l'épisode, puis il faut remonter vers la serie/saison et la collection. -Exemple: `is_original` peut etre disponible sur les episodes, mais pas directement sur la collection. Si le site veut cette information au niveau collection, il faut definir une regle explicite de remontee. +Exemple: `is_original` peut être disponible sur les épisodes, mais pas directement sur la collection. Si le site veut cette information au niveau collection, il faut definir une règle explicite de remontee. -### Peu d'observabilite proactive +### Peu d'observabilité proactive -Aujourd'hui, l'equipe est souvent reactive. Les problemes sont decouverts quand la production ou les sites signalent une erreur. +Aujourd'hui, l'équipe est souvent reactive. Les problèmes sont decouverts quand la production ou les sites signalent une erreur. -Exemples deja rencontres: +Exemples déjà rencontrès: - supervisor down; - worker queue down; - migration oubliee lors d'un changement de serveur; - programmation attendue absente du site; -- synchro incomplete; -- donnees manquantes dans Directus. +- synchro incomplète; +- données manquantes dans Directus. -## Decision recommandee +## Decision recommandée -La recommandation principale est de ne plus utiliser Directus comme moteur principal de publication web. +La recommandation principale est de ne plus utilisér Directus comme moteur principal de publication web. -L'application interne devrait produire des JSON statiques prets a consommer par les sites. +L'application interne devrait produire des JSON statiques prêts à consommer par les sites. Architecture cible: @@ -188,18 +187,18 @@ Louise SQL full export -> Mogador Toolkit actuel -> Content Publication Engine interne -> snapshots / diffs / rapports - -> generation de JSON statiques + -> génération de JSON statiques -> publication vers bucket/CDN par plateforme -> sites web consomment les JSON ``` -L'app interne ne serait pas exposee a Internet. Les sites ne parlent pas a Laravel ou AdonisJS directement. Ils lisent des fichiers JSON publics publies dans un bucket/CDN. +L'app interne ne serait pas exposée à Internet. Les sites ne parlent pas à Laravel ou AdonisJS directement. Ils lisent des fichiers JSON publics publiés dans un bucket/CDN. -## Deux chantiers a ne pas melanger +## Deux chantiers à ne pas mélanger -### Chantier A: amelioration interne de la synchro +### Chantier A: amélioration interne de la synchro -Ce chantier est sous notre controle. +Ce chantier est sous notre contrôle. Il contient: @@ -208,26 +207,26 @@ Il contient: - contrat interne `media_assets`; - contrat interne `publication_jobs`; - `Publication Console` pour corrections d'urgence; -- `Published Content Feed`, les JSON publies vers bucket/CDN. +- `Published Content Feed`, les JSON publiés vers bucket/CDN. -Ce chantier peut commencer sans attendre une refonte par PCI. Au debut, il peut continuer a lire les donnees officielles via l'export SQL et le Mogador Toolkit actuel. +Ce chantier peut commencer sans attendre une refonte par PCI. Au début, il peut continuer à lire les données officielles via l'export SQL et le Mogador Toolkit actuel. -### Chantier B: discussion PCI / evolution Louise-Mogador +### Chantier B: discussion PCI / évolution Louise-Mogador -Ce chantier est un projet separe. +Ce chantier est un projet séparé. -Objectif: discuter avec PCI pour moderniser l'acces aux donnees officielles Louise/Mogador. +Objectif: discuter avec PCI pour moderniser l'accès aux données officielles Louise/Mogador. Il peut inclure: - une API Louise/Mogador v2; - des endpoints bulk plus efficaces; -- une meilleure compatibilite SSL; -- des limites de concurrence documentees; -- des exports plus faciles a consommer; -- a long terme, des events/webhooks comme signal de changement pour aller vers une publication presque instantanee. +- une meilleure compatibilité SSL; +- des limites de concurrence documentées; +- des exports plus faciles à consommer; +- à long terme, des events/webhooks comme signal de changement pour aller vers une publication presque instantanee. -Ce chantier a une relation directe avec la synchro interne, mais il ne doit pas bloquer le chantier A. La synchro interne doit etre concue pour fonctionner avec le Mogador Toolkit actuel, puis remplacer son lecteur source par Louise API v2 si elle arrive. +Ce chantier a une relation directe avec la synchro interne, mais il ne doit pas bloquer le chantier A. La synchro interne doit être conçue pour fonctionner avec le Mogador Toolkit actuel, puis remplacer son lecteur source par Louise API v2 si elle arrive. ## Flow d'information cible @@ -240,13 +239,13 @@ flowchart TD Importer["Import SQL interneBase source locale"] Toolkit["Mogador ToolkitAPI legacy actuelle"] - Snapshot["Snapshot Collectorlit les donnees officielles"] + Snapshot["Snapshot Collectorlit les données officielles"] SnapshotStore["Snapshot Storeruns source + checksums"] - Diff["Diff Builderfabrique l'incrementiel interne"] + Diff["Diff Builderfabrique l'incrémentiel interne"] MediaPipeline["Media PipelineAdonisJS/JWP"] JWP["JWPplateforme video"] - MediaAssets["media_assetsetat media interne"] + MediaAssets["media_assetsétat media interne"] Console["Publication Consolemini CMS interne"] Overrides["overridescorrections d'urgence"] @@ -256,8 +255,8 @@ flowchart TD Validator["Validation + rapportsattendu vs publie"] Runs["Published Content Feedruns JSON immuables"] Manifest["manifest.jsonpointe vers le run actif"] - Bucket["Bucket/CDNexposition publique controlee"] - Sites["Sites webTFO / IDELLO / ONFR / lineaire"] + Bucket["Bucket/CDNexposition publique contrôlee"] + Sites["Sites webTFO / IDELLO / ONFR / linéaire"] Alerts["Slack / Better Stackalertes anomalies"] Louise --> LouiseExport @@ -291,13 +290,13 @@ flowchart TD Bucket --> Sites ``` -Ce schema represente ce qu'on controle nous-memes. Il ne depend pas d'une API Louise/Mogador v2. +Ce schema représente ce qu'on contrôle nous-mêmes. Il ne depend pas d'une API Louise/Mogador v2. -### Chantier B: evolution PCI +### Chantier B: évolution PCI ```mermaid flowchart TD - Louise["Louisesysteme source"] + Louise["Louisesystème source"] CurrentExport["Export SQL actuelfull truncate + insert"] CurrentToolkit["Mogador Toolkit actuelAPI legacy"] Discussion["Discussion PCIupgrade Louise/Mogador"] @@ -319,13 +318,13 @@ Le `Content Publication Engine` devrait avoir un `Source Reader` abstrait: ```text Version 1: -Source Reader -> Mogador Toolkit actuel -> DB importee depuis Louise Export +Source Reader -> Mogador Toolkit actuel -> DB importée depuis Louise Export Version future: Source Reader -> Louise API v2 ``` -Le reste du systeme interne ne devrait pas changer: +Le reste du système interne ne devrait pas changer: - diff interne; - `media_assets`; @@ -340,22 +339,22 @@ Le reste du systeme interne ne devrait pas changer: 1. Louise produit un export complet toutes les 3 heures. 2. Le SQL est importe dans une base interne. -3. Le Mogador Toolkit expose les donnees officielles. -4. Le Snapshot Collector lit les donnees officielles. -5. Le Diff Builder compare le snapshot courant au snapshot precedent. -6. Le Media Pipeline gere JWP et ecrit l'etat media dans `media_assets`. -7. La Publication Console gere les corrections d'urgence et ecrit les overrides. -8. Les changements creent des `publication_jobs`. -9. Le Content Publication Engine combine donnees officielles, media, overrides et regles metier. -10. Il genere un run JSON complet. +3. Le Mogador Toolkit expose les données officielles. +4. Le Snapshot Collector lit les données officielles. +5. Le Diff Builder compare le snapshot courant au snapshot précédent. +6. Le Media Pipeline gère JWP et écrit l'état media dans `media_assets`. +7. La Publication Console gère les corrections d'urgence et écrit les overrides. +8. Les changements créent des `publication_jobs`. +9. Le Content Publication Engine combine données officielles, media, overrides et règles métier. +10. Il génère un run JSON complet. 11. Il valide le run et produit un rapport. 12. Il publie les fichiers JSON immuables. -13. Il met a jour `manifest.json` seulement si le run est valide. +13. Il met à jour `manifest.json` seulement si le run est valide. 14. Les sites lisent le manifest, puis les fichiers du run actif. -## Fabrication d'un incremental a partir d'un full export +## Fabrication d'un incrémental à partir d'un full export -Louise ne fournit pas d'incrementiel. Chaque export est complet. +Louise ne fournit pas d'incrémentiel. Chaque export est complet. La solution est de sauvegarder des snapshots internes et de comparer les snapshots entre eux. @@ -373,23 +372,88 @@ Exemple: -> snapshot_12h00 Diff snapshot_09h00 -> snapshot_12h00: - -> programmes ajoutes - -> programmes retires - -> produits modifies - -> images modifiees - -> dates de programmation modifiees + -> programmes ajoutés + -> programmes retirés + -> produits modifiés + -> images modifiées + -> dates de programmation modifiées -> erreurs ou anomalies ``` Cela permet: -- de savoir ce qui a change; -- de generer un `latest.json`; +- de savoir ce qui a changé; +- de générer un `latest.json`; - de limiter certaines republications; - de produire un rapport clair; - de conserver un historique. -## Donnees internes proposees +## Publication incrémentale protégée + +Le Content Publication Engine ne devrait pas régénérer aveuglément les 8 000 ou 22 000 produits à chaque run. + +Il devrait plutôt construire le nouveau run à partir du dernier run valide: + +```text +Run 1: +8 000 produits publiés + +Run 2: ++ 10 nouveaux produits +- 5 produits retirés += le CPE traite les 10 nouveaux produits, retire les 5 produits, et conserve les fichiers inchangés du run 1 +``` + +Du point de vue des sites, le run 2 reste complet. Il contient tout ce qui est publié pour la plateforme. Mais physiquement, le CPE n'a pas besoin de recalculer tous les fichiers si seulement quelques entités ont changé. + +Principe: + +```text +Snapshot source + = ce que Louise/Mogador dit aujourd'hui + +Dernier état publié valide + = ce que les sites consomment déjà avec succès + +Diff + = ce qui est ajouté, modifié, retiré ou impacté + +Nouveau run + = dernier run valide + patch validé +``` + +Un produit inchangé ne devrait pas être republié uniquement parce qu'il existe dans le nouveau snapshot. + +Il devrait être republié seulement si: + +- son hash source a changé; +- sa programmation a changé; +- son media a changé; +- ses images ont changé; +- un override a changé; +- une règle de publication impactante a changé; +- une republication manuelle est demandée. + +Pour les suppressions: + +- les produits retirés ne sont plus inclus dans les indexes du nouveau run; +- leurs fichiers peuvent ne pas être copiés dans le nouveau run; +- ils apparaissent dans `latest.json` ou dans un rapport comme `removed`; +- une trace est conservée dans une table comme `deleted_programs` ou `publication_removed_items`. + +Ce modèle résout un problème important: si PCI introduit un bug dans une version de Mogador et que plusieurs anciens produits deviennent soudainement incomplets dans la nouvelle extraction, le système ne doit pas écraser automatiquement les anciens JSON valides. + +Dans ce cas, le CPE devrait: + +- conserver le dernier fichier publié valide pour les produits non réellement modifiés; +- marquer les nouvelles données incomplètes comme anomalies; +- alerter l'équipe; +- empêcher la propagation massive d'une régression fournisseur; +- publier seulement les changements validés, ou bloquer le run si l'anomalie est critique. + +Ce compromis rend le système plus rapide et plus fiable. On garde les bénéfices d'un run complet pour les sites, mais avec une stratégie de génération incrémentale protégée. + +## Données internes proposées Tables possibles: @@ -419,11 +483,11 @@ onfr linear ``` -Cela evite de dupliquer toute la logique dans des tables separees comme `tfo_products`, `idello_products`, `onfr_products`, sauf si une contrainte technique oblige a garder cette separation. +Cela évite de dupliquer toute la logique dans des tables séparées comme `tfo_products`, `idello_products`, `onfr_products`, sauf si une contrainte technique oblige à garder cette séparation. -## Published Content Feed: JSON statiques proposes +## Published Content Feed: JSON statiques proposés -Au lieu d'un seul gros JSON, il faut publier plusieurs fichiers specialises. +Au lieu d'un seul gros JSON, il faut publier plusieurs fichiers spécialisés. Exemple pour TFO: @@ -440,7 +504,7 @@ Exemple pour TFO: /tfo/v1/runs/20260730-0900/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/CDN. C'est preferable a un gros fichier unique. +Pour 8 000 produits TFO et 22 000 produits IDELLO, ce volume de fichiers JSON n'est pas un problème pour un bucket/CDN. C'est préférable à un gros fichier unique. Le site ne code pas un chemin de run en dur. Il lit toujours: @@ -448,7 +512,7 @@ Le site ne code pas un chemin de run en dur. Il lit toujours: /tfo/v1/manifest.json ``` -Puis utilise le `base_path` retourne: +Puis utilise le `base_path` retourné: ```text /tfo/v1/runs/20260730-0900 @@ -478,15 +542,15 @@ Cache-Control: public, max-age=60, stale-while-revalidate=120 Cache-Control: public, max-age=31536000, immutable ``` -Compromis acceptable si Infra veut reduire les appels: +Compromis acceptable si Infra veut réduire les appels: ```text manifest.json: max-age=300 ``` -Donc 5 minutes. Trois heures serait trop long pour les corrections d'urgence, les rollbacks et les republications apres media JWP. +Donc 5 minutes. Trois heures serait trop long pour les corrections d'urgence, les rollbacks et les republications après media JWP. -Important: les runs sont des copies completes et immuables. Donc oui, garder plusieurs runs multiplie le nombre de fichiers stockes. +Important: les runs sont des copies complètes et immuables. Donc oui, garder plusieurs runs multiplie le nombre de fichiers stockes. Exemple simplifie avec TFO: @@ -496,9 +560,9 @@ Exemple simplifie avec TFO: = environ 40 000 fichiers produits ``` -Et il faut ajouter les collections, schedules, indexes, `today.json`, `latest.json`, etc. +Et il faut ajoutér les collections, schedules, indexes, `today.json`, `latest.json`, etc. -Estimation plus complete pour TFO avec 5 runs: +Estimation plus complète pour TFO avec 5 runs: ```text Produits: @@ -511,26 +575,26 @@ Schedules: environ 11 jours x 5 runs = 55 fichiers Indexes / today / latest / divers: -environ 50 a 150 fichiers +environ 50 à 150 fichiers Total estime: -environ 41 500 a 42 000 fichiers +environ 41 500 à 42 000 fichiers ``` -Le `manifest.json` n'est pas multiplie de la meme facon: il pointe seulement vers le run actif. +Le `manifest.json` n'est pas multiplie de la même façon: il pointe seulement vers le run actif. -Ce volume reste raisonnable pour un bucket/CDN, mais il doit etre assume dans la strategie de retention. C'est pour cela qu'on garde: +Ce volume reste raisonnable pour un bucket/CDN, mais il doit être assume dans la stratégie de retention. C'est pour cela qu'on garde: - les runs recents utiles au rollback; - un minimum de 3 runs valides; - une limite de retention, par exemple 10 jours; - des policies de nettoyage automatique. -Le compromis est volontaire: on accepte plus de fichiers stockes pour obtenir une publication atomique, un rollback simple, un cache agressif sur les runs, et aucun risque qu'un site lise une publication a moitie generee. +Le compromis est volontaire: on accepte plus de fichiers stockes pour obtenir une publication atomique, un rollback simple, un cache agressif sur les runs, et aucun risque qu'un site lise une publication à moitie génèree. ### today.json -Contient ce qui doit etre en ligne aujourd'hui. +Contient ce qui doit être en ligne aujourd'hui. ```json { @@ -541,7 +605,7 @@ Contient ce qui doit etre en ligne aujourd'hui. ### latest.json -Contient les nouveautes et changements depuis la derniere publication. +Contient les nouveautes et changements depuis la dernière publication. ```json { @@ -554,7 +618,7 @@ Contient les nouveautes et changements depuis la derniere publication. ### schedule/YYYY-MM-DD.json -Contient la programmation d'une date precise. +Contient la programmation d'une date précise. ```json { @@ -573,7 +637,7 @@ Contient la programmation d'une date precise. ### products/{id}.json -Contient le detail d'un produit. +Contient le détail d'un produit. ```json { @@ -593,7 +657,7 @@ Contient le detail d'un produit. ### collections/{biznumber}/full.json -Contient le modele attendu par les sites. +Contient le modèle attendu par les sites. ```json { @@ -628,11 +692,11 @@ Contient le modele attendu par les sites. ## Programmations futures -Pour afficher des messages comme "prochain episode le 8 aout", il faut extraire une fenetre future de programmation. +Pour afficher des messages comme "prochain épisode le 8 aout", il faut extraire une fenêtre future de programmation. -Limite v1 recommandee: J+10. +Limite v1 recommandée: J+10. -Configuration proposee: +Configuration proposée: ```env TFO_SCHEDULE_DAYS_AHEAD=10 @@ -669,7 +733,7 @@ Un fichier comme: /tfo/v1/runs/{run_id}/search/index.json ``` -peut servir a alimenter Algolia, Meilisearch, Typesense ou un autre moteur de recherche. +peut servir à alimenter Algolia, Meilisearch, Typesense ou un autre moteur de recherche. Il peut contenir seulement les champs utiles: @@ -686,7 +750,7 @@ Il peut contenir seulement les champs utiles: ] ``` -Si les sites ont besoin d'une vraie recherche rapide sur 8 000 a 22 000 items, un moteur dedie reste preferable a un gros fichier recherche charge cote client. +Si les sites ont besoin d'une vraie recherche rapide sur 8 000 à 22 000 items, un moteur dédié reste préférable à un gros fichier recherche chargé côté client. ## Publication atomique et retention @@ -698,15 +762,15 @@ Principe: /tfo/v1/manifest.json ``` -Si la generation du run `20260730-1200` echoue, `manifest.json` continue de pointer vers `20260730-0900`. Une sync ratee ne casse pas le site. +Si la génération du run `20260730-1200` échoue, `manifest.json` continue de pointer vers `20260730-0900`. Une sync ratée ne casse pas le site. -Retention proposee: +Retention proposée: ```text -JSON publies: +JSON publiés: - garder les runs des 10 derniers jours - garder au minimum les 3 derniers runs valides -- supprimer les runs incomplets jamais publies +- supprimer les runs incomplets jamais publiés Rapports: - garder 90 jours @@ -737,7 +801,7 @@ Version dans chaque fichier: } ``` -Documentation recommandee: +Documentation recommandée: ```text docs/ @@ -760,22 +824,22 @@ docs/ Avant de publier un run: ```text -1. generer tous les JSON +1. générer tous les JSON 2. valider chaque type de fichier contre son JSON Schema 3. produire le rapport 4. publier seulement si les erreurs critiques sont absentes -5. mettre a jour manifest.json +5. mettre à jour manifest.json ``` -Swagger/OpenAPI est utile pour les endpoints internes de la Publication Console. Pour les JSON statiques, JSON Schema et exemples versionnes sont plus importants. +Swagger/OpenAPI est utile pour les endpoints internes de la Publication Console. Pour les JSON statiques, JSON Schema et exemples versionnés sont plus importants. ## Role futur de Directus Deux options sont possibles. -### Option 1: retirer Directus progressivement +### Option 1: retirér 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. +Si les sites consomment les JSON statiques et si les permissions fournisseurs sont gérées par bucket ou préfixe, Directus n'est plus nécessaire dans la chaîne de publication. Permissions possibles: @@ -785,7 +849,7 @@ bucket-idello bucket-onfr ``` -Ou un seul bucket avec prefixes: +Ou un seul bucket avec préfixes: ```text publication/tfo/ @@ -798,43 +862,43 @@ publication/onfr/ Directus peut rester pendant une periode de transition pour: - consultation interne; -- edition d'urgence existante; -- acces read-only fournisseur existant; +- édition d'urgence existante; +- accès read-only fournisseur existant; - comparaison avec les nouveaux JSON. -Mais il ne devrait plus composer le JSON relationnel final utilise par les sites. +Mais il ne devrait plus composer le JSON relationnel final utilisé par les sites. -## Publication Console: edition d'urgence +## Publication Console: édition d'urgence -Si Directus est retire ou reduit, il faut remplacer son role d'edition d'urgence. +Si Directus est retiré ou reduit, il faut remplacer son rôle d'édition d'urgence. -La proposition est de creer une `Publication Console` interne, non exposee a Internet. +La proposition est de créer une `Publication Console` interne, non exposée à Internet. -Acces proposes: +Accès proposés: ```text Admin sync: - peut configurer et publier -- peut gerer les utilisateurs +- peut gérer les utilisateurs - peut faire rollback Edimestre: - peut rechercher et consulter -- peut creer une correction d'urgence +- peut créer une correction d'urgence - peut voir les overrides actifs -- ne peut pas changer la configuration systeme +- ne peut pas changer la configuration système Read-only interne: -- peut consulter les donnees, rapports et JSON publies +- peut consulter les données, rapports et JSON publiés - ne peut pas modifier ``` Fonctions minimales: - rechercher un produit, programme, collection ou serie; -- voir les donnees venant de Louise/Mogador; +- voir les données venant de Louise/Mogador; - voir le JSON actuellement publie; -- ajouter une correction temporaire; +- ajoutér une correction temporaire; - mettre une raison; - mettre une date d'expiration; - republier les JSON concernes; @@ -859,50 +923,50 @@ manual_overrides - updated_at ``` -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. +Important: il ne faut pas modifier les JSON publiés directement à la main. Les overrides doivent être appliqués dans le pipeline de génération, sinon ils seront perdus ou impossibles à auditer. Chaque override devrait inclure: - l'utilisateur; -- le role; +- le rôle; - la raison; - la date d'expiration; -- l'entite touchee; +- l'entité touchee; - l'ancien contenu; - le nouveau contenu; -- le run dans lequel la correction a ete publiee. +- le run dans lequel la correction a été publiée. -## Media Pipeline: role de l'app AdonisJS/JWP +## Media Pipeline: rôle de l'app AdonisJS/JWP -L'app AdonisJS qui synchronise les videos vers JWP ne devrait pas devenir le moteur de publication JSON complet. Son role naturel est: +L'app AdonisJS qui synchronise les vidéos vers JWP ne devrait pas devenir le moteur de publication JSON complet. Son rôle naturel est: -> verifier les videos, envoyer ou mettre a jour les medias dans JWP, suivre leur statut, et declarer qu'un produit doit etre republie quand le media est pret. +> vérifier les vidéos, envoyer ou mettre à jour les medias dans JWP, suivre leur statut, et declarer qu'un produit doit être republie quand le media est prêt. Le point important n'est pas la technologie de cette app, mais le contrat entre le Media Pipeline et le Content Publication Engine. Elle devrait faire: - lire les infos video source depuis Louise/Mogador ou depuis le snapshot interne; -- verifier la presence du fichier video source; -- creer ou mettre a jour le media dans JWP; -- gerer poster, sous-titres, metadata et statut d'encodage; +- vérifier la presence du fichier video source; +- créer ou mettre à jour le media dans JWP; +- gérer poster, sous-titres, métadonnées et statut d'encodage; - maintenir une table interne `media_assets`; -- creer un job de republication quand un media change. +- créer un job de republication quand un media change. Elle ne devrait pas faire: - publier les JSON finaux des sites; -- connaitre toute la logique collection/saison/episode; -- ecrire directement dans les fichiers publics; +- connaitre toute la logique collection/saison/épisode; +- écrire directement dans les fichiers publics; - remplacer le Content Publication Engine. ## Contrat entre Media Pipeline et Content Publication Engine ### Table `media_assets` -Cette table represente l'etat media interne d'un produit. +Cette table représente l'état media interne d'un produit. -Champs proposes: +Champs proposés: ```text id @@ -955,9 +1019,9 @@ Exemple: ### Table `publication_jobs` -Cette table sert a dire au Content Publication Engine: "quelque chose a change, republie ce qui est touche". +Cette table sert à dire au Content Publication Engine: "quelque chose a change, republie ce qui est touché". -Champs proposes: +Champs proposés: ```text id @@ -1015,12 +1079,12 @@ Pourquoi cette table est le meilleur compromis: - rejouable si le Content Publication Engine est temporairement down; - observable dans un dashboard ou rapport; - compatible avec plusieurs workers; -- idempotent si on utilise une cle unique par entite/reason/run; -- rapide, car le job peut etre traite presque tout de suite; -- plus simple a auditer; -- ne force pas le Media Pipeline et le Content Publication Engine a etre deployes ensemble. +- idempotent si on utilisé une cle unique par entité/reason/run; +- rapide, car le job peut être traite presque tout de suite; +- plus simple à auditer; +- ne force pas le Media Pipeline et le Content Publication Engine a être déployés ensemble. -On peut garder un scan periodique comme filet de securite, par exemple toutes les 15 ou 30 minutes, pour detecter un media modifie qui n'aurait pas cree de job. +On peut garder un scan periodique comme filet de securite, par exemple toutes les 15 ou 30 minutes, pour détectér un media modifie qui n'aurait pas crée de job. ## Rapport et alertes @@ -1031,11 +1095,11 @@ Il doit comparer: ```text ce que Louise/Mogador contient vs -ce que le Content Publication Engine a traite +ce que le Content Publication Engine a traité vs -ce qui a ete publie en JSON +ce qui a été publié en JSON vs -eventuellement ce qui reste dans Directus pendant la transition +éventuellement ce qui reste dans Directus pendant la transition ``` Exemple de rapport: @@ -1044,46 +1108,46 @@ Exemple de rapport: Plateforme: TFO Run: 20260730-0900 -Export SQL recu: oui -Import MySQL: succes +Export SQL reçu: oui +Import MySQL: succès Mogador Toolkit: OK Programmes attendus aujourd'hui: 1230 -Programmes publies: 1229 +Programmes publiés: 1229 Produits attendus: 8142 -Produits publies: 8139 +Produits publiés: 8139 Ecarts: - 1 programme absent du JSON final - 2 produits sans video JWP - 5 images manquantes -- 1 produit ignore car type extrait +- 1 produit ignoré car type extrait Publication: - statut: publie avec avertissements - manifest pointe vers: /tfo/v1/runs/20260730-0900 ``` -Alertes a mettre en place: +Alertes à mettre en place: -- export SQL non recu; -- fichier SQL trop petit ou checksum identique de facon suspecte; -- import MySQL echoue; +- export SQL non reçu; +- fichier SQL trop petit ou checksum identique de façon suspecte; +- import MySQL échoue; - Mogador Toolkit 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; +- programme prévu à 6h absent de la publication avant 6h; - video JWP manquante; - image ou transcription manquante; - override actif proche expiration. ## Fichier SQL hors application -Le fait que `export_mogador.sql` soit hors du repertoire de l'application n'est pas un probleme. +Le fait que `export_mogador.sql` soit hors du repertoire de l'application n'est pas un problème. -Le script d'import peut ecrire un fichier de statut dans un chemin connu: +Le script d'import peut écrire un fichier de statut dans un chemin connu: ```json { @@ -1092,7 +1156,7 @@ Le script d'import peut ecrire un fichier de statut dans un chemin connu: "import_finished_at": "2026-07-30T09:48:00-04:00", "sql_file_size": 306184192, "checksum": "abc123", - "status": "success" + "status": "succèss" } ``` @@ -1108,7 +1172,7 @@ Le Content Publication Engine lit ce statut pour produire son rapport. ## Timeline du chantier A: synchro interne -Important: les durees ci-dessous representent des estimations d'effort si l'equipe travaille presque a temps plein sur le projet. Si l'equipe a 35-40% d'operations courantes, il faut convertir ces estimations en duree calendrier. +Important: les durées ci-dessous représentent des estimations d'effort si l'équipe travaille presque à temps plein sur le projet. Si l'équipe a 35-40% d'opérations courantes, il faut convertir ces estimations en durée calendrier. Exemple: @@ -1117,22 +1181,22 @@ Exemple: = environ 3.3 semaines calendrier ``` -En pratique, une estimation doit souvent etre multipliee par environ 1.5 a 1.7 si l'equipe n'est disponible qu'a 60-65% pour le projet. +En pratique, une estimation doit souvent être multipliée par environ 1.5 à 1.7 si l'équipe n'est disponible qu'à 60-65% pour le projet. ### Phase 0: contrat technique -Duree estimee: 1 semaine. +Durée estimée: 1 semaine. Livrables: - schema `media_assets`; - schema `publication_jobs`; - structure JSON v1; -- regles de statut media; -- regles de republication; +- règles de statut media; +- règles de republication; - convention de logs et rapports. -### Phase 1: observabilite +### Phase 1: observabilité Objectif: savoir ce qui se passe avant de tout remplacer. @@ -1145,16 +1209,16 @@ Objectif: savoir ce qui se passe avant de tout remplacer. ### Phase 2: Media Pipeline minimal -Duree estimee: 1 a 2 semaines. +Durée estimée: 1 à 2 semaines. -- L'app AdonisJS ecrit dans `media_assets`. -- Elle cree des jobs `publication_jobs`. -- Elle detecte les medias `missing`, `processing`, `ready`, `failed`. -- Elle produit un rapport simple sur les videos manquantes ou en erreur. +- L'app AdonisJS écrit dans `media_assets`. +- Elle crée des jobs `publication_jobs`. +- Elle détecté les medias `missing`, `processing`, `ready`, `failed`. +- Elle produit un rapport simple sur les vidéos manquantes ou en erreur. -### Phase 3: publication JSON en parallele +### Phase 3: publication JSON en parallèle -Duree estimee: 2 a 3 semaines. +Durée estimée: 2 à 3 semaines. - Generer `/manifest.json`. - Generer `/today.json`. @@ -1167,20 +1231,20 @@ Duree estimee: 2 a 3 semaines. ### Phase 4: premier site pilote -Duree estimee: 2 semaines. +Durée estimée: 2 semaines. - Choisir ONFR ou une portion TFO. -- Publier dans un bucket/prefix dedie. +- Publier dans un bucket/prefix dédié. - Valider performance, structure JSON, cache, rollback et medias JWP. - Ajouter alertes Slack/Better Stack. ### Phase 5: Publication Console -Duree estimee: 2 semaines. +Durée estimée: 2 semaines. - Ajouter `manual_overrides`. - Ajouter interface interne. -- Ajouter auth et roles. +- Ajouter auth et rôles. - Ajouter audit trail. - Ajouter expiration automatique. - Ajouter rapport des overrides actifs. @@ -1189,48 +1253,48 @@ Duree estimee: 2 semaines. - Garder Directus seulement pendant transition. - Migrer les usages fournisseurs vers buckets/CDN. -- Retirer progressivement les dependances Directus. +- Retirer progressivement les dépendances Directus. ## Timeline du chantier B: PCI / Louise-Mogador -Ce chantier peut avancer en parallele, mais il ne devrait pas bloquer le chantier interne. +Ce chantier peut avancer en parallèle, mais il ne devrait pas bloquer le chantier interne. -### Etape B1: clarifier les problemes actuels +### Etape B1: clarifier les problèmes actuels -Points a documenter pour PCI: +Points à documenter pour PCI: - SSL non fonctionnel ou non compatible; - lenteur des appels API; - limite de concurrence actuelle; -- trop grand nombre d'appels necessaires pour reconstruire un produit complet; -- absence d'incrementiel; +- trop grand nombre d'appels nécessaires pour reconstruire un produit complet; +- absence d'incrémentiel; - absence de signal de changement; - besoin de bulk; - besoin de pagination/cursor; - besoin de checksums ou export id; -- besoin de documentation claire et versionnee. +- besoin de documentation claire et versionnée. ### Etape B2: demander une API v2 bulk Exemples de besoins: -- recuperer tous les produits/programmes d'une plateforme pour une fenetre de dates; -- recuperer une collection complete; -- recuperer un produit complet; -- recuperer les horaires J+10; -- recuperer les droits et pays autorises; -- recuperer les informations video source, mais pas les champs JWP. +- reçuperer tous les produits/programmes d'une plateforme pour une fenêtre de dates; +- reçuperer une collection complète; +- reçuperer un produit complet; +- reçuperer les horaires J+10; +- reçuperer les droits et pays autorises; +- reçuperer les informations video source, mais pas les champs JWP. -### Etape B3: demander un mode evenementiel +### Etape B3: demander un mode événementiel -PCI pourrait envoyer un event quand une modification est sauvegardee dans Louise. Cet event ne publie rien directement. Il sert seulement a declencher une relecture officielle par notre systeme interne. +PCI pourrait envoyer un event quand une modification est sauvegardée dans Louise. Cet event ne publie rien directement. Il sert seulement a déclencher une relecture officielle par notre système interne. Exemple: ```json { "event_id": "evt_123", - "sequence": 987654, + "séquence": 987654, "event_type": "product.updated", "platforms": ["tfo"], "product_key": "GP123456", @@ -1238,7 +1302,7 @@ Exemple: } ``` -Notre systeme recoit l'event, relit le detail via API officielle, applique les validations, enrichit avec JWP/overrides, puis republie les JSON touches. +Notre système recoit l'event, relit le détail via API officielle, applique les validations, enrichit avec JWP/overrides, puis republie les JSON touches. ## Vision long terme: publication presque instantanee @@ -1256,63 +1320,63 @@ A court terme: A moyen terme: -- demander a PCI une API Louise/Mogador v2 bulk fiable; -- reduire le temps de lecture; -- eviter les milliers d'appels API individuels; +- demander à PCI une API Louise/Mogador v2 bulk fiable; +- réduire le temps de lecture; +- éviter les milliers d'appels API individuels; - garder le snapshot complet comme filet de securite. A long terme: -- demander a PCI des evenements/webhooks comme signal; -- chaque changement dans Louise envoie un evenement; -- notre systeme relit le detail officiel via API; +- demander à PCI des événements/webhooks comme signal; +- chaque changement dans Louise envoie un événement; +- notre système relit le détail officiel via API; - le snapshot complet continue de tourner pour reconciler les ecarts. -Important: le webhook ne devrait pas publier directement vers les sites. Il devrait seulement dire: "quelque chose a change". Notre systeme interne reste responsable de valider, enrichir, publier, alerter et rollback. +Important: le webhook ne devrait pas publier directement vers les sites. Il devrait seulement dire: "quelque chose a change". Notre système interne reste responsable de valider, enrichir, publier, alerter et rollback. ## Choix technique recommande pour la nouvelle app v2 -La nouvelle app v2 devrait etre faite en Laravel. +La nouvelle app v2 devrait être faite en Laravel. Raisons principales: -- le projet est surtout un systeme metier back-office, pas une API publique temps reel; -- Laravel gere tres bien les jobs, le scheduler, les commandes, les retries et les traitements planifies; -- Horizon donne une bonne visibilite sur les queues si Redis est utilise correctement; -- l'ecosysteme Laravel est tres solide pour construire une `Publication Console` interne avec auth, roles, policies et audit; -- les migrations, seeders, commands et jobs sont bien adaptes a ce type de pipeline; -- l'equipe connait deja le contexte Laravel de la synchro actuelle; -- la logique de publication doit etre fiable et observable plus que fashionable; +- le projet est surtout un système métier back-office, pas une API publique temps reel; +- Laravel gère très bien les jobs, le scheduler, les commandes, les retries et les traitements planifies; +- Horizon donne une bonne visibilité sur les queues si Redis est utilisé correctement; +- l'ecosystème Laravel est très solide pour construire une `Publication Console` interne avec auth, rôles, policies et audit; +- les migrations, seeders, commands et jobs sont bien adaptés à ce type de pipeline; +- l'équipe connait déjà le contexte Laravel de la synchro actuelle; +- la logique de publication doit être fiable et observable plus que fashionable; - le rollback, les rapports, les overrides et la validation JSON sont des cas naturels pour Laravel. -Le Media Pipeline existant peut rester separe. Ce qui compte, c'est qu'il respecte le contrat: +Le Media Pipeline existant peut rester séparé. Ce qui compte, c'est qu'il respecte le contrat: ```text Media Pipeline - -> ecrit media_assets - -> cree publication_jobs + -> écrit media_assets + -> crée publication_jobs Content Publication Engine -> lit media_assets -> traite publication_jobs - -> genere les JSON publics + -> génère les JSON publics ``` -Avec cette separation, le Media Pipeline peut evoluer independamment. La nouvelle app v2, elle, devrait etre le systeme de publication fiable, auditable et operationnel; Laravel est le meilleur choix pour ce role. +Avec cette séparation, le Media Pipeline peut évoluer independamment. La nouvelle app v2, elle, devrait être le système de publication fiable, auditable et opérationnel; Laravel est le meilleur choix pour ce rôle. ## Risques principaux |Risque|Probabilite|Impact|Reponse| |---|---|---|---| -|Le projet devient trop large et tente de remplacer Directus, Mogador, JWP et les sites en meme temps|Elevee|Eleve|Decouper en pilote, garder PCI comme chantier separe, livrer par increments| -|Les regles metier actuelles sont implicites dans le vieux code|Elevee|Eleve|Extraire les regles, valider avec production, ajouter rapports de comparaison| -|Les corrections d'urgence entrent en conflit avec Louise au prochain export|Elevee|Eleve|Definir precedence, expiration d'override, audit et rapport d'ecart| -|Le manifest est cache trop longtemps|Moyenne|Eleve|TTL court sur manifest, runs immuables caches longtemps, procedure purge CDN| +|Le projet devient trop large et tente de remplacer Directus, Mogador, JWP et les sites en même temps|Élevée|Eleve|Decouper en pilote, garder PCI comme chantier séparé, livrer par increments| +|Les règles métier actuelles sont implicites dans le vieux code|Élevée|Eleve|Extraire les règles, valider avec production, ajoutér rapports de comparaison| +|Les corrections d'urgence entrent en conflit avec Louise au prochain export|Élevée|Eleve|Definir precedence, expiration d'override, audit et rapport d'ecart| +|Le manifest est cache trop longtemps|Moyenne|Eleve|TTL court sur manifest, runs immuables cachés longtemps, procedure purge CDN| |Media Pipeline et Publication Engine se couplent trop fortement|Moyenne|Eleve|Passer uniquement par `media_assets` et `publication_jobs`| -|Le systeme publie un JSON incomplet mais valide techniquement|Moyenne|Eleve|Ajouter validations metier, rapports attendu vs publie et seuils bloquants| -|L'absence d'API PCI v2 maintient certaines lenteurs|Elevee|Moyen|Concevoir le `Source Reader` remplacable et optimiser avec snapshots/diffs internes| -|PCI ne livre pas d'events/webhooks a court terme|Elevee|Moyen|Ne pas en faire une dependance du MVP; garder polling 3h et overrides internes| -|Infra refuse l'exposition de l'app interne|Moyenne|Moyen|Exposer seulement les JSON via bucket/CDN; garder la console sur reseau interne| +|Le système publie un JSON incomplet mais valide techniquement|Moyenne|Eleve|Ajouter validations métier, rapports attendu vs publie et seuils bloquants| +|L'absence d'API PCI v2 maintient certaines lenteurs|Élevée|Moyen|Concevoir le `Source Reader` remplacable et optimiser avec snapshots/diffs internes| +|PCI ne livre pas d'events/webhooks à court terme|Élevée|Moyen|Ne pas en faire une dépendance du MVP; garder polling 3h et overrides internes| +|Infra refuse l'exposition de l'app interne|Moyenne|Moyen|Exposer seulement les JSON via bucket/CDN; garder la console sur réseau interne| |Migration depuis Directus cause une interruption|Moyenne|Eleve|Double-run, comparaison, pilote, rollback, aucun big bang| ## Noms recommandes @@ -1322,32 +1386,32 @@ Louise Systeme source editorial. Louise Export - Export SQL complet genere par Louise. + Export SQL complet génère par Louise. Mogador Toolkit - API legacy actuelle autour de la base importee. + API legacy actuelle autour de la base importée. Louise API v2 Future API PCI demandee pour lecture bulk et events. Content Publication Engine - Notre moteur interne qui genere les JSON publics. + Notre moteur interne qui génère les JSON publics. Media Pipeline - Notre service interne qui gere JWP et l'etat media. + Notre service interne qui gère JWP et l'état media. Publication Console - Mini CMS interne pour edimestres/admins et overrides. + Mini CMS interne pour édimestres/admins et overrides. Published Content Feed - Les fichiers JSON versionnes consommes par les sites. + Les fichiers JSON versionnés consommes par les sites. ``` Avec ces noms, on peut parler de l'architecture sans que "Mogador" veuille dire quatre choses differentes. ## Position finale -La proposition recommandee est: +La proposition recommandée est: ```text Content Publication Engine interne @@ -1361,15 +1425,15 @@ Content Publication Engine interne + alertes ``` -Directus peut etre garde temporairement, mais ne devrait plus etre le moteur principal de publication web. +Directus peut être garde temporairement, mais ne devrait plus être le moteur principal de publication web. Cette approche respecte les contraintes: -- Louise reste source de verite. -- Le Mogador Toolkit actuel peut rester utilise au depart. -- L'app interne n'est pas exposee 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. +- Louise reste source de vérité. +- Le Mogador Toolkit actuel peut rester utilisé au depart. +- L'app interne n'est pas exposée à Internet. +- Les sites recoivent des données simples et rapides. +- Les fournisseurs peuvent être isolés par bucket ou préfixe. +- L'équipe interne garde la capacite de corriger en urgence. - Les erreurs deviennent visibles avant que la production les signale. - L'architecture reste compatible avec une future API Louise/Mogador v2 de PCI. \ No newline at end of file