Commit Graph
23 Commits
Author SHA1 Message Date
bruno 587ec8d61b fix: A27 phase 1 — 4 243 L de JS inline extraites + eslint actif (v7.21.0)
FlowDeck CI / lint (push) Canceled after 0s
FlowDeck CI / test (push) Canceled after 0s
FlowDeck CI / docker (push) Canceled after 0s
Extraction des 7 templates dont le JS n'est PAS interpolé Jinja → 9 fichiers
static/js/*.js (4 243 lignes, -30 % du JS inline : 13 904 → 9 661) :
- agent_panel_1/_2 (bloc de 1 788 L livré sur CHAQUE page), library (1 039),
  gitea_workspace (626), _icon_picker_1/_2, _ctx_menu, import, workspaces
- UN fichier par bloc : ordre/timing identiques (pas de defer, attributs
  conservés dont data-cfasync), cache-busting via ?v={{ asset_version }}
  (source unique A40), scripts externes = 'self' en CSP (pas de nonce requis)
- garde-fou : le script refuse tout bloc contenant {{ ou {%
- vérifs : node --check vert sur les 9, 0 script inline restant dans les
  cibles, suite complète 1089/1089

Lint (la moitié « ajouter les templates à eslint » de l'audit) :
- eslint.config.mjs existait (flat v9, sans dépendances npm) mais AUCUN
  binaire eslint n'était installé → npm i -g eslint
- `eslint static/js` → 0 erreur, 120 warnings (no-unused-vars 69,
  no-empty 36, no-undef 15) sur 8 fichiers = baseline à nettoyer
- les extraits sont couverts d'office par la config (static/js/**/*.js)

Reste A27 : blocs interpolés Jinja (page_editor 2 517, local_workspace 2 031,
base 1 523, database_table 1 323, settings 1 093, realtime 531 ≈ 9 661 L)
→ extraction en 2 temps (config JSON injectée + script statique).

suite **1089/1089** · ruff OK · docs à jour
2026-10-01 15:55:09 -04:00
bruno c718fe06de fix: A20 (partiel) — CSP nonce par requête, unsafe-inline sort de script-src (v7.7.0)
FlowDeck CI / lint (push) Canceled after 0s
FlowDeck CI / test (push) Canceled after 0s
FlowDeck CI / docker (push) Canceled after 0s
- ContentSecurityPolicyMiddleware : nonce aléatoire par requête dans la
  ContextVar `CSP_NONCE` (posée avant `call_next` → visible des templates),
  `script-src 'self' 'unsafe-eval' 'nonce-…'` — plus aucun script inline
  sans nonce ne tourne (fin des XSS injectés en JS)
- 38 tags `<script>` des templates : `nonce="{{ csp_nonce() }}"` (passage
  scripté, vérifié : 0 restant) ; `LOCAL_LOGIN_HTML` (constante de module) :
  helper `_with_nonce()` au rendu ; collections.py : 3 scripts Python
  (chart/form/map) noncés
- `<meta name="htmx-config" content='{"inlineScriptNonce": …}'>` dans base.html
  : htmx ré-injecte les <script> des réponses boostées avec le bon nonce
- `script-src-attr 'unsafe-inline'` : les 74 handlers `onclick=` inline
  restent couverts (le nonce les aurait désactivés aussi)
- chart.js (cdn.jsdelivr.net) et leaflet (unpkg) ajoutés à script-src/style-src
  : vues chart/map déjà BLOQUÉES par la CSP depuis toujours
  (commentaire ponytail: upgrade = vendoriser puis retirer les hôtes)
- reste d'A20 : unsafe-eval (Alpine x-data → @alpinejs/csp), externalisation
  JS (A27), resserrer img-src/connect-src

test : test_csp_nonce_per_request (page base.html + page hors template,
nonce unique par requête)

