cookie flowdeck_session seulement (sa PR corrige cela)
{fd}/pages/<id>, {fd}/db/<id>
TikTak
GET /api/search?q= (et /api/v1/search)
session native, cookie SSO draco_session, ou Bearer tck_…
{tk}/search?q=<q>&task=<id>
Kanbante
aucun endpoint JSON — page SSR GET /search uniquement (sa PR fournit GET /api/search)
—
{kb}/board/<owner>/<repo> (la carte n'a pas d'URL propre adressable)
Console agent-commun
aucun endpoint de recherche des discussions ; l'agent n'est pas un hôte de la barre
—
—
Conséquence honnête : pas de section Console (rien à agréger sans inventer une API). L'endpoint ObsiGate existait déjà et n'est pas modifié — seule sa lisibilité cross-origin change (voir ci-dessous).
Architecture choisie : page par hôte + agrégation côté client
Identique aux autres PR du chantier (voir PR TikTak #220 pour l'argumentaire complet) : pas de hub central (SPOF, dépendance runtime entre apps), pas de proxy fan-out serveur (l'hôte ne possède pas de credential sœur sans créer un relais d'identité générique). La page appelle les 4 API en parallèle depuis le navigateur (credentials: "include" : cookies de chaque origine, dont le SSO partagé draco_session, Domain=.dracodev.net), avec debounce 250 ms, timeout 8 s par section, et états chargement/vide/erreur par application. Résolution des bases : data-base-* rendus par l'hôte > DRACO_BAR.urls (barre v0.1.6) > dérivation -dev > href des onglets > défauts prod. Aucun fichier ui/barre-apps.* touché. Clavier : / ou Ctrl+K focalise la recherche, ↑/↓ navigue, Entrée ouvre, Échap efface.
Ce qui change (ObsiGate)
frontend/recherche.html (nouveau) + frontend/js/recherche.js (nouveau, logique partagée du chantier) + frontend/recherche.css (nouveau) : page GET /recherche avec 4 sections (ObsiGate, Flowdeck, TikTak, Kanbante), titre/extrait/contexte par résultat, liens profonds. La page est volontairement autonome (navigation minimale) : le fragment de barre vit dans index.html, la SPA — la dupliquer ici créerait deux barres à maintenir.
backend/main.py : route GET /recherche déclarée avant le catch-all SPA (comme /admin.html, sinon index.html serait servi). Elle sert frontend/recherche.html avec les jetons {{URL_*}} remplacés par urls_publiques() (même contrat que le fragment de barre) et le nonce CSP frais ; elle pose sa propre CSP (préservée par SecurityHeadersMiddleware, qui ne la pose que si elle est absente) dont le connect-src autorise les origines sœurs — sinon le navigateur bloquerait les appels sœurs avant même CORS. La CSP par défaut reste inchangée pour toutes les autres pages. La page n'exige pas d'authentification propre (comme index.html) : ce sont les API appelées qui authentifient.
backend/recherche_cors.py (nouveau, ASGI pur) + backend/main.py : CORS bornée pour GET /api/search uniquement — origines sœurs de urls_publiques(), plus les origines prod ou -dev officielles de l'environnement de la requête (couverture du cas où la configuration seule ne déclare pas l'environnement courant). Jamais *, jamais d'autre route, jamais d'écriture. Le middleware est ajouté après le CORSMiddleware global (donc exécuté avant lui) et répond lui-même aux preflights OPTIONS. La politique same-origin explicite du middleware global (allow_origins=[], #87 T8) reste la règle par défaut pour tout le reste — cette PR ne la perce que pour GET /api/search et les origines sœurs.
frontend/index.html : 1 ligne — l'action palette de la barre va désormais sur /recherche au lieu de focaliser le champ de recherche interne. La recherche interne de la SPA (champ, palette, /api/search avancée) reste inchangée. Vérifié : le fichier poussé ne diffère de main que par cette ligne.
Tests : tests/test_recherche_cors.py (pytest, 6 tests) + tests/frontend/recherche.test.mjs (Node ESM, sans jsdom, 8 assertions : résolution, lien profond ObsiGate, repli TikTak). Le JS partagé a été durci pour l'ESM (globalThis, frontend/js étant "type": "module") — même version repoussée sur les branches TikTak, Kanbante et Flowdeck.
/api/search lui-même est inchangé (auth et format déjà adaptés : draco accepté, vault/path/title/snippet exposés).
Limites connues (à valider après déploiement)
Les sections Flowdeck, TikTak et Kanbante restent en erreur tant que leurs PR respectives (draco + 401, CORS bornée, endpoint JSON) ne sont pas déployées — comportement prévu, pas une régression.
La page /recherche n'embarque pas la barre complète (voir ci-dessus) ; l'entrée se fait par le bouton « Rechercher partout » de la barre dans la SPA.
Validation en direct (clic réel sur chaque lien profond, depuis og-dev et og) à faire par Bruno après redéploiement — non vérifiable depuis la sandbox (pas d'accès aux instances).
Tests (chiffres réels, exécutés le 2026-10-28)
node tests/frontend/recherche.test.mjs (miroir local de l'arborescence) : 8 assertions OK ; node tests/recherche.test.js (logique partagée complète) : 25 assertions OK ; import ESM du JS vérifié.
Vérification Python de backend/recherche_cors.py (chargé par chemin, pytest absent de la sandbox) : assertions OK — origines sœurs dev, ajout de l'environnement de la requête, refus tiers, preflight, middleware ASGI (preflight sœur → 204 + Access-Control-Allow-Origin exact, autre route → aucun en-tête ajouté).
python3 -m py_compile sur backend/main.py, backend/recherche_cors.py, tests/test_recherche_cors.py : OK.
Diff branche vs main vérifié après push : backend/main.py+76 / −0 lignes (les 2 insertions seules), frontend/index.html1 ligne changée.
Non exécutés ici (dépendances applicatives absentes de la sandbox) : pytest tests/test_recherche_cors.py et le serveur — à valider en CI / après déploiement. Zéro régression revendiquée au-delà de ce qui est mesuré ci-dessus.
Rebase de la PR #40 sur main post-#70 et post-#69 (conflits frontend/index.html et backend/main.py résolus : suppression du bouton ••• et du relais menu de #70 et contenu alertes #69 conservés, palette → /recherche appliquée, middleware CORS et route /recherche de #68 ajoutés sans retirer la CSP sœurs #69. Contenu par ailleurs identique à #40.
## Rechercher partout — page de résultats unifiée + CORS bornée /api/search (fusion #68, chantier 1)
Branche `recherche-partout-68` → `main`. Ne pas merger sans le go du coordinateur ; aucune version bumpée, aucune issue fermée par cette PR.
### Audit des endpoints de recherche réels (vérifié sur `main`, 2026-10-28)
| App | Endpoint JSON | Auth acceptée | Lien profond vérifié |
|---|---|---|---|
| ObsiGate | `GET /api/search?q=&vault=all&limit=` (`backend/routers/search.py`, `SearchResponse.results[] : vault, path, title, snippet`) | Bearer `access_token`, cookie `access_token`, ou repli cookie SSO `draco_session` (`backend/auth/middleware.py`) | `{og}/#file={vault}:{path}` (`frontend/js/app.js` : `Viewer.openFile`) |
| Flowdeck | `GET /api/search?q=` | cookie `flowdeck_session` seulement (sa PR corrige cela) | `{fd}/pages/<id>`, `{fd}/db/<id>` |
| TikTak | `GET /api/search?q=` (et `/api/v1/search`) | session native, cookie SSO `draco_session`, ou Bearer `tck_…` | `{tk}/search?q=<q>&task=<id>` |
| Kanbante | **aucun endpoint JSON** — page SSR `GET /search` uniquement (sa PR fournit `GET /api/search`) | — | `{kb}/board/<owner>/<repo>` (la carte n'a pas d'URL propre adressable) |
| Console agent-commun | **aucun endpoint de recherche** des discussions ; l'agent n'est pas un hôte de la barre | — | — |
Conséquence honnête : **pas de section Console** (rien à agréger sans inventer une API). L'endpoint ObsiGate existait déjà et n'est pas modifié — seule sa lisibilité cross-origin change (voir ci-dessous).
### Architecture choisie : page par hôte + agrégation côté client
Identique aux autres PR du chantier (voir PR TikTak #220 pour l'argumentaire complet) : pas de hub central (SPOF, dépendance runtime entre apps), pas de proxy fan-out serveur (l'hôte ne possède pas de credential sœur sans créer un relais d'identité générique). La page appelle les 4 API en parallèle depuis le navigateur (`credentials: "include"` : cookies de chaque origine, dont le SSO partagé `draco_session`, `Domain=.dracodev.net`), avec debounce 250 ms, timeout 8 s par section, et états chargement/vide/erreur **par application**. Résolution des bases : `data-base-*` rendus par l'hôte > `DRACO_BAR.urls` (barre v0.1.6) > dérivation `-dev` > href des onglets > défauts prod. Aucun fichier `ui/barre-apps.*` touché. Clavier : `/` ou Ctrl+K focalise la recherche, ↑/↓ navigue, Entrée ouvre, Échap efface.
### Ce qui change (ObsiGate)
- `frontend/recherche.html` (nouveau) + `frontend/js/recherche.js` (nouveau, logique partagée du chantier) + `frontend/recherche.css` (nouveau) : page `GET /recherche` avec 4 sections (ObsiGate, Flowdeck, TikTak, Kanbante), titre/extrait/contexte par résultat, liens profonds. La page est volontairement autonome (navigation minimale) : le fragment de barre vit dans `index.html`, la SPA — la dupliquer ici créerait deux barres à maintenir.
- `backend/main.py` : route `GET /recherche` déclarée **avant** le catch-all SPA (comme `/admin.html`, sinon `index.html` serait servi). Elle sert `frontend/recherche.html` avec les jetons `{{URL_*}}` remplacés par `urls_publiques()` (même contrat que le fragment de barre) et le nonce CSP frais ; elle pose sa propre CSP (préservée par `SecurityHeadersMiddleware`, qui ne la pose que si elle est absente) dont le `connect-src` autorise les origines sœurs — sinon le navigateur bloquerait les appels sœurs avant même CORS. La CSP par défaut reste inchangée pour toutes les autres pages. La page n'exige pas d'authentification propre (comme `index.html`) : ce sont les API appelées qui authentifient.
- `backend/recherche_cors.py` (nouveau, ASGI pur) + `backend/main.py` : CORS bornée pour `GET /api/search` uniquement — origines sœurs de `urls_publiques()`, **plus** les origines prod ou `-dev` officielles de l'environnement de la requête (couverture du cas où la configuration seule ne déclare pas l'environnement courant). Jamais `*`, jamais d'autre route, jamais d'écriture. Le middleware est ajouté après le `CORSMiddleware` global (donc exécuté avant lui) et répond lui-même aux preflights OPTIONS. **La politique same-origin explicite du middleware global (`allow_origins=[]`, #87 T8) reste la règle par défaut pour tout le reste** — cette PR ne la perce que pour `GET /api/search` et les origines sœurs.
- `frontend/index.html` : **1 ligne** — l'action `palette` de la barre va désormais sur `/recherche` au lieu de focaliser le champ de recherche interne. La recherche interne de la SPA (champ, palette, `/api/search` avancée) reste inchangée. Vérifié : le fichier poussé ne diffère de `main` que par cette ligne.
- Tests : `tests/test_recherche_cors.py` (pytest, 6 tests) + `tests/frontend/recherche.test.mjs` (Node ESM, sans jsdom, 8 assertions : résolution, lien profond ObsiGate, repli TikTak). Le JS partagé a été durci pour l'ESM (`globalThis`, `frontend/js` étant `"type": "module"`) — même version repoussée sur les branches TikTak, Kanbante et Flowdeck.
- `/api/search` lui-même est **inchangé** (auth et format déjà adaptés : draco accepté, `vault`/`path`/`title`/`snippet` exposés).
### Limites connues (à valider après déploiement)
- Les sections Flowdeck, TikTak et Kanbante restent en erreur tant que leurs PR respectives (draco + 401, CORS bornée, endpoint JSON) ne sont pas déployées — comportement prévu, pas une régression.
- La page `/recherche` n'embarque pas la barre complète (voir ci-dessus) ; l'entrée se fait par le bouton « Rechercher partout » de la barre dans la SPA.
- Validation en direct (clic réel sur chaque lien profond, depuis `og-dev` et `og`) à faire par Bruno après redéploiement — non vérifiable depuis la sandbox (pas d'accès aux instances).
### Tests (chiffres réels, exécutés le 2026-10-28)
- `node tests/frontend/recherche.test.mjs` (miroir local de l'arborescence) : **8 assertions OK** ; `node tests/recherche.test.js` (logique partagée complète) : **25 assertions OK** ; import ESM du JS vérifié.
- Vérification Python de `backend/recherche_cors.py` (chargé par chemin, pytest absent de la sandbox) : **assertions OK** — origines sœurs dev, ajout de l'environnement de la requête, refus tiers, preflight, middleware ASGI (preflight sœur → 204 + `Access-Control-Allow-Origin` exact, autre route → aucun en-tête ajouté).
- `python3 -m py_compile` sur `backend/main.py`, `backend/recherche_cors.py`, `tests/test_recherche_cors.py` : **OK**.
- Diff branche vs `main` vérifié après push : `backend/main.py` **+76 / −0 lignes** (les 2 insertions seules), `frontend/index.html` **1 ligne changée**.
- Non exécutés ici (dépendances applicatives absentes de la sandbox) : `pytest tests/test_recherche_cors.py` et le serveur — à valider en CI / après déploiement. Zéro régression revendiquée au-delà de ce qui est mesuré ci-dessus.
---
Rebase de la PR #40 sur main post-#70 et post-#69 (conflits frontend/index.html et backend/main.py résolus : suppression du bouton ••• et du relais menu de #70 et contenu alertes #69 conservés, palette → /recherche appliquée, middleware CORS et route /recherche de #68 ajoutés sans retirer la CSP sœurs #69. Contenu par ailleurs identique à #40.
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.
Rechercher partout — page de résultats unifiée + CORS bornée /api/search (fusion #68, chantier 1)
Branche
recherche-partout-68→main. Ne pas merger sans le go du coordinateur ; aucune version bumpée, aucune issue fermée par cette PR.Audit des endpoints de recherche réels (vérifié sur
main, 2026-10-28)GET /api/search?q=&vault=all&limit=(backend/routers/search.py,SearchResponse.results[] : vault, path, title, snippet)access_token, cookieaccess_token, ou repli cookie SSOdraco_session(backend/auth/middleware.py){og}/#file={vault}:{path}(frontend/js/app.js:Viewer.openFile)GET /api/search?q=flowdeck_sessionseulement (sa PR corrige cela){fd}/pages/<id>,{fd}/db/<id>GET /api/search?q=(et/api/v1/search)draco_session, ou Bearertck_…{tk}/search?q=<q>&task=<id>GET /searchuniquement (sa PR fournitGET /api/search){kb}/board/<owner>/<repo>(la carte n'a pas d'URL propre adressable)Conséquence honnête : pas de section Console (rien à agréger sans inventer une API). L'endpoint ObsiGate existait déjà et n'est pas modifié — seule sa lisibilité cross-origin change (voir ci-dessous).
Architecture choisie : page par hôte + agrégation côté client
Identique aux autres PR du chantier (voir PR TikTak #220 pour l'argumentaire complet) : pas de hub central (SPOF, dépendance runtime entre apps), pas de proxy fan-out serveur (l'hôte ne possède pas de credential sœur sans créer un relais d'identité générique). La page appelle les 4 API en parallèle depuis le navigateur (
credentials: "include": cookies de chaque origine, dont le SSO partagédraco_session,Domain=.dracodev.net), avec debounce 250 ms, timeout 8 s par section, et états chargement/vide/erreur par application. Résolution des bases :data-base-*rendus par l'hôte >DRACO_BAR.urls(barre v0.1.6) > dérivation-dev> href des onglets > défauts prod. Aucun fichierui/barre-apps.*touché. Clavier :/ou Ctrl+K focalise la recherche, ↑/↓ navigue, Entrée ouvre, Échap efface.Ce qui change (ObsiGate)
frontend/recherche.html(nouveau) +frontend/js/recherche.js(nouveau, logique partagée du chantier) +frontend/recherche.css(nouveau) : pageGET /rechercheavec 4 sections (ObsiGate, Flowdeck, TikTak, Kanbante), titre/extrait/contexte par résultat, liens profonds. La page est volontairement autonome (navigation minimale) : le fragment de barre vit dansindex.html, la SPA — la dupliquer ici créerait deux barres à maintenir.backend/main.py: routeGET /recherchedéclarée avant le catch-all SPA (comme/admin.html, sinonindex.htmlserait servi). Elle sertfrontend/recherche.htmlavec les jetons{{URL_*}}remplacés parurls_publiques()(même contrat que le fragment de barre) et le nonce CSP frais ; elle pose sa propre CSP (préservée parSecurityHeadersMiddleware, qui ne la pose que si elle est absente) dont leconnect-srcautorise les origines sœurs — sinon le navigateur bloquerait les appels sœurs avant même CORS. La CSP par défaut reste inchangée pour toutes les autres pages. La page n'exige pas d'authentification propre (commeindex.html) : ce sont les API appelées qui authentifient.backend/recherche_cors.py(nouveau, ASGI pur) +backend/main.py: CORS bornée pourGET /api/searchuniquement — origines sœurs deurls_publiques(), plus les origines prod ou-devofficielles de l'environnement de la requête (couverture du cas où la configuration seule ne déclare pas l'environnement courant). Jamais*, jamais d'autre route, jamais d'écriture. Le middleware est ajouté après leCORSMiddlewareglobal (donc exécuté avant lui) et répond lui-même aux preflights OPTIONS. La politique same-origin explicite du middleware global (allow_origins=[], #87 T8) reste la règle par défaut pour tout le reste — cette PR ne la perce que pourGET /api/searchet les origines sœurs.frontend/index.html: 1 ligne — l'actionpalettede la barre va désormais sur/rechercheau lieu de focaliser le champ de recherche interne. La recherche interne de la SPA (champ, palette,/api/searchavancée) reste inchangée. Vérifié : le fichier poussé ne diffère demainque par cette ligne.tests/test_recherche_cors.py(pytest, 6 tests) +tests/frontend/recherche.test.mjs(Node ESM, sans jsdom, 8 assertions : résolution, lien profond ObsiGate, repli TikTak). Le JS partagé a été durci pour l'ESM (globalThis,frontend/jsétant"type": "module") — même version repoussée sur les branches TikTak, Kanbante et Flowdeck./api/searchlui-même est inchangé (auth et format déjà adaptés : draco accepté,vault/path/title/snippetexposés).Limites connues (à valider après déploiement)
/recherchen'embarque pas la barre complète (voir ci-dessus) ; l'entrée se fait par le bouton « Rechercher partout » de la barre dans la SPA.og-devetog) à faire par Bruno après redéploiement — non vérifiable depuis la sandbox (pas d'accès aux instances).Tests (chiffres réels, exécutés le 2026-10-28)
node tests/frontend/recherche.test.mjs(miroir local de l'arborescence) : 8 assertions OK ;node tests/recherche.test.js(logique partagée complète) : 25 assertions OK ; import ESM du JS vérifié.backend/recherche_cors.py(chargé par chemin, pytest absent de la sandbox) : assertions OK — origines sœurs dev, ajout de l'environnement de la requête, refus tiers, preflight, middleware ASGI (preflight sœur → 204 +Access-Control-Allow-Originexact, autre route → aucun en-tête ajouté).python3 -m py_compilesurbackend/main.py,backend/recherche_cors.py,tests/test_recherche_cors.py: OK.mainvérifié après push :backend/main.py+76 / −0 lignes (les 2 insertions seules),frontend/index.html1 ligne changée.pytest tests/test_recherche_cors.pyet le serveur — à valider en CI / après déploiement. Zéro régression revendiquée au-delà de ce qui est mesuré ci-dessus.Rebase de la PR #40 sur main post-#70 et post-#69 (conflits frontend/index.html et backend/main.py résolus : suppression du bouton ••• et du relais menu de #70 et contenu alertes #69 conservés, palette → /recherche appliquée, middleware CORS et route /recherche de #68 ajoutés sans retirer la CSP sœurs #69. Contenu par ailleurs identique à #40.