From a8c4012aac9d8f42652a645bb44556a0d579c33f Mon Sep 17 00:00:00 2001 From: Pierre Martin Date: Fri, 17 Jul 2026 20:06:19 +0200 Subject: [PATCH] docs: capitalize the mairie publication check solution (T2) Co-Authored-By: Claude Opus 4.8 --- ...ion-sur-l-agenda-mairie-l-e6h6-solution.md | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 docs/solutions/2026-07-17-verifier-la-publication-sur-l-agenda-mairie-l-e6h6-solution.md diff --git a/docs/solutions/2026-07-17-verifier-la-publication-sur-l-agenda-mairie-l-e6h6-solution.md b/docs/solutions/2026-07-17-verifier-la-publication-sur-l-agenda-mairie-l-e6h6-solution.md new file mode 100644 index 0000000..ec86b11 --- /dev/null +++ b/docs/solutions/2026-07-17-verifier-la-publication-sur-l-agenda-mairie-l-e6h6-solution.md @@ -0,0 +1,121 @@ +# Solution : [T2] Vérifier la publication sur l'agenda mairie (+ lien direct) + +## Problème résolu + +Un bénévole qui avait poussé un événement vers le formulaire mairie n'avait +**aucun retour** : le formulaire est modéré, la publication arrive plus tard, et +rien dans l'Écho du Huit ne disait « c'est en ligne ». On ne savait pas si un +événement était *à faire* ou *déjà publié*, et pour le retrouver sur le site il +fallait le chercher à la main — au risque de le re-soumettre. + +Objectif tenu : l'extension **détecte** qu'un événement Nextcloud est réellement +publié sur l'agenda public de la mairie, affiche un badge **« Publié »** + le +**lien direct** vers la fiche, et **retire le bouton « Créer »** (anti-doublon). +Ce statut *publié* est **dérivé** de l'agenda à la volée (décision 2026-06-29), +jamais un tag écrit dans Nextcloud : c'est la mairie qui fait foi, pas notre +intention. Aucun stockage, aucun `credentials` (agenda public). + +## Approche choisie + +**Scraping HTML de l'agenda + match strict `date locale Cugnaux + titre +normalisé`, biais précision v1** (approche 1 du brainstorm, variante +conservatrice). + +Il n'y a **pas d'API mairie** : la seule source est le HTML public. Le vrai +risque n'était donc pas « aller chercher la page » mais **la fiabilité du +match** — et il est gouverné par une **asymétrie de risque** structurante : + +- *Faux positif* (marquer « publié » à tort) → le bénévole croit que c'est fait, + l'événement **ne sera jamais publié**. **Grave.** +- *Faux négatif* (rater un match réel) → au pire il revérifie, et le formulaire + **modéré** rattrape un doublon. **Bénin.** + +→ On privilégie la **précision** : match strict (date identique + titre normalisé +identique), et dans le doute on **n'affirme pas** « publié ». + +Alternatives écartées : +- **Match par slug dérivé** : la slugification WordPress de la mairie n'est pas + connue et ajoute des suffixes (`atelier-dessin-2`) → égalité stricte cassée, + faux négatifs. On matche sur `date + titre` ; le lien est **lu** dans la carte, + jamais reconstruit. +- **Score de confiance + confirmation humaine** des cas ambigus (approche 3) : + meilleur rappel mais 3ᵉ état d'affichage et un état à mémoriser — or *publié* + n'a pas de tag et l'état local est proscrit. Reporté hors v1 ; la porte reste + ouverte si les faux négatifs se voient à l'usage. + +## Décisions clés + +- **Seam extraction impure / matching pur.** `DOMParser` est **absent de Bun** : + impossible de tester l'extraction DOM en `bun test`. On isole donc + `extraireCartes(html)` (impur, DOMParser, non testé unitairement — validé par + le test humain) du **matching pur** `publication.js`, testé à fond car c'est le + vrai risque produit. Même logique que `formulaire-valeurs.js` (pur, testé) vs + `formulaire-mairie.js` (impur, DOM). La boucle de pagination reste testable en + **injectant** `fetchImpl`/`extraireCartesImpl`. +- **L'agenda est paginé** (`.../agenda/page/N/?f=1&…`). Un seul fetch « période » + ne suffit pas : on boucle jusqu'à une page vide, avec un **plafond + anti-boucle** (12) au cas où un changement HTML masquerait la page vide. +- **Fuseau : jamais de conversion.** Le `