Skip to main content

Analyse de contenu — détails techniques

Fiche fonctionnelle

À quoi sert l'analyse de contenu, ce que chaque vérification produit, les modes de déclenchement et les réglages d'administration : Analyse de contenu.

Positionnement

Un service dédié, content-analysis-api, déployé par son propre chart Helm. C'est un orchestrateur : il ne classe rien lui-même, il appelle deux moteurs et assemble le résultat.

MoteurRôleRemonté sous
LanguageToolOrthographe et grammairelanguagetool
Classifieur de toxicité (Detoxify)Verdict safe et scores par catégoriemoderation

Les deux sont indépendants : l'un peut être hors ligne pendant que l'autre répond. L'analyse correspondante est alors absente du résultat, et le moteur manquant est nommé dans unavailable plutôt que silencieusement omis.

C'est le service qui détient la politique (GET / PUT /config), pas ent-core.yaml : d'où le fait qu'un changement de réglage prenne effet sans redémarrage, et que la politique soit la même pour tous les modules.

Où l'analyse s'insère

L'éditeur n'appelle jamais le service directement : il passe par le module qui l'héberge, qui relaie. C'est ce qui permet de conserver la session et les droits de l'utilisateur, et de ne pas exposer le service.

Éditeur de texte enrichi (Tiptap)

├─ au chargement : GET <module>/content-analysis/config
│ └─ { enabled, moderationAction, checks } ← la politique, pas codée en dur

