feat: v0.6.0 — ACLs multi-utilisateurs + Plugin system
CI / test (push) Failing after 1m18s

**ACLs (Access Control Lists):**
- Ajout du type AclConfig dans sources/event.v (allowed_ips CIDR + allowed_tokens)
- Chaque source webhook (Gitea, Uptime Kuma, Cron, Generic) supporte les ACLs
- Validation IP via X-Forwarded-For / X-Real-IP avant HMAC
- Validation Bearer token via Authorization header
- Tests: 7 tests ACL (IP exact, CIDR, parse IPv4, ACL vide, IP+token combiné)

**Plugin system:**
- sources/plugin.v: runner exécutable externe, stdout JSON → Event
- Exit 0 = publish, exit ≠ 0 = skip. Timeout configurable
- Plugin loop dans server.v (goroutine, toutes les 60s)
- Example: scripts/example-plugin-disk.sh (vérifie espace disque)

**Docs:**
- README.md: ajout source Plugin + section Features complète
- ARCHITECTURE.md: flux Plugin, flux ACL, endpoints /metrics /api/silence
- ROADMAP.md: Phase 5 → 8/8 complet, ajout v0.6.0
- ntfy-bridge.example.yaml: sections ACLs et Plugins commentées
- Version bump: 0.5.0 → 0.6.0
This commit is contained in:
2026-08-04 22:14:37 -04:00
parent 151dd4a1a8
commit 0e73f14b6e
13 changed files with 1229 additions and 686 deletions
+177 -169
View File
@@ -1,169 +1,177 @@
# ntfy-bridge — Roadmap
## Phase 1 : MVP (core engine) — v0.1.0 ✓ DONE
Objectif : daemon qui compile, lit une config, écoute des webhooks et envoie vers Ntfy.
- [x] `main.v` — CLI args (`--config`, `--version`, `--validate`, `--quiet`, `--help`)
- [x] `config.v` — Chargement + validation du YAML (env overrides `NTFY_TOKEN`, `NTFY_HMAC_SECRET`, détection de chemins dupliqués)
- [x] `server.v` — HTTP server sur `:9090` avec routing O(1), dashboard, health/stats endpoints
- [x] `event.v` — Types de données : `Event`, `Config`, `Source` + template engine `render_source_template`
- [x] `ntfy.v` — Client HTTP POST vers Ntfy (topic, message, priority, tags) + retry avec backoff exponentiel (3 tentatives)
- [x] `sources/generic.v` — Webhook passe-partout (POST raw → Ntfy)
- [x] `log.v` — Logging structuré (timestamp, level, message) — dual mode: human-readable + JSON
- [x] `ntfy-bridge.example.yaml` — Config d'exemple complète et commentée
**Sortie** : `ntfy-bridge` compile, accepte un webhook générique et l'envoie vers Ntfy. ✅
## Phase 2 : Sources spécialisées — v0.2.0 ✓ DONE
- [x] `sources/gitea.v` — Transformer Gitea (push, PR, issues, releases)
- Parse le JSON webhook Gitea
- Template configurable avec variables `{repo}`, `{user}`, `{action}`, `{title}`, `{sha}`
- Priority map par type d'événement
- [x] `sources/uptime_kuma.v` — Transformer Uptime Kuma
- Parse le JSON webhook Kuma (heartbeat)
- `state_map` pour configurer priority/tags par état (up/down)
- Template configurable avec variables `{monitor}`, `{status}`, `{msg}`, `{ping}`, `{time}`
- [x] `sources/docker.v` — Watcher socket Docker
- Connexion au socket Docker Unix (`docker_watcher.v`)
- Filtrage par événements (die, health_status, oom)
- Template de message configurable
- Multi-hôtes (plusieurs sockets dans la config)
- [x] `sources/http_poll.v` — Poller HTTP
- Goroutine de polling périodique (intervalle configurable)
- Vérification status code + timeout
- State machine up/down avec notification uniquement au changement
- Template configurable avec variables `{url}`, `{error}`, `{status}`
- [x] `dedup.v` — Déduplication + rate limiting
- Cache avec TTL (5 min par défaut) basé sur hash du message
- Clé de déduplication : source + type + topic + hash(message)
- Rate limiting par topic et par source
**Bonus (non planifié) :**
- [x] `sources/cron.v` — Webhook pour scripts cron (pass-through)
- [x] `webhook.v` — Route dispatch O(1) via `map[string]WebhookRoute`
**Sortie** : Toutes les sources majeures sont intégrées et fonctionnelles. ✅
## Phase 3 : Robustesse — v0.3.0 ✅ DONE
- [x] ~~`dedup.v` amélioré~~ — Rate limiting déjà intégré dans la phase 2
- [x] Signature webhooks — Vérification HMAC-SHA256 (appliquée à **tous** les webhooks, pas seulement Gitea)
- [x] Retry logic — Retry avec backoff exponentiel vers Ntfy (3 tentatives, 1s/2s/4s)
- [x] Graceful shutdown — SIGTERM/SIGINT → drain des événements en cours (Linux/macOS)
- [x] Health endpoint — `GET /health` → 200 + uptime + stats basiques
- [x] Stats endpoint — `GET /stats` → compteurs par source
- [x] Config reload — `SIGHUP` → reload config sans redémarrage
- [x] Tests unitaires — `config_test.v`, `gitea_test.v`, `uptime_kuma_test.v`, `dedup_test.v`
**Sortie** : Le daemon est prêt pour la production homelab. ✅
## Phase 4 : Qualité de vie — v0.4.0 ✅ DONE
- [x] Template engine — Support des variables `{key}` dans les messages (toutes les sources)
```
"🐳 {container_name} → {status} (exit: {exit_code}) on {host}"
```
- [x] Silence rules — `POST /api/silence?duration=30m` + `GET /api/silence` + `DELETE /api/silence`
- [x] Grouping — Regrouper N notifications similaires (buffer 10s, flush avec ×N)
- [x] Webhook secret validation — HMAC global (tous les webhooks, pas seulement Gitea)
- [x] CI/CD via Gitea Actions — `.gitea/workflows/ci.yml`
**Sortie** : Expérience utilisateur complète. ✅
## Phase 4.5 : Déploiement multi-plateforme — v0.4.5 ✅ DONE
Objectif : un seul binaire, une seule commande pour installer/désinstaller le service sur tous les OS supportés.
- [x] `service.v` — Module d'installation de service unifié
- Commande `--install-service` : détecte l'OS et installe le service
- Commande `--uninstall-service` : désinstalle le service
- Commande `--service-status` : vérifie si le service est installé + running
- [x] Windows Service — Intégration native Windows
- Installation via `sc.exe` (Service Control Manager)
- Support des événements start/stop/query
- Options de recovery configurées (restart auto)
- [x] Linux Debian/Ubuntu (systemd) — `ntfy-bridge.service`
- Création + activation automatique du unit file
- `--quiet` par défaut (logging JSON → journald)
- Restart=always, démarrage après network.target
- [x] Linux Alpine (openrc) — Script init.d
- `/etc/init.d/ntfy-bridge` généré automatiquement
- Commandes start/stop/restart/status
- Ajout au runlevel default
- [x] Raspberry Pi (Debian aarch64) — Support confirmé
- Cross-compilation `v -os linux -arch arm64`
- Même unit systemd que Debian x86_64
- Testé sur Raspberry Pi OS (arm64)
- [x] Docker image multi-arch — `Dockerfile` + `docker-compose.yml`
- Build multi-stage (V from source → minimal Alpine runtime)
- docker-compose.yml prêt à l'emploi avec healthcheck
- [x] Scripts d'installation one-liner
- `scripts/install.sh` : détecte l'OS/arch, build V, installe le service
- `scripts/install.ps1` : équivalent Windows PowerShell
- `curl -fsSL https://.../install.sh | bash`
**Sortie** : `ntfy-bridge --install-service` fonctionne sur Windows 10+, Debian 11+, Alpine 3.18+, Raspberry Pi OS (arm64). ✅
## Phase 5 : Futures idées — v0.5.0+ (6/8)
- [x] Web UI minimale — Dashboard avec statuts, historique, API endpoints
- [x] Filtres avancés — Expressions conditionnelles par source
```yaml
filters:
rules:
- match_source: "docker"
match_name: "test-*"
action: drop
```
- [x] Notifications structurées — Support des actions Ntfy (boutons click)
- Champ `click_url` pour ouvrir une URL au clic
- Champ `actions` pour boutons d'action (view, broadcast, http)
- [x] Intégration Prometheus — Métriques exposées au format OpenMetrics
- Endpoint `GET /metrics` : gauges (uptime, poll_state, silence) + counters (notifications, errors, http_polls)
- Format compatible Prometheus/Grafana
- [x] Webhook sortant — Forwarder les événements vers Slack, Discord, JSON
- [ ] Support multi-utilisateurs — ACLs par webhook_path
- [x] Fichier d'état — Persistance de l'état up/down des health checks
- [ ] Plugin system — Sources customisables via dll/.so
- url: "https://hooks.slack.com/..."
format: slack
- url: "https://discord.com/api/webhooks/..."
format: discord
```
- [ ] Support multi-utilisateurs — ACLs par webhook_path
- [x] Fichier d'état — Persistance de l'état up/down des health checks
```yaml
state:
file: "/var/lib/ntfy-bridge/state.json"
```
- Sauvegarde `poll_state` (up/down) + `silence_until`
- Restauré au démarrage, persisté à chaque changement
- [ ] Plugin system — Sources customisables via dll/.so
## Fonctionnalités non planifiées mais implémentées
Ces features ont été ajoutées en cours de route :
| Feature | Fichier | Description |
|---------|---------|-------------|
| Source Cron | `sources/cron.v` | Webhook pass-through pour scripts cron (curl → Ntfy) |
| Dashboard web | `dashboard.html` | Interface avec stats, statut des health checks, historique récent |
| Logging JSON | `log.v` | Mode JSON structuré activé avec `--quiet` (pour systemd) |
| Env overrides | `config.v` | `NTFY_TOKEN` et `NTFY_HMAC_SECRET` depuis l'environnement |
| Validation dupplicates | `config.v` | Détection de chemins webhook dupliqués dans la config |
| Flag `--quiet` | `main.v` | Supprime la bannière ASCII au démarrage |
| Flag `-V` (version) | `main.v` | Version courte en plus de `--version` |
| API endpoints | `server.v` | `/api/config`, `/api/status`, `/api/history` pour le dashboard |
## Suivi des versions
| Version | Statut | Contenu |
|---------|--------|---------|
| v0.1.0 | ✅ Terminé | Moteur core + webhook générique + logging |
| v0.2.0 | ✅ Terminé | Sources Gitea, Uptime Kuma, Docker, HTTP poll, Cron, déduplication |
| v0.3.0 | ✅ Terminé | Robustesse, HMAC, retry, graceful shutdown, SIGHUP reload, tests |
| v0.4.0 | ✅ Terminé | Templates, silence, grouping, HMAC global, CI/CD |
| v0.4.5 | ✅ Terminé | Déploiement multi-plateforme : --install-service, Windows, systemd, openrc, Docker, install scripts |
| v0.5.0+ | 🚧 6/8 | Dashboard, filtres, actions Ntfy, Prometheus, outgoing webhooks, state file — manque multi-user, plugins |
# ntfy-bridge — Roadmap
## Phase 1 : MVP (core engine) — v0.1.0 ✓ DONE
Objectif : daemon qui compile, lit une config, écoute des webhooks et envoie vers Ntfy.
- [x] `main.v` — CLI args (`--config`, `--version`, `--validate`, `--quiet`, `--help`)
- [x] `config.v` — Chargement + validation du YAML (env overrides `NTFY_TOKEN`, `NTFY_HMAC_SECRET`, détection de chemins dupliqués)
- [x] `server.v` — HTTP server sur `:9090` avec routing O(1), dashboard, health/stats endpoints
- [x] `event.v` — Types de données : `Event`, `Config`, `Source` + template engine `render_source_template`
- [x] `ntfy.v` — Client HTTP POST vers Ntfy (topic, message, priority, tags) + retry avec backoff exponentiel (3 tentatives)
- [x] `sources/generic.v` — Webhook passe-partout (POST raw → Ntfy)
- [x] `log.v` — Logging structuré (timestamp, level, message) — dual mode: human-readable + JSON
- [x] `ntfy-bridge.example.yaml` — Config d'exemple complète et commentée
**Sortie** : `ntfy-bridge` compile, accepte un webhook générique et l'envoie vers Ntfy. ✅
## Phase 2 : Sources spécialisées — v0.2.0 ✓ DONE
- [x] `sources/gitea.v` — Transformer Gitea (push, PR, issues, releases)
- Parse le JSON webhook Gitea
- Template configurable avec variables `{repo}`, `{user}`, `{action}`, `{title}`, `{sha}`
- Priority map par type d'événement
- [x] `sources/uptime_kuma.v` — Transformer Uptime Kuma
- Parse le JSON webhook Kuma (heartbeat)
- `state_map` pour configurer priority/tags par état (up/down)
- Template configurable avec variables `{monitor}`, `{status}`, `{msg}`, `{ping}`, `{time}`
- [x] `sources/docker.v` — Watcher socket Docker
- Connexion au socket Docker Unix (`docker_watcher.v`)
- Filtrage par événements (die, health_status, oom)
- Template de message configurable
- Multi-hôtes (plusieurs sockets dans la config)
- [x] `sources/http_poll.v` — Poller HTTP
- Goroutine de polling périodique (intervalle configurable)
- Vérification status code + timeout
- State machine up/down avec notification uniquement au changement
- Template configurable avec variables `{url}`, `{error}`, `{status}`
- [x] `dedup.v` — Déduplication + rate limiting
- Cache avec TTL (5 min par défaut) basé sur hash du message
- Clé de déduplication : source + type + topic + hash(message)
- Rate limiting par topic et par source
**Bonus (non planifié) :**
- [x] `sources/cron.v` — Webhook pour scripts cron (pass-through)
- [x] `webhook.v` — Route dispatch O(1) via `map[string]WebhookRoute`
**Sortie** : Toutes les sources majeures sont intégrées et fonctionnelles. ✅
## Phase 3 : Robustesse — v0.3.0 ✅ DONE
- [x] ~~`dedup.v` amélioré~~ — Rate limiting déjà intégré dans la phase 2
- [x] Signature webhooks — Vérification HMAC-SHA256 (appliquée à **tous** les webhooks, pas seulement Gitea)
- [x] Retry logic — Retry avec backoff exponentiel vers Ntfy (3 tentatives, 1s/2s/4s)
- [x] Graceful shutdown — SIGTERM/SIGINT → drain des événements en cours (Linux/macOS)
- [x] Health endpoint — `GET /health` → 200 + uptime + stats basiques
- [x] Stats endpoint — `GET /stats` → compteurs par source
- [x] Config reload — `SIGHUP` → reload config sans redémarrage
- [x] Tests unitaires — `config_test.v`, `gitea_test.v`, `uptime_kuma_test.v`, `dedup_test.v`
**Sortie** : Le daemon est prêt pour la production homelab. ✅
## Phase 4 : Qualité de vie — v0.4.0 ✅ DONE
- [x] Template engine — Support des variables `{key}` dans les messages (toutes les sources)
```
"🐳 {container_name} → {status} (exit: {exit_code}) on {host}"
```
- [x] Silence rules — `POST /api/silence?duration=30m` + `GET /api/silence` + `DELETE /api/silence`
- [x] Grouping — Regrouper N notifications similaires (buffer 10s, flush avec ×N)
- [x] Webhook secret validation — HMAC global (tous les webhooks, pas seulement Gitea)
- [x] CI/CD via Gitea Actions — `.gitea/workflows/ci.yml`
**Sortie** : Expérience utilisateur complète. ✅
## Phase 4.5 : Déploiement multi-plateforme — v0.4.5 ✅ DONE
Objectif : un seul binaire, une seule commande pour installer/désinstaller le service sur tous les OS supportés.
- [x] `service.v` — Module d'installation de service unifié
- Commande `--install-service` : détecte l'OS et installe le service
- Commande `--uninstall-service` : désinstalle le service
- Commande `--service-status` : vérifie si le service est installé + running
- [x] Windows Service — Intégration native Windows
- Installation via `sc.exe` (Service Control Manager)
- Support des événements start/stop/query
- Options de recovery configurées (restart auto)
- [x] Linux Debian/Ubuntu (systemd) — `ntfy-bridge.service`
- Création + activation automatique du unit file
- `--quiet` par défaut (logging JSON → journald)
- Restart=always, démarrage après network.target
- [x] Linux Alpine (openrc) — Script init.d
- `/etc/init.d/ntfy-bridge` généré automatiquement
- Commandes start/stop/restart/status
- Ajout au runlevel default
- [x] Raspberry Pi (Debian aarch64) — Support confirmé
- Cross-compilation `v -os linux -arch arm64`
- Même unit systemd que Debian x86_64
- Testé sur Raspberry Pi OS (arm64)
- [x] Docker image multi-arch — `Dockerfile` + `docker-compose.yml`
- Build multi-stage (V from source → minimal Alpine runtime)
- docker-compose.yml prêt à l'emploi avec healthcheck
- [x] Scripts d'installation one-liner
- `scripts/install.sh` : détecte l'OS/arch, build V, installe le service
- `scripts/install.ps1` : équivalent Windows PowerShell
- `curl -fsSL https://.../install.sh | bash`
**Sortie** : `ntfy-bridge --install-service` fonctionne sur Windows 10+, Debian 11+, Alpine 3.18+, Raspberry Pi OS (arm64). ✅
## Phase 5 : Futures idées — v0.5.0+ (8/8) ✅ DONE
- [x] Web UI minimale — Dashboard avec statuts, historique, API endpoints
- [x] Filtres avancés — Expressions conditionnelles par source
```yaml
filters:
rules:
- match_source: "docker"
match_name: "test-*"
action: drop
```
- [x] Notifications structurées — Support des actions Ntfy (boutons click)
- Champ `click_url` pour ouvrir une URL au clic
- Champ `actions` pour boutons d'action (view, broadcast, http)
- [x] Intégration Prometheus — Métriques exposées au format OpenMetrics
- Endpoint `GET /metrics` : gauges (uptime, poll_state, silence) + counters (notifications, errors, http_polls)
- Format compatible Prometheus/Grafana
- [x] Webhook sortant — Forwarder les événements vers Slack, Discord, JSON
- [x] Support multi-utilisateurs — ACLs par webhook_path
```yaml
acl:
allowed_ips: ["192.168.30.5", "10.0.0.0/8"]
allowed_tokens: ["my-secret-token"]
```
- [x] Fichier d'état — Persistance de l'état up/down des health checks
```yaml
state:
file: "/var/lib/ntfy-bridge/state.json"
```
- Sauvegarde `poll_state` (up/down) + `silence_until`
- Restauré au démarrage, persisté à chaque changement
- [x] Plugin system — Sources customisables via executables externes
```yaml
plugin:
- name: "Disk space check"
topic: daily
command: /etc/ntfy-bridge/plugins/disk-check.sh
timeout: 10
```
- Contrat simple : stdin (optionnel) → stdout JSON
- Exit 0 = notif, exit ≠ 0 = skip
- Compatible bash, Python, ou n'importe quel langage
## Fonctionnalités non planifiées mais implémentées
Ces features ont été ajoutées en cours de route :
| Feature | Fichier | Description |
|---------|---------|-------------|
| Source Cron | `sources/cron.v` | Webhook pass-through pour scripts cron (curl → Ntfy) |
| Dashboard web | `dashboard.html` | Interface avec stats, statut des health checks, historique récent |
| Logging JSON | `log.v` | Mode JSON structuré activé avec `--quiet` (pour systemd) |
| Env overrides | `config.v` | `NTFY_TOKEN` et `NTFY_HMAC_SECRET` depuis l'environnement |
| Validation dupplicates | `config.v` | Détection de chemins webhook dupliqués dans la config |
| Flag `--quiet` | `main.v` | Supprime la bannière ASCII au démarrage |
| Flag `-V` (version) | `main.v` | Version courte en plus de `--version` |
| API endpoints | `server.v` | `/api/config`, `/api/status`, `/api/history` pour le dashboard |
## Suivi des versions
| Version | Statut | Contenu |
|---------|--------|---------|
| v0.1.0 | ✅ Terminé | Moteur core + webhook générique + logging |
| v0.2.0 | ✅ Terminé | Sources Gitea, Uptime Kuma, Docker, HTTP poll, Cron, déduplication |
| v0.3.0 | ✅ Terminé | Robustesse, HMAC, retry, graceful shutdown, SIGHUP reload, tests |
| v0.4.0 | ✅ Terminé | Templates, silence, grouping, HMAC global, CI/CD |
| v0.4.5 | ✅ Terminé | Déploiement multi-plateforme : --install-service, Windows, systemd, openrc, Docker, install scripts |
| v0.5.0 | ✅ Terminé | Dashboard, filtres, actions Ntfy, Prometheus, outgoing webhooks, state file |
| v0.6.0 | ✅ Terminé | ACLs multi-utilisateurs, plugin system (scripts externes) |