From 9e2096c9b66e54a67cb4c793368751f40a8bd694 Mon Sep 17 00:00:00 2001 From: Spark Date: Wed, 14 Oct 2026 08:02:49 -0400 Subject: [PATCH] =?UTF-8?q?chore(release):=20Kanbante=200.22.0=20=E2=80=94?= =?UTF-8?q?=20login,=20sidebar,=20chantier=20B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ app/digest.py | 2 +- pyproject.toml | 2 +- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c38faee..5f79c35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,51 @@ # Changelog +## 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) diff --git a/app/digest.py b/app/digest.py index 4fa9147..4664e84 100644 --- a/app/digest.py +++ b/app/digest.py @@ -143,7 +143,7 @@ async def _mcp_session(client: httpx.AsyncClient, url: str, token: str) -> None: { "protocolVersion": MCP_PROTOCOL_VERSION, "capabilities": {}, - "clientInfo": {"name": "kanbante", "version": "0.21.0"}, + "clientInfo": {"name": "kanbante", "version": "0.22.0"}, }, req_id=1, ) diff --git a/pyproject.toml b/pyproject.toml index 520dac2..7347333 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kanbante" -version = "0.21.0" +version = "0.22.0" description = "Kanban project manager integrated with Gitea" requires-python = ">=3.11" dependencies = [