├─ pendant la frappe (vérifications "live", après 1,5 s d'inactivité)
│ et systématiquement juste avant l'envoi (toutes vérifications activées)
│ POST <module>/content-analysis/analyze { text, checks, language: "fr" }
│ └─ { enabled, corrections?, moderation? }
│ ├─ corrections → soulignement dans l'éditeur
│ └─ moderation → avertissement ou blocage, selon moderationAction

└─ envoi du contenu par le module

Un éditeur auquel on ne passe pas contentAnalysisEndpoints n'émet aucun appel réseau : la fonctionnalité est simplement absente pour lui, sans réglage à poser.

Le POST porte le jeton anti-CSRF entcore (X-XSRF-TOKEN), comme tout POST authentifié.

Ce que le mode de déclenchement engage vraiment

triggerMode est une indication rendue à l'éditeur : le service ne filtre rien dessus. Ce qu'il fait respecter, c'est checks[].enabled — une vérification décochée n'est pas exécutée même si l'éditeur la demande explicitement.

Côté client, analyzeNow() sans argument couvre toutes les vérifications activées, live comme on-demand : c'est cette forme que le module consommateur doit appeler avant de soumettre, sinon une vérification réglée « à la demande » serait sautée au moment qui compte. analyzeOnDemand() ne couvre que les on-demand.

Replacement des corrections dans le document

Les offset / length renvoyés portent sur un texte à plat construit par buildTextIndex(doc), pas sur editor.getText(). Le texte envoyé à l'analyse et l'index servant à replacer les résultats viennent donc de la même fonction : les soulignements tombent au bon endroit quelle que soit la structure du document (titres, listes, tableaux) et quel que soit le séparateur de bloc choisi par Tiptap.

L'extension Tiptap est purement visuelle — elle n'émet aucun appel réseau et se contente d'exposer deux commandes (setContentAnalysisCorrections, clearContentAnalysisCorrections) pilotées par le hook.

Décalage transitoire en mode « live »

Si le document change pendant qu'une analyse est en cours, les corrections reçues sont appliquées au document tel qu'il est à leur arrivée, pas à celui qui a été analysé. Un léger décalage est donc possible pendant une frappe rapide ; il se corrige de lui-même à l'analyse suivante.

Raccordement

Deux raccordements distincts, parce que deux appelants différents.

La console d'administration, pour piloter la politique — variable d'environnement du dashboard :

CONTENT_ANALYSIS_INTERNAL_URL=http://content-analysis-api:8020

Les routes /api/content-analysis/* du dashboard relaient vers le service. Elles sont réservées au super-administrateur, contrôle fait côté serveur et pas seulement par le garde de la page : ces routes changent la politique appliquée à tous les éditeurs de la plateforme.

Route du dashboardRoute du service
GET /api/content-analysisGET /health
GET / PUT /api/content-analysis/configGET / PUT /config
POST /api/content-analysis/analyzePOST /api/content/analyze

Les modules, pour l'analyse elle-même — bloc content-analysis du module dans ent-core.yaml :

content-analysis:
api-url: ${CONTENT_ANALYSIS_API_URL}

Seul le raccordement est ici : ni le mode de déclenchement, ni le comportement de modération ne se règlent dans ent-core.yaml.

Délais

AppelDélai maximal
État du service, lecture/écriture de la politique4 s
Analyse d'un texte (test admin)20 s

Le délai court sur la configuration est délibéré : un service mal configuré ou déployé sur le mauvais cluster ne doit pas faire traîner la requête assez longtemps pour déclencher un délai d'attente d'ingress en amont — cas déjà constaté en production. Le délai long sur l'analyse l'est tout autant : une vraie analyse à froid, le temps que le modèle de classification se charge, dépasse largement le budget d'une lecture de configuration.

Le chronomètre du panneau d'administration mesure l'aller-retour complet côté navigateur, pas le temps de calcul du moteur : le trajet réseau et le relais du dashboard y sont inclus. C'est volontaire — c'est l'attente réelle d'un utilisateur dans l'éditeur. Pour un temps par moteur au sens strict, il faudrait que content-analysis-api renvoie ses propres durées dans la réponse ; ce n'est pas le cas aujourd'hui.

Comportement en cas de panne

Un service injoignable ne bloque jamais la saisie ni l'envoi : le hook retombe sur { enabled: false } et l'éditeur se comporte comme si la fonctionnalité était absente. Une panne du service d'analyse ne doit pas empêcher un enseignant d'écrire aux familles. Le même raisonnement que failOnError côté antivirus, avec le choix inverse assumé : ici il n'y a rien à protéger en refusant.

La console d'administration, elle, affiche franchement « Hors ligne » et le service renvoie un 503 explicite plutôt qu'un échec muet.

Le blocage est appliqué côté client

moderationAction est rendu au client avec le résultat d'analyse ; c'est le module consommateur qui décide d'avertir ou de refuser l'envoi. Le service ne refuse rien lui-même, et rien n'est vérifié à l'enregistrement côté serveur.

C'est donc une barrière d'usage, pas un contrôle d'intégrité : efficace contre le message écrit sous le coup de la colère, sans prétention à résister à un contournement délibéré. Un contrôle réellement opposable supposerait de rejouer l'analyse dans le module au moment de l'écriture — non fait.

État de l'implémentation

ÉlémentÉtat
Service content-analysis-api + ses deux moteursen place
Panneau d'administration (politique, test, temps de réponse)en place
Extension Tiptap de soulignementen place
Hook useContentAnalysisen place
Raccordement d'un module consommateurà faire — le carnet de liaison est le premier visé

Deux points d'attention pour qui reprend le sujet :

  • Deux implémentations du hook coexistent. Celle du framework patché (libs/openent-frontend-framework) porte le contrat de référence : un mode par vérification (live / on-demand) et l'envoi de checks dans la requête. Celle du dépôt applicatif (frontend/libs/react-editor) est restée au contrat précédent — un mode global (on-publish / live), sans checks. Le panneau d'administration expose le contrat de référence : tant que la seconde n'est pas alignée, les modes par vérification qu'on y règle ne sont pas honorés par les éditeurs qui en dépendent.
  • Le mode « à la demande » n'a pas d'affordance dans l'éditeur. analyzeOnDemand() existe et attend un bouton « Vérifier » dans la barre d'outils, qui n'est pas encore là. Réglée ainsi, une vérification ne part donc aujourd'hui qu'au moment de l'envoi.
  • Le soulignement n'est pas stylé. L'extension pose la classe content-analysis-issue (déclinée par type de correction), mais aucune feuille de style du framework ne la définit : c'est au thème de le faire, sans quoi les corrections sont calculées sans être visibles.

Couverture de tests

Aucun test e2e à ce jour, ni sur le panneau d'administration, ni sur le raccordement des éditeurs.

Conformité

Maillon de la chaîne qualitéRéférence
🎯 Fonctionnalités attenduesfiche fonctionnelle
🧪 Tests réalisésaucun test e2e à ce jour
✅ Tests de conformitétableau de conformité

Voir aussi