Analyse de contenu — détails techniques
À 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.
| Moteur | Rôle | Remonté sous |
|---|---|---|
| LanguageTool | Orthographe et grammaire | languagetool |
| Classifieur de toxicité (Detoxify) | Verdict safe et scores par catégorie | moderation |
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.
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 dashboard | Route du service |
|---|---|
GET /api/content-analysis | GET /health |
GET / PUT /api/content-analysis/config | GET / PUT /config |
POST /api/content-analysis/analyze | POST /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
| Appel | Délai maximal |
|---|---|
| État du service, lecture/écriture de la politique | 4 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 moteurs | en place |
| Panneau d'administration (politique, test, temps de réponse) | en place |
| Extension Tiptap de soulignement | en place |
Hook useContentAnalysis | en 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 dechecksdans 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), sanschecks. 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 attendues | fiche fonctionnelle |
| 🧪 Tests réalisés | aucun test e2e à ce jour |
| ✅ Tests de conformité | tableau de conformité |
Voir aussi
- Antivirus — détails techniques — l'autre contrôle branché sur les contenus déposés, côté fichier et non côté texte.
- Modération des signalements — le traitement après publication, que l'analyse automatique ne remplace pas.