Commit Graph
28 Commits
Author SHA1 Message Date
bruno 39d34ac866 fix(llm): Mistral 403 tier_not_allowed — défauts tous-plans + sonde chat + migration 36 (v7.59.1)
FlowDeck CI / lint (push) Failing after 2m8s
FlowDeck CI / test (push) Failing after 20m4s
FlowDeck CI / docker (push) Skipped
La clé fonctionne: /v1/models 200 + chat 200 (vérifié live). L'échec venait
du modèle: mistral-large-latest (défaut PROVIDERS + tête de liste) n'est pas
servi par les plans d'abonnement basiques → 403 code 1910 « tier_not_allowed »,
et le Test connection sélectionnait systématiquement ce premier candidat.

- PROVIDERS mistral default → mistral-small-latest (tous plans)
- PROVIDER_MODELS réordonnée: tous-plans d'abord (ordre du test de connexion)
- mistral ∈ _CHAT_VALIDATED_PROVIDERS: le fetch modèles ne garde que les
  modèles réellement servis (46 listés → 25 utilisables avec la clé du compte)
- migration 36: default_model bloqué (large/pixtral-large) reset en base

Test live déployé: {ok:true, model:mistral-small-latest, reply:PONG,
verified:true} · tests/test_agent.py 53/53 · nouveau test d'ancrage
test_mistral_defaults_are_tier_safe
2026-10-07 16:25:04 -04:00
bruno 16f73fe39e feat: Add plugins — catalogue on/off à effet réel (v7.58.0, phase 8/8)
FlowDeck CI / lint (push) Successful in 2m14s
FlowDeck CI / docker (push) Canceled after 0s
FlowDeck CI / test (push) Canceled after 2h7m52s
- app/services/plugins.py + migration 35 : table plugins (slug, name,
  description, enabled) pré-remplie avec 3 modules câblés — web-tools,
  web-clipper, automations ; ligne absente = activé (défaut sûr)
- automations OFF → dépendance FastAPI posée à l'include_router dans main.py
  (aucun router touché) → toutes les routes /workspace/automations* refusées +
  garde de tick du scheduler en arrière-plan
