Fusion #69 : Alertes unifiées (panneau + pastille, agrégation à la demande) #36

Merged
bruno merged 6 commits from alertes-unifiees-69-rebase into main 2026-10-28 12:47:36 -04:00
Owner

Fusion #69 (chantier 2) — Alertes unifiées, côté Kanbante.

Audit (vérifié sur main, pas supposé)

  • Kanbante n'a PAS de table de notifications et n'expose aucun endpoint notifications : sa seule source réelle d'activité est le journal d'événements, déjà exposé par GET /api/events?limit=100 ({ok, events:[{repo_full_name,issue_number,event_type,from_column,to_column,created_at}]}) et rendu par /activity. AUCUN état lu/non lu n'existe dans Kanbante.
  • Conséquence honnête, codée dans le module : les événements Kanbante sont tous de l'historique et ne sont JAMAIS comptés dans la pastille d'actives.
  • Les autres sources (même audit que les autres PR du chantier) : Flowdeck GET /api/notifications (non lues = actives), TikTak GET /api/notifications (non lues = actives), ObsiGate : aucune notification entrante consultable (ses /api/notify/* sont des envois sortants admin).
  • Kanbante n'énonce en CSP que frame-src (console Spark) : aucune ouverture connect-src n'est nécessaire côté Kanbante comme visualiseur. En revanche, sans CORS, la lecture de /api/events depuis un autre hôte est bloquée : cette PR l'ouvre étroitement.

Ce qui change (cette PR Kanbante)

  • static/js/draco-alertes.js (nouveau, module partagé, pas un fichier ui/barre-apps.*) + static/css/draco-alertes.css : panneau Alertes (actives d'abord, puis historique, par application, origine/titre/date/état/lien profond ; textContent uniquement). Pastille via DRACO_BAR.setCounts({alertes: n}). Bases résolues dans l'ordre barre v0.1.6 : config explicite > hôte -dev dérivé > href rendu > défaut prod. Aucun nouvel endpoint : le module consomme /api/events existant.
  • app/templates/_draco_bar.html : branche alertes → DRACO_ALERTES.open() (repli : /activity) ; le toast « Alertes unifiées : arrive avec la fédération » DISPARAÎT ; chargement du module.
  • app/main.py : nouveau DracoAlertesCorsMiddleware (ajouté après AuthMiddleware, donc le plus externe) limité à /api/events pour les seules origines sœurs résolues par resoudre_urls_draco() ; preflight OPTIONS sans données ; le GET reste soumis à AuthMiddleware (session/jeton).
  • Tests : tests/test_draco_alertes.py (3 tests) + tests/draco-alertes.test.js (5 tests Node).

Limites, dites honnêtement

  • Agrégation À LA DEMANDE, pas une fédération temps réel (relecture à l'ouverture + au chargement pour la pastille).
  • Vue unifiée complète seulement quand les 4 PR du chantier sont déployées (chaque hôte autorise les sœurs en CSP/CORS) ; sinon la section de l'hôte manquant affiche « Connexion requise » ou « injoignable » avec son lien natif, jamais de faux contenu.
  • Pastille = Flowdeck non lues + TikTak non lues uniquement.
  • Aucun bump de version, aucun merge, aucune fermeture d'issue dans cette PR (coordinateur).

Tests (chiffres réels, sandbox)

  • pytest tests/test_draco_alertes.py : 3 passed.
  • pytest tests/test_draco_barre.py : 21 passed, 0 échec (non-régression).
  • node --test tests/draco-alertes.test.js : 5 passed.
  • Note d'environnement : les tests Kanbante échouent au chargement dans la sandbox si les variables proxy de la sandbox restent définies (httpx lit no_proxy et échoue sur ses entrées IPv6 entre crochets) ; les chiffres ci-dessus sont obtenus avec ces variables neutralisées — préexistant, sans rapport avec cette PR.
  • Validation déployée (pastille et sections inter-apps en conditions réelles) reste à faire par Bruno après déploiement des 4 PR.

Rebase de la PR #34 sur main post-#70 et post-#68 (conflits _draco_bar.html et app/main.py résolus : suppression du bouton ••• de #70 conservée, palette /recherche de #68 conservée, ajouts #69 appliqués — CSS/JS draco-alertes, handler alertes, middleware CORS /api/events — sans ressusciter le bouton ••• ni la branche menu, et sans retirer le contenu #68). Contenu par ailleurs identique à #34.

Fusion #69 (chantier 2) — Alertes unifiées, côté Kanbante. ## Audit (vérifié sur main, pas supposé) - Kanbante n'a PAS de table de notifications et n'expose aucun endpoint notifications : sa seule source réelle d'activité est le journal d'événements, déjà exposé par `GET /api/events?limit=100` (`{ok, events:[{repo_full_name,issue_number,event_type,from_column,to_column,created_at}]}`) et rendu par `/activity`. AUCUN état lu/non lu n'existe dans Kanbante. - Conséquence honnête, codée dans le module : les événements Kanbante sont tous de l'historique et ne sont JAMAIS comptés dans la pastille d'actives. - Les autres sources (même audit que les autres PR du chantier) : Flowdeck `GET /api/notifications` (non lues = actives), TikTak `GET /api/notifications` (non lues = actives), ObsiGate : aucune notification entrante consultable (ses `/api/notify/*` sont des envois sortants admin). - Kanbante n'énonce en CSP que `frame-src` (console Spark) : aucune ouverture `connect-src` n'est nécessaire côté Kanbante comme visualiseur. En revanche, sans CORS, la lecture de `/api/events` depuis un autre hôte est bloquée : cette PR l'ouvre étroitement. ## Ce qui change (cette PR Kanbante) - `static/js/draco-alertes.js` (nouveau, module partagé, pas un fichier `ui/barre-apps.*`) + `static/css/draco-alertes.css` : panneau Alertes (actives d'abord, puis historique, par application, origine/titre/date/état/lien profond ; `textContent` uniquement). Pastille via `DRACO_BAR.setCounts({alertes: n})`. Bases résolues dans l'ordre barre v0.1.6 : config explicite > hôte -dev dérivé > href rendu > défaut prod. Aucun nouvel endpoint : le module consomme `/api/events` existant. - `app/templates/_draco_bar.html` : branche `alertes` → `DRACO_ALERTES.open()` (repli : `/activity`) ; le toast « Alertes unifiées : arrive avec la fédération » DISPARAÎT ; chargement du module. - `app/main.py` : nouveau `DracoAlertesCorsMiddleware` (ajouté après `AuthMiddleware`, donc le plus externe) limité à `/api/events` pour les seules origines sœurs résolues par `resoudre_urls_draco()` ; preflight OPTIONS sans données ; le GET reste soumis à `AuthMiddleware` (session/jeton). - Tests : `tests/test_draco_alertes.py` (3 tests) + `tests/draco-alertes.test.js` (5 tests Node). ## Limites, dites honnêtement - Agrégation À LA DEMANDE, pas une fédération temps réel (relecture à l'ouverture + au chargement pour la pastille). - Vue unifiée complète seulement quand les 4 PR du chantier sont déployées (chaque hôte autorise les sœurs en CSP/CORS) ; sinon la section de l'hôte manquant affiche « Connexion requise » ou « injoignable » avec son lien natif, jamais de faux contenu. - Pastille = Flowdeck non lues + TikTak non lues uniquement. - Aucun bump de version, aucun merge, aucune fermeture d'issue dans cette PR (coordinateur). ## Tests (chiffres réels, sandbox) - `pytest tests/test_draco_alertes.py` : 3 passed. - `pytest tests/test_draco_barre.py` : 21 passed, 0 échec (non-régression). - `node --test tests/draco-alertes.test.js` : 5 passed. - Note d'environnement : les tests Kanbante échouent au chargement dans la sandbox si les variables proxy de la sandbox restent définies (httpx lit `no_proxy` et échoue sur ses entrées IPv6 entre crochets) ; les chiffres ci-dessus sont obtenus avec ces variables neutralisées — préexistant, sans rapport avec cette PR. - Validation déployée (pastille et sections inter-apps en conditions réelles) reste à faire par Bruno après déploiement des 4 PR. --- Rebase de la PR #34 sur main post-#70 et post-#68 (conflits _draco_bar.html et app/main.py résolus : suppression du bouton ••• de #70 conservée, palette /recherche de #68 conservée, ajouts #69 appliqués — CSS/JS draco-alertes, handler alertes, middleware CORS /api/events — sans ressusciter le bouton ••• ni la branche menu, et sans retirer le contenu #68). Contenu par ailleurs identique à #34.
bruno added 6 commits 2026-10-28 12:47:23 -04:00
bruno merged commit e89f7903e1 into main 2026-10-28 12:47:36 -04:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Projets/kanbante#36