{fd}/pages/<id>, {fd}/db/<id> (émis par le service lui-même)
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).
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 (Flowdeck)
app/templates/recherche.html (nouveau) + static/js/recherche.js (nouveau, logique partagée du chantier) + static/css/recherche.css (nouveau) : page GET /recherche avec 4 sections (ObsiGate, Flowdeck, TikTak, Kanbante), titre/extrait/contexte par résultat, liens profonds.
app/routers/search.py :
GET /recherche (nouveau) : coquille rendue via ENV (même patron que les pages existantes), bases sœurs passées explicitement depuis draco_urls.toutes(). La palette Ctrl+K native est inchangée.
GET /api/search : repli SSO draco_session via le validateur local existant app.services.draco.user_for_draco (même sémantique que TikTak/Kanbante), et authentification désormais requise (401 sinon). Correctif de sécurité préexistant : sans session, la route donnait auparavant une recherche sans périmètre (user_id=None → 1=1 dans _scope_where, tous les espaces) — y compris pour la palette d'un visiteur non connecté. Les résultats d'un utilisateur authentifié restent périmétrés comme avant.
app/middleware/recherche_cors.py (nouveau, ASGI pur) + app/main.py : CORS bornée pour GET /api/search uniquement — origines sœurs résolues par draco_urls.toutes(), plus les origines prod ou -dev officielles de l'environnement de la requête (nécessaire car ce middleware s'exécute avant le middleware CSP qui pose le contexte d'hôte pour draco_urls ; sans cela, une page servie par flowdeck-dev verrait ses sœurs -dev refusées quand la configuration seule ne les déclare pas). Jamais *, jamais d'autre route, jamais d'écriture. Le middleware répond lui-même aux preflights OPTIONS (qui ne portent jamais de cookies). La politique CORS globale est inchangée.
app/middleware/security.py (ContentSecurityPolicyMiddleware) : connect-src de la page /recherche uniquement, étendue aux origines sœurs (ObsiGate, TikTak, Kanbante) — sinon le navigateur bloque les appels avant même CORS. Les autres pages gardent la CSP inchangée.
app/templates/_draco_bar.html : 1 ligne — l'action palette de la barre va désormais sur /recherche au lieu du toast « arrive avec la fédération ». Le reste du fragment est inchangé (attention au chantier parallèle sur la barre : conflit possible sur ce fichier, à résoudre au merge).
Tests : tests/test_recherche.py (pytest, 6 tests) + tests/recherche.test.js (Node, 25 assertions : résolution d'URL, liens profonds, normalisation des 4 formats).
Limites connues (à valider après déploiement)
Les sections ObsiGate, TikTak et Kanbante restent en erreur tant que leurs PR respectives (CORS bornée, CORS bornée, endpoint JSON) ne sont pas déployées — comportement prévu, pas une régression.
La correction 401 de /api/search change le comportement pour un visiteur non connecté (la palette ne renvoie plus de résultats sans périmètre) — c'est le correctif voulu, à confirmer au merge.
Validation en direct (clic réel sur chaque lien profond, depuis flowdeck-dev et flowdeck) à 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/recherche.test.js : 25 assertions OK.
Vérification Python de app/middleware/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 app/main.py, app/middleware/security.py, app/routers/search.py, app/middleware/recherche_cors.py, tests/test_recherche.py : OK.
Non exécutés ici (dépendances applicatives absentes de la sandbox) : pytest tests/test_recherche.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 #30 sur main post-#70 et post-#69 (conflits _draco_bar.html et app/main.py résolus : suppression du bouton ••• de #70 et contenu alertes #69 conservés, palette → /recherche appliquée, middleware CORS #68 ajouté sans retirer les allow_origins sœurs #69. security.py NON modifié : la CSP sœurs #69 (connect-src sur toutes les pages) couvre déjà /recherche, le correctif CSP #68 serait redondant — il n'est pas repris, sans perte fonctionnelle. Contenu par ailleurs identique à #30.
## Rechercher partout — page de résultats unifiée + draco sur /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=` (`SearchResponse.results[] : vault, path, title, snippet`) | Bearer `access_token`, cookie `access_token`, ou repli cookie SSO `draco_session` | `{og}/#file={vault}:{path}` |
| Flowdeck | `GET /api/search?q=` (`app/routers/search.py`) | cookie `flowdeck_session` **seulement** (voir correctif ci-dessous) | `{fd}/pages/<id>`, `{fd}/db/<id>` (émis par le service lui-même) |
| 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).
### 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 (Flowdeck)
- `app/templates/recherche.html` (nouveau) + `static/js/recherche.js` (nouveau, logique partagée du chantier) + `static/css/recherche.css` (nouveau) : page `GET /recherche` avec 4 sections (ObsiGate, Flowdeck, TikTak, Kanbante), titre/extrait/contexte par résultat, liens profonds.
- `app/routers/search.py` :
- `GET /recherche` (nouveau) : coquille rendue via `ENV` (même patron que les pages existantes), bases sœurs passées explicitement depuis `draco_urls.toutes()`. La palette Ctrl+K native est inchangée.
- `GET /api/search` : **repli SSO `draco_session`** via le validateur local existant `app.services.draco.user_for_draco` (même sémantique que TikTak/Kanbante), **et authentification désormais requise (401 sinon)**. Correctif de sécurité préexistant : sans session, la route donnait auparavant une recherche **sans périmètre** (`user_id=None` → `1=1` dans `_scope_where`, tous les espaces) — y compris pour la palette d'un visiteur non connecté. Les résultats d'un utilisateur authentifié restent périmétrés comme avant.
- `app/middleware/recherche_cors.py` (nouveau, ASGI pur) + `app/main.py` : CORS bornée pour `GET /api/search` uniquement — origines sœurs résolues par `draco_urls.toutes()`, **plus** les origines prod ou `-dev` officielles de l'environnement de la requête (nécessaire car ce middleware s'exécute avant le middleware CSP qui pose le contexte d'hôte pour `draco_urls` ; sans cela, une page servie par `flowdeck-dev` verrait ses sœurs `-dev` refusées quand la configuration seule ne les déclare pas). Jamais `*`, jamais d'autre route, jamais d'écriture. Le middleware répond lui-même aux preflights OPTIONS (qui ne portent jamais de cookies). La politique CORS globale est inchangée.
- `app/middleware/security.py` (`ContentSecurityPolicyMiddleware`) : `connect-src` de la page `/recherche` uniquement, étendue aux origines sœurs (ObsiGate, TikTak, Kanbante) — sinon le navigateur bloque les appels avant même CORS. Les autres pages gardent la CSP inchangée.
- `app/templates/_draco_bar.html` : **1 ligne** — l'action `palette` de la barre va désormais sur `/recherche` au lieu du toast « arrive avec la fédération ». Le reste du fragment est inchangé (attention au chantier parallèle sur la barre : conflit possible sur ce fichier, à résoudre au merge).
- Tests : `tests/test_recherche.py` (pytest, 6 tests) + `tests/recherche.test.js` (Node, 25 assertions : résolution d'URL, liens profonds, normalisation des 4 formats).
### Limites connues (à valider après déploiement)
- Les sections ObsiGate, TikTak et Kanbante restent en erreur tant que leurs PR respectives (CORS bornée, CORS bornée, endpoint JSON) ne sont pas déployées — comportement prévu, pas une régression.
- La correction 401 de `/api/search` change le comportement pour un visiteur non connecté (la palette ne renvoie plus de résultats sans périmètre) — c'est le correctif voulu, à confirmer au merge.
- Validation en direct (clic réel sur chaque lien profond, depuis `flowdeck-dev` et `flowdeck`) à 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/recherche.test.js` : **25 assertions OK**.
- Vérification Python de `app/middleware/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 `app/main.py`, `app/middleware/security.py`, `app/routers/search.py`, `app/middleware/recherche_cors.py`, `tests/test_recherche.py` : **OK**.
- Non exécutés ici (dépendances applicatives absentes de la sandbox) : `pytest tests/test_recherche.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 #30 sur main post-#70 et post-#69 (conflits _draco_bar.html et app/main.py résolus : suppression du bouton ••• de #70 et contenu alertes #69 conservés, palette → /recherche appliquée, middleware CORS #68 ajouté sans retirer les allow_origins sœurs #69. security.py NON modifié : la CSP sœurs #69 (connect-src sur toutes les pages) couvre déjà /recherche, le correctif CSP #68 serait redondant — il n'est pas repris, sans perte fonctionnelle. Contenu par ailleurs identique à #30.
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 + draco sur /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=(SearchResponse.results[] : vault, path, title, snippet)access_token, cookieaccess_token, ou repli cookie SSOdraco_session{og}/#file={vault}:{path}GET /api/search?q=(app/routers/search.py)flowdeck_sessionseulement (voir correctif ci-dessous){fd}/pages/<id>,{fd}/db/<id>(émis par le service lui-même)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).
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 (Flowdeck)
app/templates/recherche.html(nouveau) +static/js/recherche.js(nouveau, logique partagée du chantier) +static/css/recherche.css(nouveau) : pageGET /rechercheavec 4 sections (ObsiGate, Flowdeck, TikTak, Kanbante), titre/extrait/contexte par résultat, liens profonds.app/routers/search.py:GET /recherche(nouveau) : coquille rendue viaENV(même patron que les pages existantes), bases sœurs passées explicitement depuisdraco_urls.toutes(). La palette Ctrl+K native est inchangée.GET /api/search: repli SSOdraco_sessionvia le validateur local existantapp.services.draco.user_for_draco(même sémantique que TikTak/Kanbante), et authentification désormais requise (401 sinon). Correctif de sécurité préexistant : sans session, la route donnait auparavant une recherche sans périmètre (user_id=None→1=1dans_scope_where, tous les espaces) — y compris pour la palette d'un visiteur non connecté. Les résultats d'un utilisateur authentifié restent périmétrés comme avant.app/middleware/recherche_cors.py(nouveau, ASGI pur) +app/main.py: CORS bornée pourGET /api/searchuniquement — origines sœurs résolues pardraco_urls.toutes(), plus les origines prod ou-devofficielles de l'environnement de la requête (nécessaire car ce middleware s'exécute avant le middleware CSP qui pose le contexte d'hôte pourdraco_urls; sans cela, une page servie parflowdeck-devverrait ses sœurs-devrefusées quand la configuration seule ne les déclare pas). Jamais*, jamais d'autre route, jamais d'écriture. Le middleware répond lui-même aux preflights OPTIONS (qui ne portent jamais de cookies). La politique CORS globale est inchangée.app/middleware/security.py(ContentSecurityPolicyMiddleware) :connect-srcde la page/rechercheuniquement, étendue aux origines sœurs (ObsiGate, TikTak, Kanbante) — sinon le navigateur bloque les appels avant même CORS. Les autres pages gardent la CSP inchangée.app/templates/_draco_bar.html: 1 ligne — l'actionpalettede la barre va désormais sur/rechercheau lieu du toast « arrive avec la fédération ». Le reste du fragment est inchangé (attention au chantier parallèle sur la barre : conflit possible sur ce fichier, à résoudre au merge).tests/test_recherche.py(pytest, 6 tests) +tests/recherche.test.js(Node, 25 assertions : résolution d'URL, liens profonds, normalisation des 4 formats).Limites connues (à valider après déploiement)
/api/searchchange le comportement pour un visiteur non connecté (la palette ne renvoie plus de résultats sans périmètre) — c'est le correctif voulu, à confirmer au merge.flowdeck-devetflowdeck) à 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/recherche.test.js: 25 assertions OK.app/middleware/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_compilesurapp/main.py,app/middleware/security.py,app/routers/search.py,app/middleware/recherche_cors.py,tests/test_recherche.py: OK.pytest tests/test_recherche.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 #30 sur main post-#70 et post-#69 (conflits _draco_bar.html et app/main.py résolus : suppression du bouton ••• de #70 et contenu alertes #69 conservés, palette → /recherche appliquée, middleware CORS #68 ajouté sans retirer les allow_origins sœurs #69. security.py NON modifié : la CSP sœurs #69 (connect-src sur toutes les pages) couvre déjà /recherche, le correctif CSP #68 serait redondant — il n'est pas repris, sans perte fonctionnelle. Contenu par ailleurs identique à #30.