suite **1037/1037** · `ruff check app tests` OK · docs à jour
2026-10-01 10:41:39 -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 d986959927 fix(cloudflare): protect agent panel, workspaces & shell scripts from Rocket Loader; trust proxy headers
FlowDeck CI / lint (push) Successful in 47s
FlowDeck CI / test (push) Successful in 4m17s
FlowDeck CI / docker (push) Successful in 45s
2026-09-13 09:51:54 -04:00
bruno 3fcc12ad8c feat: sweep complet — tous les émojis → outline SVG icons
Templates modifiés (22 fichiers):
- _icons.html: +14 new icons (paperclip, external-link, sparkles, lightbulb, tag,
  file-text, save, upload, trending-up, zap, alert-triangle, user, eye-off)
- base.html: +8 JS icons, 🦎🐙🔑🔗👁📋🔲📑❓⚠️→SVG
- page_editor.html: 43→0 émojis (📎📄🔒🔗⭐📋📁✨📝🗄📑📊📅🗓🖼📥🌐✏💬💡 etc)
- settings.html: 30→0 (⚙️📋🏷🧩👥💾🙈👁🔒🌙☀️🌳📊📝⚠🦎✅🐙🔗✏🗑)
- local_workspace.html: 25→0 (📄📁✏🗑⚠📋➕)
- gitea_workspace.html: 25→0 (🔗📄📤🔄⚙📁📄🔒✏🗑💾)
- board.html: 13→0 (📁📊📋☰📈👥✕✓🗑⚡🔍)
- workspace.html: 11→0 (🏠🔑⚙📁🔗📂🐙)
- landing.html: 8→0 (📚🚀📝📊🦎🌐🔒⚡)
- trash.html, table_view, dashboard, accounts, card_detail, public_page,
  workspaces, team_load, notes, _header, detailed_board, card, board_fragment
- Ajouté import _icons.html aux fragments standalone
- 143 tests passent
2026-07-21 08:27:10 -04:00
bruno 3d10400f8f fix: workspace cards edit/delete + remaining workspaces emojis
- ✏️→edit SVG (card rename button)
- 🔗→link SVG (Gitea section title, Connect button)
- 🔍→removed (search placeholder)
- 🔒→lock SVG (private project indicator)
- 143 tests passent
2026-07-21 08:03:31 -04:00
bruno d94dd3da99 fix: workspaces topbar 🔑⚙ → outline SVG key+settings
- _icons.html: +key icon (Lucide style)
- getSvgIcon JS: +key (matching SVG)
- workspaces.html: 🔑 Login → fd_icon('key'), ⚙ Settings → fd_icon('settings')
- 143 tests passent
2026-07-21 07:55:46 -04:00
bruno aa434e9fe9 fix: derniers émojis — workspaces 🏠, hover actions, sidebar context menu
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
- workspaces.html: 🏠→home SVG (page_icon, header)
- local_workspace.html: ✏️🗑 ✕→SVG (rename, delete, clear buttons, rename modal)
- base.html: ✏️🗑️📁📄→SVG (context menus Rename/Delete/New File/Folder)
  + pageIcon default '📁'→'folder', modal title '📁 New Folder'→SVG
- 143 tests passent
2026-07-20 23:13:01 -04:00
bruno b835dd6b5e fix: WORKSPSACES section + remaining emoji icons replaced
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- base.html: séparateur entre version et Log out, _local_workspaces_for_user
- board.py: _local_workspaces_for_user helper, app_version, fix emoji icons
- dashboard.py: _local_workspaces_for_user helper
- library.html: 📚📁📄🕒⭐👥🌐🔒📦 → SVG + icon map
- workspaces.html: 📁🔍🗑📝 → SVG
- local_workspace.html: page_icon, empty states, icon functions → SVG
- settings.html: 👤🔔 → SVG nav icons
- _icons.html: +'bell' icon
- CSS: .nav-icon-inline, .empty-state-icon
- 143 tests passent
2026-07-20 20:58:02 -04:00
bruno 63773cb904 fix: 4 correctifs UX — workspace +, library empty, settings spacing
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
- Workspaces: bouton bleu '+' maintenant centré, 48px, min-height 140px (plus coupé)
- Library no-workspace: 'Open a Workspace...' avec lien Go to Workspaces au lieu de Loading
- Library: boutons '+ Add new' et 'New page' cachés quand pas de workspace
- Settings: espacement bouton Upload photo (margin-bottom, margin-top augmentés)
- 143 tests passent
2026-07-20 11:21:14 -04:00
bruno d751415308 feat: add Notion-style breadcrumb navigation with dropdown menus
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
Backend:
- Added _nav_breadcrumb() to build page hierarchy chain (root → current)
- New /api/nav/menu endpoint returns workspace/folder children with has_children flag
- view_page() and view_page_root() now pass breadcrumb_items, nav_workspace_id, nav_page_id to template

