vault backup: 2026-08-01 16:32:03

This commit is contained in:
2026-08-01 16:32:03 -04:00
parent 50341b49c4
commit 006017c6b2
3 changed files with 490 additions and 65 deletions
@@ -0,0 +1,319 @@
## Objectif
Ce document liste les tests à prévoir pour un pilote du `Content Publication Engine`.
Le but n'est pas seulement de vérifier que les JSON sont générés. Le but est de valider que l'architecture est fiable dans les cas réels:
- export Louise/Mogador incomplet;
- bug fournisseur;
- produit retiré;
- correction d'urgence;
- vidéo JWP manquante;
- cache CDN;
- rollback;
- run partiellement généré;
- consommation par un site fournisseur.
## Principe du pilote
Le pilote devrait être limité à une plateforme ou à un sous-ensemble.
Options recommandées:
```text
Option 1: ONFR
- plus petit volume;
- plus facile à valider;
- bon premier test technique.
Option 2: sous-ensemble TFO
- plus proche des enjeux réels;
- permet de tester collections/saisons/épisodes;
- plus représentatif pour la production.
```
Le pilote ne devrait pas remplacer Directus ou la synchro actuelle immédiatement. Il devrait tourner en parallèle.
## Critères de réussite
- Le CPE génère un run JSON complet et valide.
- `manifest.json` pointe seulement vers un run validé.
- Les sites peuvent consommer le feed via manifest + fichiers JSON.
- Une correction d'urgence peut être publiée rapidement.
- Un rollback peut être exécuté rapidement.
- Un produit inchangé n'est pas écrasé par une donnée source suspecte.
- Les anomalies sont visibles avant les plaintes de production.
- Les performances sont suffisantes pour la plateforme pilote.
- Le format JSON est validé par au moins un fournisseur/site consommateur.
## Tests d'ingestion source
|Test|Résultat attendu|
|---|---|
|Export SQL reçu correctement|Le CPE détecte le nouvel export ou son statut d'import|
|Export SQL absent|Alerte, aucun nouveau run publié|
|Export SQL trop petit|Alerte, aucun run publié sans validation manuelle|
|Export SQL identique au précédent|Run ignoré ou marqué sans changement|
|Import MySQL réussi|Snapshot peut commencer|
|Import MySQL échoué|Alerte, manifest inchangé|
|Mogador Toolkit indisponible|Alerte, manifest inchangé|
|Réponses API lentes|Retry/backoff, rapport de lenteur|
|Réponses API partielles|Anomalie, pas d'écrasement massif|
## Tests de snapshot et diff
|Test|Résultat attendu|
|---|---|
|Nouveau produit|Produit présent dans `latest.added` et fichier produit généré|
|Produit modifié|Produit présent dans `latest.updated` et fichier produit régénéré|
|Produit supprimé|Produit absent des indexes, présent dans `latest.removed`|
|Programmation ajoutée|`today.json` ou `schedule/YYYY-MM-DD.json` mis à jour|
|Programmation modifiée|`changed_fields` indique le changement|
|Programmation supprimée|Programme absent du schedule concerné|
|Image modifiée|Produit ou collection impactée régénérée|
|Média modifié|Produit/collection impactée régénérée|
|Aucun changement|Nouveau run optionnel, ou aucun run publié|
## Tests de publication incrémentale protégée
|Test|Résultat attendu|
|---|---|
|Run 1 contient 8 000 produits, run 2 ajoute 10 produits|Le CPE traite les 10 nouveaux et conserve les fichiers inchangés|
|Run 2 retire 5 produits|Les 5 produits disparaissent des indexes du run 2|
|Produit inchangé dans le snapshot|Le dernier JSON valide est conservé|
|Produit inchangé devient soudainement incomplet|Anomalie, ancien JSON valide conservé|
|Bug source sur plusieurs anciens produits|Alerte globale, pas d'écrasement massif|
|Trop d'anomalies dans un run|Run bloqué ou publié avec seuil contrôlé|
|Diff incohérent|Manifest inchangé, rapport d'erreur|
Point à ne pas oublier: il faut définir des seuils.
Exemples:
```text
Si plus de 5% des produits deviennent incomplets sans raison connue:
-> bloquer le run
Si 1 produit nouveau est incomplet:
-> publier avec avertissement ou exclure selon règle métier
Si un produit prévu aujourd'hui à 6h est incomplet:
-> alerte critique
```
## Tests de génération JSON
|Test|Résultat attendu|
|---|---|
|`manifest.json` généré|Contient `schema_version`, `platform`, `run_id`, `base_path`, `published_at`|
|`today.json` généré|Contient les programmes légers du jour|
|`schedule/YYYY-MM-DD.json` généré|Contient les programmes de la date|
|Schedule J+10 généré|Les 10 prochains jours sont disponibles|
|`products/{product_key}.json` généré|Contient produit, programmations, média, images|
|`collections/{biznumber}/full.json` généré|Contient collection -> saisons -> épisodes|
|Produit multi-plateforme|Chaque plateforme a sa version contextualisée|
|Champs obligatoires manquants|Validation échoue ou anomalie créée|
|JSON invalide|Run non publié|
|JSON Schema échoue|Run non publié|
## Tests de fichiers et chemins
|Test|Résultat attendu|
|---|---|
|Chemins sans caractères problématiques|Aucun espace ou caractère ambigu dans les paths|
|`product_key` numérique ou string|Convention documentée et stable|
|`biznumber` avec zéros en début|Zéros conservés|
|Produit absent|Retour HTTP attendu défini, ex. 404|
|Ancien run consulté|Disponible pendant la rétention|
|Run supprimé par rétention|Plus accessible après purge contrôlée|
|Chemins de liens dans `today.json`|Pointent vers le bon `base_path`|
## Tests de publication atomique
|Test|Résultat attendu|
|---|---|
|Run complet généré avec succès|Fichiers uploadés, validation OK, manifest mis à jour|
|Run échoue pendant génération|Manifest reste sur ancien run|
|Run échoue pendant upload|Manifest reste sur ancien run|
|Run échoue après upload partiel|Manifest reste sur ancien run, fichiers incomplets nettoyés ou ignorés|
|Manifest upload échoue|Ancien manifest reste actif|
|Manifest pointe vers run inexistant|Détecté par validation pré-publication|
|Deux runs simultanés|Lock empêche collision ou ordre déterministe|
## Tests de cache CDN
|Test|Résultat attendu|
|---|---|
|`manifest.json` cache court|Nouveau run visible après TTL attendu|
|Fichiers de run cache long|Fichiers immuables servis efficacement|
|Rollback manifest|Site revient au run précédent après TTL/purge|
|Purge manifest CDN|Nouveau manifest visible rapidement|
|Fichier immutable modifié par erreur|Test doit échouer, les runs sont immuables|
|Site garde un ancien manifest|Comportement acceptable documenté|
Point facile à oublier: les sites doivent gérer le cas où le manifest change pendant une navigation.
Recommandation:
```text
Une page devrait utiliser un seul run_id pendant son rendu.
Elle ne devrait pas mélanger des fichiers de deux runs différents dans la même réponse.
```
## Tests de rollback
|Test|Résultat attendu|
|---|---|
|Rollback vers run précédent|Manifest repointe vers le run précédent|
|Rollback après bug source|Anciens JSON valides disponibles|
|Rollback après mauvais override|Override désactivé, run précédent ou nouveau run correct publié|
|Rollback audité|Qui, quand, pourquoi enregistré|
|Rollback communiqué au site|Site détecte nouveau `run_id`|
## Tests de Publication Console
|Test|Résultat attendu|
|---|---|
|Login édimestre|Accès autorisé seulement en interne|
|Rôle read-only|Consultation seulement|
|Rôle édimestre|Peut créer override autorisé|
|Rôle admin|Peut approuver, rollback, republier|
|Override avec expiration|Désactivation automatique après expiration|
|Override sans raison|Refusé|
|Override sans audit|Refusé|
|Override produit|`publication_job` ciblé créé|
|Override collection|Collection et indexes impactés régénérés|
|Override supprimé|Nouveau run revient aux données source|
|Conflit override vs nouveau snapshot|Rapport d'écart généré|
Point facile à oublier: un override doit avoir une durée de vie.
Sans expiration, la Publication Console devient un CMS parallèle et on recrée le problème de gouvernance.
## Tests Media Pipeline / JWP
|Test|Résultat attendu|
|---|---|
|Vidéo prête|`media_assets.status = ready`, produit republié|
|Vidéo manquante|`media_assets.status = missing`, alerte si critique|
|Vidéo en encodage|`processing`, JSON indique un état contrôlé|
|Vidéo échouée|`failed`, rapport visible|
|Poster manquant|Anomalie non bloquante ou bloquante selon règle|
|Sous-titres manquants|Anomalie selon règle d'accessibilité|
|Media Pipeline down|CPE continue avec dernier `media_assets` connu|
|JWP indisponible|Pas d'écrasement des anciens médias valides|
|`publication_job media_ready`|Produit/collection impactés republiés|
Point facile à oublier: le CPE ne devrait pas appeler JWP directement pour construire chaque JSON. Il doit lire l'état interne `media_assets`.
## Tests de sécurité et accès
|Test|Résultat attendu|
|---|---|
|App interne non exposée Internet|Accès bloqué hors réseau/VPN/SSO|
|Bucket par plateforme ou préfixe|Chaque fournisseur voit seulement son feed|
|Secrets absents des JSON|Aucun token, URL signée privée ou donnée interne sensible|
|`product_key` visible selon règle|Confirmer ce qui peut être exposé aux fournisseurs|
|Logs sans secret|Aucun credential dans logs/rapports|
|Accès écriture bucket limité|Seul le CPE peut publier|
|Suppression accidentelle bucket|Protection IAM ou versioning bucket|
Point facile à oublier: les JSON publics ne doivent pas contenir d'information réservée à l'équipe interne.
## Tests d'observabilité
|Test|Résultat attendu|
|---|---|
|Rapport par run|Disponible après chaque tentative|
|Rapport attendu vs publié|Écarts listés clairement|
|Alerte export absent|Envoyée rapidement|
|Alerte programme 6h absent|Critique avant l'heure de diffusion|
|Alerte queue bloquée|Visible avant impact site|
|Alerte trop d'anomalies|Run bloqué ou escaladé|
|Dashboard dernier run|Plateforme, statut, durée, anomalies|
|Logs corrélés par `run_id`|Diagnostic possible rapidement|
## Tests de performance
|Test|Résultat attendu|
|---|---|
|Génération complète pilote|Durée mesurée|
|Génération incrémentale 10 produits|Beaucoup plus rapide qu'une génération complète|
|Publication 8 000 produits|Durée upload mesurée|
|Publication 22 000 produits|Estimation IDELLO réaliste|
|Lecture manifest CDN|Latence faible|
|Lecture produit CDN|Latence faible|
|Lecture collection full|Taille et latence acceptables|
|Search index|Taille acceptable ou moteur dédié requis|
Mesures à collecter:
```text
durée extraction source
durée diff
durée génération JSON
durée validation JSON Schema
durée upload
durée publication manifest
nombre de fichiers
taille totale
nombre d'anomalies
temps de rollback
```
## Tests avec fournisseurs sites
|Test|Résultat attendu|
|---|---|
|Fournisseur lit `manifest.json`|OK|
|Fournisseur charge `today.json`|OK|
|Fournisseur charge un produit via `links.product`|OK|
|Fournisseur charge une collection complète|OK|
|Fournisseur gère `latest.json`|OK ou besoin clarifié|
|Fournisseur gère un produit retiré|OK|
|Fournisseur gère un rollback|OK|
|Fournisseur ne mélange pas deux runs|OK|
|Champs manquants identifiés|Ajustement JSON v1 avant gel|
## Détails faciles à oublier
Voici les points qui peuvent sembler petits, mais qui ont un gros impact:
- `manifest.json` ne doit jamais pointer vers un run incomplet.
- Les fichiers dans `/runs/{run_id}/` doivent être immuables.
- Une page site doit utiliser un seul `run_id` pendant son rendu.
- Les zéros au début des `biznumber` doivent être conservés.
- Les dates doivent inclure la timezone.
- `product_key` et `program_key` doivent avoir un type stable, idéalement string dans les JSON.
- Les produits multi-plateformes doivent être contextualisés par plateforme.
- Les overrides doivent expirer.
- Les suppressions doivent être visibles dans `latest.json` et dans les rapports.
- Les produits retirés ne doivent plus apparaître dans les indexes.
- Les anciens fichiers retirés ne doivent pas rester découvrables via les indexes actifs.
- Les fichiers lourds comme `collections/{biznumber}/full.json` doivent être mesurés.
- Les champs internes ou sensibles ne doivent pas sortir dans les JSON publics.
- Le CPE doit être idempotent: relancer un job ne doit pas casser l'état.
- Les seuils d'anomalies doivent être définis avant le pilote.
- Le run doit avoir un rapport lisible par humains, pas seulement des logs techniques.
- Le rollback doit être testé avant le premier incident réel.
- La rétention doit être automatisée.
- Le bucket/CDN doit avoir une stratégie de purge du manifest.
- Les sites doivent savoir quoi faire si un fichier lié retourne 404.
- Les liens dans les JSON doivent être relatifs au `base_path` ou documentés clairement.
- Les JSON Schema doivent être validés dans le pipeline.
- Le feed JSON ne doit pas devenir une API dynamique cachée.
## Décision de fin de pilote
À la fin du pilote, il faut pouvoir répondre clairement:
- Est-ce que les sites peuvent consommer le feed JSON?
- Est-ce que la génération est assez rapide?
- Est-ce que le modèle protège contre les bugs source?
- Est-ce que les rapports permettent d'être proactifs?
- Est-ce que les corrections d'urgence sont assez rapides?
- Est-ce que le rollback est simple?
- Est-ce que le périmètre reste maîtrisé?
- Est-ce qu'on peut généraliser à TFO, IDELLO, ONFR et linéaire?