fix: side peek des bases repasse en vanilla JS + largeur 1100px standard (v7.49.0)
FlowDeck CI / test (push) Failing after 3h13m58s
FlowDeck CI / lint (push) Successful in 2m12s
FlowDeck CI / docker (push) Skipped

- Panneau peek: les bindings Alpine (x-data absent du conteneur) rendaient
  loovverture et le redimensionnement inoperants -> cblage direct sur le document.
- Helper unique window.fdWirePeekResize (app.js): pointer capture, 300px-90vw,
  clic=fermer, largeur persiste fd_peek_width partagee entre les 4 peeks.
- database-table-container margin:0 (tableau colle a gauche, marge Library).
- .lib-container remonte dans app.css (trash etait pleine largeur), .db-index 1100px.
- ObsiGate verifie sans code: creation .xlsx OK (openpyxl, #186).
This commit is contained in:
2026-10-05 22:47:36 -04:00
parent 894004a1f5
commit 1d1cdbd618
63 changed files with 9473 additions and 393 deletions
+109
View File
@@ -175,6 +175,115 @@ Propriétés custom, AI keywords, sync API, 12 tables DB
---
## v7.46.0 — Sidebar : onglets compressibles Home / Chat / Meeting / Inbox ✅ (2026-10-04)
> **Objectif** : remplacer la rangée d'icônes par une navigation par onglets
> (Home, Chat, Meeting, Inbox dans cet ordre) où l'onglet actif est une pilule
> étiquetée, les autres sont réduits à leur icône, et chaque sélection remplace
> le contenu de la barre latérale. **COMPLETED**.
- [x] **Onglets compressibles** — `sidebar-nav-row` : 4 onglets dans l'ordre
**Home → Chat → Meeting → Inbox**, libellé visible uniquement sur l'onglet
actif (pilule), `role="tab"` + `aria-selected`, onglet mémorisé
(`fd_sidebar_tab`, valeur validée)
- [x] **Panneaux contextuels** — 4 panneaux Alpine (`sidebar-tab-panel`) :
Home (arbre + sections + libraries), Chat, Meeting, Inbox ; un seul visible
à la fois, footer commun conservé
- [x] **Onglet Chat branché sur l'historique réel** — raccourcis circulaires
d'agents + conversations groupées *Past 30 days* / *Older* ; clic →
`window.fdAgent.openConversation(id)` ouvre le panneau agent sur la
conversation
- [x] **Onglet Meeting branché sur le calendrier réel** — nouveau
`GET /api/v2/meetings/upcoming` (collections calendaires liées, propriété
date, horizon paramétrable et clampé), filtres *Upcoming* / *Today*,
actions *Transcribe a podcast* et *New AI meeting note*
- [x] **Onglet Inbox branché sur les notifications réelles** — All / Unread,
marquage lu au clic, *Mark all read*, état *Inbox Zero*, badge non lus- [x] **Verrouillé** — `tests/test_sidebar_tabs.py` (15 tests) +
`e2e/sidebar_tabs.spec.js` (3 scénarios, mesure de largeur de la pilule,
clic Home n'affiche que le libellé Home, CSS périmée en cache) ;
suite complète 1182 tests verts
## v7.46.0 — Audit de fonctionnement : 10 anomalies corrigées ✅ (2026-10-04)
> **Objectif** : passer l'instance au crible (routes, sécurité, navigation,
> schémas) et supprimer les anomalies constatées. **COMPLETED**.
- [x] **Audited** : 677 routes, 280 endpoints GET sondés anonymement, 64
templates/JS croisés avec les routes enregistrées, crawl Playwright
authentifié (12 pages), intégrité SQLite. **10 anomalies**, toutes corrigées.
- [x] **Écritures anonymes closes** — `POST/DELETE /api/workspaces`,
`PUT /api/workspaces/{id}`, `select` et `local-workspace/items` répondaient
200 **sans session** (repli `uid = … else 1`) : un anonyme pouvait renommer
ou supprimer un espace. → `_require_user_id()` + `_require_ws_owner()`
- [x] **Router `/workspace` authentifié** — `export/csv`, historique,
commentaires, sprints, dashboards et templates servaient des données réelles
en anonyme (500 inclus). → `Depends(_require_session)` sur le router, la page
de partage public bascule dans un `public_router` sans dépendance
- [x] **`password_hash` retiré** de `/auth/user` **et du cookie de session**
(signé mais non chiffré) → `app.auth.session.public_user()`
- [x] **OAuth Gitea** — placeholders `test-id`/`test-secret` traités comme
« provider non configuré » (avant : redirection Gitea avec un client_id
invalide) ; `GITEA_OAUTH_CLIENT_ID/SECRET` documentés dans `.env.example`
- [x] **Bouton Home** — pointait sur `local_workspaces[0]` (1er espace **trié
par nom**) au lieu de l'espace actif : le clic pouvait changer d'espace sans
annonce. → `local_ws_id` exposé par les 2 sidebars (`gitea_mirror_ws_id`
séparé) et prioritaire dans `base.html`
- [x] **`/api/v2/agents/conversations`** — 422 car masqué par
`/agents/{agent_id}` → `{agent_id:int}`
- [x] **Sélecteur de blocs synchronisés** — `/api/synced-blocks` (404) →
`/board/api/synced-blocks`, message d'aide corrigé
- [x] **`/workspace/favorites`** — 500 permanent (`no such column:
f.collection_id`, dérive de la migration v2.2.0) → schéma actuel + propriété
du favori
- [x] **Synced blocks** — 500 anonyme (`NoneType.get`) + absence de contrôle de
propriété sur PUT/DELETE → 401 / 403 (auteur ou admin)
- [x] **Jinja non silencieux** — `LoggingUndefined` : rendu identique, mais un
`WARNING` journalise toute variable absente du contexte (c'est ce silence
qui avait masqué le bug du bouton Home)
- [x] **Tests** — `tests/test_anomalies_v746.py` : **34 tests** (fuites,
écriture anonyme, propriété, ordre de routes, schéma, navigation, logs).
**Suite complète : 1167 tests verts**, `ruff check app/ tests/` propre
---
## v7.46.0 — Web tools de l'agent & 11 nouveaux skills ✅ (2026-10-04)
> **Objectif** : doter l'agent d'un accès au web (recherche en ligne, lecture de
> page, recherche GitHub) et élargir la galerie de skills. **COMPLETED**.
- [x] **3 nouveaux tools agent** — `app/services/tool_registry.py` (25 tools, +3) :
- `web_search` — recherche web sourcée (titre + URL + extrait), provider piloté
par `WEB_SEARCH_PROVIDER`
- `fetch_url` — télécharge une page et la rend en Markdown (titres, listes,
code, tableaux) pour que l'IA puisse la citer
- `search_code` — GitHub `repositories | code | issues`, sans PAT (10 req/min)
ou avec `GITHUB_TOKEN` (30 req/min)
- [x] **Service réseau** — `app/services/web_search.py` (nouveau) : Exa (recherche
sémantique + extraits) avec repli DuckDuckGo sans compte, client partagé A42,
**aucune dépendance ajoutée**, couche `transport` injectable pour les tests
- [x] **Garde-fou SSRF réutilisé** — `fetch_url` s'appuie sur
`importers.url_fetch._validate_url` / `_is_public_host` : schémas http(s)
uniquement, résolution DNS puis refus des IP loopback / privées / lien-local
/ réservées, **re-validation à chaque saut de redirection** (une URL publique
ne peut pas rediriger vers `169.254.169.254`)
- [x] **Config** — `WEB_SEARCH_PROVIDER`, `EXA_API_KEY`, `GITHUB_TOKEN`,
`WEB_FETCH_MAX_CHARS` (`app/config.py` + `.env.example`)
- [x] **Galerie : 6 → 17 presets** — `app/services/skill_gallery.py` :
- **vague 1 (locaux)** : veille-documentaire, chasse-decisions, onboarding-nouveau,
audit-base, sprint-review
- **vague 2 (web)** : recherche-marche, veille-techno, debug-web — chaque
affirmation doit porter sa source `[titre — URL]`, sinon « non vérifié »
- **vague 3 (pouvoir)** : triage-incident, nettoyage-base (aperçu avant toute
écriture), briefing-quotidien
- [x] **UI** — libellés d'action du journal agent pour les 3 tools
(`Recherche web effectuée`, `Page web lue`, `Recherche GitHub effectuée`)
- [x] **Tests** — `tests/test_agent_web_tools.py` : **29 tests**, réseau **et DNS**
jamais touchés (`httpx.MockTransport` + résolution neutralisée) : registre +
schémas + périmètre, cohérence galerie/registre, export→import des presets
web, provider + repli + filtrage des URLs anti-bot, markdown + troncature +
**6 vecteurs SSRF refusés** (localhost, 127.0.0.1, metadata cloud, IPv6
loopback, `file:`, `ftp:`) + redirection vers metadata cloud + redirection
publique suivie, GitHub repos/issues/quota. **Suite complète : 1128 tests verts.**
---
## 🔜 Prochaines versions
### v4.0.1 — Onboarding & Polish ✅ (2026-07-18)