feat: HUB-21 — réglages généraux du Hub consommés par ObsiGate (bannière + drapeau recherche_partout) #229
This commit is contained in:
+23
-1
@@ -1,6 +1,6 @@
|
||||
# ObsiGate — Roadmap
|
||||
|
||||
> **Version :** 2.85.1 | **Dernière mise à jour :** 2026-11-06
|
||||
> **Version :** 2.85.2 | **Dernière mise à jour :** 2026-11-06
|
||||
> **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)**
|
||||
@@ -70,6 +70,28 @@
|
||||
- [x] Garde `require_admin_hub` sur les routes `/api/auth/admin/*`
|
||||
- [x] Tests `tests/test_hub_roles.py` (client + intégration du chemin draco)
|
||||
|
||||
### 229. Hub HUB-21 — consommation des réglages généraux du Hub par ObsiGate
|
||||
|
||||
- **Effort :** ~0,5 jour | **Impact :** 🟡 | **Ouvert :** 2026-11-06 | **Statut :** ✅ livré en 2.85.2 (voir CHANGELOG ; PR en attente de fusion ; redéploiement Docker requis)
|
||||
- **Fiche :** [features/hub-reglages-obsigate-229.md](./features/hub-reglages-obsigate-229.md)
|
||||
- **Description :** propagation de HUB-21 (pilote TikTak 0.61.22, liste
|
||||
fermée D6(a)) : consultation côté serveur de
|
||||
`GET {hub}/api/reglages/effectifs` (endpoint public, délai 2 s),
|
||||
cache mémoire 60 s (horodatage posé avant l'appel), repli intégral
|
||||
sur les défauts actuels si le Hub est muet, en erreur ou de forme
|
||||
inattendue. Bannière d'annonce injectée sous la barre commune (page
|
||||
principale et /recherche, texte échappé, fermable, masquage
|
||||
mémorisé en `sessionStorage`) ; drapeau `recherche_partout` rendu
|
||||
en `data-recherche-partout` de la page /recherche — faux = partie
|
||||
fédérée désactivée, recherche locale intacte. `domaine_defaut`
|
||||
**non consommé** : pas de notion de domaine propre à ObsiGate (le
|
||||
sélecteur de la barre pilote le panneau Spark).
|
||||
- **Sous-tâches :**
|
||||
- [x] Client `backend/hub_reglages.py` (forme D6(a), cache/repli, URL du Hub résolue comme la barre — `draco_config.app_url("hub")`)
|
||||
- [x] Bannière injectée (`backend/main.py::_fragment_banniere_hub`, `_index_html`, `serve_recherche_page`) + styles `frontend/style.css`
|
||||
- [x] Jeton `{{RECHERCHE_PARTOUT}}` dans `frontend/recherche.html` + branchement du JS vendangé `frontend/js/recherche.js`
|
||||
- [x] Tests `tests/test_hub_reglages.py` (client + intégration) et `tests/frontend/recherche.test.mjs` étendu
|
||||
|
||||
### 226. Hub HUB-13 — API d'administration des comptes (machine-à-machine)
|
||||
|
||||
- **Effort :** ~0,5 jour | **Impact :** 🟡 | **Ouvert :** 2026-11-05 | **Statut :** ✅ livré en 2.84.0 (PR en attente de fusion — voir CHANGELOG ; redéploiement Docker requis)
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
# #229 — HUB-21 : consommation des réglages généraux du Hub par ObsiGate
|
||||
|
||||
**Carte :** propagation de HUB-21 (fusion #135) — le pilote TikTak
|
||||
(0.61.22, en production) a posé le patron de client ; ObsiGate le
|
||||
consomme à son tour, comme les autres hôtes de la suite.
|
||||
**Version cible :** 2.85.2 (branche depuis le main 2.85.1).
|
||||
|
||||
## Contrat consommé (liste fermée D6(a))
|
||||
|
||||
- `GET {hub}/api/reglages/effectifs` — endpoint **public** (aucun
|
||||
cookie relayé), `Accept: application/json`, délai **2 s** ;
|
||||
- réponse 200, forme figée : `{"recherche_partout": bool,
|
||||
"banniere": str, "domaine_defaut": "pro"|"famille"|"perso"|null,
|
||||
"ttl_secondes": 60}`, `Cache-Control: public, max-age=60` ;
|
||||
- **URL du Hub** : `draco_config.app_url("hub")`, la résolution de la
|
||||
barre commune (#223) — variable explicite d'abord, dérivation par
|
||||
l'hôte sœur ensuite, défaut officiel enfin. Jamais d'URL dev figée.
|
||||
|
||||
## Client — `backend/hub_reglages.py`
|
||||
|
||||
Sur le patron du pilote TikTak (`app/hub_reglages.py`, httpx → urllib
|
||||
comme `backend/hub_roles.py`) :
|
||||
|
||||
- cache mémoire **60 s** ; horodatage posé **avant** l'appel : un
|
||||
échec conserve l'ancien cache et ne déclenche pas de rafale vers un
|
||||
Hub en panne ;
|
||||
- forme validée strictement ; toute erreur (réseau, délai, statut
|
||||
≠ 200, JSON illisible, forme hors contrat) → **repli intégral** sur
|
||||
les défauts actuels (`recherche_partout: true`, `banniere: ""`,
|
||||
`domaine_defaut: null`) — le comportement d'ObsiGate avant HUB-21.
|
||||
Le module ne lève jamais ; aucun appel au démarrage.
|
||||
|
||||
## Consommation
|
||||
|
||||
1. **`banniere`** — `backend/main.py::_fragment_banniere_hub()`
|
||||
construit le fragment (texte **échappé** via `html.escape`, jamais
|
||||
de HTML injecté), injecté sous la barre commune par `_index_html`
|
||||
(page principale, juste avant le rappel de la barre) et par
|
||||
`serve_recherche_page` (page /recherche, après l'en-tête de la
|
||||
barre). Le script inline (nonce CSP ajouté par `inject_csp_nonce`)
|
||||
révèle le bandeau sauf si le même texte a été fermé dans la
|
||||
session du navigateur (`sessionStorage`, clé
|
||||
`obsigate_banniere_masquee`) : une nouvelle annonce réapparaît.
|
||||
Bannière vide = aucun fragment rendu, zéro changement visuel.
|
||||
Styles `.banniere-hub*` dans `frontend/style.css`, sur les
|
||||
variables du thème (`var(--accent)`).
|
||||
2. **`recherche_partout`** — `serve_recherche_page` remplace le jeton
|
||||
`{{RECHERCHE_PARTOUT}}` de `frontend/recherche.html`, rendu en
|
||||
attribut `data-recherche-partout` du `<main id="recherche">`. Le
|
||||
JS vendangé `frontend/js/recherche.js` (modification identique
|
||||
dans les 4 hôtes applicatifs : fonction pure
|
||||
`federationAutorisee`) n'interroge plus les applications sœurs ni
|
||||
la console quand la valeur est `false` — leurs sections affichent
|
||||
« Recherche fédérée désactivée… » — tandis que la recherche locale
|
||||
ObsiGate (même origine) continue. Attribut absent ou illisible =
|
||||
fédération active (repli).
|
||||
3. **`domaine_defaut` — non consommé.** ObsiGate n'a pas de notion
|
||||
de domaine (Pro/Famille/Perso) propre à ses vues : le sélecteur de
|
||||
domaine de la barre commune pilote le panneau Spark, pas
|
||||
ObsiGate. La valeur est lue et validée par le client, sans effet
|
||||
local. Seul l'hôte console (agent) applique ce réglage.
|
||||
|
||||
## i18n
|
||||
|
||||
Aucun texte d'interface du SPA n'est ajouté : la bannière est un
|
||||
contenu d'annonce servi par le Hub (texte libre de l'administrateur),
|
||||
et le libellé « Fermer l'annonce » est l'attribut d'accessibilité du
|
||||
fragment injecté côté serveur, sur le même patron que les autres
|
||||
hôtes. Pas de clé `frontend/locales/*` ajoutée.
|
||||
|
||||
## Tests
|
||||
|
||||
- `tests/test_hub_reglages.py` (nouveau) : contrat exact de l'appel
|
||||
(URL, aucun cookie, délai 2 s), formes inattendues → repli, erreur
|
||||
HTTP / Hub injoignable / JSON illisible → repli, cache 60 s,
|
||||
ancien cache conservé sans rafale ; intégration TestClient :
|
||||
bannière présente et échappée sur `/` et `/recherche`, absente si
|
||||
vide ou Hub muet, `data-recherche-partout` selon la valeur du
|
||||
drapeau (faux / vrai / Hub muet).
|
||||
- `tests/frontend/recherche.test.mjs` : assertions ajoutées pour
|
||||
`federationAutorisee` (seules les valeurs explicitement négatives
|
||||
désactivent ; absent/illisible = actif).
|
||||
Reference in New Issue
Block a user