Files
Spark 7852d860fe
CI / test (push) Successful in 2m13s
fix(0.31.1): compositeur de création refait, description en <details> natif
- Carte compositeur : en-tête + colonne d'arrivée, champ
  pleine largeur, bouton primaire ; neutralise le
  display:flex imposé par .board-toolbar aux formulaires.
- 'Ajouter une description' devient un <details> natif :
  aucun JS requis, insensible au cache et aux erreurs de
  scripts (le bouton 0.31.0 pouvait rester inerte).
- Assets du board versionnés (?v=APP_VERSION) contre les
  mélanges de cache après redéploiement ; Ctrl+Entrée.
- Vérifié en Chromium réel sur le vrai board (captures
  contrôlées) ; 261 tests verts.
2026-10-23 09:48:17 -04:00

54 KiB
Raw Permalink Blame History

Changelog

0.31.1 — 2026-10-23

Corrigé — compositeur de création refait

Retour de Bruno sur la 0.31.0 : la barre de création n'était ni élégante ni professionnelle, et le bouton « + Description » pouvait rester sans effet (écouteur JavaScript non enregistré selon l'état du cache ou des scripts de la page).

  • Compositeur en carte : en-tête « Nouvelle issue » avec la colonne d'arrivée (« arrive dans 📥 Backlog », nom personnalisé de l'espace respecté), champ titre pleine largeur avec anneau de focus, bouton primaire « Créer l'issue ».
  • Description en <details> natif : « Ajouter une description ▾ » déplie la zone texte sans aucun JavaScript — impossible à casser par un script en erreur ou un fichier en cache. Aide intégrée (Markdown, Ctrl+Entrée pour créer, actif aussi depuis le titre).
  • Assets du board versionnés (?v=<version> sur le CSS et board.js du board) : un redéploiement invalide le cache navigateur au lieu de servir un mélange d'anciennes et nouvelles pièces.
  • Vérifié en navigateur réel (Chromium) sur le vrai board : captures fermé/ouvert contrôlées visuellement, clic sur le libellé, zone visible et éditable.

0.31.0 — 2026-10-23

Ajouté — description éditable, pièces jointes, clic fiable

Retours de Bruno : impossible d'ajouter une description après création, aucun moyen de joindre des fichiers comme dans Gitea, et clic sur les cartes capricieux.

  • Titre et description éditables dans le tiroir de détail (bouton « ✏️ Modifier le titre et la description ») : l'enregistrement écrit directement dans l'issue de la forge (PATCH), le journal consigne « edited ✏️ », et la carte du board reflète le nouveau titre sans recharger.
  • Description dès la création : le formulaire « Nouvelle issue » gagne un bouton « + Description » qui déplie un champ texte transmis à la création.
  • Pièces jointes d'issues (Gitea) : dans le tiroir, liste des fichiers (nom, taille, date), ajout par le sélecteur de fichier (25 Mio max), téléchargement proxifié par Kanbante (le jeton ne quitte jamais le serveur ; suit le browser_download_url de Gitea, dont l'endpoint d'asset ne renvoie que la fiche JSON — attrapé au smoke réel), suppression avec confirmation. Sur GitHub, l'API ne gère pas les pièces jointes d'issues : l'écran l'explique et renvoie à l'interface web.
  • Clic sur les cartes fiabilisé : l'ouverture du tiroir passe en délégation d'événement — avant, l'écouteur était posé carte par carte au chargement ; le premier rafraîchissement temps réel remplaçait les fragments et les cartes devenaient muettes. Le seuil anti-glisser (6 px) et l'exclusion liens/boutons sont conservés, et les cartes affichent un curseur pointeur.

0.30.0 — 2026-10-23

Ajouté — colonnes personnalisables et mapping étiquette ↔ colonne

Demande de Bruno : pouvoir personnaliser, retirer et ajouter des colonnes (Backlog, À faire, En cours, …) et configurer le mapping label/colonne depuis l'interface web.

  • Colonnes par espace (Administration → Colonnes, ou le bouton 🧱 Colonnes sur un board) : ajouter une colonne (insérée avant Terminé), la renommer (le nom affiché est libre, émojis compris), changer sa couleur, la monter ou la descendre, la supprimer — ses cartes sont alors déplacées vers une colonne de destination choisie. Réinitialisation aux six colonnes historiques en un clic. Chaque espace a SES colonnes.
  • Clés immuables : une colonne garde sa clé interne (en_developpement) quoi qu'on renomme — les cartes, les limites WIP et les règles y restent rattachés. Backlog et Terminé sont des colonnes système (renommables, non supprimables) : défaut des cartes neuves, et issues fermées.
  • Mapping étiquette ↔ colonne configurable : chaque colonne de flux a son étiquette mappée (défaut kanban:<clé>) posée sur l'issue à chaque déplacement (miroir), plus des alias reconnus à l'adoption — par exemple déclarer kanban_a_faire (convention Flowdeck) en alias de la colonne À faire fait adopter cette colonne par le board. Adoption : exactement une étiquette reconnue, comme avant.
  • Focus / Wallboard : chaque colonne déclare si elle y figure (case « Dans Focus / Wallboard ») ; les nouvelles colonnes y sont par défaut.
  • Sans personnalisation, tout est strictement identique à avant (définitions semées paresseusement depuis les valeurs historiques). Le triage au clavier garde ses touches historiques (1 = À faire, 2 = En cours, …).

0.29.0 — 2026-10-23

Modifié — panneau Spark V3 : la console en surimpression pleine page

Le bouton « Console ↗ » du panneau Spark (demande de Bruno) ne part plus en nouvel onglet : la console web du service d'agents (https://agent.dracodev.net/) s'ouvre désormais dans la même page, en surimpression qui recouvre tout l'écran avec la même animation d'ouverture que la barre latérale (panneau vendangé draco-panneau.js, recopié octet-identique dans les 4 apps ; les styles de la surimpression sont injectés par le panneau lui-même). La barre de la surimpression offre les deux sorties : « Mode sidebar » referme la console et rouvre l'agent en barre latérale, « Fermer l'agent » ferme la surimpression et le panneau. La discussion affichée et l'app d'origine (?disc=<id>&app=kanbante) passent comme avant à la console. Côté service d'agents : la console autorise l'encadrement par les 4 apps (frame-ancestors, service 0.20.0). Même livraison : TikTak 0.60.0, Flowdeck 7.81.0, ObsiGate 2.77.0. Redéploiement Docker requis pour l'activer.

0.28.1 — 2026-10-22

Ajouté — panneau Spark : bouton « Console ↗ »

Bouton « Console ↗ » dans la barre des discussions du panneau Spark (demande de Bruno) : ouvre la console web du service d'agents (https://agent.dracodev.net/) dans un nouvel onglet, sur la discussion actuellement affichée (?disc=<id>, URL construite au clic) et avec l'app d'origine (?app=kanbante, déduite du sous-domaine). Panneau recopié octet-identique dans les 4 apps (TikTak 0.59.1, Flowdeck 7.80.1, Kanbante 0.28.1, ObsiGate 2.76.1). Redéploiement Docker requis pour l'activer.

