- 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.
54 KiB
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_urlde 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éclarerkanban_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,backlogpar défaut). Réutilise le service de création existant (_do_capture→create_issuedu 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 (sourcemcp). Réponse JSON :number,title,html_url,repo_full_name,column.add_comment— arguments :owner,repo,number(entier),body— tous requis. Réutilisecreate_commentdu client de forge (mêmes validations que l'API web : corps non vide, 10 000 caractères max) et journalise l'événementcommented(sourcemcp). Réponse JSON :id,body,html_url,repo_full_name,number.- Garde inchangée : les deux outils passent par le même
/mcpet le même middleware que les lectures — session, Basic ouAuthorization: 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ésultatisErroravec le message). GET /mcpdéclare désormaisread_only: falseet la listewrite_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éskbt_, 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/mcpet/api/: un jeton ne déverrouille jamais l'interface web. Révocation et désactivation du compte ont effet immédiat ;last_used_atjournalise l'usage. - Usage visé : créer un jeton « service-agents » et le poser en
AGENT_MCP_KANBANTE_KEYdans le.envdu 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-leftdu 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 dubackdrop-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 parGET /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) ettest_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_SECRETou 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,
/logoutréel. Protection CSRF sur le formulaire, redirectionnextlimité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
alletopen, jalons — pour chaque projet actif) et les persiste dans SQLite (tablesnapshots, é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 dansstatic/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 :
prTab →Projets/,kanTab →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-tilerestent 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.gatherborné (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.htmlreste 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 dansrender()(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.jspartagé, 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é, sourcebranch, é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.pyreconstruit 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) depuisKANBANTE_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.pyapparie branches (feature/12-x,issue-12), PRs (références#ndans 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, endpointGET /api/issues/{o}/{r}/{n}/code. - PR fusionnée → carte Terminé (issue #2) : le webhook accepte
pull_requestfermée + fusionnée ; les issues liées sont fermées dans Gitea si besoin et leurs cartes passent en Terminé, idempotent, journalisé sourcewebhook. - 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é : conditionscolumn,min_age_days,label,wip_over; actionsadd_label,notify,move_top), évalué toutes les 15 min par le planificateur et à la demande ; chaque action est journalisée (événementrule, sourcerule) ; page/rulesavec é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/todaycalme — 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/metricsexposeweekly_closuresetthroughput_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, endpointGET /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,Espacebascule 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é enaddEventListener('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 ».
/triageliste 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–5envoient dans À faire / En cours / QA / Révision / Terminé,Xferme,Louvre le panneau d'étiquettes (bascule via l'API existante),As'assigne l'issue (nouvel endpointPOST /api/issues/{o}/{r}/{n}/assign-self, idempotent),Entréepasse à la suivante,Zannule 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.htmlpartagé avec la page), même pipeline de réconciliation/adoption que le board HTML. Côté client,board-live.jsapplique 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é siprefers-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 endpointGET /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, sourcecapture) :POST /api/capture: endpoint machine-à-machine protégé par un jeton de capture dédié (KANBANTE_CAPTURE_TOKEN, en-têteX-Capture-Tokenou 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_TOPICest défini, un abonné en tâche de fond (flux JSON du topic, reconnexion avec recul, curseur persisté danskv_store— aucun rejeu au redémarrage) transforme chaque message en issue. Les messages taguéskanbantesont 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/depotfige 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 (sourcegitea). Règles : exactement une étiquettekanban:*fait foi ; zéro ou plusieurs = l'état local gagne ; inactif siKANBANTE_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": nullsur les issues ordinaires ; le filtre_is_issuetestait 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,
nullsur les issues), plus 4 tests de régression dédiés (88 tests au total). Smoke test réel : le boardbruno/flowdeckpasse 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_TIMEvia 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 /mcpdé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.jsque 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 --checkavant 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 quandKANBANTE_WEBHOOK_SECRETest 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 surGET /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-motionrespecté. - 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/eventsetGET /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 (sourcegitea). 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 surboard_state.updated_atpuis 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 affichen/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_PATHest enfin lue par le code — la base SQLite atterrit dans le volume/datacomme prévu. - Authentification : Basic Auth optionnelle mais recommandée
(
KANBANTE_AUTH_USER/KANBANTE_AUTH_PASSWORD,KANBANTE_REQUIRE_AUTH=1pour 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=0pour 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 drapeauarchivedde 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_statene plante plus sur une colonne inconnue ; migration automatique des bases 0.1.0 (colonneposition,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/readinessteste réellement SQLite et Gitea,/api/healthreste 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
Authorizationseulement si un jeton est configuré, uid résolu via/user(plus deuid=1ni d'utilisateur codés en dur),.envchargé 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),
lifespanFastAPI à la place deon_eventdéprécié, imports nettoyés. - CSS : fond des badges corrigé (
color-mix()remplace l'invalidevar(--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.