From 5a5d7a5c5932b5b943637d8cf3354d5710c8d8ba Mon Sep 17 00:00:00 2001 From: Spark Date: Fri, 6 Nov 2026 19:07:29 +0000 Subject: [PATCH] fix: brancher aussi la barre d'ObsiGate sur /sso/logout (BUG-122, fusion #141) --- CHANGELOG.md | 2 +- docs/features/deconnexion-globale-bug-122.md | 3 +++ frontend/index.html | 1 + tests/test_draco_barre.py | 10 ++++++++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1026dc3..2e638ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ et [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [2.86.0] — 2026-11-06 -- **BUG-122 — Déconnexion globale navigable : `GET /sso/logout`** (fusion #141) : le bouton « Déconnexion » du menu compte de la barre commune ne faisait rien dans les applications sœurs — la barre relaie l'action à l'hôte, et la déconnexion globale d'ObsiGate (ACC-3.1, #216) n'était appelable qu'en same-origin depuis l'interface d'ObsiGate (`POST /api/auth/logout`). Nouvelle route `GET /sso/logout?return_to=`, symétrique de `/sso/authorize` : elle exécute la déconnexion globale — logique extraite dans `apply_global_logout()` (`backend/auth/router.py`), désormais partagée par les deux entrées (jetons natifs refresh/access révoqués, `jti` du cookie `draco_session` révoqué, cookie effacé sur le domaine parent) — puis redirige vers le `return_to` validé par la liste blanche existante (`validate_return_to` : https + `*.dracodev.net`, repli « / »). Idempotente sans session. Les applications sœurs branchent leur action `deconnexion` sur cette route (leur session locale est détruite d'abord chez celles qui en ont une). Tests : `tests/test_draco_session.py` (+3 : révocation et redirection, liste blanche, idempotence). Fiche : `docs/features/deconnexion-globale-bug-122.md`. +- **BUG-122 — Déconnexion globale navigable : `GET /sso/logout`** (fusion #141) : le bouton « Déconnexion » du menu compte de la barre commune ne faisait rien dans les applications sœurs — la barre relaie l'action à l'hôte, et la déconnexion globale d'ObsiGate (ACC-3.1, #216) n'était appelable qu'en same-origin depuis l'interface d'ObsiGate (`POST /api/auth/logout`). Nouvelle route `GET /sso/logout?return_to=`, symétrique de `/sso/authorize` : elle exécute la déconnexion globale — logique extraite dans `apply_global_logout()` (`backend/auth/router.py`), désormais partagée par les deux entrées (jetons natifs refresh/access révoqués, `jti` du cookie `draco_session` révoqué, cookie effacé sur le domaine parent) — puis redirige vers le `return_to` validé par la liste blanche existante (`validate_return_to` : https + `*.dracodev.net`, repli « / »). Idempotente sans session. Les applications sœurs branchent leur action `deconnexion` sur cette route (leur session locale est détruite d'abord chez celles qui en ont une) — et la barre d'ObsiGate elle-même aussi (`frontend/index.html`, retour à sa racine). Tests : `tests/test_draco_session.py` (+3 : révocation et redirection, liste blanche, idempotence), `tests/test_draco_barre.py` (+1 : branchement de la barre d'ObsiGate). Fiche : `docs/features/deconnexion-globale-bug-122.md`. --- diff --git a/docs/features/deconnexion-globale-bug-122.md b/docs/features/deconnexion-globale-bug-122.md index 4e384e6..948e773 100644 --- a/docs/features/deconnexion-globale-bug-122.md +++ b/docs/features/deconnexion-globale-bug-122.md @@ -39,6 +39,9 @@ elle-même. Or : sous-domaine) — aucun relais ouvert. - Idempotente : sans session, la route redirige quand même (les hôtes y naviguent même si leur session a déjà expiré). +- La barre d'ObsiGate elle-même branche son action `deconnexion` sur + cette route (`frontend/index.html`, retour à sa racine) — garde : + `tests/test_draco_barre.py::test_barre_deconnexion_branchee`. ## Côté hôtes (PR sœurs, carte fusion #141) diff --git a/frontend/index.html b/frontend/index.html index b3e2eb1..f5d5127 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -410,6 +410,7 @@ return; } if (act === "palette") { location.href = "/recherche"; return; } + if (act === "deconnexion") { location.href = "/sso/logout?return_to=" + encodeURIComponent(location.origin + "/"); return; } /* Correctif fusion #70 : relais "menu" supprimé avec le bouton trois points de la barre (la console agent est dans le menu de la marque, entrée « Console Spark »). Le bouton natif #header-menu-btn d'ObsiGate lui-même est inchangé et reste utilisable depuis l'en-tête ObsiGate. */ if (act === "alertes") { if (window.DRACO_ALERTES) { window.DRACO_ALERTES.open(); } else { dire("Alertes unifiées : le module n'a pas pu se charger."); } return; } if (act === "spark") { diff --git a/tests/test_draco_barre.py b/tests/test_draco_barre.py index c7bd9f4..4f1e9ea 100644 --- a/tests/test_draco_barre.py +++ b/tests/test_draco_barre.py @@ -184,6 +184,16 @@ def test_urls_ecosysteme_via_injection_hote_223(): assert "DRACO_URLS[a.dataset.app]" in html +def test_barre_deconnexion_branchee(): + # BUG-122 (fusion #141) : la barre d'ObsiGate elle-même branche + # l'action « deconnexion » sur son point d'entrée de déconnexion + # globale (GET /sso/logout, retour à la racine) — avant, le clic + # ne faisait rien ici non plus. + html = _index() + assert 'act === "deconnexion"' in html + assert '"/sso/logout?return_to="' in html + + def test_rail_mobile_vers_le_vrai_hamburger(): html = _index() assert 'matchMedia("(max-width: 768px)")' in html