0.28.0 — 2026-10-22

Ajouté — émission d'événements vers le journal du service d'agents (Lot 2)

Kanbante émet désormais ses changements de colonne au journal d'activité cross-app du service d'agents (contrat ACC-0.2) : kanbante.card.moved pour tout déplacement réel d'une carte — glisser-déposer de l'interface, adoption d'une étiquette kanban:* posée dans la forge, fermeture/réouverture venue de la forge (webhook ou réconciliation à l'affichage), fusion de PR, création de branche — et kanbante.card.review_requested quand une carte entre en colonne Révision. Enveloppe signée HMAC-SHA256 avec la clé propre à Kanbante (AGENT_EVENEMENTS_CLE, URL réglable par AGENT_EVENEMENTS_URL) ; émission au mieux, en arrière-plan : inactive sans clé, et une panne du service d'agents n'affecte jamais un déplacement. Aucun changement de comportement visible. Redéploiement Docker requis.

0.27.0 — 2026-10-22

Ajouté — panneau Spark v2 (Lot 1)

Le panneau vendangé passe en v2, à l'identique dans les 4 apps : réponses de l'agent en Markdown rendu (HTML du service d'agents 0.10.0, sanitizé côté serveur, rapports de missions compris), largeur réglable persistée, thème clair/sombre aligné sur l'app hôte ou le système, et discussions façon Muse : discussion principale perpétuelle + parallèles créées/archivées/supprimées depuis le tiroir du panneau. Redéploiement Docker requis.

0.26.0 — 2026-10-21

Ajouté — panneau Spark intégré

Le bouton Spark de la barre commune ouvre désormais le panneau de l'agent commun (conversation, Aujourd'hui, approbations, missions), comme dans TikTak et Flowdeck : assets draco-panneau.js/css vendangés à l'identique, action spark branchée sur DRACO_PANNEAU.toggle(). Redéploiement Docker requis (avec le reste de la 0.26.0).

