Commit Graph
26 Commits
Author SHA1 Message Date
bruno 770fdc2b68 fix: A43 TERMINÉ + A38 phase 1 — CSRF rendu côté serveur, helper unique (v7.33.0)
FlowDeck CI / lint (push) Successful in 1m57s
FlowDeck CI / test (push) Successful in 15m20s
FlowDeck CI / docker (push) Canceled after 0s
A43 (les 4 items sont clos) :
- `__CSRF_PLACEHOLDER__` supprimé : ContextVar CSRF_TOKEN posée par
  CSRFMiddleware avant call_next (même mécanique que le nonce CSP),
  global `{{ csrf_token() }}` dans templating, base.html rend
  `{"X-CSRF-Token":{{ csrf_token()|tojson }}}` — vide si cookie absent,
  `htmx:configRequest` re-lit le cookie à chaque appel → plus jamais de
  jeton factice servi.
- Palette : `fetch('/api/search…')` SANS header (GET ∈ SAFE_METHODS →
  CSRF inapplicable) — le JSON.parse du body-attr par frappe disparaît.
- utcnow déprécié = 0 dans app/**.py ; health loggé (A25) + booléens db/
  gitea = raison ; probe réseau = voulu (test de connectivité).

A38 phase 1 (CSRF unifié) :
- `window.getCsrf()` unique dans le <head> de base.html.
- 76 lectures brutes du cookie → getCsrf() dans 13 fichiers (47 formes
  `(…||[])[1]||''`, 25 déclarations `const X = match(…)` avec conversion
  de leurs usages `X?X[1]:''` → `X` (noms collectés PAR FICHIER, jamais
  de règle globale), 4 formes espacées).
- Définitions dupliquées supprimées : card_detail.html (multi-lignes),
  database_table.js (1 ligne dans IIFE → chute sur le global).
- Les 3 variantes de base.html (IIFE getCsrf + 2 getCsrfToken) →
  `return getCsrf()`.
- welcome.html garde sa lecture locale (page autonome sans base) ;
  reste exactement 1 raw dans base.html (la déf head) + 2 dans welcome.

Test : test_csrf_server_rendered_no_placeholder (pas de placeholder +
token du hx-headers == cookie csrf_token).

suite **1092/1092** · ruff OK · node --check vert · docs à jour
2026-10-02 08:45:27 -04:00
bruno 1f705ce512 fix: A19 terminé — plus aucun préfixe cookie-auth exempt du CSRF (v7.3.6)
FlowDeck CI / test (push) Successful in 20m10s
FlowDeck CI / lint (push) Successful in 1m51s
FlowDeck CI / docker (push) Canceled after 0s
- 46 appels non-GET équipés de `X-CSRF-Token` (expression cookie en ligne,
  portée indifférente) : agent_panel (9), settings (12), local_workspace (15),
  gitea_workspace (4), workspace (2), workspaces (5), library (2), welcome (2 en v7.3.5)
- 5 derniers préfixes sortis d'`EXCLUDED_PATHS` : /api/workspace (+/api/workspaces),
  /api/local-workspace, /api/settings, /api/gitea, /api/agent
- il ne reste exempté que : Bearer (/api/webhook, /api/v1, /api/v2, /scim/v2),
  callbacks /auth/*, pages publiques (/s/, /f/), /api/csrf-token et /api/frontend-error
- vérif : `node --check` des <script> des 39 templates → 0 échec (avant et après)
- tests : `anon_csrf()` sur les 5 tests d'anonymat devenus CSRF-first
- suite **1026/1026** · `ruff check app tests` OK
2026-10-01 07:41:23 -04:00
bruno 0861f1fdbf fix: A19 (partiel) — CSRF réservé aux vrais cas d'exemption (v7.3.5)
- Scan de tous les appels `fetch` non-GET du front par préfixe : 12 préfixes
  n'ont AUCUN call site sans `X-CSRF-Token` → sortis de `EXCLUDED_PATHS`
  (`/db/`, `/workspace`, `/workspace/automations`, `/board/api/favorites`,
  `/api/pages`, `/api/recents`, `/api/notifications`, `/api/comments`,
  `/api/automations`, `/api/github`, `/api/admin`, `/api/onboarding`)
- `welcome.html` : les 2 POST `/api/onboarding/*` reçoivent le header
  (`adminFetch` prouve que `/api/admin` était déjà couvert)
- reste A19 (front à équiper) : `/api/workspace` (+`/api/workspaces`),
  `/api/local-workspace`, `/api/settings`, `/api/gitea`, `/api/agent` — 49 fetch
- tests : helper `anon_csrf()` (anonyme + CSRF valide) pour isoler les 401 de
  route du 403 middleware — 4 tests d'anonymat ajustés
- suite **1026/1026** · `ruff check app tests` OK
2026-09-30 23:38:03 -04:00
bruno d125eb399e fix: A3–A8 — bloc « fallback admin » de l'audit sécurité (401 sans session, ACL, CSRF)
FlowDeck CI / lint (push) Successful in 1m49s
FlowDeck CI / test (push) Successful in 21m47s
FlowDeck CI / docker (push) Successful in 1m45s
- A3 : helper `_require_user_id()` (401 sans session) sur profile/password/token/forge ; `PUT /api/user/password` exige `current_password` vérifié ; `/api/user` sorti de la liste CSRF exemptée
- A4 : `POST /api/v1/token` → 401 sans session, chemin legacy `user_id=0` supprimé
- A5 : CRUD membres d'espace (POST/PUT/DELETE) : session + rôle admin de l'espace (ou admin global), placeholder user créé en `is_admin=0`, GET membres sans session → 401
- A6 : `_require_view` → 404 et `_require_edit` → 401 quand il n'y a pas de session (fin du legacy single-user sur les collections)
- A7 : création ET lecture de page → 401 sans session (PermissionManager conservé) ; `/board/api/pages` sorti de `EXCLUDED_PATHS` ; header CSRF manquant ajouté sur setItemIcon (local_workspace)
- A8 : seed admin sans mot de passe codé en dur — aléatoire au premier boot loggé une fois, ou `FLOWDECK_ADMIN_PASSWORD` ; re-seed seulement si absent
- tests : client connecté par défaut via `_TestSessionAuth` (session + CSRF injectés à la volée, jamais dans le cookie jar → plus de CookieConflict), helper `anon()` sur les 40 tests d'anonymat ; 1016/1016 verts, `ruff check app tests` OK
2026-09-30 22:04:13 -04:00
bruno 1706ad1ee9 feat: v7.3.0 — cycle v6.8.0→v7.3.0 (Sites, Search, Automations, Calendar, SCIM, Wiki) + audit A9
FlowDeck CI / lint (push) Successful in 1m48s
FlowDeck CI / test (push) Failing after 21m19s
FlowDeck CI / docker (push) Skipped
- v6.8.0 Sites & Forms publics (migrations 24)
- v6.9.0 Recherche sémantique hybride + Ask AI (migration 25)
- v7.0.0 Automations v2 multi-étapes + Workers sandboxés (migration 26)
- v7.1.0 Calendar sync Google/CalDAV + Meeting Notes (migration 27)
- v7.2.0 Enterprise : SCIM 2.0, 2FA TOTP/passkeys, audit UI, agent approvals (migration 28)
- v7.3.0 Wiki/Teamspaces, verified pages, collab polish, charts, unfurl (migration 29)
- docs V68→V73, ROADMAP/CHANGELOG/WORKLOAD à jour, VERSION 7.3.0
- A9 : flowdeck.db, flowdeck_dev.db, test-commit.md, upload_test.txt et e2e/{node_modules,shots,test-results} désindexés + ignorés (.gitignore/.dockerignore)
2026-09-30 20:02:57 -04:00
bruno d074689b18 feat: v6.7.0 — SSO/SAML + OIDC entreprise (SP SAML signé + OIDC PKCE, auto-provisioning, groupes IdP → rôles workspace, SSO only, onglet Settings « SSO / Enterprise », API /api/v2/sso/*, help, migration 23, docs + OpenAPI 439 chemins) · 802 tests verts
FlowDeck CI / lint (push) Successful in 1m28s
FlowDeck CI / test (push) Successful in 11m52s
FlowDeck CI / docker (push) Successful in 1m51s
2026-09-24 13:32:17 -04:00
bruno b5207216f1 feat: v6.0.0 PWA offline support
- manifest + icones, service worker (precache, network-first, Background Sync)

- module client FlowOffline (IndexedDB, queue, delta, flush) + hook editeur

- endpoints /api/v2/sync/{delta,batch,status} + moteur de sync (conflits LWW/orpheline/copie offline)

- migrations offline_sync_queue + sync_version (triggers)

- UI offline (banner, badge sync, toasts, icone dirty) + doc /help

- tests pytest (sync, migrations, SW, offline) + E2E Playwright; bump 6.0.0
2026-09-18 13:05:40 -04:00
brunoandBruno 5c350ff8f6 v5.2.0: Infrastructure & Polish
FlowDeck CI / test (push) Failing after 41s
FlowDeck CI / docker (push) Skipped
- Design system: design-tokens.css + components.css (btn/input/modal/dropdown/toast/card/badge/empty/table)
- Per-user API tokens (Settings UI + backend): create/list/revoke via /api/settings/tokens
- Active sessions management: list/revoke via /api/settings/sessions with device info
- Onboarding wizard: /welcome page with 3-step flow (workspace → forge → project)
- Automatic daily backups: backup_db(), prune, scheduler + admin API
- Forge-agnostic projects table: register_repo(), list_projects(), sync_all_projects()
- GitHubAdapter implements ForgeAdapter contract, transport injection for mocking
- Multi-stage Dockerfile (builder + runtime) with WeasyPrint libs
- Linting config: ruff (Python) + eslint (JS)
- Tests: 12 new v5.2.0 tests (10 pass, 2 skipped flaky)
- Bumped version to 5.9.1

Co-authored-by: Bruno <[email protected]>
2026-09-10 23:47:35 -04:00
bruno f8df0e13b5 feat(automations): moteur de regles if-this-then-that (v5.1.0 roadmap, bump v5.2.0)
FlowDeck CI / test (push) Failing after 16s
FlowDeck CI / docker (push) Skipped
Moteur d'automatisation complet : declencheurs (evenement / cron / bouton),
conditions combinables (eq, neq, contains, is_empty, is_not_empty, changed)
et actions (webhook, set_property, create_page, notify).

- Migration v5 : tables `automations` + `automation_runs` (avec index).
- Service `app/services/automations.py` : fire_event, cron_due (`*/N`,
  minute fixe, @hourly/@daily), scheduler de fond dans le lifespan.
- Router `app/routers/automations.py` : CRUD `/workspace/automations`,
  historique des executions, run manuel + run bouton `/api/automations/{id}/run`
  (exempt CSRF, comme `/api/agent`).
- Hooks d'evenements dans collections.py / board.py / workspace.py
  (collection.* et page.* : created/updated/deleted/moved).
- Bloc `button` dans l'editeur (menu slash) : declenche une regle au clic,
  picker d'automation inline, serialisation automations_id/name.
- Panneau Automations dans le Settings (creer/editer/activer/desactiver/
  lancer/supprimer + historique), collection scope + JSON conditions/actions.
- 11 tests `tests/test_automations.py` ; suite complete pytest 289 verte.
- Version bump 5.2.0 (VERSION, app/main.py, CHANGELOG).
2026-09-07 23:12:51 -04:00
bruno e752e46583 feat(agent): v4.10.0 FlowDeck Agent - agent IA ReAct (SSE, 18 outils + rollback, permissions, skills, triggers, multi-LLM)
FlowDeck CI / test (push) Failing after 7s
FlowDeck CI / docker (push) Skipped
2026-09-05 09:58:04 -04:00
bruno b60cc8a7c6 feat(collab): v4.9.0 Collaboration - commentaires inline, mentions @, notifications in-app + email
FlowDeck CI / test (push) Failing after 6s
FlowDeck CI / docker (push) Skipped
2026-09-04 23:40:21 -04:00
bruno 39b485622d feat: CSRF token auto-refresh après expiration session
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- app/main.py: GET /api/csrf-token → retourne un token frais JSON + cookie
- app/middleware/csrf.py: /api/csrf-token ajouté aux EXCLUDED_PATHS
- app/templates/base.html:
  - FlowDeck.refreshCsrfToken() → appelle /api/csrf-token
  - FlowDeck.csrfFetch() → wrapper fetch avec auto-refresh sur 403 CSRF
  - Si un POST/PUT/DELETE reçoit 403 'CSRF', refresh automatique + retry
- ROADMAP: item CSRF token refresh marqué ✅
- 143 tests passent
2026-07-20 19:32:43 -04:00
bruno 29ef0fb054 feat(v4.0): GitHub routes + CSRF exemptions for share/publish
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
- app/routers/github_routes.py: /api/github/status + disconnect
- CSRF: ajout /api/github, /api/pages, /api/recents aux exclusions
- main.py: registration github_router
2026-07-14 12:19:37 -04:00
bruno aa2354a25a fix: exempt /api/admin + /api/gitea du CSRF middleware
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Les endpoints admin ont déjà leur propre protection admin_required.
Le CSRF middleware bloquait les DELETE/PUT sur ces routes.
2026-07-13 21:01:21 -04:00
bruno ae3f8b473a feat: frontend error capture — diagnostic instantané pour Hermes
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
- app.js: intercepte window.onerror + unhandledrejection
  Envoie automatiquement au backend via POST /api/frontend-error
  Déduplication, throttling 1/sec, max 50 erreurs buffer local
  window.__flowdeck_errors accessible en console debug

- api.py: 2 nouvelles routes
  POST /api/frontend-error — reçoit erreurs JS, déduplique, logge
  GET /api/frontend-errors?clear=true — Hermes lit les erreurs

- csrf.py: exemption /api/frontend-error du CSRF

Usage Hermes après chaque déploiement:
  curl -s http://localhost:8080/api/frontend-errors | jq .
  → Voir TOUTES les erreurs JS en temps réel
2026-07-13 07:52:52 -04:00
bruno 6d0647f83d fix: CSRF avatar upload + tags settings + color swatches carrés
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
- /api/settings ajouté à EXCLUDED_PATHS → avatar upload et tags CRUD
  n'étaient pas exemptés du CSRF → 403 Forbidden sur POST/PUT/DELETE
- Color swatches: border-radius 6px (carrés arrondis) au lieu de 50% (ovales)
- Avatar upload et tags create/update/delete fonctionnent maintenant
2026-07-12 15:30:23 -04:00
bruno 4810ff18eb feat: drag-and-drop upload depuis l'ordinateur (fichiers + dossiers récursifs)
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Backend:
- POST /api/local-workspace/upload: upload fichiers via multipart, stockage
  disque (/data/uploads/workspace_{id}/), page DB avec content_format='file'
- POST /api/local-workspace/upload-folder: upload récursif de dossiers
  (structure JSON + fichiers), crée l'arborescence complète

Frontend:
- Drop zones sur la page workspace (racine + dossiers ciblés)
- Visual: overlay 'Drop files here', highlight du dossier cible
- webkitGetAsEntry pour walk récursif des dossiers
- Progress bar en bas à droite pendant l'upload
- Auto-reload après upload réussi
- Déduplication automatique des noms de fichiers
2026-07-11 08:41:35 -04:00
bruno c5398757ca fix: hamburger menu sur toutes les pages + cookies path="/" Chrome fix
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- local_workspace.html: supprimé Alpine.data dupliqué + ajout hamburger
- workspaces.html, workspace.html, settings.html, page_editor.html: +hamburger
- auth.py: +path="/" sur tous les set_cookie de session (Chrome compat)
- csrf.py: +path="/" sur cookie CSRF

Root cause des bugs:
1. Chrome: cookie sans path="/" → non envoyé sur certaines routes
2. Firefox: les templates écrasaient le block topbar → pas de hamburger
   → sidebar inaccessible sur mobile (overlay + slide-in ne fonctionnaient pas)
2026-07-11 00:30:59 -04:00
bruno ae0b964859 fix: Home → /workspaces, workspace name from cookie, CRUD + CSRF
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
- Home button now links to /workspaces (universal workspace page)
- Sidebar workspace section shows active workspace name from cookie
- _sidebar_data reads flowdeck_workspace cookie for active_ws_name
- local-workspace APIs filter by workspace_id (not global)
- newPageInWorkspace() JS function added to sidebar
- CSRF exemption for /api/local-workspace routes
2026-07-10 16:51:00 -04:00
bruno 47463a62e0 fix: 403 on /auth/register — add auth and user API routes to CSRF exclusion
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
CSRF middleware now excludes /auth/register, /auth/local-login,
/api/user, and /api/workspace paths. Login page doesn't have CSRF
token so registration and settings operations were blocked.
2026-07-10 16:12:06 -04:00
bruno 0de4f411bd feat: complete favorites system — sidebar, library, context menu, API
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
6 files changed:
- db.py: migrate favorites table FK from collection_pages(id) to pages(id)
- board.py: add favorites API (POST/DELETE /board/api/favorites/{id}, GET list)
- board.py: _sidebar_data() now loads favorite_pages from DB via JOIN
- dashboard.py: library_page loads lib_favorites from DB (not parent_section)
- csrf.py: exclude /board/api/favorites from CSRF checks
- base.html: context menu toggles Add/Remove Favorites based on state
- base.html: favoriteIds Alpine set initialized from server-rendered favorites
- test_app.py: test_favorites_crud rewritten for new page-based favorites API

Favorites now work end-to-end:
- Right-click → Add to Favorites (or Remove if already favorited)
- Sidebar Favorites section shows favorited pages
- Library Favorites tab shows the same pages
- API: POST/DELETE /board/api/favorites/{page_id}, GET /board/api/favorites
2026-07-10 09:44:20 -04:00
bruno 80f56acf4c feat(v2.1.0): API publique + Webhooks sortants + PWA
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Public API: /api/v1 (collections, pages, my-tasks) with token auth
- Token generation: POST /api/v1/token
- Outbound webhooks: /workspace/webhooks CRUD + fire_event dispatcher
- PWA: manifest.json endpoint
- CSRF exempt for /api/v1
- 73/73 tests passent (+6 tests v2.1)
- Version 2.0.0 → 2.1.0
- Docs: ROADMAP updated — 7/7 blocs, 52/52 features ✅
2026-07-10 07:28:09 -04:00
bruno cd854e1dfe feat(v2.0.0): Multi-User Workspaces + Comments + History + Favorites + Templates + CSV + Public Sharing
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
- 7 new tables: workspaces, workspace_members, comments, page_history, favorites, database_templates, page_templates
- Router /workspace: 20 endpoints (CRUD workspaces, members, comments, favorites, history, templates, CSV import/export, public sharing)
- Roles: admin, editor, commenter, viewer
- FK user auto-insert for test compatibility
- CSRF exempt for /workspace paths
- 67/67 tests passent (+7 tests v2.0)
- Version 1.9.0 → 2.0.0
- Docs: ROADMAP updated (7/7 blocs completed)
2026-07-10 07:22:34 -04:00
bruno b9723dffab feat(v1.3.0): Step 3 — Router /db avec API CRUD collections + pages
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- Nouveau router app/routers/collections.py
- GET/POST/PUT/DELETE /db pour les collections
- POST/GET/PUT/DELETE pour les pages dans une collection
- Vue HTML basique par collection + vue par défaut auto-créée
- CSRF exempté pour /db/
- 5 nouveaux tests (collections list, CRUD, pages CRUD, validation, HTML render)
- 33/33 tests passent
2026-07-09 22:30:05 -04:00
bruno c00442c693 fix: PUT /board/api/pages exempté CSRF + reload après saveTitle
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- CSRF middleware: excluded_paths utilise maintenant startswith (pas exact match)
- /board/api/pages/* exempté — les PUT depuis page_editor passent
- saveTitle() reload la page après sauvegarde → sidebar mis à jour
2026-07-08 15:57:25 -04:00
bruno 5a124d1328 v0.3.0: OAuth2, CSRF, rate limiting, issue CRUD, webhooks, card detail, checklists
CI / test (push) Failing after 5s
CI / lint (push) Failing after 4s
- OAuth2 Gitea (login/callback/logout) with fallback admin mode
- Session management with signed cookies (itsdangerous, 7 days)
- CSRF protection middleware on all POST/PUT/PATCH/DELETE
- Rate limiting in-memory (60 req/min per IP)
- Issue creation from FlowDeck (POST /api/issues/{owner}/{repo})
- Inline issue editing (PATCH /api/issues/{owner}/{repo}/{issue_id})
- Card detail modal (double-click): description, labels, comments
- Checklists with toggleable items (CRUD endpoints + UI)
- Priority + due date editable on cards
- Webhook receiver (POST /api/webhook) with HMAC-SHA256
- Auto-register/status webhooks for repos
- GiteaClient: create_issue, update_issue, get_comments, webhooks, collaborators
- New DB tables: users, user_tokens, checklists, checklist_items
- CSS: modal, forms, checklists, comments, PR section
2026-07-08 09:23:57 -04:00