Workflows
Les échecs qui répondent 200
Comment repérer et éviter les échecs de l'API workflow qui ne renvoient jamais d'erreur : contenu assaini, clés de placement supprimées, surcharges de thème figées, et polices remplacées silencieusement.
La majeure partie de cette API refuse ce qu'elle ne peut pas faire.
Une poignée d'écritures, à l'inverse, acceptent la requête, font
discrètement moins que ce qui a été demandé, et répondent 200 ou 201
comme si de rien n'était. Aucune de ces situations n'est un bug (chacune
est un choix délibéré et documenté), mais chacune ne peut être repérée
qu'en relisant un champ précis, jamais en lisant le code de statut.
Les workflows sont en bêta privée, disponible sur demande à [email protected] ; voir Workflows.
Repérez votre symptôme
| Symptôme | Cause | Où ça apparaît |
|---|---|---|
| Le contenu écrit disparaît après rechargement | L'assainisseur le retire à l'enregistrement | sanitisation/stored de validate, removed_tags/removed_attributes |
| Le libellé d'un placement n'apparaît jamais | Clé de placement mal orthographiée | Rien (la clé a disparu de la section enregistrée) |
| Un token affiche son nom de variable, pas sa valeur | Token <variable> inerte | inert_tokens dans sanitisation/stored |
| Une image s'affiche comme un cadre vide | Image citée par une URL externe | unreachable_images dans sanitisation/stored |
| Un paragraphe devient deux ou trois dans la sortie | Élément de bloc éjecté d'un <p> | ejected_from_paragraph de sanitisation |
| Une règle CSS posée n'a aucun effet visible | Déclaration supprimée de style | removed_css_declarations dans sanitisation/stored |
| Un en-tête ou pied de page perd ses premières lignes | Bande tronquée à la marge | clipped_bands de stored, validate seulement |
| Modifier le thème ne change plus une section | Valeur en ligne figée face au thème | Rien (relire le contenu propre de la section) |
| PATCH | Valeur non interprétable abandonnée | Relire le thème après l'avoir écrit |
| Le texte s'affiche dans une graisse inattendue | Aucune famille ne porte cette graisse | workflow_selfcheck seulement (MCP), pas un champ REST |
1. Le contenu est assaini à l'enregistrement
Vous écrivez : un fragment de contenu riche ou de titre courant
contenant une balise <script>, un attribut onclick, ou toute autre
chose hors de la liste blanche de l'assainisseur.
Ce qui se passe : le POST/PATCH sur la section répond 200/201
avec le fragment déjà retiré. La balise ou l'attribut interdit a disparu
de ce qui est enregistré ; rien dans la réponse ne le signale.
Comment le repérer : simulez le fragment exact via
POST .../validate avec content: ["<fragment>"] avant de
l'enregistrer. Voir Valider. Les
endpoints de création/mise à jour de section eux-mêmes ne donnent aucun
signal dans un sens ou dans l'autre.
Comment l'éviter : traitez sanitisation.clean de validate comme le
portail avant toute écriture qui porte du HTML nouveau, pas le code de
statut de l'endpoint de section.
2. Une clé de placement mal orthographiée est supprimée
Vous écrivez : un objet de placement sur une section
image_with_variable avec une clé qui n'est pas exactement l'une de
id, kind, variable, value, x, y, width, height, align, font_size, color, font_family, font_weight.
Ce qui se passe : la clé inconnue est retirée silencieusement.
L'écriture répond quand même 200/201 ; le libellé ne s'affiche
simplement jamais à la position qu'il aurait dû occuper.
Comment le repérer : rien ne le signale après coup. La clé a disparu,
pas été signalée. Comparez ce que vous envoyez avec
capabilities.placement.keys_by_kind/.keys avant de l'envoyer.
Comment l'éviter : orthographiez les clés de placement exactement
comme les liste l'endpoint capabilities en direct ; ne codez jamais en
dur une liste mémorisée.
3. Un token inerte affiche son propre nom
Vous écrivez : un élément <variable> avec la bonne balise mais sans
la classe editor-parsed (ou toute autre classe que requiert
capabilities.content.tokens).
Ce qui se passe : il survit à l'assainissement et passe le contrôle
d'intégrité (ce n'est pas un broken_reference), mais au moment du rendu
il affiche son propre nom de variable au lieu de sa valeur.
Comment le repérer : sanitisation/stored de validate le signalent
comme inert_tokens. Rien d'autre dans l'API ne le signale.
Comment l'éviter : écrivez toujours le HTML de token exact que donne
capabilities.content.tokens pour le type de champ, par exemple pour un
texte : <variable class="editor-text-variable non-editable-content editor-parsed">field_name</variable>.
4. Une image externe affiche un cadre vide
Vous écrivez : un <img> citant une URL absolue ou externe au lieu
d'une URL renvoyée par POST .../images ou .../background.
Ce qui se passe : le moteur de rendu n'émet aucune requête réseau en produisant le PDF, donc l'image s'affiche comme rien : un cadre vide, pas une erreur.
Comment le repérer : sanitisation/stored de validate le
signalent comme unreachable_images.
Comment l'éviter : importez chaque image via les endpoints images ou arrière-plan d'abord, et citez uniquement le token/l'URL qu'ils renvoient.
5. Un élément de bloc est éjecté d'un paragraphe
Vous écrivez : un div, un table, ou un autre <p> imbriqué dans
un <p>.
Ce qui se passe : l'analyseur HTML5 le déplace hors du paragraphe, le scindant en jusqu'à trois éléments frères. Rien n'est retiré, donc même un comptage de balises avant/après reste propre en apparence.
Comment le repérer : sanitisation de validate le signale comme
ejected_from_paragraph.
Comment l'éviter : n'imbriquez jamais un élément de niveau bloc dans un paragraphe.
6. Une déclaration CSS est supprimée de style
Vous écrivez : un attribut style="..." où une déclaration n'est pas
sur la liste des propriétés autorisées par l'assainisseur.
Ce qui se passe : l'attribut lui-même survit (donc
removed_attributes reste vide), mais cette déclaration précise à
l'intérieur est retirée. Le fragment « paraît propre » au seul comptage
des attributs.
Comment le repérer : sanitisation/stored de validate le
signalent séparément, comme removed_css_declarations.
Comment l'éviter : vérifiez removed_css_declarations spécifiquement
; ne déduisez pas la sécurité du seul fait que removed_attributes est
vide.
7. Une bande de titre courant est tronquée
Vous écrivez : une bande d'en-tête ou de pied de page dont le contenu rendu est plus long que la marge réservée sur ce côté.
Ce qui se passe : le moteur de rendu la tronque sans erreur nulle part. Il tronque depuis les lignes du début, pas depuis la fin.
Comment le repérer : seul stored.clipped_bands de validate, avec
un nombre de lignes estimé. L'aperçu en simulation de sanitisation ne
vérifie pas la longueur du tout ; ceci n'apparaît qu'une fois la bande
réellement enregistrée.
Comment l'éviter : gardez les bandes assez courtes pour les marges de
la page ; vérifiez stored.clipped_bands après tout changement à un
en-tête/pied de page ou aux marges de la page elles-mêmes.
8. Une valeur en ligne se fige par rapport au thème
Vous écrivez : une propriété de thème directement sur une section, avec une valeur qui correspond déjà à ce que le thème du modèle déclare actuellement pour ce type de bloc.
Ce qui se passe : le rendu est identique aujourd'hui. La section arrête de suivre le thème à partir de ce moment. Une modification ultérieure du thème (une nouvelle police, une nouvelle taille) n'atteindra plus cette section, parce qu'elle porte désormais sa propre valeur figée.
Comment le repérer : rien ne le signale : aucune anomalie, aucun
champ stored. C'est une discipline de modélisation, pas une règle
vérifiée.
Comment l'éviter : réglez le thème du document d'abord, avant d'écrire le contenu des sections, et ne déclarez une propriété en ligne que lorsque vous voulez délibérément surcharger le thème pour cette seule section.
9. Une écriture de thème non interprétable est abandonnée
Vous écrivez : PATCH .../theme avec une valeur qui ne s'interprète
pas selon les règles de cette propriété : une famille de police que le
moteur de rendu ne provisionne pas, un line_height portant une unité
(par exemple "1.45em"), un font_size dans une unité autre que pt,
une taille ou un interlignage hors de ses bornes, un color non
hexadécimal, un bloc ou une propriété inconnus, ou n'importe quel
font_weight (délibérément jamais une propriété modifiable).
Ce qui se passe : la valeur fautive est abandonnée (propriété par
propriété, pas requête par requête), et l'écriture répond quand même
200. Un nom de famille connu qui se résout vers un autre est en
revanche réécrit silencieusement (par exemple "Arial" est enregistré
sous son substitut métrique, "Liberation Sans").
Comment le repérer : la réponse est toujours le thème enregistré et renormalisé, relu après l'écriture, jamais un écho de ce que vous avez envoyé. Lire cette réponse est le seul moyen de voir un abandon se produire.
Comment l'éviter : après chaque PATCH .../theme, comparez la
réponse à ce que vous avez envoyé, propriété par propriété, plutôt que de
faire confiance au 200.
| Valeur | Bornes/unité |
|---|---|
| font_size | 6-96, unité pt |
| line_height | 1.0-2.5, sans unité |
| color | hex 3 ou 6 chiffres |
| font_weight | jamais une propriété modifiable, toujours abandonnée |
Un cas corrigé, pour information
Un payload dont les conditions excluaient toutes les sections, ou n'en
laissait subsister que celles qui ne rendaient aucun contenu visible,
était autrefois
livré comme un document vide avec un statut de succès. Ceci est corrigé :
les deux cas sont aujourd'hui refusés avec un 422
(excluded_sections/printing_nothing) sur
POST /api/v1/document_requests. Voir
Modèles workflow. Ce point n'est
listé ici que parce qu'un code d'intégration ancien, ou une documentation
ancienne, pourrait encore supposer ce comportement de page blanche ; rien
à ce sujet n'est un piège actif.
10. Une graisse qu'aucune famille ne porte
Vous écrivez : une graisse dans le contenu ou dans le thème qu'aucune famille de police provisionnée ne porte réellement.
Ce qui se passe : aucune écriture ne la refuse. Le moteur de rendu arrondit ou synthétise la graisse la plus proche qu'il possède et l'affiche à la place : une épaisseur que personne n'a demandée.
Comment le repérer : validate ne le vérifie pas. Seule la couche
MCP, via workflow_selfcheck, le révèle, comme
weights_no_family_carries, calculé à partir de stored.typography
contre capabilities.authoring.fonts.
Comment l'éviter : choisissez les graisses parmi les familles
déclarées de capabilities.authoring.fonts, pas parmi ce qu'un menu
d'éditeur propose par hasard.