v0.3.0
CI / test (push) Successful in 1m39s
Version, CHANGELOG (palier 1) et README (fonctionnalités, KANBANTE_WIP_LIMITS / KANBANTE_AGING_DAYS, nouvelles routes).
Kanbante
Kanban project manager integrated with Gitea — lightweight, self-hosted, dark theme.
Features
- 📋 Dashboard — tous tes projets Gitea en un coup d'œil (actifs / inactifs / archivés — le vrai drapeau Gitea)
- 🗂️ Kanban Board — colonnes Backlog → À faire → En cours → Révision → Terminé, ordre des cartes persisté
- 🎯 Drag & Drop — glisse les issues entre colonnes ; en cas d'échec, la carte est replacée
- 🔗 Gitea Sync bidirectionnelle — « Terminé » ferme l'issue dans Gitea, la ressortir la rouvre ; l'état local est réconcilié à chaque chargement
- ➕ Création d'issues depuis le board, filtres texte + étiquettes, cartes liées à Gitea
- 🗂️ Panneau détail — clic sur une carte : corps markdown, commentaires, et réponse postée dans Gitea sans quitter le board
- 📰 Journal d'événements — chaque mouvement est horodaté : fil d'activité (
/activity), métriques de débit et de temps de cycle (/api/metrics) - ⏳ Vieillissement + limites WIP — badge d'ancienneté par colonne et limites souples configurables
- 🎯 Vue Focus — tout ce qui est En cours / En révision, tous projets confondus (
/focus) - 📝 Notes — bloc-notes par projet
- 🔐 Authentification Basic Auth intégrée + protection CSRF (voir Sécurité)
- 🌙 Dark theme — conçu pour les longues sessions
- 🐳 Docker — un seul conteneur, utilisateur non-root, healthcheck
- 📴 Aucun CDN — les bibliothèques JS sont vendorées dans
static/vendor/, l'app fonctionne hors-ligne
Quick Start
# 1. Installer les dépendances
cd kanbante
pip install -e .
# 2. Configurer les variables d'environnement
export GITEA_URL=https://git.dracodev.net
export GITEA_TOKEN=ton_token_gitea
# Recommandé dès que le service dépasse localhost :
export KANBANTE_AUTH_USER=ton_nom
export KANBANTE_AUTH_PASSWORD=ton_mot_de_passe
# 3. Lancer
uvicorn app.main:app --reload --port 8080
Ouvrir http://localhost:8080
Docker
Avec docker-compose (recommandé)
cat > .env <<'EOF'
GITEA_TOKEN=ton_token
KANBANTE_AUTH_USER=ton_nom
KANBANTE_AUTH_PASSWORD=ton_mot_de_passe
EOF
docker compose up -d
La base SQLite vit dans le volume kanbante_data (monté sur /data,
chemin KANBANTE_DB_PATH) : les positions de cartes et les notes
survivent aux recréations du conteneur.
Avec docker uniquement
docker build -t kanbante:latest .
docker volume create kanbante_data
docker run -d \
--name kanbante \
-p 8080:8080 \
-v kanbante_data:/data \
-e GITEA_URL=https://git.dracodev.net \
-e GITEA_TOKEN=ton_token \
-e KANBANTE_AUTH_USER=ton_nom \
-e KANBANTE_AUTH_PASSWORD=ton_mot_de_passe \
--restart unless-stopped \
kanbante:latest
Déploiement sur Deepin 25 (Debian Bookworm)
sudo apt install -y docker.io docker-compose docker-buildx
sudo usermod -aG docker $USER
sudo systemctl enable --now docker
# Builder et lancer (voir section "Avec docker uniquement")
Configuration
| Variable | Défaut | Rôle |
|---|---|---|
GITEA_URL |
https://git.dracodev.net |
Instance Gitea |
GITEA_TOKEN |
(vide) | Jeton API Gitea — portée conseillée : lecture + écriture des issues, sur un compte dédié, pas un jeton admin. Sans jeton : contenu public seulement |
KANBANTE_DB_PATH |
~/.kanbante/kanbante.db |
Base SQLite locale (en Docker : /data/kanbante.db) |
KANBANTE_AUTH_USER / KANBANTE_AUTH_PASSWORD |
(vide) | Active la Basic Auth dès que les deux sont définis |
KANBANTE_REQUIRE_AUTH |
0 |
1 = l'app refuse de servir (503) si l'auth n'est pas configurée |
KANBANTE_ACTIVE_WINDOW_DAYS |
365 |
Un dépôt non archivé mis à jour depuis moins de N jours est « actif » |
KANBANTE_CACHE_TTL |
30 |
Secondes de cache des listes Gitea (dépôts, issues) |
KANBANTE_MAX_NOTE_CHARS |
20000 |
Taille maximale d'une note de projet |
KANBANTE_SYNC_GITEA |
1 |
0 = les déplacements ne ferment/rouvrent plus les issues Gitea |
KANBANTE_WIP_LIMITS |
(vide) | Limites souples par colonne, ex. in_progress:5,review:3 (affichage n/limite, rouge en dépassement, jamais bloquant) |
KANBANTE_AGING_DAYS |
7 |
Jours dans la même colonne avant le badge « ⏳ » sur une carte (rouge au double) |
Sécurité
- Sans
KANBANTE_AUTH_*, quiconque atteint le port 8080 voit tous les dépôts visibles par le jeton et peut modifier les boards — l'app l'annonce par un avertissement au démarrage. Définis les identifiants, ou mets Kanbante derrière un reverse proxy authentifiant, et poseKANBANTE_REQUIRE_AUTH=1pour échouer fermé. - Tous les POST exigent un jeton CSRF (cookie double-submit posé par les
pages) : les appels API directs doivent d'abord charger une page pour
obtenir le cookie, puis envoyer le jeton (en-tête
X-CSRF-Tokenou champcsrf_token). - Aucun secret n'est versionné : le jeton passe uniquement par
l'environnement / le fichier
.envlocal (ignoré par git).
Architecture
kanbante/
├── app/
│ ├── main.py # FastAPI app (routes, auth, CSRF, lifespan)
│ ├── config.py # Réglages par variables d'environnement
│ ├── gitea_client.py # Client API Gitea asynchrone, paginé, avec cache
│ ├── models.py # SQLite (état du board local + migrations)
│ └── templates/ # Jinja2 (dashboard, board, focus, error)
├── static/
│ ├── css/style.css # Design system dark theme
│ ├── js/board.js # Drag & drop, filtres, création d'issues
│ └── vendor/ # HTMX, Alpine, SortableJS (vendorés, aucun CDN)
├── tests/ # Suite pytest
├── Dockerfile
├── docker-compose.yml
└── README.md
API
| Méthode | Route | Description |
|---|---|---|
| GET | / |
Dashboard tous les projets |
| GET | /board/{owner}/{repo} |
Kanban board |
| GET | /focus |
En cours + En révision, tous projets actifs |
| GET | /activity |
Fil d'activité (journal d'événements, tous projets) |
| POST | /api/move |
Déplacer une issue (ordre persisté, synchro Gitea) |
| POST | /api/issues |
Créer une issue Gitea depuis le board |
| GET | /api/issues/{owner}/{repo}/{n} |
Détail d'une issue + commentaires (panneau) |
| POST | /api/issues/{owner}/{repo}/{n}/comments |
Commenter l'issue dans Gitea |
| GET | /api/events |
Derniers événements du journal (?repo=, ?limit=) |
| GET | /api/metrics |
Débit + temps de cycle moyen (?repo=, ?window=) |
| POST | /api/notes |
Sauvegarder des notes |
| GET | /api/stats |
Statistiques JSON |
| GET | /api/projects |
Projets JSON (actifs / inactifs / archivés) |
| GET | /api/health |
Liveness (aucune dépendance) |
| GET | /api/readiness |
Readiness : teste SQLite + Gitea (503 si KO) |
Les POST répondent avec des codes explicites : 400 entrée invalide,
403 jeton CSRF manquant/invalide, 413 note trop longue, 502 Gitea
injoignable.
Tests
pip install -e ".[dev]"
pytest
La CI (.gitea/workflows/ci.yml) lance la même suite à chaque push.
Licence
MIT — voir LICENSE. Historique des versions : CHANGELOG.md.
Releases
26
Languages
Python
57.8%
HTML
17.1%
JavaScript
14.4%
CSS
10.5%
Dockerfile
0.2%