docs: conventions versioning + doc + paliers de risque (v0.2.0)
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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 |
|
||||
@@ -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/<type>-<slug>.md`.
|
||||
|
||||
---
|
||||
|
||||
## <Nom de l'asset>
|
||||
|
||||
- **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** : `<sha ou URL>`
|
||||
- **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 <sha>`).
|
||||
- Effets de bord à nettoyer.
|
||||
|
||||
### Tests / vérification
|
||||
- Comment vérifier que l'asset fonctionne et reste read-only si applicable.
|
||||
@@ -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.
|
||||
@@ -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: <artefact> — <quoi> (vX.Y.Z)
|
||||
|
||||
<pourquoi / contexte>. Palier de risque : <réversible|privilégié>.
|
||||
```
|
||||
|
||||
## 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/<slug>.v<MAJEUR.MINEUR.PATCH>.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).
|
||||
Reference in New Issue
Block a user