diff --git a/CHANGELOG.md b/CHANGELOG.md index c4e4d05..a8e78f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,40 @@ # Changelog - FlowDeck +## v7.33.0 (2026-10-01) — Audit : A43 TERMINÉ + A38 phase 1 (CSRF unifié) + +### Fixed + +- **A43-1 — plus de `__CSRF_PLACEHOLDER__` servi** : ContextVar + `CSRF_TOKEN` posée par `CSRFMiddleware` **avant** `call_next` (même + mécanique que le nonce CSP), global `{{ csrf_token() }}` ajouté à + templating ; `base.html` rend `{"X-CSRF-Token":{{ csrf_token()|tojson }}}` + — vide si le cookie est absent sur cette 1ʳᵉ requête, mais + `htmx:configRequest` re-lit le cookie à chaque appel → jamais de jeton + factice. Test `test_csrf_server_rendered_no_placeholder` (pas de + placeholder + token == cookie) +- **A43-2 — palette : plus de re-parse par frappe** : `fetch('/api/search…')` + sans header (GET ∈ `SAFE_METHODS` → le CSRF ne s'applique pas) — le + `JSON.parse(document.body.getAttribute('hx-headers'))` par frappe disparaît + +### Changed + +- **A38 phase 1 — helper CSRF unique** : `window.getCsrf()` défini dans le + `
` de `base.html` (le plus tôt possible) ; **76 lectures brutes du + cookie → `getCsrf()`** dans 13 fichiers (47 formes `(…||[])[1]||''`, + 25 déclarations `const X = match(…)` + leurs usages `X?X[1]:''` → `X`, + 4 formes espacées) ; définitions dupliquées supprimées (`card_detail`, + `database_table`) ; les 3 variantes de `base.html` (IIFE + 2 + `getCsrfToken`) unifiées sur `return getCsrf()` ; `welcome.html` garde sa + lecture locale (page autonome documentée) + +### Notes + +- A43 = **TERMINÉ** (4/4 : utcnow déprécié = 0 dans app/**.py, health + loggé, placeholder, palette) +- A38 reste : 12 fonctions dupliquées entre templates (wrappeur) + 21 + méthodes jumelles library/local_workspace +- Suite complète : **1092/1092** · ruff OK · node --check vert + ## v7.32.0 (2026-10-01) — Audit : A28 TERMINÉ (board, dernier lot) ### Changed diff --git a/ROADMAP.md b/ROADMAP.md index 9a26bce..b6a1539 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1161,12 +1161,12 @@ Quality DB views, Agent IA Palette → Realtime + E ### 🟢 P3 — Basses / hygiène -- [ ] **A38 — Duplication front systémique** : helper CSRF réimplémenté **10× sous 5 noms** (`getCsrfToken` ×3 dont 2 corps différents dans `base.html:852,1732`, `getCsrf` ×2, `_getCsrf`, `csrf()`, `csrfTok()`) + ~25 `document.cookie.match(/csrf_token=…)` en dur ; 12 `function` définies dans 2+ templates (`onDoc` ×5, `escHtml`, `esc`, `getCsrf`, `openCardDetail`…) sans IIFE systématique → ombre silencieuse entre partials ; `library.html` et `local_workspace.html` partagent **21 noms de méthodes identiques** (1 039 + 2 030 lignes quasi jumelles). *Fix : un `window.FlowDeck.getCsrf` + wrappeur IIFE/`type="module"` + un `workspace-tree.js` partagé. Effort : **M**.* +- [ ] **A38 — Duplication front systémique** : helper CSRF réimplémenté **10× sous 5 noms** (`getCsrfToken` ×3 dont 2 corps différents dans `base.html:852,1732`, `getCsrf` ×2, `_getCsrf`, `csrf()`, `csrfTok()`) + ~25 `document.cookie.match(/csrf_token=…)` en dur ; 12 `function` définies dans 2+ templates (`onDoc` ×5, `escHtml`, `esc`, `getCsrf`, `openCardDetail`…) sans IIFE systématique → ombre silencieuse entre partials ; `library.html` et `local_workspace.html` partagent **21 noms de méthodes identiques** (1 039 + 2 030 lignes quasi jumelles). *Fix : un `window.FlowDeck.getCsrf` + wrappeur IIFE/`type="module"` + un `workspace-tree.js` partagé. Effort : **M**.* **Phase 1 faite 2026-10-01 (CSRF unifié)** : helper **unique `window.getCsrf()`** dans le `` de `base.html` (le plus tôt possible) ; **76 lectures brutes du cookie → `getCsrf()`** (47 `(…||[])[1]||''` + 25 déclarations `const X = match(…)` avec leurs usages `X?X[1]:''` → `X` + 4 formes espacées) dans 9 fichiers statiques + 4 partials ; les 2 définitions dupliquées supprimées (`card_detail.html`, `database_table.js`) ; les **3 variantes de base.html** (IIFE `getCsrf`, `FlowDeck.getCsrfToken` ×2) unifiées sur `return getCsrf()` ; `welcome.html` garde sa lecture locale (page autonome sans base, documenté). **Reste A38** : les 12 `function` définies dans 2+ templates (`onDoc` ×5, `escHtml`, `esc`, `openCardDetail`… → wrappeur IIFE/module) + les 21 méthodes jumelles library/local_workspace (`workspace-tree.js` partagé). → suite 1092/1092, version 7.33.0. - [x] **A39 — HTMX chargé (49,7 Ko) pour 10 attributs réels** vs 265 `fetch(` manuels. *Fix : soit drop `htmx.min.js` et convertir les 10, soit rien.* — **décision 2026-10-01 : rien** (option proposée par l'audit) : 32 attributs `hx-*` réels répartis dans 6 templates (view-switch board/dashboard/notes, `hx-boost`) ; les convertir = refonte du view-switching en JS sans couverture automatisée, coût/risque > gain de 49,7 Ko. **Reconsidérer** dès qu'un test E2E couvre le view-switch. - [x] **A40 — Assets** : `?v=` incohérent (`app.css?v=5.1.1` mais CSS modifié le 2026-09-14 > dernier bump 2026-09-12 → servi depuis le cache), la même liste d'assets est **dupliquée** dans `sw.js:19-31`, htmx/alpine/prism vendored **sans bannière de version ni SRI**, 3 ` - +