Fusion #69 (chantier 2) — Alertes unifiées, côté Flowdeck.
Audit (vérifié sur main, pas supposé)
Flowdeck expose réellement : GET /api/notifications?limit=50 ({notifications:[{id,ntype,title,message,url,is_read,created_at}], unread}) + GET /api/notifications/unread-count + cloche native _notification_bell.html (poll 30 s, marquage lu). Actif = is_read = 0 ; lien profond = base + url (ex. /collections/{id}). Les rappels deviennent des notifications via services/reminders.py (scan + reminder_log anti-doublon) : ils sont donc couverts sans inventer une seconde source.
Kanbante : GET /api/events (aucun état lu/non lu → tout historique, jamais compté actif ; lien /board/{repo}).
ObsiGate : aucune notification entrante consultable (ses /api/notify/* sont des canaux d'envoi sortants admin).
Verrous constatés : CSP connect-src fermée aux seules origines self/agent, et CORS limité à app_base_url (+ localhost/extensions) → la lecture inter-origines était impossible sans les ouvertures ci-dessous, étroites et limitées aux sœurs.
Ce qui change (cette PR Flowdeck)
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.
app/templates/_draco_bar.html : branche alertes → DRACO_ALERTES.open() (repli : cloche native) ; le toast « Alertes unifiées : arrive avec la fédération » DISPARAÎT ; chargement du module. (Hors périmètre : le toast de la branche palette « Recherche fédérée » est inchangé — autre chantier.)
app/main.py : allow_origins du CORSMiddleware += origines sœurs résolues par draco_urls.toutes() (lecture GET ; les POST restent soumis au CSRFMiddleware).
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 ; sinon la section manquante 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).
Caveat de test : dans la sandbox, les pages applicatives authentifiées ne sont pas atteignables telles quelles (l'écran de connexion est servi pour / comme pour /dashboard) ; le test de barre vérifie donc le gabarit livré + les statiques servis, et la CSP est vérifiée sur la réponse HTML servie. Le rendu authentifié complet reste à valider après déploiement, comme la pastille inter-apps en conditions réelles (par Bruno).
Fusion #69 (chantier 2) — Alertes unifiées, côté Flowdeck.
## Audit (vérifié sur main, pas supposé)
- Flowdeck expose réellement : `GET /api/notifications?limit=50` (`{notifications:[{id,ntype,title,message,url,is_read,created_at}], unread}`) + `GET /api/notifications/unread-count` + cloche native `_notification_bell.html` (poll 30 s, marquage lu). Actif = `is_read = 0` ; lien profond = base + `url` (ex. `/collections/{id}`). Les rappels deviennent des notifications via `services/reminders.py` (scan + `reminder_log` anti-doublon) : ils sont donc couverts sans inventer une seconde source.
- TikTak : `GET /api/notifications` (non lues = actives ; lien `/?task={id}` sinon `/notifications`).
- Kanbante : `GET /api/events` (aucun état lu/non lu → tout historique, jamais compté actif ; lien `/board/{repo}`).
- ObsiGate : aucune notification entrante consultable (ses `/api/notify/*` sont des canaux d'envoi sortants admin).
- Verrous constatés : CSP `connect-src` fermée aux seules origines self/agent, et CORS limité à `app_base_url` (+ localhost/extensions) → la lecture inter-origines était impossible sans les ouvertures ci-dessous, étroites et limitées aux sœurs.
## Ce qui change (cette PR Flowdeck)
- `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.
- `app/templates/_draco_bar.html` : branche `alertes` → `DRACO_ALERTES.open()` (repli : cloche native) ; le toast « Alertes unifiées : arrive avec la fédération » DISPARAÎT ; chargement du module. (Hors périmètre : le toast de la branche `palette` « Recherche fédérée » est inchangé — autre chantier.)
- `app/main.py` : `allow_origins` du CORSMiddleware += origines sœurs résolues par `draco_urls.toutes()` (lecture GET ; les POST restent soumis au CSRFMiddleware).
- `app/middleware/security.py` : CSP `connect-src` += origines sœurs (même résolution que `frame-src` agent).
- 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 ; sinon la section manquante 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_fusion_draco.py tests/test_draco_urls_devprod.py` : 32 passed, 0 échec (non-régression).
- `node --test tests/draco-alertes.test.js` : 5 passed.
- Caveat de test : dans la sandbox, les pages applicatives authentifiées ne sont pas atteignables telles quelles (l'écran de connexion est servi pour `/` comme pour `/dashboard`) ; le test de barre vérifie donc le gabarit livré + les statiques servis, et la CSP est vérifiée sur la réponse HTML servie. Le rendu authentifié complet reste à valider après déploiement, comme la pastille inter-apps en conditions réelles (par Bruno).
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fusion #69 (chantier 2) — Alertes unifiées, côté Flowdeck.
Audit (vérifié sur main, pas supposé)
GET /api/notifications?limit=50({notifications:[{id,ntype,title,message,url,is_read,created_at}], unread}) +GET /api/notifications/unread-count+ cloche native_notification_bell.html(poll 30 s, marquage lu). Actif =is_read = 0; lien profond = base +url(ex./collections/{id}). Les rappels deviennent des notifications viaservices/reminders.py(scan +reminder_loganti-doublon) : ils sont donc couverts sans inventer une seconde source.GET /api/notifications(non lues = actives ; lien/?task={id}sinon/notifications).GET /api/events(aucun état lu/non lu → tout historique, jamais compté actif ; lien/board/{repo})./api/notify/*sont des canaux d'envoi sortants admin).connect-srcfermée aux seules origines self/agent, et CORS limité àapp_base_url(+ localhost/extensions) → la lecture inter-origines était impossible sans les ouvertures ci-dessous, étroites et limitées aux sœurs.Ce qui change (cette PR Flowdeck)
static/js/draco-alertes.js(nouveau, module partagé, pas un fichierui/barre-apps.*) +static/css/draco-alertes.css: panneau Alertes (actives d'abord, puis historique, par application, origine/titre/date/état/lien profond ;textContentuniquement). Pastille viaDRACO_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.app/templates/_draco_bar.html: branchealertes→DRACO_ALERTES.open()(repli : cloche native) ; le toast « Alertes unifiées : arrive avec la fédération » DISPARAÎT ; chargement du module. (Hors périmètre : le toast de la branchepalette« Recherche fédérée » est inchangé — autre chantier.)app/main.py:allow_originsdu CORSMiddleware += origines sœurs résolues pardraco_urls.toutes()(lecture GET ; les POST restent soumis au CSRFMiddleware).app/middleware/security.py: CSPconnect-src+= origines sœurs (même résolution queframe-srcagent).tests/test_draco_alertes.py(3 tests) +tests/draco-alertes.test.js(5 tests Node).Limites, dites honnêtement
Tests (chiffres réels, sandbox)
pytest tests/test_draco_alertes.py: 3 passed.pytest tests/test_fusion_draco.py tests/test_draco_urls_devprod.py: 32 passed, 0 échec (non-régression).node --test tests/draco-alertes.test.js: 5 passed./comme pour/dashboard) ; le test de barre vérifie donc le gabarit livré + les statiques servis, et la CSP est vérifiée sur la réponse HTML servie. Le rendu authentifié complet reste à valider après déploiement, comme la pastille inter-apps en conditions réelles (par Bruno).