Vue d'ensemble du CMS
Comment les surfaces de contenu, modèles de données, médias, sections, pages, design tokens et modèles d'e-mails de Yayaw s'articulent.
Vue d'ensemble
Le CMS de Yayaw est la couche d'exploitation de contenu dans le dashboard. Il combine données structurées, sections réutilisables, pages, ressources média, design tokens publics, modèles d'e-mails transactionnels et recettes de composants sous un même modèle d'autorisation.
Le point d'entrée principal est :
/dashboard/content
Ce dashboard résume l'inventaire des pages, l'inventaire des sections, le stockage média, les données CMS publiées, les jobs IA, la santé de publication et les raccourcis vers chaque surface de contenu disponible pour l'utilisateur courant.
Carte des surfaces
| Surface | Route | Objectif |
|---|---|---|
| Tableau de bord CMS | /dashboard/content | Vue opérationnelle et santé du contenu |
| Pages | /dashboard/content/pages | Composition de pages publiques et d'organisation |
| Sections | /dashboard/content/sections | Sections de page réutilisables et recettes générées |
| Modèles de données | /dashboard/content/data-models | Définitions typées de modèles CMS |
| Entrées de données | /dashboard/content/data | Contenu publié singleton et collection |
| Médias | /dashboard/content/media | Ressources binaires scopées par organisation et images générées |
| Composants | /dashboard/content/components | Registre de composants UI, aperçus et imports |
| Design tokens | /dashboard/content/design-tokens | Surcharges de tokens de thème publics au runtime |
| Modèles d'e-mails | /dashboard/content/email-templates | Modèles transactionnels React Email |
Pile de contenu
Le CMS est volontairement organisé en couches :
- Les modèles de données définissent les champs typés, les règles de localisation et la cardinalité.
- Les entrées de données publient des valeurs partagées, comme les menus d'en-tête, les menus de pied de page et les variables de site.
- Les ressources média fournissent des URL publiques durables pour les fichiers sélectionnés ou générés.
- Les composants définissent l'inventaire UI réutilisable et les moteurs de rendu de recettes.
- Les sections lient des littéraux, des données CMS ou des médias dans des unités de page réutilisables.
- Les pages composent des noeuds de mise en page, des références de composants et des références de sections publiées dans des routes publiques ou réservées aux membres d'organisation.
- Les design tokens modifient la présentation publique via les couches globales et organisation. Une page globale peut aussi porter une couche bornée de couleurs sémantiques et de rôles sans/serif dans sa révision.
- Les modèles d'e-mails transactionnels réutilisent les variables CMS quand cela convient, mais sont envoyés par le runtime e-mail, pas par le moteur de rendu des pages publiques.
Cette séparation garde le contenu réutilisable au même endroit. Les pages doivent référencer des sections et des entrées de données publiées au lieu de copier le JSON de menu, les promesses partagées, les images ou le contenu répété dans chaque document.
Flux d'édition
Une modification CMS typique suit ce parcours :
- Créer ou mettre à jour la source structurée dans les modèles de données, les entrées de données ou la médiathèque.
- Construire une section réutilisable quand le contenu doit apparaître sur plus d'une page.
- Composer la page dans l'éditeur Puck avec des noeuds de mise en page intégrés, des références de sections et des références directes de composants seulement si nécessaire.
- Publier la page ou la section une fois les diagnostics de validation propres.
- Vérifier la route publique ou réservée aux membres d'organisation.
La largeur de page et le rythme des sections appartiennent au layout sérialisé.
Un plan contextuel définit page.layout.bodyWidth,
page.layout.sectionGap et page.layout.sectionFrame. Ces valeurs pilotent le
container, l'espacement et le cadre partagé du PageStack racine.
sectionFrame: "token" conserve le wrapper public standard ; "none" laisse
les sections art-directed maîtriser leurs limites sans second cadre uniforme.
Une direction artistique isolée pour une page globale peut définir
page.designTokens sans modifier le registre global. À la création, l'omission
ou null hérite ; lors d'un rework, l'omission préserve la couche cible,
null la supprime et un payload la remplace. Le payload versionné accepte les
couleurs sémantiques clair/sombre et les rôles sans/serif chargés et approuvés.
Les tokens de layout ou d'effet, les polices mono, le CSS arbitraire, les URL et
les familles non enregistrées sont rejetés. La couche normalisée est liée par
hash à la révision et utilise le même wrapper dans l'aperçu immuable et le
runtime publié.
Les flux assistés par IA suivent le même modèle de persistance. Page AI promeut le contenu généré en sections réutilisables, la génération d'images Page AI persiste les médias via la médiathèque, et l'absence de publication d'une section produit un échec explicite au lieu d'un fallback inline.
Le design de page assisté par MCP suit le même modèle, mais le client Codex ou ChatGPT connecté porte le raisonnement créatif et la génération d'images. Yayaw n'appelle pas un second modèle texte côté serveur pour ce workflow. Le MCP fournit la guidance bornée, l'inventaire du CMS, l'ingestion durable des médias, la validation, la persistance des brouillons et les aperçus.
La guidance de design externe utilisée par ce flux est gérée comme un ensemble de dépendances avec checksums et licences conservées. Voir Dépendances de skills de design du CMS pour le workflow de mise à jour et de vérification.
Workflow MCP contextuel de design
Les nouvelles pages et les reworks utilisent un seul parcours obligatoire :
- Lire d'abord les couches de design tokens actives. Enregistrer toute
modification globale ou organisation approuvée avant de créer le contexte,
puis appeler
yayaw_cms_design_prepareavec la surface, le scope, les locales, l'audience, l'objectif, la direction visuelle, les faits, la stratégie média etvisualIntent. Quand cette intention manque, la préparation pose seule une première question localisée pour choisirnew_art_direction,evolve_existingoupreserve_existing. Les autres questions qui changent le résultat ne viennent qu'après cette réponse. Un appelant ne peut pas présélectionner lacompositionStrategytechnique sans cette intention. Le serveur dérive unecompositionStrategycompatible ; un appelant ne peut pas choisir une stratégie non créative pour contourner les prototypes. L'outil renvoie un contexte lié à l'acteur avec sonexpiresAt, une preuve d'inventaire, la guidance versionnée utile et jusqu'à trois questions qui changent réellement le résultat. Les médias de marque explicites sont résolus avant que le contexte soit prêt. Pour une page globale, un média appartenant à une organisation n'entre dans l'inventaire immuable que si l'acteur peut lister la médiathèque propriétaire et lire chaque média sélectionné ; les refreshs conservent ces références vérifiées. Une réponse prête commence au stage de guidancebrief, énumère les stages requis et indique explicitement si le workflow de prototypes exact-runtime version 2 est obligatoire. Pendant une longue pause,yayaw_cms_design_context_renewprolonge un contexte non expiré sans modifier ses preuves, dans une limite de deux heures depuis la création de la session. Un contexte expiré reste terminal. - Les clients MCP modernes répondent via l'élicitation par formulaire. Les
clients classiques reçoivent le même état
input_requiredet continuent avecyayaw_cms_design_resume; les deux chemins produisent le même contexte. Une fois le contexte prêt, chargerbrief,compositionetcritiqueviayayaw_cms_design_guidance_get, ainsi quereworkpour un rework. Les stages de guidance ne sont enregistrés comme chargés que lorsque leur contenu est effectivement renvoyé ; un chargement sans contenu ne débloque ni les prototypes ni le dry-run. Le serveur hash aussi le contenu exact de chaque stage et sa trace de sources. L'enregistrement des prototypes soumet des décisions structurées avec des IDs de directive. Les IDs soumis doivent couvrir exactement une fois toutes les directives renvoyées par chaque stage requis et chargé ; tout ID omis, dupliqué ou inventé est refusé. Le serveur possède la classification de chaque directive et son garde-fou d'implémentation ; le client ne peut donc pas abaisser une règle visuelle. Chaque directiveprototype_applicableporte un emplacement observé et validé pour chacun des trois candidats ; une directiveimplementation_onlynomme son garde-fou ultérieur imposé par le serveur. Une trace version 2 porte aussi leverificationCheckIddéterministe et optionnel possédé par le serveur pour les directives vérifiables plus tard. Le plan reconnaît exactement ce sous-ensemble d'implémentationserver_checked, vérifiable par le serveur, viaguidanceVerification: [{ directiveId }], sans pouvoir fournir de checker ni de chemin de preuve ; Yayaw exécute le contrôle et conserve le ledger immuable. Une directiveprocess_onlyn'a pas deverificationCheckId: elle reste contraignante par sa décision structurée lors de l'enregistrement et par la preuve de processus ou l'attestation normale de son garde-fou, mais elle n'entre ni dansguidanceVerificationni dans le ledger de preuve déterministe.not_applicablen'est disponible que lorsque le serveur l'autorise, exige une raison concrète liée au brief ou à la surface et reste plafonné par stage. - Le modèle client conçoit une structure commune à toutes les locales et fige
les entrées que les prototypes rendront. Il réutilise les données, médias,
composants et sections publiés avant de créer de nouvelles compositions. Les
textes, métadonnées SEO, textes alternatifs et faits sont localisés sans
modifier les IDs structurels. Si une modification large de tokens est
découverte seulement ici, abandonner le contexte, enregistrer la couche et
reprendre à l'étape 1 : un contexte existant ne peut pas être actualisé vers
un autre hash de tokens. Pour une direction propre à une page globale,
définir une couche
page.designTokensbornée par candidat, la placer dans sonpageShell, puis recopier exactement celle du candidat sélectionné dans le plan. Hors du scope d'une page globale, chaque candidat utilisedesignTokens: null. - Uploader ou importer tous les médias de récit et de recette avec le
designContextIdactif, terminer leur finalisation avecyayaw_media_upload_completeet ne conserver que des images finalisées avec MIME, dimensions et hash SHA-256. Exécuter ensuite l'uniqueyayaw_cms_design_inventory_refreshde présélection. Il ne peut qu'ajouter des médias de ce contexte sans modifier les baselines de catalogue, données, pages ou tokens. - Construire et inspecter trois planches statiques complètes, les uploader avec
le
designContextId, puis appeleryayaw_cms_prototypes_registeraveckind: "generated_set_v2". Un prototype utilisateur peut ancrer un candidat mais ne réduit jamais le jeu sous trois. Chaque planche mesure au moins 1200 × 900, montre les héros desktop/mobile et toutes les sections prévues, et utilise le même ensemble ordonné d'IDs/libellés de régions. Les candidats fournissent des preuves d'originalité distinctes, un manifeste de capacités non vide, les décisions de guidance et les comparaisons A/B, A/C et B/C. Chaque candidat exact passe aussi un seuil de richesse créative calculé :display_typographyetresponsive_recompositionsont tous deux requis ; au moins une signature structurelle parmilayered_composition,sticky_narrative,custom_grid_ratios,continuous_canvasetcompact_band; puis au moins un traitement de direction artistique parmiimage_art_direction,paper_collage,watercolor_wash,media_textureetdecorative_shapes. Un texte manuscritnoteseul n'infère paspaper_collage. Au moins une région signature doit inférer ensemble ces quatre dimensions ; répartir des primitives inertes entre des régions sans lien ne franchit pas le seuil. Une direction rejetée ou combinée impose un jeu de remplacement complet. Chaque région fournit son ledger de faisabilité exact : nœuds et chemins canoniques, props,recipePropSchema,recipePropNames,recipePropBindings, médias, responsive, thèmes, réduction de mouvement et fallback. Toute image utilise$props.<identifier>lié à unmedia_assetoulocalized_media_assetfinalisé de l'inventaire préparé. Chaque texte, lien, label, placeholder, texte alternatif ou message d'upload visible est un sink direct$props.<identifier>. Les textes sont des littéraux localisés exacts pour toutes les locales préparées ; les liens sont des cibles sûres et bornées. Les bindings global-data critiques ainsi querepeat/$item/$indexsont refusés ; les éléments répétés visibles sont développés en nœuds explicites. Les recettes exactes refusent aussi les combinaisons valides mais inertes : ancre hors overlay, props de grille desktop sur overlay absolu, canvas composé uniquement d'overlays qui s'effondre, ou hauteur d'image fixe combinée à des ratios responsive. La grille, les stacks directionnels, les placements et le sticky utilisent tous le breakpoint de recompositionmd.mobileSpan: "2"est refusé car la grille mobile de base ne possède qu'une colonne explicite. Une composition artisanale peut utiliser le traitementwashou lepigment-washplus intense et les matériaux de frame additifswatercolor-paper,deckle-paperoutaped-paper. Les valeurs historiqueswash,paper,deckleettapedconservent exactement leur rendu. L'overflow art-directed est explicite :section.overflowetframe.overflowacceptentclipouvisible. La valeur visible n'infèrecontinuous_canvasque si un placement descendant, une frame tournée ou scotchée, ou une grande décoration/wash peut réellement traverser la frontière. Les images acceptent des traitementsblendbornés (normal,multiply,screen,soft-light) etopacity(solid,soft,faint) ; les traitements de texture non standards infèrentmedia_texture. Les actions et submits exposent les apparencesbare,outline,paper,solidetunderline; les fields exposentbare,line,outlineetpaper; les uploads exposentbare,dashedetpaper. Le renderer créatif canonique conserve toutes les valeurs de props liées exactement et n'applique jamais la normalisation historique de démo catalogue après validation du manifeste de rendu.reuse_publishedpointe vers le composant publié exact ;new_recipene peut pas cloner une topologie déjà publiée et doit ensuite correspondre à une révision créée dans le même contexte. Yayaw exige trois signatures A/B/C distinctes de structure, d'implémentation et de rendu. LescompositionHashrégionaux ordonnés forment la signature structurelle du candidat. Le manifeste normalisé du page shell est épinglé séparément et doit correspondre exactement au candidat sélectionné dans le plan et le runtime ; il ne fait pas partie de la signature de distinction entre candidats. LesimplementationHashetrenderManifestHashrégionaux ordonnés forment les deux autres. Des changements de contenu, média, palette, défauts de schéma ou bindings ne transforment pas une topologie inchangée en direction séparée. - Chaque candidat fournit aussi un
pageShellexact (layoutet couchedesignTokensbornée ounull) ainsi que desartifactBoundsentiers pour chaque région. Une région mesure au moins 200 × 120 pixels et 2 % de la planche ; l'union des régions couvre au moins 40 % de la planche ; le chevauchement de deux régions ne dépasse pas 50 % de la plus petite. Le serveur fingerprint chaque crop et exige, pour chaque paire de candidats, qu'au moins une région correspondante soit matériellement distincte ; changer uniquement le chrome de la planche échoue. Le client fournit les arbres, schémas, bindings et bounds, mais jamais lescompositionHash,implementationHash,renderManifestHash, hashes depageShell,visualFingerprintouruntimeHash. Le serveur les calcule depuis les artefacts durables, le snapshot de tokens, les manifestes exacts, le ledger média finalisé, les locales, le renderer canonique et l'empreinte de déploiement. En production, cette résolution échoue de façon fermée sans fingerprint immuable fourni parNEXT_DEPLOYMENT_ID, legitCommitSharésolu tel queDEPLOYMENT_GIT_COMMIT_SHA, ou ledeploymentIdrésolu. Le fallback"local"n'existe que hors production. Le fingerprint et la version du contrat renderer entrent dansruntimeHash: un changement de build renderer change donc le hash et invalide la revue antérieure. - L'enregistrement renvoie, pour A, B et C, un
runtimeHash, des URLs signées de rendu canonique par locale et le contrat d'upload de preuve. Ouvrir ces aperçus, ou renouveler seulement leurs URLs expirées avecyayaw_cms_prototype_runtime_previews_getlorsque le runtime reste courant. Capturer chaque locale préparée en desktop/mobile et clair/sombre. Chaque capture pleine page est une image durable distincte avec lesdesignContextId,designPlanHashégal auruntimeHashcandidat, etvisualRolerenvoyés exactement. Le desktop fait au moins 1024 pixels de large et le mobile entre 240 et 767. Chaque image finalisée porte aussi une attestation de capture version 1 liée à son hash d'artefact, son hash de runtime, son scénario, la hauteur de document observée et les IDs de région ordonnés. Ces régions forment une partition verticale contiguë de0à la hauteur image/document, avec IDs uniques, bandes d'au moins 24 pixels, sans trou ni chevauchement. La hauteur de l'image égale la hauteur attestée et reste sous le maximum renvoyé. Les IDs et hashes de fichier sont distincts. Ces screenshots post-enregistrement sont interrogés directement par ID : ne pas actualiser l'inventaire pour eux. - Soumettre la matrice complète à
yayaw_cms_prototype_runtime_review_completeavecboardMatchesRuntime: true, les huit champs de fidélité àtrueet aucun blocage ni écart non approuvé.reviewerRole: "visual_qa"est un rôle logique lié à l'acteur courant, pas la preuve d'une autre personne ou d'un autre credential. La planche et le runtime canonique restent deux artefacts séparés comparés visuellement ; fingerprints, manifestes, hashes, provenance et bindings de capture détectent substitution, troncature, rejeu et dérive. Sans contexte de formulaire live, l'aperçu conserve exactement le layout et les contrôles du formulaire enregistré, mais rend son wrapper inerte et impossible à soumettre ; le contexte de formulaire ne modifie donc pas la composition revue. La comparaison serveur utilisecms-server-visual-comparison-v3: les bandes de référence et runtime sont normalisées par échantillonnage contenu 192 × 192 avec des seuils plus stricts de structure, topologie, aspect, contours, luminance et palette. La suppression d'un wash ou d'une texture signature échoue ainsi la fidélité. La frontière immuable courante est le contrat page7et le contrat prototype4. La frontière expliciteclient_observed_server_validatedne prétend pas prouver cryptographiquement que le client a réellement piloté un navigateur. - Une revue runtime courante est obligatoire avant
yayaw_cms_prototype_select. Les étapes ultérieures résolvent à nouveau le candidat et son ledger de captures. Une modification du renderer ou du déploiement, d'une recette, d'un média, d'une capture ou du snapshot de tokens rend la revue périmée. Remplacer et réenregistrer les trois candidats avant sélection. Un changement de design tokens après l'enregistrement v2 exige un nouveau contexte, trois prototypes et une nouvelle revue ; un refresh ne peut pas rebaser le gate. - Après une revue runtime courante, appeler
yayaw_cms_prototype_selectsans candidat. L'opération présente l'ordre canonique A/B/C, les preuves d'originalité comparées et des aperçus runtime frais. Les clients MCP modernes recueillent le choix enum par élicitation et l'enregistrent dans le même appel. Les clients classiques reçoivent la même présentationinput_required, puis reprennent avec sonchallengeIdborné et leprototypeIdchoisi. Exact-v2 refuse toutdecisionNoteécrit par le client : le reçu immuable généré côté serveur lie le challenge, la présentation, la revue runtime, la source de réponse et le choix. Le plan et la publication recalculent ce reçu et échouent si la preuve manque ou a été modifiée.resumable_clientreste une attestation du client liée à l'acteur, pas une preuve cryptographique d'un clic humain ; l'élicitation fournit une preuve d'interaction protocolaire plus forte, mais toujours médiée par le client. Copier ledesignBasisimmuable renvoyé. Importer, compiler et publier lesnew_reciperetenues avec le mêmedesignContextId. Finaliser aussi tous les médias supplémentaires que le plan liera, puis exécuter unyayaw_cms_design_inventory_refreshavec le même hash de tokens. Ce refresh conserve le gate v2, le reçu runtime, la sélection et la base tout en ajoutant les révisions publiées exactes et chaque asset lié. - Soumettre un plan strict
version: 2avecpage.layout, ledesignBasisrenvoyé et l'inventaire actualisé àyayaw_cms_page_designouyayaw_cms_page_rework, d'abord avecdryRun: true, puis persister le même plan hashé. Chaque section se mappe dans l'ordre à<prototypeId>#<regionId>, et tout composant déclaré nouveau est utilisé par sa révision publiée exacte à la racine de la composition. La page reproduit aussi exactement lepageShell.layoutet la valeurdesignTokensdu candidat sélectionné. Le dry-run revalide le prototype, le runtime-review receipt et les manifestes exacts avant d'émettre la preuve de design version 2. - Appeler
yayaw_cms_page_review, ouvrir chaque aperçu immuable et exécuter la matrice finale locales × desktop/mobile × clair/sombre, la réduction de mouvement et les contrôles par section. Un pass Visual QA explicite est requis avant l'upload des preuvesvisual-review:*. Une personne ou un agent séparé est préférable quand disponible, mais le rôle persistant ne prouve pas une identité indépendante. Soumettre ensuite les IDs durables àyayaw_cms_page_review_complete. Toute correction ou dépendance modifiée invalide le runtime, les captures et le reçu, et impose une nouvelle révision et une nouvelle revue. - La publication reste une opération séparée et explicite. Elle revalide le prototype sélectionné, la revue runtime v2, la preuve de design, le reçu de page et chaque ligne de capture avant l'avancement sérialisable du pointeur. Un reçu valide est une preuve nécessaire, pas une autorisation : publier seulement après une demande explicite de l'utilisateur.
Lors d'un déploiement progressif, les serveurs compatibles en lecture
comprennent les contextes legacy prototypeSet.kind: "generated_set" et le
champ séparé prototypeGateV2.kind: "generated_set_v2", et échouent de façon
fermée si les deux coexistent. Le champ séparé distingue les formats, mais ne
sécurise pas à lui seul une flotte mixte : une instance antérieure au reader
compatible peut encore opérer sur l'état legacy, l'écrire ou le sélectionner.
La production utilise donc deux switches d'écriture explicites et mutuellement
exclusifs. Déployer le build reader avec
CMS_LEGACY_PROTOTYPE_WRITES_ENABLED=true et
CMS_PROTOTYPE_RUNTIME_V2_WRITES_ENABLED=false, drainer toutes les instances
antérieures et faire de ce build le rollback floor. Configurer et vérifier les
uploads privés via staging. Par défaut, les grants opaques passent par le proxy
applicatif same-origin et gardent S3_ENDPOINT interne. Ne configurez
S3_SIGNED_PUBLIC_ENDPOINT que si l'hébergeur applicatif ne peut pas streamer
le contrat média de 250 Mo ; ce doit être une origine d'API S3 HTTPS publique
sûre et seuls les uploads basculent en direct. Les deux transports utilisent
des PUT conditionnels sans écrasement. L'objet de staging vérifié reste privé
pendant l'expiration du grant et une stabilisation de 24 heures pour bloquer les
rejeux inter-instances. Le reaper répète la suppression pendant cette fenêtre
et ne marque le nettoyage terminé qu'après le DELETE final. Passer ensuite les
deux switches à false, redémarrer
et drainer les writers legacy. Activer ensuite la v2 seule : legacy false, v2
true. Les deux à true échouent de façon fermée. Pour chaque déploiement
progressif ultérieur du renderer, utiliser le même protocole manuel de
confiance : geler et prouver toutes les ressources typées sur un SHA complet,
émettre ou reprendre explicitement son reçu immuable, revérifier le drain live,
passer à activating, déployer et revérifier exact, puis consommer le reçu. Une
exécution activating en échec revient seulement à freeze et reprend la même
opération avec une preuve fraîche. Si la flotte a déjà avancé vers un
descendant strict de main, l'opérateur fournit explicitement l'ancienne
opération et son SHA ; le workflow prouve le descendant gelé, active
atomiquement son reçu de remplacement et marque l'ancien reçu terminal
superseded. Cette récupération ne fait jamais avancer le runtime floor. Le
déploiement automatique normal de
production reste réservé au reader. Le déploiement de PR development peut
préserver un freeze déjà configuré et prouvé live, mais il ne peut initier ni
freeze ni exact. Après le nouveau SHA immuable de PR, il prouve que chaque
conteneur app/worker live conserve ce SHA et freeze avant l'activation exacte
manuelle. La production refuse les écritures v2 sans staging privé ni identifiant
d'opération de rollout valide. Le premier gate exact exige le reçu consommé
correspondant et lie définitivement cette opération au runtime floor de base
de données. Dès qu'un contexte v2 existe, ne jamais rollback sous ce floor ni
réactiver les écritures legacy. Les contextes legacy existants restent
lisibles et annulables, mais ne peuvent plus être renouvelés, sélectionnés,
planifiés, persistés, revus ou publiés. Tout asset issu d'un grant d'upload
direct legacy doit être réuploadé via le staging privé avant de servir de
prototype exact ou de preuve de revue. Un writer v2 désactivé renvoie
cms_design_prototype_runtime_rollout_pending ; réessayer la v2 une fois le
floor établi et le flag activé. En local et dans les autres
environnements hors production, les écritures v2 sont activées par défaut
lorsque la variable est absente.
La garantie de preuve exacte est ponctuelle et va jusqu'à la publication. Une
évolution comportementale ultérieure du renderer ne recapture pas
automatiquement les pages déjà publiées. Tant que le déploiement ne sait pas
inventorier les contrats publiés et fournir soit un rendu versionné
rétrocompatible, soit une migration avec nouvelle revue visuelle avant
promotion, toute évolution comportementale du renderer de page ou de prototype
bloque la release. Les versions partagées de cms-renderer-contract.ts doivent
être revues et incrémentées explicitement ; ce bump trace la frontière mais ne
rend pas sûr un déploiement qui ne l'est pas.
La boucle de blocage est exacte : dry-run et persistance d'une révision
immuable, obtention de review_ready, puis Visual QA sur cette
révision et ce runtime. Si les diagnostics statiques/runtime échouent, ou si le
Visual QA détecte un scénario ou champ de fidélité en échec, un problème
bloquant ou un écart non approuvé, il ne faut ni uploader de preuve
visual-review:*, ni terminer la revue, ni publier. Le même plan contextuel est
corrigé, une nouvelle révision immuable est persistée et la boucle reprend au
dry-run. Seul un PASS sans problème bloquant ni écart autorise
l'upload des preuves et la complétion de la revue. Toute correction ou
modification de dépendance ultérieure invalide ce pass et le reçu, puis relance
la boucle.
Orchestration des rôles client et garde-fou visuel
Pour creative_rework, design_system_extension ou un prototype approuvé, les
clients qui prennent en charge la délégation parallélisent les lectures bornées
tout en conservant un seul writer MCP :
- le Creative Director verrouille le design read, le récit, le contrat de sections, les intentions média/tokens, le mouvement et le niveau de détail, puis produit les trois planches composites et leur trace de guidance
- l'Implementer possède toutes les mutations catalogue/page, les actualisations d'inventaire, les dry-runs, le hash du plan et la persistance du brouillon
- un rôle Visual QA examine les trois candidats avant sélection puis
l'aperçu immuable après implémentation, sans mutation ; il rend un
PASSexplicite lié à la révision/runtime exacts après le premier brouillon immuable et après chaque correction immuable - un Technical QA peut vérifier en parallèle le responsive, les thèmes, la réduction de mouvement, l'accessibilité, le chargement média et les erreurs runtime
Les agents transmettent un ledger compact contenant le profil et la trace de
guidance, tous les IDs de prototypes et références d'artefacts, l'ID
sélectionné, le designBasis exact, designContextId, inventoryHash, les
révisions exactes des composants/sections, pageId, la révision de page,
planHash et runtimeHash. Le Visual QA relit le même profil complet au lieu
de se fier à un résumé amont. Après publication du catalogue,
yayaw_cms_design_inventory_refresh actualise l'inventaire du même contexte
sans perdre le jeu de prototypes, la sélection ni la base. Après chaque
correction, la nouvelle révision immuable est revue depuis zéro. Sans
délégation, le client peut suivre la préparation et l'implémentation
séquentiellement, mais un workflow créatif fondé sur un prototype ne peut ni
uploader ses preuves de revue ni publier sans le pass du Visual QA. Ce rôle est
un garde-fou qualité, pas une frontière d'identité authentifiée séparément.
Les références de preuve des scénarios et du mode mouvement réduit sont des IDs d'assets média durables. Chacune porte l'attestation pleine page version 1 renvoyée, avec runtime, scénario, hauteur de document et bandes de sections contiguës exacts. Leur kind image, contexte de design, hash de plan, octets statiques, dimensions de viewport, rôles et attestation sont vérifiés côté serveur et conservés dans le ledger du reçu. La publication retélécharge et réinspecte ce ledger ainsi que les preuves prototype source/runtime ; toute capture supprimée, modifiée, animée, tronquée, rejouée, reclassifiée ou provenant d'un autre contexte rend la revue périmée.
Les stratégies de composition sont explicites et ne peuvent pas être dégradées silencieusement :
content_onlyinterdit les nouvelles sections de composition.compose_existingautorise intentionnellement l'assemblage du catalogue.creative_reworkexige au moins trois nouvelles compositions, un hero et une section narrative nouvellement composés, avec au plus 50 % de sections réutilisées.design_system_extensionajoute les mêmes garde-fous et exige au moins une recette composant source-backed importée, compilée, publiée et présente dans l'inventaire actualisé du même contexte, puis réellement utilisée par révision exacte dans une nouvelle composition. Utiliser une recette déclarativecreative-compositionpour les layouts imbriqués, médias, actions et structures répétées explicitement développées. Un import source résolu vers le fallback génériquecompositene satisfait pas ce garde-fou.
Les stratégies créatives imposent aussi une auto-critique bloquante : la page
doit rester reconnaissable sans son logo, raconter une histoire cohérente,
inclure une interaction ou une composition originale et ne pas devenir une
simple checklist de fonctionnalités. Si l'orchestration échoue, le client doit
corriger le plan structuré ou s'arrêter ; il ne peut pas basculer vers
compose_existing sans préparer un nouveau brief.
yayaw_cms_page_design n'accepte que le plan contextuel multilingue. Les outils
directs yayaw_pages_create_draft et yayaw_pages_save_draft sont des bypass
de maintenance bas niveau audités, réservés à control-plane:admin et
désactivés sauf si CMS_LOW_LEVEL_PAGE_ADMIN_BYPASS_ENABLED=true. L'outil de compatibilité
obsolète yayaw_cms_page_design_legacy_admin est aussi réservé aux admins et
reste désactivé sauf si
CMS_LEGACY_PAGE_DESIGN_ADMIN_BYPASS_ENABLED=true; il ne sert qu'à une courte
migration ou à une réponse d'incident.
Les URLs d'aperçu sont des identifiants bearer. Elles expirent rapidement,
résolvent une révision immuable, contournent les caches publics et l'analytics,
utilisent noindex/nofollow et sont bloquées sur les domaines personnalisés
d'organisation. En production, configurer CMS_PREVIEW_SIGNING_SECRET avec un
secret serveur dédié à forte entropie ; BETTER_AUTH_SECRET sert de repli.
Résolution au runtime
Le contenu publié se résout depuis des révisions immuables et des lignes de publication :
- les pages chargent
ui_page_publicationset rendent lePuckPageDocumentV1publié - les références de sections se résolvent via
ui_section_publications - les bindings littéraux de composants et sections acceptent directement des
valeurs JSON bornées, y compris tableaux, objets imbriqués et
null; les contratsvalueShaperécursifs valident les champs imbriqués tout en gardant les anciennes chaînes JSON lisibles - les bindings de données résolvent les entrées de données CMS globales ou d'organisation publiées
- les bindings média utilisent l'URL publique stockée dans
media_assets - les design tokens publics se résolvent depuis les payloads globaux/organisation, puis une couche de révision optionnelle s'applique dans le wrapper d'une page globale
- les e-mails transactionnels chargent le modèle actif en base pour la locale demandée avant de retomber sur les valeurs par défaut des composants
Les pages publiques globales alimentent /sitemap.xml et les métadonnées SEO
publiques. Les pages membres d'organisation exigent une adhésion et émettent des
métadonnées noindex même quand des champs SEO existent au niveau de la page.
Localisation
Les documents CMS utilisent les locales applicatives configurées dans
src/config/i18n.config.ts. Les locales actuelles sont l'anglais et le
français.
Le contenu localisé apparaît dans :
- le texte des pages et les champs SEO
- les valeurs d'entrées de données globales et d'organisation
- les entrées de menus d'en-tête et de pied de page
- les valeurs de recettes de sections générées
- les objets, textes d'aperçu, HTML de corps et exports texte des e-mails transactionnels
Les bindings de sections de page générées sont stockés comme texte d'objet JSON
dans le document Puck (propsBindingsJson, apiBindingsJson,
harnessBindingsJson et champs de binding associés). Les valeurs contenues dans
ces objets sont de vraies valeurs JSON et ne doivent pas être stringifiées
individuellement. La validation applique des limites récursives, bloque les clés
d'objet dangereuses, vérifie les valueShape imbriqués et refuse les sections
générées sans binding variant valide.
Les docs anglaises sont canoniques. Du contenu français peut exister dans le produit, mais la nouvelle documentation technique doit d'abord mettre à jour l'anglais.
Autorisation
Le CMS utilise le modèle d'autorisation par groupes et rôles de Yayaw. La navigation du dashboard n'est qu'un indice ; les loaders serveur, actions, services et opérations MCP doivent encore autoriser chaque lecture ou mutation.
Ressources CMS courantes :
pagesectionsglobal-datamediacomponentsglobal-variablesemail-template
Les membres d'organisation reçoivent normalement l'accès list/read au contenu scopé par organisation. Les managers, admins, owners et superadmins reçoivent l'accès de gestion selon leurs bindings de rôles de groupe.
Plan de contrôle (control plane)
Les workflows CMS opérationnels doivent partager la logique de service entre le dashboard, MCP, les scripts CLI et les tests quand ils sont exposés hors de l'interface.
La couverture actuelle du plan de contrôle (control plane) inclut :
- opérations de pages
- opérations de données CMS
- opérations de modèles d'e-mails transactionnels
- opérations de catalogue de facturation utilisées par les variables CMS
Quand vous ajoutez une fonctionnalité CMS, décidez si les clients MCP de
confiance doivent pouvoir l'opérer. Si oui, ajoutez des schémas typés, un
reason pour les écritures, des enregistrements d'audit, des contrôles
d'autorisation et des mises à jour de documentation. Si non, documentez pourquoi
la fonctionnalité est volontairement limitée au dashboard.
Règles opérationnelles
- Stocker le contenu réutilisable comme données, médias, sections ou modèles publiés.
- Garder les documents de page comme documents de composition, pas comme stores de contenu dupliqué.
- Ne pas exécuter de code de composant stocké en base.
- Ne pas stocker les binaires média dans Postgres.
- Garder les design tokens publics scopés hors des routes dashboard et auth.
- Scoper explicitement les données CMS globales et les données CMS d'organisation.
- Revalider les chemins dashboard et runtime publics affectés après publication/archivage.
- Traiter les fichiers assistants générés comme des artefacts dérivés ; mettre
d'abord à jour
content/llm/llm-source.md, puis les régénérer.
Validation
Vérifications utiles après des changements de documentation ou de comportement CMS :
bun run docs:generate
bun run docs:check-links
bun run docs:check-translations
bun run docs:llm:generate
bun run docs:llm:check
bun run check
bunx tsc --noEmitExécuter les tests de domaine au besoin quand des changements d'implémentation touchent les pages, sections, modèles de données, médias, composants, tokens ou modèles d'e-mails.
La validation contextuelle bloque les bases prototype/page existante
incohérentes, les layouts absents, un composant ancien ou étranger déclaré
comme nouveau, les décisions de composant dupliquées et
created_component_not_used. La revue prototype bloque un artefact substitué,
une région inventée, dupliquée ou non couverte, un contrôle de fidélité absent
ou tout unapprovedDeviations.