- web-clipper OFF → GET /extensions et tout /api/v2/web-clipper/* refusés
- web-tools OFF → web_search et fetch_url retirés du schéma ET de execute()
  via ToolRegistry._all() : le LLM ne les voit plus
- UI rendue côté serveur : global Jinja plugin_enabled(slug) — nav
  « Extensions » / « Automations » en {% if %} (absentes du DOM), sections
  conditionnées en x-show dans settings.html
- menu + : l'entrée « Add plugins » devient vivante (fini disabled:true) —
  liste des 3 plugins avec bascule, GET/PATCH /api/agent/plugins[/slug]
  (slug inconnu → 404, 401 sans session)
- tests : tests/test_v758_plugins.py (10 tests) — routes refusées (302 hors
  /api, 404 JSON pour /api*), outils retirés, nav disparue, persistance,
  câblage ; assertions disabled:true == 0 dans les tests des phases 1/3/4/5/7
- livraison : VERSION + app/main = 7.58.0, OpenAPI 525 chemins, CHANGELOG,
  ROADMAP phase 8 cochée (menu + complet), avenant phase 8 (docs)
2026-10-07 10:19:25 -04:00
bruno f8acb906e5 feat: connecteurs Discord/Telegram/MCP + outils MCP dynamiques au registre (v7.57.0)
FlowDeck CI / lint (push) Successful in 2m14s
FlowDeck CI / test (push) Failing after 17m51s
FlowDeck CI / docker (push) Skipped
- presets Discord / Telegram : colonnes kind + auth (bearer/bot/none) sur
  agent_connectors (migration 34) ; Discord envoie le jeton préfixé dans
  l'en-tête d'autorisation, Telegram le place dans l'URL via le substitut
  {secret} remplacé à l'appel — jamais stocké en clair
- Teams : scope ChannelMessage.Read.All ajouté aux Graph scopes M365
- app/services/mcp_client.py : handshake initialize → notifications/initialized
  → tools/list → tools/call (JSON-RPC 2.0, réponse JSON ou premier data: d'un
  text/event-stream), garde SSRF, outils cachés en base (tools_json) —
  le bouton « Tester » rejoue le handshake
- ToolRegistry._all() merge le cache MCP à chaque run : outils exposés au LLM
  sous mcp_<serveur>_<outil> avec leur inputSchema, dispatch tools/call ;
  serveur désactivé → outil absent du schéma, échec réseau → ToolResult(error)
- menu + : champ Type dans le formulaire connecteur (preset URL + auth),
  badge « · N outil(s) » sur la fiche d'un serveur MCP
- tests : tests/test_v757_mcp_discord.py (12 tests, 0 appel réseau réel) ;
  suite complète 1331 verts, ruff 0, eslint 0
- livraison : VERSION + app/main = 7.57.0, OpenAPI 523 chemins, CHANGELOG,
  ROADMAP phase 7 cochée, avenant phase 7 dans docs/V74_Agent_Plus_Menu.md
2026-10-07 09:09:19 -04:00
bruno 1d7750bda0 feat: connecteurs Google + Microsoft 365 (OAuth2 PKCE) — phase 6/8 (v7.56.0)
FlowDeck CI / lint (push) Successful in 2m14s
FlowDeck CI / test (push) Failing after 16m4s
FlowDeck CI / docker (push) Skipped
- app/services/oauth_connectors.py : flow OAuth2 complet PKCE (S256) pour
  2 fournisseurs décrits par 1 dict — Google (Drive/Gmail/Calendar en lecture
  seule) et Microsoft 365 (Graph Files.Read / Mail.Read / Calendars.Read) ;
  begin() = URL d'autorisation + state + code_verifier, complete() = échange du
  code, access_token() = refresh automatique (60 s de marge, refresh_token
  conservé si absent de la réponse), api_get() = path absolu refusé + validation
  SSRF + borne 20 000 car.
- Tokens chiffrés Fernet en réutilisant calendar_sync._encrypt_tokens (zéro
  dépendance) dans la table connector_tokens (migration 33, PK (kind, user_id)).
- 4 routes /api/agent/connectors/oauth/{kind}/… : status, authorize (cookies
  d'état HttpOnly 10 min, retour same-origin validé), callback (GET safe, state
  comparé en temps constant, tokens stockés puis cookies purgés, redirection
  ?oauth=connected / ?oauth_error=), disconnect. OpenAPI 523 chemins.
- Config + .env.example : GOOGLE_CLIENT_ID/SECRET, MS_CLIENT_ID/SECRET (vidés =
  « non configuré »), redirect URI dérivé d'APP_BASE_URL.
- Catalogue : google/ms365 en natifs avec badge connecté/non connecté ;
  connector_fetch et Tester passent par l'API du fournisseur avec le token de
  l'utilisateur (user_id transmis par l'outil LLM).
- Menu + : « Se connecter » / « Déconnecter » sur la fiche, toast au retour du
  flux (URL nettoyée par history.replaceState). État dans la fiche du menu
  plutôt qu'une page dédiée.
- Tests : tests/test_v756_oauth_connectors.py (13), 0 appel réseau réel
  (_post_form / _api_get monkeypatchés) — state forgé refusé sans échange,
  tokens chiffrés en base, refresh, URL absolue refusée, 401/404, câblage menu ;
  test_v755 adapté (5 natifs). Suite complète 1319 verts (-n auto), ruff 0,
  eslint 0 erreur (19 warnings préexistants hors fichiers touchés).
2026-10-07 08:29:22 -04:00
bruno 18c72d77fe feat: menu + — Connecteurs (socle) — phase 5/8 (v7.55.0)
FlowDeck CI / lint (push) Successful in 2m11s
FlowDeck CI / test (push) Failing after 15m16s
FlowDeck CI / docker (push) Skipped
- Table agent_connectors (migration 32) : colonnes plates name, url,
  secret_encrypted, enabled, status, detail — config_json remis (YAGNI, les
  scopes OAuth des phases 6-7 ajouteront le leur).
- app/services/connectors.py : 1 fichier au lieu du package connectors/ —
  3 natifs (gitea, github, web) servis à la volée avec statut sans réseau,
  CRUD des personnels (URL validée par _validate_url = garde SSRF, clé chiffrée
  Fernet et jamais renvoyée — seul has_secret), probe() qui persiste
  status/detail, connector_fetch() borné à 20 000 car.
- API /api/agent/connectors : GET, POST (400 URL privée), PATCH, DELETE,
  POST /connectors/probe — 401 sans session, CSRF global. OpenAPI 519 chemins.
- Outil LLM connector_fetch (26e outil) : un seul outil qui dispatche vers
  Gitea/GitHub/web/personnalisé (id ou nom ou kind + path + query) au lieu d'un
  outil par connecteur ; désactivé/inconnu = erreur outil, jamais de run cassé.
- Menu + : section « Connecteurs » (catalogue avec badge ✓/✗/⚠/?), fiche par
  connecteur (Tester, Activer/Désactiver, Supprimer — masqués pour les natifs),
  formulaire « Ajouter un connecteur personnalisé » (clé en type=password).
- Tests : tests/test_v755_connectors.py (13) — 3 natifs, roundtrip Fernet de la
  clé, 5 URLs refusées (localhost, 127.0.0.1, metadata cloud, ftp:, file:),
  toggle persisté, 401, probe OK/erreur, outil complet, câblage menu ;
  test_v751/v753/v754 adaptés (1 seule section « bientôt » = plugins).
  Suite complète 1306 verts (-n auto), ruff 0, eslint 0 problème.
2026-10-06 23:26:19 -04:00
bruno 64c85caffc feat: menu + — Mémoire de l'agent — phase 4/8 (v7.54.0)
FlowDeck CI / lint (push) Successful in 2m13s
FlowDeck CI / test (push) Failing after 3h10m19s
FlowDeck CI / docker (push) Skipped
- Le moteur n'envoie jamais l'historique (system + objectif courant seulement)
  : chaque run repartait de zéro. Nouveau service app/services/agent_memory.py —
  une ligne résumé par conversation (table agent_memory, migration 31),
  écrite en fin de run et ré-injectée au contexte du run suivant.
- context_for() : bloc « ## Mémoire de la conversation », budget 4000 car.
  (troncature gauche + marqueur). remember() : 1 note/échange (180 → 700 car.),
  20 notes max, upsert, erreurs journalisées — un run ne peut pas échouer à
  cause de la mémoire. Toggle OFF = ni lecture ni écriture.
- Toggle « Mémoire » dans le menu + : entrée racine à l'état réel (🧠/💭 +
  libellé), PATCH /api/agent/conversations/{id} avec memory_enabled ajouté au
  whitelist, état lu à l'ouverture et à la création, défaut AGENT_MEMORY_DEFAULT
  (settings.agent_memory_default) + memory_enabled dans la réponse de création.
- Décision : mémoire d'espace (lignes workspace_id NULL) remise — YAGNI, rien
  ne l'écrivait ; noté ponytail: dans le service avec le chemin de montée.
- Tests : tests/test_v754_memory.py (8) dont 2 runs réels du moteur (FakeLLM
  capture le prompt : mémoire présente ON / absente OFF) ; test_v751 et
  test_v753 adaptés (2 sections « bientôt » restantes). Suite complète 1293
  verts (-n auto, 2e run ; 1 échec intermittent sur test_v56_import URL au
  1er run, vert isolé + vert au run suivant = flake préexistant), ruff 0,
  eslint 0 problème. OpenAPI 516 chemins / 7.54.0.
2026-10-06 22:53:15 -04:00
bruno 1d1cdbd618 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).
2026-10-05 22:47:36 -04:00
bruno f706424f90 fix: A31 — transaction par migration + helper columns() (v7.6.0)
FlowDeck CI / lint (push) Canceled after 0s
FlowDeck CI / test (push) Canceled after 0s
FlowDeck CI / docker (push) Canceled after 0s
- `_apply_one()` : BEGIN explicite → `fn(conn)` → marque `schema_version` →
  commit ; rollback complet à l'échec. Avant le DDL sortait en autocommit
  (isolation_level legacy) : un échec au milieu laissait un schéma partiel
  commité SANS ligne de version, et la reprise rejouait un DDL déjà appliqué.
  Si une transaction englobante subsiste (init_db commit juste avant), on la
  vide d'abord plutôt que de l'englober.
- Helper unique `columns(conn, table)` (valide l'identifiant, ValueError sinon)
  : 25 copies de `{r[1] for r in conn.execute("PRAGMA table_info(...)")}`
  éliminées dans migrations.py (21 littéraux + 3 f-string + 1 variante row).
  `table_exists`/`column_exists` préconisés par l'audit NON livrés : aucune
  migration n'interroge sqlite_master, un contrôle unitaire se lit dans le set.
- Smoke : DB fraîche → 28 migrations → version 29, ré-apply idempotent.

tests : test_migration_transaction_rolls_back (DDL partiel annulé + zéro marque
de version), test_columns_helper_validates_table_name

suite **1036/1036** · `ruff check app tests` OK · OpenAPI 511 chemins / 7.6.0
docs (ROADMAP/CHANGELOG/WORKLOAD/VERSION) à jour
2026-10-01 10:13:23 -04:00
bruno ffa1fa89ab fix: A25 + A21 (partiel) — plus d'exception muque, transaction protégée (v7.3.8)
FlowDeck CI / lint (push) Successful in 1m51s
FlowDeck CI / docker (push) Canceled after 0s
FlowDeck CI / test (push) Canceled after 10m12s
- A25 — 84 `except Exception: pass/…` → `logger.exception("<fonction>")`
  (19 fichiers : api_v2 30, dashboard 10, board 7, sites 5, workspace 5,
  api_v2_helpers 5, …) ; `logger` ajouté là où il manquait (api_v2_helpers,
  sites + `import logging`)
- A25 critique — les `try` autour de `materialize_properties` supprimés dans
  `create_collection_v2` ET `apply_db_template_v2` : un échec interrompt la
  transaction au lieu de commiter une collection sans schéma
- test `test_collection_rollback_when_materialize_fails` (Bearer v2, monkeypatch
  qui lève, assertions : RuntimeError + 0 ligne commitée)
- A21 partiel — `PRAGMA busy_timeout=5000` dans `get_conn()` (point d'entrée
  unique) ; commentaire `ponytail:` : le wrapper async + les 510 call sites
  restent à migrer module par module
- suite **1028/1028** · `ruff check app tests` OK
2026-10-01 08:16:42 -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 5951c707eb feat: v6.5.0 Synced blocks production — pages contenu par lignes de DB, résolution serveur à chaque lecture, propagation écrite réelle
FlowDeck CI / lint (push) Successful in 1m27s
FlowDeck CI / test (push) Successful in 10m51s
FlowDeck CI / docker (push) Successful in 1m21s
2026-09-24 08:28:25 -04:00
bruno ce0d561ade feat(share,permissions): partage de page par groupes (page_shares)
FlowDeck CI / lint (push) Failing after 1m10s
FlowDeck CI / test (push) Successful in 9m55s
FlowDeck CI / docker (push) Successful in 1m11s
- app/db.py: ajout colonne shared_with_group_id (FK user_groups, migration
  backfill v5.x) dans page_shares
- app/routers/sharing.py: POST /api/pages/{id}/share accepte group_id
  (upsert, verif FK groupe), GET /shares expose kind/group_name, synchro
  bidirectionnelle avec page_permissions (mirror grant/revoke) pour que
  PermissionManager donne un acces effectif (view/comment/edit) aux membres
  du groupe; PUT/DELETE gardent le miroir a jour
- app/routers/board.py, library.py: received/made incluent les partages via
  groupes (JOIN group_members)
- app/templates/_page_editor_content.html, _page_editor_scripts.html:
  dialogue Share — invite groups (fetch /api/v2/groups, filtre deja partages),
  pickInviteGroup, shareInvite(group_id), rendu accessList avec avatar groupe
- tests/test_share_groups.py: 10 tests (CRUD groupe, kind, miroir ACL)

Chore: inclut evolutions v6.4.0 deja en working copy (webhooks prod,
migrations, sync, config/main) pour garder l'arbre coherent.
2026-09-21 06:38:02 -04:00
bruno 95bc861cdb feat: v6.3.0 API publique complete v2 (REST /api/v2, scopes, OpenAPI)
FlowDeck CI / lint (push) Successful in 1m13s
FlowDeck CI / test (push) Successful in 9m20s
FlowDeck CI / docker (push) Successful in 1m10s
- Router api_v2.py (~100 endpoints) : tokens, users, workspaces/members,
  collections, pages, proprietes, vues/dashboards, commentaires/mentions,
  notifications, favoris/tags/recents, partage/publish, historique, sprints,
  templates, export/import, forges, recherche FTS, admin, webhooks CRUD
- Helpers api_v2_helpers.py : Bearer unifie (sha256/expires_at/extension_devices),
  scopes hierarchiques read<write<admin, pagination + X-Total-Count, ISO-8601,
  RFC 7807, idempotence, audit, rate-limit par token
- Migration 20 : api_tokens.scopes/expires_at, webhook_deliveries,
  api_audit_log, idempotency_keys
- main.py : handler d'erreurs unifie StarletteHTTPException, /docs + /redoc
- config : PUBLIC_API_INSECURE_OK (dev only), API_V2_RATE_LIMIT_PER_TOKEN
- OpenAPI docs/openapi-v2.json (402 chemins), tests/test_public_api_v2.py (24)
- Docs : CHANGELOG (v6.2.0/6.2.1 clipper + v6.3.0), ROADMAP, API_GUIDE_V6,
  V6_Web_Clipper, README, ARCHITECTURE, /help
- Suite complete 668 verte, ruff OK
2026-09-20 13:19:29 -04:00
bruno 0b251649e5 feat: v6.2.0 Web Clipper — extension navigateur (capture article/selection/bookmark/screenshot)
FlowDeck CI / lint (push) Successful in 1m11s
FlowDeck CI / test (push) Failing after 8m32s
FlowDeck CI / docker (push) Skipped
- Service app/services/web_clipper.py: sanitize HTML, html->blocks, extraction article, creation page workspace-aware, rate limit 50/h, device registration
- Router app/routers/web_clipper.py: POST /api/v2/web-clipper/clip, GET /status, POST /auth/verify, GET/DELETE /devices, GET /extensions (download page), auth via session ou Bearer (api_tokens / extension_devices)
- Migration 19: extension_devices + extension_clips (+ indexes)
- Extension Manifest V3: content.js (floating button, selection), background.js (clip + contextMenus), popup.html/js, clipper.css, icons
- Settings UI: onglet Extensions (liste devices, revoke, test clip, liens download), page /extensions
- Tests: 16 tests web_clipper (sanitize, blocks, article/bookmark/selection/screenshot, bearer, rate-limit, devices, extensions page)
- Bump version 6.1.0 -> 6.2.0
2026-09-19 23:26:03 -04:00
bruno 13d5f8625a feat: v6.1.0 granular permissions (page/collection/property ACL + groups + audit)
FlowDeck CI / lint (push) Failing after 1m8s
FlowDeck CI / test (push) Failing after 8m5s
FlowDeck CI / docker (push) Skipped
- Migration 18: 6 tables + 3 colonnes permission_type + indexes
- PermissionManager: heritage page->collection->workspace, least privilege, groups, cache 60s
- API /api/v2: pages/collections/properties/groups/users/audit (401/403/404/400)
- Guards board.py + collections.py (404/403, admin/owner bypass)
- Tests 21/21 (inherit/restricted/private, grant, revoke, batch, group, audit)
- Docs + ROADMAP + CHANGELOG + VERSION 6.1.0
2026-09-19 22:54:16 -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
brunoandFlowDeck bf3d1ac0cc feat: v5.14.0 Synced blocks - block created once, edited everywhere
FlowDeck CI / lint (push) Failing after 57s
FlowDeck CI / test (push) Successful in 6m34s
FlowDeck CI / docker (push) Successful in 59s
- Table synced_blocks (source of truth) + page_synced_blocks (references)
- Migration 15 + service app/services/synced_blocks.py
- API endpoints: CRUD synced blocks, add/remove page references
- Editor: /synced slash command, synced block rendering with badge
- Realtime: _propagate_synced broadcasts updates to all referencing rooms
- Export: synced blocks resolved in Markdown/HTML/PDF
- 18 tests in tests/test_v514_synced_blocks.py

Co-authored-by: FlowDeck <[email protected]>
2026-09-17 20:08:09 -04:00
bruno 88e4ae1db8 fix(agent): purge les api_base LLM obsoletes (Mistral/Cohere /v2)
FlowDeck CI / lint (push) Successful in 53s
FlowDeck CI / test (push) Successful in 5m46s
FlowDeck CI / docker (push) Successful in 48s
Un api_base stocke (ex. https://api.mistral.ai/v2) ecrasait l'URL par defaut corrigee et faisait echouer le test de connexion. Desormais: normalisation a l'ecriture (une base egale au defaut n'est pas stockee), possibilite de vider le champ (api_base='' vs None), et migration 14 qui efface les bases obsoletes/redondantes dans user_llm_keys et llm_config.

Tests de non-regression ajoutes.
2026-09-14 23:04:39 -04:00
bruno 9dfc38706c feat(wiki,templates): v5.11.0 wiki-links & mentions + v5.12.0 templates & page lock (release 5.12.0)
FlowDeck CI / lint (push) Successful in 50s
FlowDeck CI / test (push) Successful in 5m41s
FlowDeck CI / docker (push) Successful in 45s
v5.11.0 Wiki-links & mentions de page :
- tokens [[fdpage:ID]] / [[fddate:ISO]] dans le texte des blocs,
  service app/services/wiki_links.py (labels, rendu HTML, extraction)
- taper [[ ouvre le picker de pages (recherche floue, clavier) ;
  le menu @ gagne les sections Pages et Date (today/tomorrow/YYYY-MM-DD)
- chips atomiques contenteditable=false relues en tokens par gtTok()
  (autosave/drag/undo preservent les liens) ; renommage propage via
  GET /board/api/wiki/titles ; backlinks reconnaissent les tokens ;
  page publique rend les chips (echopee)

v5.12.0 Templates & verrouillage :
- template picker global sur + New page : 5 built-in
  (app/services/block_templates.py) + templates perso
  (table page_global_templates, migration 13)
- POST /board/api/page-templates (save current page) + /{id}/use
  (instantiate, id 0 = built-in par cle)
- page lock : POST /api/pages/{id}/lock, garde _ensure_page_editable
  -> 423 en ecriture pour les non-privileged, deblocage par
  locked_by ou admin seulement (403 sinon), banniere + read-only UI
- full-width / small text par page (pages.full_width/font_small,
  POST /api/pages/{id}/options, classes CSS)
- migration 13 : is_locked, locked_by, full_width, font_small,
  page_global_templates

Tests : tests/test_v511_v512_wiki_templates.py (15) ; suite complete
538 verte ; ruff OK ; node --check des templates JS OK.
2026-09-14 06:38:09 -04:00
bruno d4adf89db5 feat(calendar): v5.8.0 calendrier & rappels + v5.7.0 database avancee (pt.2)
FlowDeck CI / lint (push) Successful in 49s
FlowDeck CI / test (push) Successful in 5m26s
FlowDeck CI / docker (push) Successful in 43s
v5.8.0 (release 5.11.7) — Calendrier & Rappels :
- moteur de recurrence RRULE subset (daily/weekly/monthly, interval,
  count, until, byweekday, timezone) — app/services/recurrence.py
- vues calendar Jour / Semaine / Mois avec expansion des occurrences
  cote serveur (GET /db/{id}/calendar/api) et popover evenement
  (Time / Timezone / Repeat / Remind)
- rappels avant echeance (scan 60 s, table reminder_log, in-app +
  email, cible = personnes assignees) — app/services/reminders.py
- fuseaux horaires : users.timezone + reglages in-app, timezone par
  evenement, liste de zones (GET /db/timezones/api)
- notifications d'assignation sur PUT /db/pages/{id}/api et
  preferences etendues (reminders, assignments)
- template Meeting notes enrichi (Agenda, Notes — migration 12)
- migrations 11-12 ; 20 tests dedies ; suite complete 523 verte

v5.7.0 (release 5.11.6, termine avant cette session, reste dans
l'arbre sans commit) — Database Avancée Pt.2 :
- proprietes person + auto-proprietes (created/last-edited time & by)
- groupes de proprietes, vues sauvegardees par utilisateur
- swimlanes, WIP limits, cartes configurables, calendar drag & drop,
  gallery couvertures ; 12 tests dedies
2026-09-13 22:49:14 -04:00
bruno 3b00cbc371 feat(import): v5.6.0 unified data import (phases 0-5)
- unified importer framework (app/services/importers/): normalized model,
  registry, common pipeline (hierarchy, attachments, collections, dedup),
  async jobs, dry-run preview, column->type mapping
- Phase 1: Obsidian, Notion, Logseq/Roam, HTML (Apple Notes/Bear/Ulysses/
  OneNote), Google Keep, generic Markdown
- Phase 2: typed CSV/TSV, Excel (openpyxl), generic JSON
- Phase 3: Word .docx (python-docx), PDF (pypdf), HTML folders
- Phase 4: Raindrop, Pocket, Readwise, Shaarli, Netscape bookmarks, .ics,
  OPML, Standard Notes, Gitea/GitHub issues (+labels/milestones)
- Phase 5: incremental re-sync (skip/update/duplicate), partial-error resume,
  forge repo files, URL web clipper (SSRF guard), batch multi-file + UI queue,
  Notion relation resolution, exportable JSON reports
- /import wizard, API /api/import/*, migration 9 (import_items, import_jobs)
- fix: property values stored by property id (correct DB view rendering)
- deps: openpyxl, beautifulsoup4, PyYAML, python-docx, pypdf
- 43 import tests; full suite 491 green; ruff clean
- bump version 5.11.5
2026-09-13 10:43:20 -04:00
bruno da3e09c215 feat(icon): Notion-style icon picker + custom workspace emojis; fix side peek file content & ctx menu overflow
FlowDeck CI / lint (push) Successful in 45s
FlowDeck CI / test (push) Failing after 3h6m55s
FlowDeck CI / docker (push) Skipped
2026-09-12 20:05:53 -04:00
bruno 6fe5d2f723 feat(v5.10.0): v5.4.0 + v5.5.0 features — backlinks, page/collection duplication, trash purge, version history, markdown import, embed/bookmark/video/audio blocks, cover & icon, OG metadata
- Migration v7: page_versions table + pages.cover_url/page_icon columns
- Trash service (purge_expired 30-day) + daily scheduler
- Board API: duplicate page, backlinks, versions (snapshot/list/restore), cover/icon upload, markdown/file import
- Collections API: duplicate collection (deep copy properties/views/pages/data sources)
- Export service: render embed/bookmark/video/audio in markdown/HTML/PDF/public
- Public page renderer: cover image + icon
- Editor: slash commands for media blocks, lightbox, version history UI, backlinks panel, cover/icon picker, import modal
- OG metadata endpoint for bookmark cards
- 386 tests passing
2026-09-11 08:56:48 -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 e4b196a528 feat(db): v5.3.0 inline databases, predefined templates & property validation
FlowDeck CI / test (push) Failing after 12s
FlowDeck CI / docker (push) Skipped
- Slash command /database (DATA group) -> template picker -> inline DB
  embed block rendered by FlowDeckDB. 'Get Started > Database' uses it too.
- 6 seeded database templates (CRM, Project tracker, Task list, Content
  calendar, Meeting notes, Reading list) with icon + schema; new service
  app/services/db_templates.py (materialize_properties, create_from_template).
- POST /db/api and /db/inline/api accept 'template' and materialize
  collection_properties. database_templates gets an icon column (migration v4).
- Property validation: collection_properties.validation_json (migration v4);
  validate_property_rule() in property_types (required/unique/min/max/
  min_length/max_length); enforced in create/update page API (400 + message,
  unique excludes current row); property API accepts 'validation'.
- UI: add-property modal exposes Required/Unique/Min/Max; cell edit shows
  validation errors (red outline + toast) and reverts.
- VERSION + app.main -> 5.1.0; CHANGELOG + ROADMAP updated.
- +9 tests (tests/test_db_advanced.py). 271 passed.
2026-09-07 00:53:13 -04:00
bruno 0c271d5972 feat(core): v5.0.0 command palette + FTS5 search, v5.2.0 versioned migrations
FlowDeck CI / test (push) Failing after 12s
FlowDeck CI / docker (push) Skipped
- Command palette Ctrl+K/Ctrl+P (base.html): universal search, fuzzy
  highlight, keyboard nav, quick actions. openQuickFind now opens it.
- GET /api/search endpoint + search service: unified pages + databases
  search, FTS5 with LIKE fallback, trash excluded, user-scoped.
- app/migrations.py: lightweight versioned migration runner (schema_version
  table); baseline schema = v1, new steps applied in order.
- Migration v2: missing indexes (users.email, user_oauth_tokens, etc).
- Migration v3: FTS5 pages_fts + sync triggers + backfill.
- VERSION + app.main -> 5.0.0; CHANGELOG + ROADMAP updated.
- +8 tests (tests/test_search_migrations.py). 259 passed (3 pre-existing
  PDF/weasyprint env failures unrelated).
2026-09-06 19:23:31 -04:00