Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf030669a0 | ||
|
|
83a81b931e | ||
|
|
23df2bdcbe |
+7
-1
@@ -6,7 +6,7 @@ Format basé sur [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/),
|
||||
et [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
> **En cours de développement** : les changements à venir sont listés dans la section
|
||||
> [Unreleased](#unreleased). La dernière version livrée est **2.86.2**.
|
||||
> [Unreleased](#unreleased). La dernière version livrée est **2.86.3**.
|
||||
|
||||
---
|
||||
|
||||
@@ -14,6 +14,12 @@ et [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
---
|
||||
|
||||
## [2.86.3] — 2026-11-08
|
||||
|
||||
- **BUG-125 — Aller-retour SSO : le pont de l'application sœur reçoit à nouveau le cookie `draco_session` quand les cookies ont disparu sous une session `sessionStorage` encore « valide »** (suite du chantier « entrée SSO », retest réel de Bruno le 2026-11-08 après le correctif BUG-123 et celui du retour sur le bon hôte) : le retour tombait bien sur l'application demanderesse, mais son pont ne voyait **aucun jeton** et déposait l'utilisateur devant le formulaire, sans message. Chaîne fautive : cookies `access_token` et `draco_session` absents alors que la session semble valide en `sessionStorage` → le chemin court d'`initAuth()` (restauration sans échange serveur, BUG-123) honore le `return_to` immédiatement — le middleware de renouvellement (`DracoRenewalMiddleware`) n'a aucune requête authentifiée à traverser, donc aucune occasion de réémettre le cookie draco manquant. Correctif (`frontend/js/auth.js`) : quand la page est l'arrivée d'un `/sso/authorize` (`return_to` présent), le chemin court est écarté et `initAuth()` passe par le refresh silencieux (cookie refresh, 7 j) suivi de `/api/auth/me` — la réponse traverse le middleware, qui réémet le cookie draco absent ou invalide **avant** que le retour soit honoré ; si le refresh échoue, l'écran de connexion s'affiche comme avant (le `return_to` reste dans l'URL, `saveToken` l'honorera après login frais). Hors arrivée `authorize`, le démarrage est inchangé. Garde : `tests/test_draco_barre.py` (`test_retour_sso_refresh_force_bug_125`) ; variante fautive reproduite puis vérifiée en navigateur réel dans la pile « conteneur dev réel » (requête du pont journalisée : sans cookie draco avant correctif, avec cookie et session ouverte après). Fiche : `docs/features/retour-sso-cookie-draco-bug-125.md`.
|
||||
|
||||
---
|
||||
|
||||
## [2.86.2] — 2026-11-08
|
||||
|
||||
- **BUG-123 — Aller-retour SSO refermé aussi quand la session ObsiGate existe déjà** (chantier « entrée SSO de bout en bout », écart constaté par Bruno en test réel le 2026-11-08) : `GET /sso/authorize?return_to=…` redirige vers `/?return_to=…`, mais le retour n'était honoré que par `AuthManager.saveToken()` (login frais, MFA, WebAuthn). Pour un utilisateur déjà connecté chez ObsiGate, `initAuth()` restaurait la session — jeton encore valide ou refresh silencieux — et affichait l'accueil sans jamais suivre le `return_to` : l'utilisateur restait chez ObsiGate, et l'application sœur ne recevait jamais son pont (aucune session locale). Correctif (`frontend/js/auth.js`) : `_honorReturnTo()` signale désormais la redirection (valeur de retour), et les deux chemins de restauration d'`initAuth()` l'invoquent avant d'afficher l'application. Les refresh silencieux **en cours de session** ne sont pas touchés : ils ne doivent jamais rediriger. Même liste blanche qu'avant (https + `*.dracodev.net`, jamais l'hôte courant). Garde : `tests/test_draco_barre.py` (`test_barre_v070_setuser_et_retour_sso_restauration`) ; chaîne complète prouvée en navigateur réel dans une pile locale aux noms publics (dossier `preuve-entree-sso`). Fiche : `docs/features/entree-sso-bug-123-124.md`.
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@
|
||||
|
||||
**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.
|
||||
|
||||
[]()
|
||||
[]()
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://www.docker.com/)
|
||||
[](https://www.python.org/)
|
||||
@@ -977,8 +977,8 @@ Ce projet est sous licence **MIT** — voir le fichier [LICENSE](LICENSE) pour l
|
||||
|
||||
## 📝 Changelog
|
||||
|
||||
Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.86.2).
|
||||
Consultez le [CHANGELOG.md](./CHANGELOG.md) pour l'historique complet de toutes les versions (v1.0.0 → v2.86.3).
|
||||
|
||||
---
|
||||
|
||||
*Projet : ObsiGate | Version : 2.86.2 | Dernière mise à jour : Septembre 2026*
|
||||
*Projet : ObsiGate | Version : 2.86.3 | Dernière mise à jour : Septembre 2026*
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
**Ultra-light web gateway for your Obsidian vaults** — Access, browse, and search all your Obsidian notes from any device via a modern, responsive web interface.
|
||||
|
||||
[]()
|
||||
[]()
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://www.docker.com/)
|
||||
[](https://www.python.org/)
|
||||
@@ -1152,8 +1152,8 @@ This project is licensed under the **MIT License** - see the [LICENSE](LICENSE)
|
||||
|
||||
## 📝 Changelog
|
||||
|
||||
See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.86.2).
|
||||
See [CHANGELOG.md](./CHANGELOG.md) for the complete version history (v1.0.0 → v2.86.3).
|
||||
|
||||
---
|
||||
|
||||
*Project: ObsiGate | Version: 2.86.2 | Last updated: September 2026*
|
||||
*Project: ObsiGate | Version: 2.86.3 | Last updated: September 2026*
|
||||
|
||||
Generated
+1
-1
@@ -2626,7 +2626,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "obsigate-desktop"
|
||||
version = "2.86.2"
|
||||
version = "2.86.3"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"env_logger",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "obsigate-desktop"
|
||||
version = "2.86.2"
|
||||
version = "2.86.3"
|
||||
description = "ObsiGate Desktop — Porte d'entrée native pour vos vaults Obsidian"
|
||||
authors = ["Bruno Charest"]
|
||||
edition = "2021"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/nicedoc/obsigate/main/desktop/tauri.conf.schema.json",
|
||||
"productName": "ObsiGate",
|
||||
"version": "2.86.2",
|
||||
"version": "2.86.3",
|
||||
"identifier": "com.obsigate.desktop",
|
||||
"build": {
|
||||
"frontendDist": "../frontend",
|
||||
|
||||
@@ -230,6 +230,7 @@ Avant de corriger quoi que ce soit, un agent IA doit :
|
||||
| *BUG-122* | Déconnexion du menu compte inerte dans les applications sœurs : la barre commune relaie `deconnexion` à l'hôte, mais la déconnexion globale d'ObsiGate (ACC-3.1) n'est appelable qu'en same-origin (`POST /api/auth/logout`) — aucun point d'entrée navigable pour les autres hôtes | 🟢 corrigé | P1 | ⚙️ backend | IA | `backend/routers/sso.py` (`GET /sso/logout`), `backend/auth/router.py` (`apply_global_logout`) | Depuis la console Spark (ou Flowdeck/TikTak/ShaarIt/Hub) : menu compte → « Déconnexion » → rien ne se passe, la session draco reste vivante (vérifié en navigateur réel : cookie présent, `/api/v1/me` toujours 200) | Nouvelle route `GET /sso/logout?return_to=` : exécute la déconnexion globale (logique partagée `apply_global_logout` : jetons natifs refresh/access révoqués, `jti` draco révoqué, cookie effacé sur le domaine parent) puis redirige vers le `return_to` validé (liste blanche https + *.dracodev.net, repli `/`). Tests `tests/test_draco_session.py` (+3) | Signalé par Bruno le 2026-11-06 (capture console), carte fusion #141 ; les hôtes branchent leur action `deconnexion` sur cette route (PR sœurs). BUG-121 reste réservé au bug de couleur « Secrets » du vault Spark (proposé, non ordonné). Redéploiement Docker requis |
|
||||
| *BUG-123* | Aller-retour SSO non refermé quand la session ObsiGate existe déjà : `GET /sso/authorize?return_to=…` dépose l'utilisateur sur `/?return_to=…`, mais le retour n'est honoré que par `AuthManager.saveToken()` (login frais, MFA, WebAuthn) — les chemins de restauration de session d'`initAuth()` (jeton encore valide en sessionStorage, ou refresh silencieux au démarrage) affichent l'accueil sans jamais suivre le `return_to` : l'utilisateur reste chez ObsiGate et, revenu manuellement à l'application sœur, n'y a toujours aucune session locale | 🟢 corrigé | P1 | 📱 frontend | IA | `frontend/js/auth.js` (`initAuth`, `_honorReturnTo`) | Navigateur avec session ObsiGate active → Kanbante → « Se connecter avec ObsiGate (SSO) » → retour automatique attendu dans Kanbante, connecté ; constaté en pile locale complète (chaîne d'URL journalisée) : arrivée sur l'accueil ObsiGate, retour jamais suivi | `_honorReturnTo()` retourne si la redirection a eu lieu ; les deux chemins de restauration d'`initAuth()` l'invoquent avant `showApp()` (les refresh en cours de session restent sans redirection). Garde : `tests/test_draco_barre.py` ; preuve navigateur complète du chantier (pile locale aux noms publics) | Signalé par Bruno le 2026-11-08 (test réel, compte « testeur » créé au Hub) ; le sous-cas login frais refermait déjà la boucle (vérifié). Fiche `docs/features/entree-sso-bug-123-124.md`. Redéploiement Docker requis |
|
||||
| *BUG-124* | Nom du compte absent du menu de la barre commune juste après le login : `renderUserSection()` met à jour le bloc latéral et le drapeau admin de la barre, mais ne pousse jamais le nom — le seul poseur d'identité de la barre est le fetch d'amorçage au `DOMContentLoaded`, limité aux sessions déjà présentes au chargement. Après un login SPA sans rechargement : avatar « ✦ » et en-tête « Compte » jusqu'au rechargement forcé | 🟢 corrigé | P2 | 📱 frontend | IA | `frontend/js/auth.js` (`renderUserSection`), `frontend/index.html`, `frontend/draco-barre.js` (vendange commons v0.7.0) | Se connecter dans la SPA puis ouvrir le menu compte de la barre sans recharger : en-tête « Compte » au lieu du nom (reproduit en pile locale, capture) | Barre commune v0.7.0 re-vendangée verbatim (nouvelle API `DRACO_BAR.setUser`, PR dracodev-commons #15) ; `renderUserSection()` appelle `setUser(name)` / `setUser(null)`, le fetch d'amorçage d'`index.html` pousse aussi le nom par `setUser`. Garde : `tests/test_draco_barre.py` | Signalé par Bruno le 2026-11-08 (captures). Fiche `docs/features/entree-sso-bug-123-124.md`. Redéploiement Docker requis |
|
||||
| *BUG-125* | Aller-retour SSO : le retour est honoré mais le pont de l'application sœur ne reçoit aucun cookie `draco_session` quand les cookies `access_token` et `draco_session` ont disparu alors que la session semble encore valide en `sessionStorage` — le chemin court d'`initAuth()` (BUG-123) repart sans aucun échange serveur, donc sans la réémission du cookie draco par `DracoRenewalMiddleware` ; côté sœur : jeton absent au pont = redirection vers le formulaire **nu, sans message** (à distinguer de l'échec de résolution, qui affiche le bandeau `draco=echec`, et du rôle « aucun », qui affiche une page 403) | 🟢 corrigé | P1 | 📱 frontend | IA | `frontend/js/auth.js` (`initAuth`) | Pile « conteneur dev réel » : login chez ObsiGate, suppression des cookies `draco_session` + `access_token` (cookie refresh conservé), Kanbante → clic SSO → la requête du pont part **sans cookie draco** (journalisée) → formulaire Kanbante nu ; un second clic, lui, aboutit (le premier passage a provoqué la réémission) | À l'arrivée d'un `/sso/authorize` (`return_to` présent), le chemin court est écarté : `initAuth()` passe par le refresh silencieux + `/api/auth/me`, dont la réponse traverse le middleware de renouvellement qui réémet le cookie draco manquant ou invalide **avant** que le retour soit honoré ; si le refresh échoue, écran de connexion comme avant (le `return_to` reste dans l'URL). Garde : `tests/test_draco_barre.py` (`test_retour_sso_refresh_force_bug_125`) ; preuve navigateur : la variante fautive de la pile retourne connectée après correctif | Signalé par Bruno le 2026-11-08 (retest réel après BUG-123 + retour sur le bon hôte) ; diagnostic complet (formes d'échec du pont cartographiées en pile) dans le dossier `preuve-retour-sso-hote`. Fiche `docs/features/retour-sso-cookie-draco-bug-125.md`. Redéploiement Docker requis |
|
||||
|
||||
| # | Titre | Statut | Priorité | Scope | Assigné | Zone (fichier) | Cmd de repro | Correctif / Commit | Notes |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
@@ -366,6 +367,7 @@ Avant de corriger quoi que ce soit, un agent IA doit :
|
||||
| 2026-10-25 | BUG-120 (suite #223) | Correction | `backend/draco_config.py`, `tests/test_draco_config.py`, `.env.example`, `CHANGELOG.md`, `docs/ISSUES_TODOLIST.md`, `docs/ROADMAP.md`, `docs/features/devprod-urls-config-223.md` | **BUG-120 — le menu inter-apps de la dev pointait la prod** : `window.DRACO_URLS` servait l'agent en `-dev` mais les quatre sœurs en noms officiels, le `.env` dev ne déclarant pas les `DRACO_<APP>_URL`. Correctif dans `draco_config.app_url()` : après l'explicite, **dérivation d'environnement** — hôte de `agent_url()` de la forme `agent<SUFFIXE>.dracodev.net` sans port → sœur en `<slug><SUFFIXE>.dracodev.net` ; hors motif (autre domaine, LAN, IP, port) aucune dérivation ; Gitea jamais dérivée. Vérifié : `test_draco_config.py` 16 passed, suite complète **1668 passed / 9 skipped**, ruff 0 et mypy 0 sur les fichiers touchés (51 erreurs ruff préexistantes ailleurs, inchangées) | 🟢 corrigé (en attente vérif utilisateur) |
|
||||
| 2026-11-06 | BUG-122 (fusion #141) | Correction | `backend/routers/sso.py`, `backend/auth/router.py`, `tests/test_draco_session.py`, `CHANGELOG.md`, `docs/ISSUES_TODOLIST.md`, `docs/features/deconnexion-globale-bug-122.md`, `VERSION` (+ dérivés) | **BUG-122 — la déconnexion du menu compte ne terminait rien hors ObsiGate** : ajout de `GET /sso/logout`, point d'entrée navigable de la déconnexion globale (logique partagée avec `POST /api/auth/logout`). Vérifié : `test_draco_session.py` 34 passed, ruff 0 et mypy 0 sur les fichiers touchés | 🟢 corrigé (en attente vérif utilisateur) |
|
||||
| 2026-11-08 | BUG-123 + BUG-124 (chantier entrée SSO) | Correction | `frontend/js/auth.js`, `frontend/index.html`, `frontend/draco-barre.js`, `tests/test_draco_barre.py`, `CHANGELOG.md`, `docs/ISSUES_TODOLIST.md`, `docs/ROADMAP.md`, `docs/features/entree-sso-bug-123-124.md`, `VERSION` (+ dérivés) | **BUG-123 — aller-retour SSO refermé à la restauration de session** : `initAuth()` honore le `return_to` sur ses deux chemins de restauration (jeton valide, refresh silencieux au démarrage), comme le faisait déjà `saveToken` après un login frais. **BUG-124 — nom du compte dans la barre dès le login** : barre commune re-vendangée en v0.7.0 (`DRACO_BAR.setUser`, PR dracodev-commons #15), branchée dans `renderUserSection()` et le fetch d'amorçage. Chaînes prouvées en navigateur réel (pile locale aux noms publics, scénario de Bruno) | 🟢 corrigé (en attente vérif utilisateur) |
|
||||
| 2026-11-08 | BUG-125 (suite entrée SSO) | Correction | `frontend/js/auth.js`, `tests/test_draco_barre.py`, `CHANGELOG.md`, `docs/ISSUES_TODOLIST.md`, `docs/ROADMAP.md`, `docs/features/retour-sso-cookie-draco-bug-125.md`, `VERSION` (+ dérivés) | **BUG-125 — retour SSO honoré mais pont sans cookie draco** : quand les cookies `access_token` et `draco_session` ont disparu alors que `sessionStorage` croit la session valide, le chemin court d'`initAuth()` repartait sans échange serveur — aucune réémission du cookie draco — et le pont de l'application sœur, sans jeton, déposait l'utilisateur devant son formulaire nu. Correctif : avec `return_to`, `initAuth()` force le refresh silencieux + `/api/auth/me` (réémission par `DracoRenewalMiddleware`) avant d'honorer le retour. Reproduit puis vérifié en navigateur réel dans la pile « conteneur dev réel » (requête du pont journalisée : sans cookie avant, avec cookie après) | 🟢 corrigé (en attente vérif utilisateur) |
|
||||
|
||||
---
|
||||
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
# ObsiGate — Roadmap
|
||||
|
||||
> **Version :** 2.86.2 | **Dernière mise à jour :** 2026-11-08
|
||||
> **Version :** 2.86.3 | **Dernière mise à jour :** 2026-11-08
|
||||
> **Ce fichier ne contient que le travail à venir** (🔵 En cours + ⚪ Backlog) et un index compact
|
||||
> vers les fonctionnalités livrées.
|
||||
> - **Méthode de livraison à appliquer pour toute tâche : [DELIVERY_WORKFLOW.md](./DELIVERY_WORKFLOW.md)**
|
||||
@@ -1229,6 +1229,7 @@
|
||||
| 225 | Panneau Spark — version du service d'agents visible en mode sidebar (pied du panneau, lue en direct via `GET /healthz`) | 2.79.0 | [features/fusion-panneau-version-agent-225.md](./features/fusion-panneau-version-agent-225.md) |
|
||||
| BUG-123 | Aller-retour SSO — le `return_to` de `/sso/authorize` est honoré aussi après restauration de session au démarrage (`initAuth`), pas seulement après un login frais | Unreleased | [features/entree-sso-bug-123-124.md](./features/entree-sso-bug-123-124.md) |
|
||||
| BUG-124 | Barre commune v0.7.0 — `DRACO_BAR.setUser` branché dans `renderUserSection()` : le nom du compte s'affiche dans le menu compte dès le login, sans rechargement | Unreleased | [features/entree-sso-bug-123-124.md](./features/entree-sso-bug-123-124.md) |
|
||||
| BUG-125 | Aller-retour SSO — à l'arrivée d'un `/sso/authorize`, `initAuth` force le refresh silencieux + `/api/auth/me` pour que le cookie `draco_session` soit réémis avant que le retour soit honoré (pont sœur sans jeton = formulaire nu) | Unreleased | [features/retour-sso-cookie-draco-bug-125.md](./features/retour-sso-cookie-draco-bug-125.md) |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
# Retour SSO — cookie draco réémis avant le retour (BUG-125)
|
||||
|
||||
Suite du chantier « entrée SSO de bout en bout » : retest réel de
|
||||
Bruno le 2026-11-08, après la fusion de BUG-123/BUG-124 (2.86.2)
|
||||
et du correctif « l'hôte de la requête fait foi » côté applications
|
||||
sœurs (Kanbante 0.46.9). Le retour tombe désormais sur le bon
|
||||
hôte, mais l'utilisateur arrive devant le formulaire de
|
||||
l'application sœur, **sans message d'erreur** — pas connecté.
|
||||
|
||||
## Diagnostic (pile « conteneur dev réel », navigateur réel)
|
||||
|
||||
Les formes d'échec du pont Kanbante ont d'abord été
|
||||
cartographiées une à une (jetons forgés/révoqués, compte lié
|
||||
désactivé, rôle « aucun » au registre du Hub) :
|
||||
|
||||
| Cause au pont | Arrivée |
|
||||
|---|---|
|
||||
| Jeton valide, correspondance saine | session ouverte |
|
||||
| Échec de résolution (compte lié désactivé) | `/login?draco=echec` **avec bandeau** |
|
||||
| Rôle « aucun » au registre | page **403 explicite** |
|
||||
| Jeton absent, illisible (signature) ou **révoqué** | `/login` **nu, sans signal** |
|
||||
|
||||
Le formulaire nu de Bruno ne peut donc venir que de la dernière
|
||||
ligne : au moment du pont, aucun jeton draco valide n'est
|
||||
présenté. La variante qui le reproduit à l'identique :
|
||||
|
||||
1. login chez ObsiGate (session établie, `sessionStorage`
|
||||
alimenté) ;
|
||||
2. suppression des cookies `access_token` et `draco_session`
|
||||
(le cookie `refresh_token`, 7 j, est conservé) ;
|
||||
3. Kanbante → « Se connecter avec ObsiGate (SSO) » ;
|
||||
4. la SPA honore le `return_to` par son chemin court
|
||||
(`sessionStorage` encore « valide ») — **aucun échange
|
||||
serveur** ;
|
||||
5. la requête du pont part **sans cookie `draco_session`**
|
||||
(journalisée) → Kanbante répond `303 /login`, formulaire nu.
|
||||
|
||||
Un second clic, lui, aboutit : le premier passage chez ObsiGate
|
||||
a provoqué entre-temps la réémission du cookie (activité
|
||||
authentifiée traversant `DracoRenewalMiddleware`).
|
||||
|
||||
## Cause racine
|
||||
|
||||
La réémission du cookie `draco_session` est opportuniste :
|
||||
`DracoRenewalMiddleware` ne peut la poser que sur la réponse
|
||||
d'une requête portant un cookie `access_token` natif valide.
|
||||
Le chemin court d'`initAuth()` (session « valide » en
|
||||
`sessionStorage`, ajouté pour BUG-123) redirige vers
|
||||
l'application sœur **sans aucune requête authentifiée** : si
|
||||
les deux cookies ont disparu indépendamment de la session
|
||||
(cookies purgés séparément, profil restauré, domaines nettoyés
|
||||
à des rythmes différents — le cookie draco vit 12 h,
|
||||
l'`access_token` 1 h, le refresh 7 j et `sessionStorage`
|
||||
suit sa propre logique d'onglet), rien ne réémet le cookie
|
||||
avant le départ, et le pont sœur est muet par construction
|
||||
(un jeton absent est indiscernable d'un visiteur jamais
|
||||
connecté).
|
||||
|
||||
## Correctif (`frontend/js/auth.js`, `initAuth()`)
|
||||
|
||||
Quand la page est l'arrivée d'un `/sso/authorize`
|
||||
(`return_to` présent dans l'URL), le chemin court est
|
||||
écarté : `initAuth()` emprunte toujours le chemin du refresh
|
||||
silencieux — `POST /api/auth/refresh` (rotation, pose un
|
||||
nouvel `access_token`) puis `GET /api/auth/me`, dont la
|
||||
requête porte ce cookie et dont la réponse traverse
|
||||
`DracoRenewalMiddleware` : le cookie draco absent, invalide
|
||||
ou en fenêtre de renouvellement est réémis **avant**
|
||||
`_honorReturnTo()`. Si le refresh échoue (plus de session
|
||||
centrale réelle), l'écran de connexion s'affiche comme
|
||||
avant et le `return_to`, toujours dans l'URL, sera honoré
|
||||
par `saveToken` après login frais.
|
||||
|
||||
Hors arrivée `authorize`, le démarrage est strictement
|
||||
inchangé (chemin court conservé pour les visites directes
|
||||
d'ObsiGate) ; les refresh en cours de session ne redirigent
|
||||
toujours jamais.
|
||||
|
||||
## Garde et preuve
|
||||
|
||||
- `tests/test_draco_barre.py::test_retour_sso_refresh_force_bug_125`
|
||||
(test épinglé : le chemin court est conditionné à l'absence
|
||||
de `return_to`, et le compte d'appels `_honorReturnTo` de
|
||||
BUG-123 reste à 2).
|
||||
- Preuve navigateur dans la pile « conteneur dev réel »
|
||||
(dossier `preuve-retour-sso-hote`, scripts `diag-*.py`) :
|
||||
la variante fautive retourne **connectée** après correctif,
|
||||
la requête du pont portant le cookie draco réémis.
|
||||
|
||||
## Périmètre
|
||||
|
||||
Ce correctif ferme le mécanisme « retour honoré sans cookie »
|
||||
côté émettrice. Les deux autres formes silencieuses relevées
|
||||
au diagnostic relèvent d'autres gestes, inchangés : jeton
|
||||
révoqué (déconnexion globale, révocation de session au Hub —
|
||||
guéri par une reconnexion ou une activité chez ObsiGate) et
|
||||
jeton illisible pour une application sœur (secret partagé
|
||||
propre à son conteneur — permanent tant que la configuration
|
||||
n'est pas alignée).
|
||||
+22
-1
@@ -503,8 +503,29 @@ const AuthManager = {
|
||||
return true;
|
||||
}
|
||||
|
||||
// BUG-125 : la page est-elle l'arrivée d'un /sso/authorize
|
||||
// (return_to présent) ? Si oui, le chemin court ci-dessous ne
|
||||
// doit PAS s'appliquer : il repartait vers l'application
|
||||
// sœur sans aucun échange serveur, donc sans laisser au
|
||||
// middleware de renouvellement (DracoRenewalMiddleware)
|
||||
// l'occasion de réémettre le cookie draco_session. Quand les
|
||||
// cookies access_token et draco_session ont disparu alors
|
||||
// que la session semble encore valide en sessionStorage
|
||||
// (cookies purgés séparément, profil restauré), le pont de
|
||||
// l'application sœur ne recevait AUCUN cookie : jeton absent
|
||||
// = formulaire nu, sans message, côté sœur. En forçant le
|
||||
// refresh silencieux ci-dessous (cookie refresh 7 j) suivi
|
||||
// de /api/auth/me — dont la requête porte le nouvel
|
||||
// access_token et dont la réponse traverse le middleware —
|
||||
// le cookie draco manquant ou invalide est réémis AVANT que
|
||||
// le retour soit honoré. Si le refresh échoue, l'écran de
|
||||
// connexion s'affiche comme avant (le return_to reste dans
|
||||
// l'URL et saveToken l'honorera après login frais).
|
||||
const retourDemande = new URLSearchParams(
|
||||
window.location.search).get("return_to");
|
||||
|
||||
// Auth enabled — check for existing session
|
||||
if (this.hasSession() && !this.isTokenExpired()) {
|
||||
if (this.hasSession() && !this.isTokenExpired() && !retourDemande) {
|
||||
// BUG-123 : session déjà établie au démarrage (jeton encore
|
||||
// valide) — si la page a été ouverte par /sso/authorize avec
|
||||
// un return_to, l'aller-retour SSO doit se refermer ici
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "obsigate",
|
||||
"version": "2.86.2",
|
||||
"version": "2.86.3",
|
||||
"description": "**Porte d'entrée web ultra-léger pour vos vaults Obsidian** — Accédez, naviguez et recherchez dans toutes vos notes Obsidian depuis n'importe quel appareil via une interface web moderne et responsive.",
|
||||
"main": "patch.js",
|
||||
"directories": {
|
||||
|
||||
@@ -164,6 +164,33 @@ def test_barre_v070_setuser_et_retour_sso_restauration():
|
||||
assert "this._honorReturnTo();\n }," in auth_js
|
||||
|
||||
|
||||
def test_retour_sso_refresh_force_bug_125():
|
||||
# BUG-125 (suite du chantier « entrée SSO », retest réel de
|
||||
# Bruno le 2026-11-08 après BUG-123) : à l'arrivée d'un
|
||||
# /sso/authorize (return_to présent), le chemin court
|
||||
# d'initAuth (« session valide en sessionStorage ») repartait
|
||||
# sans aucun échange serveur — donc sans réémission du
|
||||
# cookie draco_session par DracoRenewalMiddleware. Cookies
|
||||
# access_token et draco_session absents (sessionStorage
|
||||
# encore « valide ») : le pont de l'application sœur ne
|
||||
# recevait aucun jeton et déposait l'utilisateur devant son
|
||||
# formulaire, sans message (reproduit en navigateur réel
|
||||
# dans la pile « conteneur dev réel », requête du pont
|
||||
# journalisée sans cookie draco). Garde : le chemin court
|
||||
# est conditionné à l'ABSENCE de return_to ; avec return_to,
|
||||
# initAuth passe par le refresh silencieux + /api/auth/me
|
||||
# (réémission du cookie) avant d'honorer le retour — le
|
||||
# nombre d'appels _honorReturnTo des chemins de restauration
|
||||
# reste celui de BUG-123 (2).
|
||||
auth_js = (FRONTEND / "js" / "auth.js").read_text(encoding="utf-8")
|
||||
assert 'get("return_to")' in auth_js
|
||||
assert "&& !retourDemande) {" in auth_js
|
||||
bloc = auth_js.split("async initAuth()", 1)[1]
|
||||
assert bloc.index("!retourDemande") < bloc.index(
|
||||
"await this.refreshAccessToken()")
|
||||
assert auth_js.count("if (this._honorReturnTo()) return true;") == 2
|
||||
|
||||
|
||||
def test_panneau_spark_integre_218():
|
||||
# #218 : le bouton Spark de la barre ouvre le panneau de l'agent
|
||||
# commun (mêmes assets partagés que TikTak / Flowdeck / Kanbante).
|
||||
|
||||
Reference in New Issue
Block a user