Header template (_header.html):
- Replaced static breadcrumb with Alpine.js fdBreadcrumb() component
- Breadcrumb items now clickable with dropdown menus showing
2026-07-17 23:30:59 -04:00
bruno 6f1eabf91d fix: Windows path handling, light theme default, file viewer in editor, first-user admin logic
FlowDeck CI / test (push) Failing after 18s
FlowDeck CI / docker (push) Has been skipped
Config:
- Fixed SQLite path parsing on Windows (handle drive letters without prepending /)
- Changed default theme from dark to light
- Updated OAuth test credentials (gitea_oauth_client_id/secret)

Auth:
- First real user (excluding default admin with no password) becomes admin
- Changed user count query to exclude users without password_hash

File viewer:
- Removed separate _render_file_viewer() —
2026-07-17 20:38:39 -04:00
bruno d4fb095baf feat: unified header across all pages (Notion-inspired breadcrumb + actions)
FlowDeck CI / test (push) Failing after 5s
FlowDeck CI / docker (push) Has been skipped
Created a shared _header.html template with:
- Hamburger button (toggle sidebar)
- Breadcrumb navigation with clickable segments and separators
- Page icon + title display
- Right-side action buttons (configurable per page)
- Dropdown panel CSS for More/New menus

Updated all pages to use the unified header:
- workspaces.html: Home / Workspaces + login/settings
- workspace.html: Workspace — Projects + login/settings
- local_workspace.html: workspace name
- gitea_workspace.html: Home / owner/repo + New/Upload/Refresh/Settings
- page_editor.html: title + Edited/Share/Copy/Favorite/More dropdown
- settings.html: Settings

Added CSS for breadcrumb, dropdown panel components.
2026-07-16 12:30:18 -04:00
bruno 17666b51c2 fix: two UX issues
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
1. Settings X button: closeSettings() goes back, skipping hash-only navigation
   → No more double-click to close

2. Workspaces page: Connect Gitea link now includes &mode=link
   → Same link as Settings → Integrations (was missing mode=link)
2026-07-15 07:56:21 -04:00
bruno e2043123f0 fix: title_prefix block for browser tab — évite conflit Jinja2 page_title double
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Erreur: block 'page_title' defined twice → TemplateAssertionError
Fix: title_prefix (nouveau bloc) pour <title>, page_title (existant) pour Alpine

10 templates mis à jour avec title_prefix.
2026-07-14 09:35:52 -04:00
bruno b771708bdc fix: @click.away→@click.outside GLOBAL — 16 instances across 5 templates
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
Alpine 3.x a renommé .away en .outside. Toutes les occurrences dans:
- base.html (3: user menu, context menu, ws ctx)
- page_editor.html (5: share, perm, access, more, gsMore)
- workspaces.html (1: dialog overlay)
- workspace.html (1: modal overlay)
- local_workspace.html (6: create, rename, delete modals, context menus)

Ces .away cassées empêchaient tous les @click Alpine de fonctionner
sur ces pages (Cancel, Delete, et tous les autres boutons modaux).
2026-07-14 07:16:56 -04:00
bruno de40c2d83e v3.0.1: qualité & stabilité — tests, sécurité, UX consolidée
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
🧪 Tests: 73 → 130 (+57 tests)
- Upload API, labels sync, commit history (401/400/502/cached)
- File create/update (sha=null, sha=abc)
- Admin delete cascade (12 tests: oauth, tags, workspaces, pages…)
- Gitea status (linked/unlinked/disconnect)
- OAuth link mode (session, redirect, callback)

