Initial commit: CLAUDE.md + spec de design Nanometrics

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Gilles Soulier
2026-05-22 07:57:09 +02:00
commit 8e44b2f335
2 changed files with 358 additions and 0 deletions
@@ -0,0 +1,192 @@
# Nanometrics — Spec de design
**Date** : 2026-05-22
**Statut** : Validé
---
## 1. Vue d'ensemble
Nanometrics est un système client-serveur de surveillance matérielle (CPU, RAM, disque, réseau, uptime) avec empreinte quasi nulle sur des machines Debian. L'objectif est de monitorer un LAN (≤20 machines) sans dépendance externe, sans authentification (réseau LAN de confiance), avec un dashboard web temps réel.
**Trois composants :**
- **Agent Rust** (`agent/`) — collecte et envoie les métriques
- **Serveur Go** (`server/`) — reçoit, persiste, expose
- **Dashboard web** (`dashboard/`) — UI Nginx, temps réel WebSocket
---
## 2. Architecture : SQLite + WebSocket
Le serveur Go reçoit les données via UDP et/ou MQTT, les persiste en SQLite, et pousse les mises à jour en temps réel via WebSocket vers le dashboard. Le dashboard est servi par un conteneur Nginx séparé.
```
Agent Rust ──UDP JSON──► Serveur Go ──WebSocket──► Dashboard Nginx
──MQTT──────► ──REST API──►
──/metrics──► Prometheus
SQLite ◄────────────────
```
**Échanges bidirectionnels :** à la connexion l'agent envoie un birth message, le serveur répond avec la config. Le dashboard peut modifier la config d'un agent via REST → serveur → agent (MQTT ou UDP).
---
## 3. Agent Rust
### Contraintes
- Pas de runtime async (pas de Tokio) — boucle mono-thread avec `std::thread::sleep`
- `sysinfo` avec `default-features = false` (pas de threads de fond)
- Profil release : `strip = true`, `opt-level = "z"`, `lto = true`
- Config via `config.toml` (serde) — rien de codé en dur
### Fréquences de collecte
- CPU, RAM : toutes les 2 s
- Réseau, uptime : toutes les 10 s
- Disque, SMART : toutes les 60 s
### Métriques
`hostname`, `ip`, `cpu_percent`, `memory_used`, `memory_free`, `hdd_total`, `hdd_used`, `hdd_free`, `uptime`, `network_rx`, `network_tx`, `status` (online/offline), `temperature` (optionnel), `smart` (optionnel — si `smartctl` disponible).
### Protocoles
Chaque métrique est configurable indépendamment par protocole :
- **UDP** : fire-and-forget JSON vers `server_ip:server_port`
- **MQTT** : bidirectionnel vers `mqtt_host:mqtt_port` (défaut 10.0.0.3:1883, sans auth)
- Auto-discovery compatible Home Assistant
- Birth message : `{topic_base}/{hostname}/status` = `online`
- Last Will message : `offline` (configuré au connect, publié par le broker si l'agent disparaît)
- Topic base configurable (défaut : `nanometrics/agents`)
### SMART
L'agent vérifie si `smartctl` est disponible (`which smartctl`). Si oui, il collecte : état général (PASSED/FAILED), température, secteurs réalloués, heures de fonctionnement, usure SSD. Envoyé au format JSON simplifié.
### Architecture future
Prévoir un canal de réception de commandes (reboot, shutdown, screen off, update, upgrade, shell cmd) sans refonte du cœur.
---
## 4. Serveur Go
### Responsabilités
- Écoute UDP (goroutine par datagramme)
- Subscribe MQTT (`{topic_base}/#`)
- Persiste en SQLite (métriques historiques, config agents, icônes)
- Expose `/metrics` Prometheus (Gauges)
- API REST pour le dashboard
- WebSocket push temps réel (métriques + changements de statut)
- Stockage et push de la config par agent
### API REST (endpoints principaux)
- `GET /api/agents` — liste des agents avec dernière métrique
- `GET /api/agents/{id}/metrics?from=&to=` — historique
- `GET /api/agents/{id}/config` — config courante de l'agent
- `PUT /api/agents/{id}/config` — mise à jour config → push à l'agent
- `POST /api/agents/{id}/icon` — upload icône (max 128×128px, ratio préservé)
- `GET /api/config` — config serveur/UI
- `PUT /api/config` — mise à jour config serveur/UI (taille popups incluse)
### SQLite
Tables : `agents`, `metrics` (avec horodatage), `agent_config`, `server_config`, `agent_icons`. Rétention configurable (défaut 30 jours).
### Déploiement
Docker Compose : conteneur Go (serveur) + conteneur Nginx (dashboard). Pas d'auth, LAN uniquement.
### Agent systemd
Fichier `.service` avec `DynamicUser=yes`, `ConfigurationDirectory=`, `ProtectSystem=strict`.
---
## 5. Dashboard web
### Structure
```
dashboard/
├── index.html
├── fonts/ (Inter, JetBrains Mono, Share Tech Mono — locaux)
├── vendor/
│ └── fontawesome/
└── design_system/
├── tokens/tokens.css
└── components/ui-kit.jsx
```
### Grille principale
Grille responsive `auto-fill minmax(220px, 1fr)`. Une tuile rectangulaire par agent. Taille minimale configurable via le panneau serveur.
**Tuile :**
- Icône agent (custom ou défaut), hostname, IP, LED de statut (ok/warn/err/offline)
- Jauges barre : CPU, RAM, disque
- Effets : halo lumineux au survol (couleur selon statut), pression 3D au clic
- Uptime en pied de tuile
- Clic → popup détail
### Popup détail agent
- Redimensionnable (`resize:both`) — taille sauvegardée via `PUT /api/config`
- Croix pour fermer (pas de bouton "Fermer")
- Icône cliquable pour upload (SVG/JPG/PNG/WEBP, max 128×128px, ratio préservé)
- KPIs actuels (CPU, RAM, disque, uptime)
- Courbes SVG historiques CPU et RAM (30 min par défaut)
- Section stockage : jauge + bouton SMART (si disponible)
- Infos : hostname, IP, protocoles actifs (badges UDP/MQTT), dernier contact
- Bouton gears (bas à droite) → popup config agent
### Popup SMART
- Verdict général (PASSED/FAILED) avec explication en français
- Indicateurs : température, secteurs défectueux, heures de fonctionnement, durée de vie SSD
- Tableau attributs détaillés avec explications non-expertes en français
### Popup configuration agent
- Tableau 3 colonnes : **MÉTRIQUE / UDP / MQTT**
- Une case à cocher indépendante par métrique par protocole
- Métriques : cpu, memory, disk, smart, uptime, network, temperature
- Section paramètres MQTT : broker, port, topic base, auto-discovery, birth, last will
- Section commandes distantes (désactivée, placeholder) : reboot, shutdown, screen off, update, upgrade, shell cmd
- Bouton "Envoyer à l'agent" → `PUT /api/agents/{id}/config`
### Popup configuration serveur/UI (header)
- Affichage tuiles : largeur minimale, taille texte
- Seuils d'alerte par défaut : warning/erreur CPU, RAM, disque
- Données : durée de rétention historique, durée des courbes
- Comportement : masquer agents hors ligne, notifications navigateur, mémoriser taille popups
- Sauvegardé via `PUT /api/config`
### Header
- Logo + LED animée blink + compteurs (total / ok / warn / err)
- Bouton thème clair/sombre (`data-theme="dark|light"` sur `<html>`)
- Bouton configuration interface (icône sliders)
### Footer
- Badge LIVE en fond accent
- CPU + RAM du serveur avec mini-jauges
- Horodatage dernière actualisation
### Tooltips
Système global : un seul `<div id="tooltip">` en `position:fixed`, mis à jour par JS (`mouseover` + `mousemove`). Jamais clippé par le parent. Délai 120ms à l'apparition.
---
## 6. Design system
**Palette :** Gruvbox seventies dark/light via variables CSS uniquement — jamais de hex en dur.
**Polices :** Inter (UI), JetBrains Mono (valeurs numériques), Share Tech Mono (labels terminal/mono).
**Icônes :** Font Awesome 6 uniquement.
### Variables clés
- `--accent` : action principale (orange)
- `--ok` / `--warn` / `--err` : statuts
- `--blue` : datavis CPU / UDP
- `--purple` : MQTT / datavis secondaire
- `--bg-0` à `--bg-5` : niveaux de fond
- `--ink-1` à `--ink-4` : niveaux de texte
### Règles `user-select`
`user-select:none` uniquement sur les éléments purement interactifs : `.hbtn`, `.btn`, `.pop-close`, `.cbox`, `.btn-agent-cfg`, `.tile-head`, `.tile-foot`. Le contenu (hostname, IP, valeurs, icônes) reste sélectionnable.
---
## 7. Hors périmètre (v1)
- Authentification / autorisation
- Support multi-utilisateurs
- Alertes par email/webhook
- Commandes distantes (placeholder uniquement)
- Support Windows/macOS pour l'agent