Ne pas merger sans le go du coordinateur ; aucune version bumpée, aucune issue fermée ou rouverte par cette PR (les issues Projets/fusion-trois-apps #68 et #69 restent les suites de validation, leur état est inchangé).
Matrice constatée par Bruno (2026-10-28 13:33 EDT, page /recherche)
Depuis TikTak : ObsiGate OK ; Flowdeck ÉCHEC ; Kanbante ÉCHEC. Depuis Kanbante : ObsiGate OK ; Flowdeck ÉCHEC ; TikTak ÉCHEC. Depuis Flowdeck : ObsiGate OK, Flowdeck OK (lui-même) ; TikTak ÉCHEC ; Kanbante ÉCHEC. Depuis ObsiGate : ObsiGate OK ; Flowdeck ÉCHEC ; TikTak OK ; Kanbante OK. Le message affiché est « Injoignable depuis cet hôte (CORS ou réseau) » (fetch sans statut : blocage CORS/CSP/réseau, pas un 401/403).
Audit (vérifié sur main, dans le code)
Flowdeck n'autorisait que l'environnement résolu : pour /api/search, app/services.draco_urls.toutes() lue en configuration seule au moment où RechercheCorsMiddleware s'exécute — avant le middleware CSP qui pose le contexte d'hôte de la requête — plus l'environnement de l'hôte de la requête ; jamais les deux à la fois. C'est le cas le plus fragile des quatre, ce qui cadre avec « Flowdeck échoue depuis tous les hôtes ».
Plus grave pour les alertes : /api/notifications passait par le CORSMiddleware global dont allow_origins est calculé une fois à l'import (configuration seule, sans hôte de requête) — aucune augmentation par requête n'était possible.
Même schéma mono-environnement chez les sœurs : TikTak (draco_urls(hote_depuis_requete)), Kanbante (resoudre_urls_draco), ObsiGate (urls_publiques(), configuration seule).
La CSP connect-src n'est PAS le verrou : la CSP Flowdeck résout ses sœurs via le contexte d'hôte posé par son propre middleware CSP, dans l'environnement de la page — et les tests dev/prod interdisent explicitement les noms prod dans la CSP/HTML d'une instance dev (tests/test_draco_urls_devprod.py). Cette PR ne touche donc à aucune CSP, pour ne pas casser cette discipline.
Le cross-origin authentifié fonctionne en principe (depuis ObsiGate, TikTak et Kanbante répondent) : aucun repli serveur (proxy fan-out) n'est implémenté, conformément au chantier.
Ce que le code ne permet pas de conclure (à valider déployé) : la configuration réelle déclarée par chaque instance (.env dev/prod), l'existence d'un Flowdeck prod joignable (la page prod résout la base prod), et un éventuel filtre Cloudflare Access devant une instance — invisibles dans le code.
Ce qui change (Flowdeck)
app/middleware/recherche_cors.py : sister_origins() retourne désormais les origines résolues plusPROD_ORIGINS | DEV_ORIGINS — les 8 origines officielles (og, flowdeck, tiktak, kanbante, avec et sans -dev, en https://*.dracodev.net), listées explicitement, jamais *, avec Access-Control-Allow-Credentials: true. Une origine inconnue reste refusée.
app/main.py : allow_origins du CORSMiddleware global unionné avec les mêmes PROD_ORIGINS | DEV_ORIGINS (importés du module CORS de la recherche, pas de duplication) — c'est ce qui débloque /api/notifications lu depuis les autres hôtes (fusion #69). Méthodes, en-têtes, CSRF et politique globale inchangés.
Tests : tests/test_recherche.py (allowlist = 8 origines quelle que soit la résolution ; autre environnement autorisé ; tiers et sosie refusés) et tests/test_draco_alertes.py (OPTIONS depuis une origine dev autorisé, tiers refusé).
Non touchés : pages /recherche et alertes, ligne d'onglets de la barre, CSP, versions, état des issues.
Tests (chiffres réels, exécutés le 2026-10-28)
Module app/middleware/recherche_cors.py chargé par chemin + middleware ASGI simulé : 8 origines, preflight prod 204 / dev 204 / tiers transmis sans en-tête — OK.
Fichier tests/test_recherche.py rejoué hors pytest (pytest absent de la sandbox) : 6 tests OK (dont les cas mis à jour).
python3 -m py_compile sur app/middleware/recherche_cors.py, app/main.py, app/middleware/security.py (inchangé, vérifié identique), les 2 fichiers de tests : OK.
Non exécutés ici (dépendances applicatives absentes de la sandbox) : pytest tests/test_recherche.py tests/test_draco_alertes.py et le serveur — à valider en CI / après déploiement.
Validation déployée restante (par Bruno)
Matrice 4 hôtes × 4 sections sur /recherche (dev et prod) + panneau Alertes unifiées depuis chaque hôte : chaque section sœur doit afficher des résultats (ou « vide »), plus jamais « Injoignable ». Cas négatif à garder : une origine tierce ne doit toujours recevoir aucun en-tête Access-Control-Allow-Origin.
## CORS recherche/alertes : allowlist sœurs prod+dev explicites (fusion #68/#69, chantier 1)
Ne pas merger sans le go du coordinateur ; aucune version bumpée, aucune issue fermée ou rouverte par cette PR (les issues Projets/fusion-trois-apps #68 et #69 restent les suites de validation, leur état est inchangé).
### Matrice constatée par Bruno (2026-10-28 13:33 EDT, page /recherche)
Depuis TikTak : ObsiGate OK ; Flowdeck ÉCHEC ; Kanbante ÉCHEC. Depuis Kanbante : ObsiGate OK ; Flowdeck ÉCHEC ; TikTak ÉCHEC. Depuis Flowdeck : ObsiGate OK, Flowdeck OK (lui-même) ; TikTak ÉCHEC ; Kanbante ÉCHEC. Depuis ObsiGate : ObsiGate OK ; Flowdeck ÉCHEC ; TikTak OK ; Kanbante OK. Le message affiché est « Injoignable depuis cet hôte (CORS ou réseau) » (fetch sans statut : blocage CORS/CSP/réseau, pas un 401/403).
### Audit (vérifié sur main, dans le code)
- Flowdeck n'autorisait que l'environnement résolu : pour `/api/search`, `app/services.draco_urls.toutes()` lue en configuration seule au moment où `RechercheCorsMiddleware` s'exécute — avant le middleware CSP qui pose le contexte d'hôte de la requête — plus l'environnement de l'hôte de la requête ; jamais les deux à la fois. C'est le cas le plus fragile des quatre, ce qui cadre avec « Flowdeck échoue depuis tous les hôtes ».
- Plus grave pour les alertes : `/api/notifications` passait par le `CORSMiddleware` global dont `allow_origins` est calculé une fois à l'import (configuration seule, sans hôte de requête) — aucune augmentation par requête n'était possible.
- Même schéma mono-environnement chez les sœurs : TikTak (`draco_urls(hote_depuis_requete)`), Kanbante (`resoudre_urls_draco`), ObsiGate (`urls_publiques()`, configuration seule).
- La CSP `connect-src` n'est PAS le verrou : la CSP Flowdeck résout ses sœurs via le contexte d'hôte posé par son propre middleware CSP, dans l'environnement de la page — et les tests dev/prod interdisent explicitement les noms prod dans la CSP/HTML d'une instance dev (`tests/test_draco_urls_devprod.py`). Cette PR ne touche donc à aucune CSP, pour ne pas casser cette discipline.
- Le cross-origin authentifié fonctionne en principe (depuis ObsiGate, TikTak et Kanbante répondent) : aucun repli serveur (proxy fan-out) n'est implémenté, conformément au chantier.
- Ce que le code ne permet pas de conclure (à valider déployé) : la configuration réelle déclarée par chaque instance (`.env` dev/prod), l'existence d'un Flowdeck prod joignable (la page prod résout la base prod), et un éventuel filtre Cloudflare Access devant une instance — invisibles dans le code.
### Ce qui change (Flowdeck)
- `app/middleware/recherche_cors.py` : `sister_origins()` retourne désormais les origines résolues **plus** `PROD_ORIGINS | DEV_ORIGINS` — les 8 origines officielles (`og`, `flowdeck`, `tiktak`, `kanbante`, avec et sans `-dev`, en `https://*.dracodev.net`), listées explicitement, jamais `*`, avec `Access-Control-Allow-Credentials: true`. Une origine inconnue reste refusée.
- `app/main.py` : `allow_origins` du `CORSMiddleware` global unionné avec les mêmes `PROD_ORIGINS | DEV_ORIGINS` (importés du module CORS de la recherche, pas de duplication) — c'est ce qui débloque `/api/notifications` lu depuis les autres hôtes (fusion #69). Méthodes, en-têtes, CSRF et politique globale inchangés.
- Tests : `tests/test_recherche.py` (allowlist = 8 origines quelle que soit la résolution ; autre environnement autorisé ; tiers et sosie refusés) et `tests/test_draco_alertes.py` (OPTIONS depuis une origine dev autorisé, tiers refusé).
- Non touchés : pages `/recherche` et alertes, ligne d'onglets de la barre, CSP, versions, état des issues.
### Tests (chiffres réels, exécutés le 2026-10-28)
- Module `app/middleware/recherche_cors.py` chargé par chemin + middleware ASGI simulé : 8 origines, preflight prod 204 / dev 204 / tiers transmis sans en-tête — OK.
- Fichier `tests/test_recherche.py` rejoué hors pytest (pytest absent de la sandbox) : **6 tests OK** (dont les cas mis à jour).
- `python3 -m py_compile` sur `app/middleware/recherche_cors.py`, `app/main.py`, `app/middleware/security.py` (inchangé, vérifié identique), les 2 fichiers de tests : OK.
- Non exécutés ici (dépendances applicatives absentes de la sandbox) : `pytest tests/test_recherche.py tests/test_draco_alertes.py` et le serveur — à valider en CI / après déploiement.
### Validation déployée restante (par Bruno)
Matrice 4 hôtes × 4 sections sur `/recherche` (dev et prod) + panneau Alertes unifiées depuis chaque hôte : chaque section sœur doit afficher des résultats (ou « vide »), plus jamais « Injoignable ». Cas négatif à garder : une origine tierce ne doit toujours recevoir aucun en-tête `Access-Control-Allow-Origin`.
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.
CORS recherche/alertes : allowlist sœurs prod+dev explicites (fusion #68/#69, chantier 1)
Ne pas merger sans le go du coordinateur ; aucune version bumpée, aucune issue fermée ou rouverte par cette PR (les issues Projets/fusion-trois-apps #68 et #69 restent les suites de validation, leur état est inchangé).
Matrice constatée par Bruno (2026-10-28 13:33 EDT, page /recherche)
Depuis TikTak : ObsiGate OK ; Flowdeck ÉCHEC ; Kanbante ÉCHEC. Depuis Kanbante : ObsiGate OK ; Flowdeck ÉCHEC ; TikTak ÉCHEC. Depuis Flowdeck : ObsiGate OK, Flowdeck OK (lui-même) ; TikTak ÉCHEC ; Kanbante ÉCHEC. Depuis ObsiGate : ObsiGate OK ; Flowdeck ÉCHEC ; TikTak OK ; Kanbante OK. Le message affiché est « Injoignable depuis cet hôte (CORS ou réseau) » (fetch sans statut : blocage CORS/CSP/réseau, pas un 401/403).
Audit (vérifié sur main, dans le code)
/api/search,app/services.draco_urls.toutes()lue en configuration seule au moment oùRechercheCorsMiddlewares'exécute — avant le middleware CSP qui pose le contexte d'hôte de la requête — plus l'environnement de l'hôte de la requête ; jamais les deux à la fois. C'est le cas le plus fragile des quatre, ce qui cadre avec « Flowdeck échoue depuis tous les hôtes »./api/notificationspassait par leCORSMiddlewareglobal dontallow_originsest calculé une fois à l'import (configuration seule, sans hôte de requête) — aucune augmentation par requête n'était possible.draco_urls(hote_depuis_requete)), Kanbante (resoudre_urls_draco), ObsiGate (urls_publiques(), configuration seule).connect-srcn'est PAS le verrou : la CSP Flowdeck résout ses sœurs via le contexte d'hôte posé par son propre middleware CSP, dans l'environnement de la page — et les tests dev/prod interdisent explicitement les noms prod dans la CSP/HTML d'une instance dev (tests/test_draco_urls_devprod.py). Cette PR ne touche donc à aucune CSP, pour ne pas casser cette discipline..envdev/prod), l'existence d'un Flowdeck prod joignable (la page prod résout la base prod), et un éventuel filtre Cloudflare Access devant une instance — invisibles dans le code.Ce qui change (Flowdeck)
app/middleware/recherche_cors.py:sister_origins()retourne désormais les origines résolues plusPROD_ORIGINS | DEV_ORIGINS— les 8 origines officielles (og,flowdeck,tiktak,kanbante, avec et sans-dev, enhttps://*.dracodev.net), listées explicitement, jamais*, avecAccess-Control-Allow-Credentials: true. Une origine inconnue reste refusée.app/main.py:allow_originsduCORSMiddlewareglobal unionné avec les mêmesPROD_ORIGINS | DEV_ORIGINS(importés du module CORS de la recherche, pas de duplication) — c'est ce qui débloque/api/notificationslu depuis les autres hôtes (fusion #69). Méthodes, en-têtes, CSRF et politique globale inchangés.tests/test_recherche.py(allowlist = 8 origines quelle que soit la résolution ; autre environnement autorisé ; tiers et sosie refusés) ettests/test_draco_alertes.py(OPTIONS depuis une origine dev autorisé, tiers refusé)./rechercheet alertes, ligne d'onglets de la barre, CSP, versions, état des issues.Tests (chiffres réels, exécutés le 2026-10-28)
app/middleware/recherche_cors.pychargé par chemin + middleware ASGI simulé : 8 origines, preflight prod 204 / dev 204 / tiers transmis sans en-tête — OK.tests/test_recherche.pyrejoué hors pytest (pytest absent de la sandbox) : 6 tests OK (dont les cas mis à jour).python3 -m py_compilesurapp/middleware/recherche_cors.py,app/main.py,app/middleware/security.py(inchangé, vérifié identique), les 2 fichiers de tests : OK.pytest tests/test_recherche.py tests/test_draco_alertes.pyet le serveur — à valider en CI / après déploiement.Validation déployée restante (par Bruno)
Matrice 4 hôtes × 4 sections sur
/recherche(dev et prod) + panneau Alertes unifiées depuis chaque hôte : chaque section sœur doit afficher des résultats (ou « vide »), plus jamais « Injoignable ». Cas négatif à garder : une origine tierce ne doit toujours recevoir aucun en-têteAccess-Control-Allow-Origin.