From c096fa946796a761a09a2b26f82732f52b70ac2a Mon Sep 17 00:00:00 2001 From: Kantin-Petit Date: Tue, 23 Jun 2026 00:59:25 +0200 Subject: [PATCH] docs: conventions versioning + doc + paliers de risque (v0.2.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pose les règles non négociables : SemVer + un-artefact-un-commit, pinning des images, export JSON des workflows n8n ; gabarit de doc d'asset ; paliers réversible/privilégié avec invariant anti-escalade ; schéma d'architecture et invariants d'exposition. Ignore settings.local.json. Co-Authored-By: Claude Opus 4.8 --- .gitignore | 3 +++ CHANGELOG.md | 9 +++++++ docs/architecture.md | 59 ++++++++++++++++++++++++++++++++++++++++++ docs/asset-template.md | 39 ++++++++++++++++++++++++++++ docs/risk-tiers.md | 36 ++++++++++++++++++++++++++ docs/versioning.md | 52 +++++++++++++++++++++++++++++++++++++ 6 files changed, 198 insertions(+) create mode 100644 docs/architecture.md create mode 100644 docs/asset-template.md create mode 100644 docs/risk-tiers.md create mode 100644 docs/versioning.md diff --git a/.gitignore b/.gitignore index 1c3d8d4..7e4392e 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,9 @@ data/ *.log logs/ +# Claude Code — réglages locaux/perso (le partagé settings.json reste versionné) +.claude/settings.local.json + # OS / éditeurs .DS_Store Thumbs.db diff --git a/CHANGELOG.md b/CHANGELOG.md index cd873a1..9c66ee0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,15 @@ incompatibles. Chaque ligne renvoie à un commit dédié (un artefact = un commi ## [Unreleased] +## [0.2.0] — 2026-06-23 +### Added +- Conventions versioning/doc : `docs/versioning.md` (SemVer, un-artefact-un-commit, + pinning images, export workflows n8n), `docs/asset-template.md` (gabarit doc), + `docs/risk-tiers.md` (réversible vs privilégié, invariant anti-escalade), + `docs/architecture.md` (schéma + invariants + composants). +### Changed +- `.gitignore` : ignore `.claude/settings.local.json` (réglages locaux). + ## [0.1.0] — 2026-06-23 ### Added - Scaffold du dépôt : `CLAUDE.md` (architecture + règles non négociables), diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..9fbd7d2 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,59 @@ +# Architecture CHLOVA + +> Vue d'ensemble. Les règles non négociables font foi dans `CLAUDE.md`. + +## Principe +CHLOVA est une **couche d'orchestration** : un LLM en boucle tool-calling +(`comprendre → choisir un outil MCP → agir → observer → répondre`) posée au-dessus +d'un homelab Debian + Docker + Traefik existant. + +## Schéma logique +``` + mobile (client léger) + │ Telegram (long-polling, zéro port ouvert) + ▼ + ┌─────────────────────────┐ réseau Docker interne (chlova-internal) + │ Backend CHLOVA │ ───────────────────────────────────────────── + │ (seule surface exposée)│ ┌───────────┐ ┌──────────────┐ + │ - boucle agent │ ─────► │ Ollama │ ─►│ ollama.com │ (egress) + │ - registry MCP │ │ (proxy │ │ modèles :cloud│ + │ - gatekeeper (P2+) │ │ cloud) │ └──────────────┘ + │ - audit log │ └───────────┘ + └─────────────────────────┘ + │ MCP (stdio/http interne) + ├───────────────► MCP n8n ──► n8n API (interne) + └───────────────► MCP Portainer ─► socket-proxy ─► Docker / Portainer +``` + +## Invariants +- **Une seule surface exposée** : le backend CHLOVA (auth + TLS). Tout le reste + (Ollama, n8n, Portainer, serveurs MCP) n'écoute **que** sur `chlova-internal`. +- **Ollama sans auth native** → jamais exposé ; il sort vers `ollama.com` pour les + modèles `:cloud` (egress filtré, seul `ollama.com` autorisé). +- **Accès Docker via socket-proxy** uniquement (pas de socket brut dans l'agent). +- **Secrets par référence** : l'agent ne voit jamais les valeurs en clair. + +## Boucle agent (Phase 1, lecture seule) +1. Message texte (Telegram) → backend. +2. Backend appelle Ollama `/api/chat` avec la liste d'outils MCP **read-only**. +3. Le modèle choisit un outil → le backend l'exécute via le serveur MCP. +4. Observation renvoyée au modèle → réponse finale → utilisateur. +5. Toute exécution d'outil est **audit-loggée**. + +En Phase 1, le **readonly-filter** garantit que seuls les outils `readOnlyHint=true` +sont exposés : aucun risque d'écriture. + +## Évolutions (interfaces posées, non implémentées) +- **Gatekeeper + table assets** : vérifie le statut avant chaque exécution (P2). +- **Cycle need-review** : PROVISOIRE → APPROUVÉ/REFUSÉ/BLOQUÉ + cron horaire (P2). +- **Auto-extension** : création d'outils/workflows en "need review" (P4). +- **Voix** : STT + wake-word + TTS (P5), après un cerveau fiable. + +## Composants & contrats +| Composant | Image / lib | Exposition | Palier | +|---|---|---|---| +| Backend CHLOVA | code maison (TS) | seule surface | — | +| Ollama (proxy cloud) | `ollama/ollama` épinglé | interne | — | +| MCP n8n | `czlonkowski/n8n-mcp` épinglé | interne | read-only (P1) | +| MCP Portainer | `portainer/portainer-mcp` épinglé | interne | read-only (P1) | +| socket-proxy | `tecnativa/docker-socket-proxy` épinglé | interne | scoping Docker | diff --git a/docs/asset-template.md b/docs/asset-template.md new file mode 100644 index 0000000..f1cc276 --- /dev/null +++ b/docs/asset-template.md @@ -0,0 +1,39 @@ +# Gabarit de doc d'asset + +Copier ce gabarit pour chaque artefact créé par/pour CHLOVA (workflow n8n, stack +Portainer, outil, image). Un asset **non documenté est incomplet**. +Fichier suggéré : `docs/assets/-.md`. + +--- + +## + +- **Type** : `workflow-n8n` | `stack-portainer` | `tool` | `image` | `service` +- **Version** : `vX.Y.Z` +- **Palier de risque** : `reversible` | `privileged` (voir `risk-tiers.md`) +- **Statut (need-review)** : `provisoire` | `approuvé` | `refusé` | `bloqué` | `n/a` +- **Lien commit** : `` +- **Créé le** : `YYYY-MM-DD` · **Expire le** : `YYYY-MM-DD` (si provisoire) + +### Rôle +Ce que fait l'asset, en une à trois phrases. Pourquoi il existe. + +### Entrées / sorties +- **Entrées** : paramètres, déclencheurs, données consommées. +- **Sorties** : effets, données produites, notifications émises. + +### Dépendances +- Services (Ollama, n8n, Portainer…), autres assets, variables d'env (par + **référence**, jamais de valeur), réseau. + +### Sécurité +- Secrets manipulés (par référence) ; pourquoi le palier de risque est celui-ci ; + surface d'exposition (doit rester interne). + +### Rollback +- **Comment annuler** : commande/étapes précises pour revenir à l'état antérieur + (ex. redeploy de la version N-1, désactivation du workflow, `git revert `). +- Effets de bord à nettoyer. + +### Tests / vérification +- Comment vérifier que l'asset fonctionne et reste read-only si applicable. diff --git a/docs/risk-tiers.md b/docs/risk-tiers.md new file mode 100644 index 0000000..411b887 --- /dev/null +++ b/docs/risk-tiers.md @@ -0,0 +1,36 @@ +# Paliers de risque + +> Règle **non négociable**. Conditionne le sursis du cycle "need review". +> Le LLM **ne doit jamais** pouvoir reclasser un asset privilégié en réversible. + +## Les deux paliers + +### `reversible` — réversible / lecture seule +- Effet nul ou trivialement annulable, pas d'accès aux secrets, pas de mutation + d'infra. +- **7 jours de sursis PROVISOIRE autorisés** (exécutable pendant la fenêtre). +- Exemples : lister workflows n8n, lire l'état d'un conteneur, lister stacks, + inspecter (read-only), récupérer des logs. + +### `privileged` — privilégié / destructeur +- **Aucun sursis** : l'asset est **BLOQUÉ** jusqu'à review explicite. +- Exemples : déploiement Portainer (stack/conteneur), montage de volume hôte, + accès à des secrets, suppression, exec dans un conteneur, modification réseau, + écriture/activation de workflow n8n, toute écriture sur l'infra. + +## Classification +- Le palier est **déterminé par la nature de l'opération**, pas déclaré par le LLM. +- En cas de doute → **`privileged`** (fail-safe). +- La classification vit dans le code (table de correspondance outil/opération → + palier), versionnée et testée. Voir `orchestrator/src/gatekeeper/`. + +## Invariant testé (anti-escalade) +- Un asset `privileged` **ne peut jamais** être réécrit en `reversible` par + l'agent. Tout changement de palier est une opération hors-agent (humain + commit). +- Ceci fait l'objet d'un test dédié (`gatekeeper.test.ts`) : tentative de + reclassement → rejet. + +## Phase 1 (lecture seule) +En Phase 1, **seuls les outils `reversible` (read-only) sont exposés** au LLM. +Les outils mutants/`privileged` ne sont même pas branchés. Le gatekeeper et la +classification sont posés comme interfaces, prêts pour la Phase 2. diff --git a/docs/versioning.md b/docs/versioning.md new file mode 100644 index 0000000..9778c4e --- /dev/null +++ b/docs/versioning.md @@ -0,0 +1,52 @@ +# Versioning & documentation + +> Git est la **source unique de vérité**. Un artefact n'est "terminé" que s'il est +> **à la fois versionné ET documenté**. Règle non négociable (voir `CLAUDE.md`). + +## Qu'est-ce qu'un "artefact" ? +Tout ce qui est créé ou modifié et qui a un effet : workflow n8n, stack/compose +Docker, code de l'orchestrateur, outil MCP, image Docker, doc d'asset. + +## SemVer (`vMAJEUR.MINEUR.PATCH`) +- **MAJEUR** : changement incompatible (rupture d'API/contrat/comportement). +- **MINEUR** : ajout rétro-compatible (nouvel outil, nouvelle capacité). +- **PATCH** : correctif rétro-compatible, doc, durcissement sans rupture. +- Phase `0.x` : on tolère des ruptures sur le MINEUR (projet pré-1.0). + +La version du dépôt est portée par `CHANGELOG.md` + un **tag git** `vX.Y.Z`. +Les assets individuels (workflow, stack, outil) portent **leur propre** version +dans leur en-tête de doc et dans la table assets (champ `version`). + +## Règle "un artefact = un commit" +Chaque création/modification d'artefact = **un commit dédié** : +- message clair (Conventional Commits : `feat:`, `fix:`, `chore:`, `docs:`…), +- bump de version approprié + entrée `CHANGELOG.md`, +- la **doc** de l'artefact mise à jour dans le même commit. + +Message type : +``` +feat: (vX.Y.Z) + +. Palier de risque : . +``` + +## Images Docker +- Tags **épinglés** et versionnés. **Jamais `:latest`**. +- Idéalement épingler aussi le **digest** (`image@sha256:…`) pour l'immuabilité. +- Tout bump d'image = commit + entrée CHANGELOG + note de rollback. + +## Workflows n8n +- Exportés en **JSON** dans `workflows-n8n/` — **le dépôt fait foi**, pas l'instance. +- Convention de nommage : `workflows-n8n/.v.json`. +- Chaque workflow a une doc d'asset (voir `asset-template.md`). + +## Documentation d'un asset +Chaque artefact a une doc suivant `docs/asset-template.md` (rôle, entrées/sorties, +dépendances, **palier de risque**, **rollback**). Un asset non documenté est +**incomplet** et ne doit pas être considéré livré. + +## Lien avec le cycle "need review" (Phase 2+) +En Phase 4, CHLOVA devra **committer + versionner + générer la doc** d'un asset +**avant** de le passer en "need review". La notification de review inclut la +**version** + le **lien commit** + le **lien doc** (champs `version`, +`lien_commit`, `lien_doc` de la table assets).