Ajouté — écritures MCP minimales et sûres (service d'agents)

Le serveur MCP n'était qu'en lecture depuis la 0.5.0. Le service d'agents (jeton kbt_ posé en production) peut désormais créer des cartes et commenter, et rien d'autre : aucune suppression, aucun changement d'état.

  • create_issue — arguments : owner (chaîne, requis), repo (chaîne, requis), title (chaîne, requis), body (chaîne, optionnel), column (optionnel, une des colonnes du board, backlog par défaut). Réutilise le service de création existant (_do_capture → create_issue du client de forge, Gitea ou GitHub selon la connexion qui détient le dépôt) : la carte est placée sur le board et journalisée (source mcp). Réponse JSON : number, title, html_url, repo_full_name, column.
  • add_comment — arguments : owner, repo, number (entier), body — tous requis. Réutilise create_comment du client de forge (mêmes validations que l'API web : corps non vide, 10 000 caractères max) et journalise l'événement commented (source mcp). Réponse JSON : id, body, html_url, repo_full_name, number.
  • Garde inchangée : les deux outils passent par le même /mcp et le même middleware que les lectures — session, Basic ou Authorization: Bearer kbt_… ; un jeton ne déverrouille toujours pas l'interface web, et sa révocation bloque aussitôt les écritures. Erreurs métier au format existant du serveur (résultat isError avec le message).
  • GET /mcp déclare désormais read_only: false et la liste write_tools (honnêteté de la découverte).
  • Redéploiement Docker de Kanbante à la charge de Bruno pour activer cette version en production.

0.25.0 — 2026-10-21

Ajouté — jetons d'API personnels pour les surfaces machine (MCP)

Depuis la 0.24.0, tout Kanbante exige une authentification (session ou Basic) — y compris /mcp. Le service d'agents s'y faisait refuser en 401 (vu en production le 2026-10-21, panneau Spark : « Source Kanbante injoignable »). Il manquait une identité machine propre.

  • Table api_tokens : jetons personnels préfixés kbt_, seule l'empreinte SHA-256 est conservée ; création, liste et révocation dans Mon profil → Jetons d'API (MCP), texte clair affiché une seule fois à la création.
  • Le middleware honore Authorization: Bearer kbt_… uniquement sur /mcp et /api/ : un jeton ne déverrouille jamais l'interface web. Révocation et désactivation du compte ont effet immédiat ; last_used_at journalise l'usage.
  • Usage visé : créer un jeton « service-agents » et le poser en AGENT_MCP_KANBANTE_KEY dans le .env du conteneur agent.

0.24.2 — 2026-10-21

Corrigé — boîtes d'édition blanches dans l'administration (#29)

Signalé par Bruno (captures) : le champ « Nouveau mot de passe » (Administration), la zone « Sélection de projets » (Espaces) et les champs « Valeur du panneau » (Paramètres) s'affichaient en blanc. Il n'existait aucune règle de base pour les champs de saisie : seuls les champs couverts par un contexte précis (.login-form, .capture-form, .admin-form pour text/password/ select seulement) étaient sombres — les textarea et tout champ hors de ces contextes gardaient le fond du navigateur.

Correctif dans style.css : une règle de base unique en spécificité zéro (:where(...)) — fond --surface-2, texte --text, bordure --border — pour input, textarea et select, qui comble les vides sans jamais écraser les règles de contexte existantes ; plus color-scheme: dark pour les contrôles natifs. Styles calculés vérifiés sur les trois pages (fond identique aux champs de référence, palette de commandes inchangée).

0.24.0 — 2026-10-21

Ajouté — multi-utilisateurs, multi-forges, espaces, archives

Réalise l'analyse du 2026-10-21 (décisions D1 à D6 appliquées selon les recommandations). Aucune configuration obligatoire : au premier démarrage, la connexion Gitea historique est créée depuis l'environnement, l'espace Principal la contient, et le compte d'environnement devient l'administrateur initial (mot de passe haché en base). Migration automatique des bases existantes (portées (1, 1) partout).

  • Connexions (P0/P1) — une forge = une connexion (Gitea ou GitHub, nouveau client complet : dépôts, issues, étiquettes par nom, jalons, PR, archivage). Jeton chiffré (Fernet) en base, jamais réaffiché (masque ••••). Registre de clients, instantanés par connexion. Webhooks par connexion (/webhooks/{slug}, signatures Gitea et GitHub) en plus du webhook historique.
  • Utilisateurs (P2) — comptes en base (PBKDF2), rôles admin/membre, activation/désactivation (une session d'un compte désactivé meurt aussitôt), journal d'audit admin. Connexion par la base ; les identifiants d'environnement restent un secours pour le compte opérateur. Liaison draco par utilisateur (le pont SSO lie et ouvre la session du bon compte ; sémantique mono-utilisateur 0.23 conservée tant qu'il n'y a qu'un compte). Page /profile : infos, mot de passe, déliaison draco, connexions personnelles.
  • Espaces de travail (P3) — l'unité de présentation : connexions attachées, membres (admin d'espace / membre / lecteur), sélection explicite de projets optionnelle. Board, notes, épingles du jour, journal : scopés par espace (le même projet peut être rangé différemment dans deux espaces). Sélecteur d'espace dans l'en-tête (visible dès qu'on a accès à plusieurs espaces), badge de connexion sur les projets quand l'espace en a plusieurs. Panneau Paramètres : l'environnement amorce, le panneau gouverne — surcharges en base pour les réglages courants (fenêtre d'activité, TTL, seuils zombies/âge, horaires des rituels, seuil d'archivage…), provenance affichée.
  • Archives (P4) — page /archives : archive locale (masque le projet dans l'espace, forge intacte, réversible), archivage sur la forge (confirmé, journalisé), purge de l'état local de l'espace, export du récapitulatif Markdown, file « À archiver ? » (inactifs depuis archive_suggest_days, 180 j par défaut) avec archivage local en lot. Les archives sortent du tableau de bord ; l'onglet Archivés y gagne un lien « Gérer ».

Limites assumées de cette version

  • Les rituels d'arrière-plan (briefing, digest, règles, serveur MCP) travaillent sur la portée historique (connexion principale, espace Principal).
  • KANBANTE_MASTER_KEY (optionnelle) : sans elle, une clé de chiffrement est générée une fois et gardée en base.

0.23.3 — 2026-10-21

Correctifs — barre commune v0.1.4 (retours de Bruno)

  • Assets de la barre versionnés (?v= dans l'adresse) : sans ça, le navigateur — surtout la webview de l'app bureau ObsiGate — gardait l'ancien JavaScript et le menu du ✦ ne s'ouvrait pas, alors que le serveur servait déjà le bon fichier.
  • Palier mobile élargi à 900 px (commons v0.1.4) : entre 700 et 900 px, la barre complète ne tenait pas alors que Kanbante est déjà en mise en page mobile — d'où le look différent des autres apps sur la capture de Bruno. Décalage du cadre aligné.

0.23.2 — 2026-10-21

Ajouté — menu des applications (barre commune v0.1.3)

  • Le ✦ de la barre ouvre le menu des 4 applications (choix de Bruno) : c'est le moyen de changer d'app en mobile, où les onglets sont repliés — et il fonctionne aussi sur bureau. Le logo est un peu plus gros (24 px). Menu construit par le JS commun depuis les onglets (mêmes liens, icônes, badges) ; fermeture au clic extérieur ou à Échap.

0.23.1 — 2026-10-21

Correctifs — barre commune et barre latérale (retours de Bruno)

  • Barre d'apps pleine largeur : elle était repoussée à droite de la barre latérale par le padding-left du cadre ; elle est maintenant fixe, pleine largeur, et le cadre entier est décalé de sa hauteur (60 px, 52 px en mobile).
  • Barre commune v0.1.2 (dracodev-commons) : palier mobile resserré selon la spec — app courante, alertes, Spark, avatar ; rail, recherche, domaines et menu disparaissent au profit des contrôles natifs de chaque app.
  • Animation du repli de la barre latérale : durée et courbe unifiées (0,26 s, cubic-bezier(0.4, 0, 0.2, 1)) entre le corps et la barre, et retrait du backdrop-filter (fond déjà opaque à 96 %) qui rendait l'animation de largeur saccadée.

0.23.0 — 2026-10-21

Fusion — Kanbante rejoint l'accès centralisé (cartes #27, #28)

  • Barre d'apps commune dracodev (ACC-1, #28) : snippet figé vendangé de dracodev-commons v0.1.1 (partiel _draco_bar.html, draco-barre.css / draco-barre.js), inclus par le cadre partagé — Kanbante était la dernière des quatre applications sans la barre. Le rail pilote le repli natif de la barre latérale, la palette ouvre la recherche & commandes native ; alertes unifiées et Spark annoncent leur arrivée avec la fédération.
  • Pont SSO draco_session (ACC-3.2, #27) : le cookie émis par ObsiGate est vérifié localement (app/draco.py — JWS HS256 au secret partagé DRACO_SESSION_SECRET, révocation de l'émettrice en cache 60 s) et converti en session Kanbante native par GET /auth/draco ; bouton « Se connecter avec ObsiGate (SSO) » sur l'écran de connexion. Kanbante étant mono-utilisateur, aucun mapping de comptes n'est nécessaire. Inerte sans le secret.
  • Tests : test_draco_sso.py (7) et test_draco_barre.py (3) ; suite complète : 211 tests verts.

0.22.1 — 2026-10-20

Correctif — colonne Terminé vide

  • Les issues fermées dans Gitea mais suivies par le board n'apparaissaient pas dans la colonne Terminé : la réconciliation plaçait bien leur ligne locale en done, mais l'affichage du board ne fusionnait que les issues ouvertes.
  • Le board (page HTML et API JSON) inclut désormais les issues fermées dont la ligne locale est en done, y compris dans la vue par milestone.
  • Test de régression ajouté ; suite complète : 201 tests verts.

0.22.0 — 2026-10-14

Écran de connexion (demande de Bruno)

  • Fini la fenêtre Basic Auth du navigateur : page /login professionnelle (carte centrée, marque dégradée, erreur claire, retour à la page demandée après connexion).
  • Session par cookie signé HMAC (7 jours, HttpOnly, SameSite=Lax) ; clé KANBANTE_SESSION_SECRET ou dérivée des identifiants — changer le mot de passe invalide les sessions.
  • L'en-tête Basic reste accepté pour les scripts ; les API reçoivent 401, seuls les navigateurs sont redirigés. Lien ⏻ Sortir dans le pied de la barre latérale, /logout réel. Protection CSRF sur le formulaire, redirection next limitée aux chemins locaux.

Barre latérale (demandes de Bruno)

  • Le bouton Replier quitte le bas de la barre : c'est une icône seule, en haut, à droite du bouton recherche.
  • Accordéon exclusif : ouvrir une section ferme les autres — une seule ouverte à la fois (état mémorisé dans kanbante-nav-open ; la section de la page courante prime).

Chantier B — instantanés d'arrière-plan (validé par Bruno)

  • Un rafraîchisseur recalcule périodiquement les listes coûteuses (index des dépôts, étoiles, issues all et open, jalons — pour chaque projet actif) et les persiste dans SQLite (table snapshots, écriture à chaque réponse du client). KANBANTE_SNAPSHOT_INTERVAL (défaut 120 s, 0 = off).
  • Au démarrage, le cache du client est hydraté depuis les instantanés (servis périmés + rafraîchis en tâche de fond, mécanique SWR) : la première page après un redémarrage ou un redéploiement ne paie plus Gitea.
  • Un webhook Gitea rafraîchit immédiatement les instantanés du dépôt touché. La fraîcheur est affichée dans le pied de la barre (« 🕐 à l'instant / il y a N min ») : les données Gitea peuvent dater d'un intervalle au plus, le journal local reste instantané.
  • Mesuré sur l'instance réelle (via le proxy de Spark, latences gonflées) : premier chargement à froid 9,4 s sans instantanés → après redémarrage avec instantanés : Projets 0,31 s, Focus 0,16 s, Triage 0,07 s, Santé 0,22 s, Prévisions 0,08 s.

0.21.0 — 2026-10-12

Sélecteur de dépôt intelligent (Capture éclair, demande de Bruno)

  • Le champ Dépôt de /capture propose les dépôts réels dès la frappe : liste filtrée en direct, correspondance sur les deux segments — « kan » suffit pour trouver Projets/kanbante, « pr/kan » aussi. Au focus, épinglés (⭐) et dépôts récents d'abord.
  • Complétion Tab segment par segment, comme un shell : « pr » Tab → Projets/ (le séparateur est posé dès que le nom d'organisation est complet), « kan » Tab → kanbante. ↑/↓ + Entrée et la souris choisissent dans la liste.
  • Validation douce : un nom qui n'existe pas dans Gitea est signalé sous le champ avant l'envoi.
  • Nouvel endpoint GET /api/repos : liste exhaustive (~130 dépôts chez Bruno — la palette Ctrl+K reste plafonnée à 60 pour son propre usage), triée épinglés → récents → archivés. Sélecteur dans static/js/repo-picker.js, réutilisable par d'autres formulaires.
  • Vérifié en Playwright sur les données réelles, geste exact de Bruno inclus : pr Tab → Projets/, kan Tab → Projets/kanbante.

0.20.1 — 2026-10-12

Correctifs tri/regroupement du dashboard (rapportés par Bruno)

  • Tri par date des tableaux réparé : le comparateur partagé lisait les dates ISO avec parseFloat — il ne retenait que l'année (« 2026 »), toutes les lignes d'une même année se retrouvaient à égalité et la colonne « Dernière activité » (vue Liste) triait dans un ordre arbitraire. La comparaison n'est numérique que si la valeur entière est un nombre ; les dates se comparent en chaînes ISO. Même piège écarté pour l'échéance des Prévisions.
  • Tri et regroupement appliqués aux Épinglés : la grille épinglée était exclue des deux outils (choix de la 0.18.0) — comme c'est la section regardée en premier, changer le Tri ou cocher « Grouper par propriétaire » semblait ne rien faire. Les quatre grilles sont maintenant traitées pareil.
  • Sens de premier clic utile : « Dernière activité », « Écart » (Prévisions) et « Zombies » (Santé) trient décroissant dès le premier clic (data-first-dir).
  • Tri grille par dates comparé en instants réels (fuseaux Gitea -04:00/-05:00), cartes sans activité en bas.
  • Vérifié en Playwright sur les données réelles : ordres strictement décroissant/croissant, regroupement et dégroupement des Épinglés, aucune erreur JS.

0.20.0 — 2026-10-12

Refonte de l'en-tête de la page Projets (demande de Bruno)

  • Titre sobre : fini le « Bonjour 👋 Voici vos projets Gitea… » — un « Projets » net, un sous-titre discret, et l'en-tête occupe deux fois moins de hauteur qu'avant.
  • Bande KPI unifiée : les 4 statistiques (projets actifs, fermées · 30 j, déplacements · 30 j, temps de cycle moyen) vivent dans UNE barre bordée à séparateurs fins, chiffres en largeur tabulaire ; les indicateurs du journal mènent à la page Activité au clic.
  • Barre d'outils unique : onglets, filtre, tri, regroupement et bascule Grille/Liste — auparavant éparpillés sur trois rangées — sont alignés dans un seul cadre. Les onglets deviennent un contrôle segmenté avec pastilles de compte (plus de dégradé violet ni d'emojis 🟢💤🗄️), le filtre passe en rectangle sobre.
  • Aucun crochet fonctionnel touché (ids et liaisons Alpine inchangés) ; responsive vérifié en captures 1600 px et 430 px sur les données réelles : aucun débordement, onglets fonctionnels. Les tuiles .stat-tile restent utilisées par le briefing quotidien.

0.19.0 — 2026-10-12

Performance + navigation « Pilotage » (chantiers A + C, décidés par Bruno)

  • Parallélisation (A1) : les pages inter-projets (dashboard, /health, /forecast, /triage, /wall) attendaient chaque dépôt à la queue leu leu ; elles utilisent maintenant un asyncio.gather borné (16) — le patron que /focus appliquait déjà.
  • Cache stale-while-revalidate (A2) : les listes Gitea (dépôts, issues, jalons, étoiles) sont servies immédiatement même périmées, et rafraîchies en tâche de fond. Fini le « mur » de rechargement à chaque expiration du cache (30 s) : seul le tout premier chargement après un démarrage paie le coût complet. Les mutations vident le cache et désarment les rafraîchissements en vol (aucune donnée périmée ressuscitée).
  • Prévisions refondues (C1) : /forecast devient un tableau de bord des jalons tous projets — une ligne par jalon (projet, échéance, progression, ETA, écart, débit), triée par risque, filtrable, colonnes triables ; le bloc jalon des cartes du dashboard y pointe directement (ancres). Le débit par projet reste en dessous, en tableau compact.
  • Santé refondue (C2) : /health devient un tableau trié par sévérité (pastille, ouvertes, zombies, goulot) ; la page santé d'un projet gagne un sélecteur de projet pour basculer sans repasser par l'index. Le tri des tableaux est mutualisé (static/js/tablesort.js, dashboard inclus).
  • Mesuré sur l'instance réelle (depuis le réseau de test) : pages chaudes 0,04–0,16 s ; le premier chargement à froid reste de quelques secondes — le chantier B (instantanés d'arrière-plan) demeure le levier pour le supprimer, si voulu.

0.18.0 — 2026-10-11

Nouveautés — vague 2, suite (4 cartes de Bruno)

  • Activité récente par projet (#19) : ligne sur la carte du dashboard calculée par UNE requête agrégée sur le journal — « 📈 X fermées · Y déplacements cette semaine », ou « 💤 aucune activité kanban depuis N j » pour les projets endormis.
  • Actions rapides sur la carte (#23) : menu ⋯ sur chaque carte — Board, ⚡ Capturer ici (la page capture accepte ?repo= et pré-remplit le dépôt), Triage du backlog, Santé, Récit de sprint, Gitea. Clavier et tactile soignés (Échap, clic extérieur).
  • Tri et regroupement (#21) : tri par activité Gitea, activité kanban, ouvertes ou nom ; regroupement par propriétaire en sections repliables ; préférences mémorisées par navigateur (localStorage).
  • Vue liste dense (#22) : bascule Grille/Liste persistée — tableau triable par colonne (Projet, Propriétaire, Ouvertes, En vol, Prochain jalon, Santé, Dernière activité) réutilisant les enrichissements des cartes, mêmes onglets et même filtre.

Note : le lien Triage du menu ⋯ est constant — la taille du backlog « stats » du dashboard ne compte que les cartes placées, pas le backlog réel ; la page Triage affiche l'état exact.

7 tests ajoutés (185 au total).

0.17.0 — 2026-10-11

Nouveautés — vague 2 « Gestion de projets » (4 cartes de Bruno)

  • Prochain jalon sur la carte projet (#17) : le jalon ouvert le plus proche de son échéance s'affiche sur la carte du dashboard — progression (compteurs Gitea), échéance en français, alerte si en retard, et ETA du journal en regard avec signal « après l'échéance » quand la prévision dépasse la date.
  • Pastille de santé par projet (#18) : point vert/orange/rouge sur chaque carte active, règles uniques partagées avec /health (zombies, cartes coincées en QA/Révision, médiane du goulot), info-bulle détaillée, clic vers la santé du projet.
  • Projets épinglés via les étoiles Gitea (#20) : section « ⭐ Épinglés » en tête du dashboard pour les dépôts étoilés ; bouton ☆/⭐ sur chaque carte (PUT/DELETE /user/starred) — la vérité vit dans Gitea, aucune table locale ; bascule sans rechargement (stars.js). Échec de l'API : dashboard intact.
  • Page Projet (#25) : /project/{owner}/{repo} — accueil du projet : jalons ouverts avec progression/échéances/ETA, santé en résumé (goulot, zombies), débit des prévisions, activité récente du journal, notes du projet et actions (board, capture, triage, santé, wallboard figé, Gitea). Le titre des cartes du dashboard pointe désormais ici ; le board reste à un clic (lien 📋 Board sur chaque carte et bouton principal).

7 tests ajoutés (178 au total).

0.16.1 — 2026-10-11

Améliorations (retour de Bruno sur la barre latérale)

  • Le bouton « Recherche & commandes » devient une icône 🔍 seule, placée à droite du titre dans l'en-tête de la barre latérale (info-bulle et Ctrl+K inchangés) ; en rail replié, elle passe sous le logo, toujours accessible.
  • Les groupes du menu deviennent des sections accordéon : en-têtes cliquables au look moderne (micro-libellés, chevron animé), ouverture/fermeture en transition douce (technique grid-template-rows), état mémorisé par navigateur appliqué avant le premier rendu. La section de la page courante s'ouvre toujours automatiquement. En rail replié, l'accordéon s'efface : toutes les icônes restent visibles.

0.16.0 — 2026-10-11

Nouveautés

  • Layout repensé (issue #16, retour de Bruno sur la 0.15.0 : disposition pas conviviale, trop de place, mobile inchangé) — la barre de pilules horizontale disparaît au profit d'une barre latérale : navigation groupée (Principal, Rituels, Pilotage, Outils), bouton palette en tête, repliable en rail d'icônes sur desktop (état mémorisé par navigateur), et tiroir hors-canvas sur mobile (burger dans une topbar mince de 52 px : fil d'Ariane + actions contextuelles seulement). Le partiel _header.html reste l'unique source du cadre.
  • Wallboard : hauteur verrouillée à l'écran (100dvh, overflow: hidden) — plus aucune barre de défilement de page ; le pied de diapositive (« ✅ Fermées aujourd'hui », « 📋 Ouvertes », « ● EN DIRECT ») reste toujours visible, au-dessus de la zone réservée à la navigation des diapos ; la liste des cartes se tronque avec un fondu et une ligne « … +N autres cartes en vol » ; mode compact sous 760 px de hauteur (TV 720p).

6 tests adaptés/ajoutés (171 au total).

0.15.0 — 2026-10-11

Nouveautés

  • Header refait (issue #16, créée et spécifiée par Bruno) : les 19 copies de markup de header sont remplacées par un partiel unique _header.html. Desktop : une seule ligne — 5 entrées primaires (Projets, Focus, Aujourd'hui, Recherche, Capture), menu « Plus ▾ » pour les 9 autres, Ctrl+K à droite, page active marquée (y compris dans « Plus »). Mobile (≤ 900 px) : burger + panneau plein largeur, cibles ≥ 44 px, fermeture Échap / clic extérieur. La page active est déduite du gabarit dans render() (active_nav) — une seule source de vérité. Le wallboard garde son plein écran sans header et la session triage utilise le même partiel. static/js/nav.js partagé, aucune dépendance ajoutée.

Corrigé

  • Prévisions : les semaines se calent désormais sur le référentiel du journal (UTC, comme les horodatages board_events) — une fermeture journalisée en soirée locale (déjà le lendemain en UTC) tombait hors de toutes les semaines et faussait le débit.

5 tests ajoutés (170 au total).

0.14.0 — 2026-10-11

Nouveautés

  • Créer la branche depuis la carte (issue #3) : le panneau détail propose issue-<n>-<slug du titre> (slug ASCII, 40 car. max, nom libre accepté après validation git-ref) et la crée dans Gitea depuis la branche par défaut (POST /api/issues/{o}/{r}/{n}/branch). La carte passe en « En cours » (journalisé, source branch, étiquette synchronisée) et la branche est aussitôt reconnue par le code lié (#1) et par l'automatisation de fusion (#2). Réponse idempotente si la branche existe déjà.
  • Santé du flux (issue #9) : app/flow.py reconstruit les séjours par colonne depuis le journal (entrée → déplacement / fermeture) : temps médian et moyen par colonne, colonne la plus lente (goulot, ≥ 2 séjours). Cartes zombies : ouvertes sans activité (journal ou Gitea) depuis KANBANTE_ZOMBIE_DAYS (défaut 30). Pages /health (résumé global) et /health/{owner}/{repo} (détail + actions rapides sur les zombies : commenter « toujours pertinent ? », remettre au Backlog, fermer — via les API existantes).

8 tests ajoutés (165 au total). La feuille de route « Différenciation » est complète : 15/15.

0.13.0 — 2026-10-11

Nouveautés

  • Cartes liées au code (issue #1) : app/code_links.py apparie branches (feature/12-x, issue-12), PRs (références #n dans titre/corps ou branche) et commits récents (références #n). Badge ⑂ sur les cartes (board + fragments temps réel), section « 🧬 Code lié » dans le panneau détail, endpoint GET /api/issues/{o}/{r}/{n}/code.
  • PR fusionnée → carte Terminé (issue #2) : le webhook accepte pull_request fermée + fusionnée ; les issues liées sont fermées dans Gitea si besoin et leurs cartes passent en Terminé, idempotent, journalisé source webhook.
  • Standup automatique (issue #6) : page /standup + /api/standup — fermé/déplacé hier (journal, titres résolus), focus aujourd'hui, blocages (cartes qui vieillissent en QA/Révision) ; bouton copier ; inclusion optionnelle au briefing ntfy (KANBANTE_BRIEFING_INCLUDE_STANDUP=1).
  • Règles d'automatisation (issue #8) : moteur déclaratif KANBANTE_RULES (JSON, validé : conditions column, min_age_days, label, wip_over ; actions add_label, notify, move_top), évalué toutes les 15 min par le planificateur et à la demande ; chaque action est journalisée (événement rule, source rule) ; page /rules avec état et dernière évaluation. Garde-fou : aucune action de fermeture ou de déplacement entre colonnes.

10 tests ajoutés (157 au total).

0.12.0 — 2026-10-11

Nouveautés

  • Focus du jour (issue #5) : le rituel des 3 cartes. Table today_picks ; bouton 📌 sur chaque carte du board (et sur les candidates) ; page /today calme — picks du jour avec leur colonne en direct, candidates de l'encours, reprises d'hier non terminées reproposées, récapitulatif « ça a bougé aujourd'hui » tiré du journal. Le briefing du matin inclut les sections « Focus du jour » et « À reprendre d'hier ». POST /api/today/pin (max 3, idempotent) et /unpin.
  • Prévisions (issue #7) : app/forecast.py — fermetures par semaine depuis le journal (8 semaines), débit moy/min/max sur les 4 dernières semaines complètes, projection en fourchette (jamais un faux chiffre précis) et silence explicite sans historique. Affichées sur le dashboard (épuisement du backlog), dans le bandeau milestone (avec alerte si l'ETA dépasse l'échéance) et sur /forecast (sparkline SVG inline, verdict par milestone). /api/metrics expose weekly_closures et throughput_4w.
  • Récit de sprint (issue #4) : app/sprint.py + page /sprint/{owner}/{repo}?milestone= — le bilan markdown du milestone écrit par le journal : livré (avec temps de cycle par carte), cartes les plus lentes, reporté avec colonnes, chiffres de la période ; boutons Copier et Télécharger .md, endpoint GET /api/sprint/... en JSON, lien « 📖 Récit de sprint » dans le bandeau milestone du board.

11 tests ajoutés (147 au total).

0.11.0 — 2026-10-11

Nouveautés

  • Wallboard navigable : flèches ← / → du clavier, boutons ❮ ❯ et pastilles cliquables pour changer de projet à la demande ; une navigation manuelle met la rotation en pause 90 s, Espace bascule une pause franche (badge visible). La position est mémorisée (sessionStorage) entre les rechargements : le mur ne repart plus à la première diapo à chaque refresh — avec 12 projets actifs × 30 s, le cycle complet (6 min) dépassait le rechargement de sécurité (5 min), rendant les dernières diapos inatteignables et donnant l'impression d'un mur figé.

Correction

  • L'écoute temps réel du wallboard utilisait onmessage, qui ne se déclenche jamais pour les événements SSE nommés (gitea) émis par le hub : les rechargements en direct ne partaient pas, seul le filet de 5 minutes fonctionnait. Corrigé en addEventListener('gitea', …).

3 tests ajoutés (136 au total).

0.10.0 — 2026-10-11

Nouveautés

  • Mode Triage (issue #11) : vider un backlog au clavier, façon « inbox zero ». /triage liste les projets actifs et la taille de leur backlog ; /triage/{owner}/{repo} présente les cartes du Backlog une par une, plein cadre (titre, extrait du corps, étiquettes, âge), file embarquée côté client — aucun rechargement entre cartes. Décisions : 1–5 envoient dans À faire / En cours / QA / Révision / Terminé, X ferme, L ouvre le panneau d'étiquettes (bascule via l'API existante), A s'assigne l'issue (nouvel endpoint POST /api/issues/{o}/{r}/{n}/assign-self, idempotent), Entrée passe à la suivante, Z annule le dernier déplacement. Barre de progression « Carte n / N » et résumé final par décision. Les raccourcis sont affichés en permanence et cliquables. Points d'entrée : bouton « Triage du backlog » sur le board et action dans la palette Ctrl+K.

6 tests ajoutés (133 au total).

0.9.0 — 2026-10-11

Nouveautés

  • Board dynamique sans refresh (issue #15) : le board reflète l'état réel en continu. Côté serveur, chaque mutation connue (déplacement, création, capture, bascule d'étiquette) est désormais diffusée sur le hub SSE — jusqu'ici seuls les webhooks émettaient — et les webhooks bénéficient du même canal pour toutes leurs actions (étiquettes, créations, éditions comprises). Nouvel endpoint GET /api/board/{owner}/{repo} : état du board en JSON avec les cartes rendues côté serveur (partiel _card.html partagé avec la page), même pipeline de réconciliation/adoption que le board HTML. Côté client, board-live.js applique le diff en place (seules les colonnes changées sont remplacées, signature par colonne), anime les cartes survivantes vers leur nouvelle place (FLIP, désactivé si prefers-reduced-motion), diffère l'application pendant un drag local, réapplique filtres/compteurs/indices, et sonde toutes les 45 s en repli (installations sans webhooks, onglet visible). Ni le défilement, ni le panneau détail, ni Sortable ne sont affectés. Focus et Wallboard conservent leur recharge douce, désormais déclenchée par toutes les mutations.

6 tests ajoutés (127 au total).

0.8.0 — 2026-10-11

Nouveautés

  • Palette de commandes (issue #10) : Ctrl+K / Cmd+K (ou le bouton ⌨️ dans la navigation) ouvre sur toutes les pages une palette façon Linear/Raycast — actions de navigation, tous les projets (filtrage local instantané) et recherche globale d'issues annotées de leur colonne (nouvel endpoint GET /api/palette?q=). Navigation entièrement au clavier (↑↓, Entrée, Échap).
  • Digest hebdo vers ObsiGate (issue #13) : le résumé markdown de la semaine (issues fermées enrichies de leurs titres, cartes en cours/QA/révision, compteurs du journal) est composé automatiquement le jour et l'heure choisis (KANBANTE_DIGEST_WEEKDAY / KANBANTE_DIGEST_TIME) avec notification ntfy — mais jamais livré sans approbation : l'envoi se fait d'un clic sur /digest, vers le serveur MCP d'ObsiGate (client MCP intégré : initialize + tools/call ; URL, jeton, nom d'outil et gabarit JSON d'arguments configurables ; bouton « Tester la connexion » qui liste les outils du serveur) ou vers un webhook générique (KANBANTE_DIGEST_WEBHOOK_URL, JSON {title, markdown, week}).

11 tests ajoutés (121 au total).

0.7.0 — 2026-10-11

Nouveauté

  • Capture éclair (issue #12 de la feuille de route) : trois entrées, un seul geste — transformer un message en issue placée sur le board (événement created, source capture) :
    • POST /api/capture : endpoint machine-à-machine protégé par un jeton de capture dédié (KANBANTE_CAPTURE_TOKEN, en-tête X-Capture-Token ou Bearer ; distinct du jeton Gitea, révocable seul ; désactivé en 503 tant qu'il n'est pas défini ; exempté d'auth Basic et de CSRF). JSON {title, body, repo, column} ou texte libre (première ligne = titre). Dépôt par défaut : KANBANTE_CAPTURE_REPO.
    • Écoute ntfy : si KANBANTE_CAPTURE_NTFY_TOPIC est défini, un abonné en tâche de fond (flux JSON du topic, reconnexion avec recul, curseur persisté dans kv_store — aucun rejeu au redémarrage) transforme chaque message en issue. Les messages tagués kanbante sont ignorés (pas d'auto-ingestion).
    • Page /capture : formulaire de saisie rapide, statut de configuration et exemples prêts à copier (curl, ntfy). Lien « ⚡ Capture » dans la navigation de toutes les pages.

12 tests ajoutés (110 au total).

0.6.0 — 2026-10-11

Nouveautés

  • Colonne QA entre « En cours » et « Révision » (🧪, étiquette kanban:qa) : une étape de validation finale avant la révision. Le flux complet devient Backlog → À faire → En cours → QA → Révision → Terminé ; la vue Focus inclut les cartes en QA.
  • Wallboard (issue #14 de la feuille de route) : GET /wall, affichage plein écran pensé pour un écran d'atelier — rotation automatique (30 s) entre les projets actifs, compteurs des six colonnes, cartes en vol (En cours / QA / Révision / À faire) avec âge, fermées du jour, horloge ; rafraîchissement en direct via le flux SSE. ?repo=Proprietaire/depot fige un seul projet. Lien « 🖥️ Wallboard » ajouté à la navigation de toutes les pages.
  • Réconciliation par étiquettes : si l'étiquette kanban:* d'une issue ouverte diverge de sa colonne enregistrée (modifiée dans Gitea ou par un autre outil), le board et la vue Focus adoptent la colonne de l'étiquette et journalisent le déplacement (source gitea). Règles : exactement une étiquette kanban:* fait foi ; zéro ou plusieurs = l'état local gagne ; inactif si KANBANTE_SYNC_LABELS=0. Déplacer une carte depuis Gitea devient donc possible.

10 tests ajoutés (98 au total).

0.5.2 — 2026-10-11

Correctif

  • L'indice « Glissez une carte ici » restait affiché après un dépôt dans une colonne vide : il est rendu par le serveur pour les colonnes vides au chargement, et le glisser-déposer ne le retirait jamais du DOM. refreshEmptyHints() recalcule désormais l'indice d'après le contenu réel de chaque colonne après tout déplacement (et après un retour arrière en cas d'échec) : retiré dès qu'une carte est présente, rétabli quand la dernière carte part. SortableJS est en outre restreint aux seules cartes (draggable: '.kanban-card'), l'indice n'est plus un élément déplaçable parasite.

0.5.1 — 2026-10-11

Correctif critique

  • Les boards étaient vides contre un vrai Gitea : l'API Gitea (1.27.3 vérifié) renvoie la clé "pull_request": null sur les issues ordinaires ; le filtre _is_issue testait la présence de la clé ("pull_request" not in item), donc chaque vraie issue était classée « pull request » et écartée. Board, vue Focus et briefing ne montraient aucune carte (le dashboard, qui lit les compteurs des dépôts, semblait normal). Corrigé : le filtre teste la valeur (not item.get("pull_request")).
  • Le faux Gitea des tests omettait la clé, ce qui masquait le bug : il reproduit désormais fidèlement le payload réel (clé toujours présente, null sur les issues), plus 4 tests de régression dédiés (88 tests au total). Smoke test réel : le board bruno/flowdeck passe de 0 à 6 cartes, dont l'issue de test « test d'ajout ! ».

0.5.0 — 2026-10-11

« Palier 3 » (points 7 à 9) + board enrichi.

Ajouts

  • Recherche globale (/search) : recherche d'issues dans tous les projets via l'API Gitea, résultats groupés par projet avec la colonne Kanban de chaque issue. Mes issues (/my) : les issues ouvertes assignées à l'utilisateur du jeton, tous projets confondus.
  • Briefing quotidien : page /briefing (encours, activité 24 h, cartes vieillissantes, milestones proches), GET /api/briefing, et envoi ntfy manuel (POST /api/briefing/send) ou automatique à KANBANTE_BRIEFING_TIME via un planificateur interne (mémoire d'envoi en base, aucun doublon après redémarrage).
  • Serveur MCP (lecture seule) : JSON-RPC 2.0 sur POST /mcp (initialize, tools/list, tools/call, ping) avec 7 outils — list_projects, get_board, get_issue, get_focus, search_issues, get_activity, get_metrics. Aucune écriture, conformément au principe « lectures d'abord ». GET /mcp décrit le serveur.
  • Gestion des étiquettes sur le board : modale de gestion (lister / créer avec palette de couleurs / supprimer les étiquettes du dépôt dans Gitea) et, dans le panneau détail, ajout / retrait d'étiquettes sur l'issue en un clic, avec mise à jour immédiate de la carte. API : GET|POST /api/repos/{o}/{r}/labels, DELETE /api/repos/{o}/{r}/labels/{id}, POST /api/issues/{o}/{r}/{n}/labels.

Améliorations

  • Panneau Notes du projet : repliable (bouton ⤢, état mémorisé par projet), largeur ajustable par glisser (mémorisée), et sauvegarde automatique après 1,2 s sans frappe avec indicateur d'état (le bouton manuel reste). Le formulaire quitte HTMX pour le même board.js que le reste du board.
  • Navigation unifiée enrichie sur toutes les pages : Mes issues, Briefing, Recherche.

Tests

  • 19 tests ajoutés (84 au total) : recherche et mes issues, briefing (page, API, envoi ntfy, format), protocole MCP, API étiquettes, marqueurs du board. Un doublon de déclaration JS attrapé par node --check avant livraison.

0.4.0 — 2026-10-11

« Palier 2 » : temps réel et visible dans Gitea — plus une refonte complète de l'interface.

Ajouts

  • Webhooks Gitea + rafraîchissement en direct : POST /webhooks/gitea (signature HMAC-SHA256 vérifiée quand KANBANTE_WEBHOOK_SECRET est défini) invalide le cache de lecture, applique les fermetures / réouvertures faites dans Gitea (idempotent : l'écho de nos propres appels ne double jamais le journal) et pousse un événement SSE sur GET /api/stream. Le navigateur se recharge en douceur quand c'est sûr (onglet visible, pas de panneau ouvert, pas de saisie en cours, pas de drag) ; sinon une pastille « Nouvelle activité » propose l'actualisation.
  • Synchro par étiquettes : les colonnes intermédiaires sont reflétées dans Gitea par des étiquettes kanban:todo, kanban:in_progress, kanban:review (créées au besoin, ajout / retrait granulaires — les étiquettes de l'utilisateur ne sont jamais touchées ; backlog et done = aucune étiquette). Désactivable : KANBANTE_SYNC_LABELS=0.
  • Boards par milestone : GET /board/{owner}/{repo}?milestone=<titre|id> filtre le board, avec bandeau d'échéance et progression (issues fermées du milestone / total). Sélecteur de milestones au-dessus du board.

Interface (refonte complète)

  • Nouveau design system : en-tête vitré sticky avec navigation en pastilles (état actif), halos d'ambiance, cartes projets qui se soulèvent au survol, barres de progression, coins plus doux, anneau de focus visible partout, prefers-reduced-motion respecté.
  • Dashboard : hero avec tuiles de synthèse (projets actifs, issues fermées et déplacements sur 30 jours, temps de cycle moyen — depuis le journal), états vides guidés pour chaque onglet, raccourci / pour la recherche (aussi sur le filtre du board).
  • Board : pastille « live » en cas d'activité externe, colonnes à défilement indépendant, placeholders de colonnes vides, panneau de notes explicité, drawer animé.
  • Cohérence : même navigation sur les 5 pages, responsive retravaillé.

Tests

  • 13 tests ajoutés (65 au total) : hub SSE et générateur de flux, webhooks (transition, idempotence, signature, JSON invalide), synchro d'étiquettes, boards par milestone, marqueurs de la refonte.

0.3.0 — 2026-10-11

« Palier 1 » : voir ce qui se passe sur les boards.

Ajouts

  • Journal d'événements (board_events, append-only) : chaque création, déplacement, fermeture, réouverture et commentaire est horodaté. Il alimente la page /activity (fil tous projets), GET /api/events et GET /api/metrics (débit par type et temps de cycle moyen : entrée en « En cours » → fermeture). Les fermetures détectées lors de la réconciliation avec Gitea sont aussi journalisées (source gitea). Un reclassement dans la même colonne n'écrit pas d'événement.
  • Panneau détail de carte : un clic sur une carte ouvre un panneau latéral avec le corps de l'issue rendu en markdown (marked + DOMPurify, vendorés), ses commentaires, assignés, milestone et échéance ; on peut commenter directement dans Gitea depuis le panneau (GET /api/issues/{owner}/{repo}/{n}, POST .../comments, 404 propre si l'issue n'existe pas).
  • Vieillissement des cartes : badge « ⏳ N j » dès qu'une carte reste dans sa colonne au-delà de KANBANTE_AGING_DAYS (défaut 7, rouge au double). Le temps en colonne vient du journal, avec repli sur board_state.updated_at puis sur la date de création de l'issue.
  • Limites WIP : KANBANTE_WIP_LIMITS="in_progress:5,review:3" — l'en-tête de colonne affiche n/limite, passe en rouge en dépassement et un toast avertit au dépôt. Limites souples : jamais bloquantes.

Tests

  • 16 tests ajoutés (52 au total) : journal et métriques, détail et commentaires, vieillissement, WIP.

0.2.0 — 2026-10-11

Consolidation complète à partir d'un audit du code 0.1.0 (chaque correctif marqué « confirmé » avait été reproduit par un test avant correction).

Critiques corrigés

  • Perte de données en Docker : KANBANTE_DB_PATH est enfin lue par le code — la base SQLite atterrit dans le volume /data comme prévu.
  • Authentification : Basic Auth optionnelle mais recommandée (KANBANTE_AUTH_USER / KANBANTE_AUTH_PASSWORD, KANBANTE_REQUIRE_AUTH=1 pour refuser de servir sans), protection CSRF (double-submit) sur tous les POST, avertissement bruyant au démarrage quand l'auth est absente.
  • Synchro bidirectionnelle : déplacer une carte vers « Terminé » ferme l'issue dans Gitea, la ressortir la rouvre (KANBANTE_SYNC_GITEA=0 pour désactiver). L'état local est réconcilié à chaque chargement de board (fermées → Terminé, supprimées → purgées).

Importants corrigés

  • Classification des projets : fenêtre d'activité glissante configurable (KANBANTE_ACTIVE_WINDOW_DAYS, défaut 365) et vrai drapeau archived de Gitea — fini l'année codée en dur et l'onglet « Archivés » mensonger.
  • Pagination complète des appels Gitea (le plafond serveur de 50 réponses par page ne tronque plus les dépôts ni les issues, en silence).
  • get_board_state ne plante plus sur une colonne inconnue ; migration automatique des bases 0.1.0 (colonne position, notes.updated_at, nettoyage des lignes invalides).
  • Gitea injoignable → page d'erreur 502 propre (JSON pour l'API) au lieu d'un 500 brut ; /api/readiness teste réellement SQLite et Gitea, /api/health reste un liveness sans dépendance.
  • Dockerfile : installation après copie du code (le package installé n'est plus vide), utilisateur non-root, HEALTHCHECK, .dockerignore.

Ajouts

  • Ordre des cartes persisté dans chaque colonne (aller-retour glisser-déposer → rechargement).
  • Création d'issues depuis le board (POST /api/issues).
  • Vue Focus (/focus) : tout ce qui est En cours / En révision, tous projets actifs confondus.
  • Filtres par texte et par étiquette sur le board ; les cartes lient vers l'issue Gitea ; les pull requests ne sont plus affichées comme des issues.
  • Suite de tests pytest (modèles, client Gitea, API, auth/CSRF) et CI Gitea Actions (.gitea/workflows/ci.yml).
  • Fichier LICENSE (MIT, annoncé par le README depuis la 0.1.0).

Détails

  • Client Gitea entièrement asynchrone (les routes ne bloquent plus la boucle d'événements), cache mémoire court des listes, en-tête Authorization seulement si un jeton est configuré, uid résolu via /user (plus de uid=1 ni d'utilisateur codés en dur), .env chargé depuis la racine du projet seulement.
  • Bibliothèques JS (HTMX, Alpine, SortableJS) vendorées dans static/vendor/ : plus aucune dépendance CDN à l'exécution.
  • Glisser-déposer : en cas d'échec serveur, la carte est replacée et le toast d'erreur est rouge ; les déplacements envoient l'ordre complet des colonnes source et destination.
  • API : codes HTTP corrects (400 colonne invalide, 403 CSRF, 413 note trop longue — limite configurable), lifespan FastAPI à la place de on_event déprécié, imports nettoyés.
  • CSS : fond des badges corrigé (color-mix() remplace l'invalide var(--accent)20).
  • Recherche du dashboard : le nom des dépôts passe par un attribut data-search échappé, plus aucune interpolation dans du JS.
  • docker-compose.yml : clé version: obsolète retirée, variables d'auth exposées, healthcheck.

0.1.0 — 2026-07-07

Version initiale : dashboard des projets Gitea, board Kanban 5 colonnes par dépôt (glisser-déposer SortableJS), notes par projet, état local SQLite, thème sombre, Dockerfile + docker-compose.