🔒 Sécurité
- ContentSecurityPolicyMiddleware (CSP headers)
- RateLimitMiddleware (100 req/min/IP)
- Pydantic models: ErrorResponse, SuccessResponse
- Input validation upload (10MB, allowed extensions)
- Pydantic request models

🎨 UX
- static/css/design-tokens.css (500 lines, thèmes + skeletons)
- Toast system: 16 alert() remplacés par toast()
- 59 lignes CSS dupliquées retirées (6 templates)
- Skeletons cohérents sur toutes les vues

⚡ Performance
- Cache TTL sur get_file_commits (consistant avec les autres méthodes)
2026-07-13 23:08:53 -04:00
bruno 6f15ad3ad4 v2.8.0 WIP: create/upload files + commit history + labels sync
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- POST /api/gitea/projects/{owner}/{repo}/upload (binary upload)
- get_file_commits() in GiteaClient
- GET /api/gitea/projects/{owner}/{repo}/commits (per-file history)
- POST .../sync-labels (Gitea labels → FlowDeck tags)
- New file form + upload button in gitea_workspace.html topbar
2026-07-13 22:33:47 -04:00
bruno e78ca4b775 feat: sidebar arborescence Gitea + tab user repos avec vrai username
FlowDeck CI / test (push) Failing after 3s
FlowDeck CI / docker (push) Has been skipped
1. Tab user repos: fetch username via /auth/user → affiche 'bruno' au lieu de 'Personal'
2. Sidebar: ws_cookie='gitea:owner:repo' → _sidebar_data() fetch le tree depuis Gitea API
3. base.html: data-gitea-path/type/sha sur les items workspace pour les projets Gitea
4. gitea_workspace.html: refonte sans tree panel → navigation via sidebar
   - Clic fichier → ouvre dans le contenu (lecture + edit + commit)
   - Clic dossier → lazy-load les enfants dans le sidebar
5. openGitea(): set cookie flowdeck_workspace avant navigation
2026-07-13 16:42:11 -04:00
bruno e9d1c32b4f feat: Gitea — register, settings connect, tabs org, search
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
1. Pas de Gitea sans config: _require_gitea() → 401 si pas de token OAuth
2. Register Gitea: boutons "Login/Register with Gitea" dynamiques selon l'onglet
3. Settings → Integrations: ✅ Active / 🔗 Connect / Disconnect + API status/disconnect
4. Workspaces: tabs par org (All | org1 | org2) + barre recherche 🔍 filtrage live
5. API: GET /api/gitea/status, DELETE /api/gitea/disconnect
2026-07-13 15:17:17 -04:00
bruno 46336df21b feat: frontend Gitea — workspaces 2 sections + gitea workspace vue
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
workspaces.html:
- Section 📁 Local Workspaces (existante, avec badges)
- Section 🔗 Gitea Projects (par organisation, lazy load)
- États: loading, not_linked (lien pour login OAuth), error (retry), ok

gitea_workspace.html:
- Arbre fichiers (lazy: un dossier à la fois)
- Vue fichier (lecture seule → bouton Edit)
- Éditeur avec zone de commit (message + historique dropdown)
- Section 🔒 Private Pages (placeholder pour pages FlowDeck locales)
- Bouton Delete fichier

Routing: /gitea-workspace?owner=X&repo=Y

Fallback: token admin serveur si pas de token OAuth utilisateur
2026-07-13 14:58:01 -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 3e6323a856 feat: workspaces system — create, select, rename, delete workspaces
FlowDeck CI / test (push) Failing after 4s
FlowDeck CI / docker (push) Has been skipped
- DB: pages.workspace_id column linking pages to workspaces table
- /workspaces: list, create, rename, delete workspaces page
- API: GET/POST/PUT/DELETE /api/workspaces + POST select
- Session: flowdeck_workspace cookie for active workspace tracking
- Sidebar: Workspace section shows active workspace name + page tree
- Local workspace APIs filter by active workspace_id
- Home redirects non-Gitea users to /workspaces
2026-07-10 16:41:40 -04:00