Le dépôt fait / explique / prouve ce qu'il affirme, vérifiable en une commande. - Phase 1 : docs/audit/affirmations.md — 54 affirmations publiques tracées vers une commande de preuve et un statut (✅/🟡/❌/⚪). - Phase 2 : CLAUDE.md réduit à un pointeur mince ; contradiction SSH levée (le code applique déjà PasswordAuthentication no + AuthenticationMethods publickey, conforme à AGENTS.md) ; section AGENTS « Codex » → « agents IA ». - Phase 3 : parcours démarrage réparé (QUICKSTART renvoyait à un modèle absent, chemins de voûte faux, commandes make périmées) ; make verifier vert (ansible-lint 33 → 0 : site.yml généré nommé, pipefail, name[template]) ; voûte Proxmox unifiée lue par le clonage (all/vault.yml). - Phase 4 : make prouver → docs/audit/preuve-<date>.md, harnais rejouable qui rappelle l'outillage existant (aucune validation réimplémentée). - Phase 5 : parcours QUICKSTART prouvé hors-ligne sur le socle ; modèle socle rendu valide (autorite interne → auto-heberge) ; split-brain d'inventaire corrigé (repli sur le répertoire existant, pas principal/). make prouver : 15 OK, 0 échec, 1 sautée (voûte). ansible-lint : 0 failure. Écarts découverts en cours de traitement (AFF-097..100) : tous résolus. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
390 lines
36 KiB
Markdown
390 lines
36 KiB
Markdown
# Registre des affirmations — Set-OPS
|
||
|
||
> **Phase 1 de la mise en conformité prouvable.** Ce document est un **audit**, sans
|
||
> aucun correctif de code ni de documentation. Chaque affirmation publique vérifiable
|
||
> du dépôt est tracée vers une commande de preuve reproductible, ou marquée comme
|
||
> invérifiable.
|
||
>
|
||
> Règle d'arbitrage (rappel) : *le dépôt ne doit jamais affirmer plus que ce qu'il
|
||
> prouve.* Les traitements (corriger la doc / corriger le code / chantier séparé)
|
||
> relèvent de la **Phase 3** — ils ne sont **pas** appliqués ici.
|
||
|
||
- **Date de l'audit** : 2026-07-20
|
||
- **Instance montée pendant l'audit** : `instance -> ../OPS-Technolibre` (inventaire `principal/`)
|
||
- **Outillage** : ansible-core 2.18.1, ansible-lint 25.1.3, Python 3.13.3, node présent.
|
||
- **Périmètre** : surfaces publiques uniquement — `README.md`, `AGENTS.md`,
|
||
`CLAUDE.md`, `QUICKSTART.md`, `SOLUTION.md`, `docs/`, `wiki/`, aide du `Makefile`,
|
||
libellés du GUI. Aucune VM / Proxmox / réseau touché (mission hors production).
|
||
|
||
Légende du statut : ✅ prouvée · 🟡 partielle · ❌ fausse · ⚪ invérifiable localement.
|
||
|
||
---
|
||
|
||
## 1. README.md
|
||
|
||
| ID | Affirmation (source) | Type | Commande de preuve | Statut | Écart constaté |
|
||
|---|---|---|---|---|---|
|
||
| AFF-001 | « Set-OPS est un moteur Ansible générique … à partir d'un plan déclaratif » (README:3) | fonctionnelle | `python3 scripts/instancier.py generer && python3 scripts/instancier.py comparer` | ✅ | « DIFF VIDE : le plan reproduit exactement l'inventaire ». Générateur opérationnel. |
|
||
| AFF-002 | « Set-OPS s'exploite entièrement à la main — la doc, `make` et le GUI suffisent, sans aucune IA » (README:9 ; AGENTS principe 10) | doctrinale | Suivre `QUICKSTART.md` de bout en bout ; `make verifier` | 🟡 | Le principe tient au niveau outillage, mais **deux trous cassent le parcours sans IA** : `make verifier` échoue (AFF-006) et `QUICKSTART` étape 2 renvoie à un modèle absent (AFF-020/021). Un opérateur seul bute. |
|
||
| AFF-003 | Registres = source unique de vérité : `serveurs.yml`, `applications.yml`, `bases-donnees.yml`, `domaines.yml`, `nomenclature.yml` (README:15) | structurelle | `make inventaire-verifier` (serveurs/applications/bases/domaines) | ✅ | Les 4 validateurs renvoient « Registre valide ». Fichiers présents dans `instance/plan/`. |
|
||
| AFF-004 | « `instance/inventories/production/hosts.yml` est généré depuis le plan — ne pas l'éditer à la main » (README:34) | procédurale | `python3 scripts/instancier.py comparer` (diff-vide) | ✅ | Diff vide confirmé. (Nuance de chemin : l'instance courante utilise `principal/` — voir AFF-023.) |
|
||
| AFF-005 | « Afficher l'aide : `make` » (README:86) | procédurale | `make` (défaut = cible `aide`) | ✅ | `.DEFAULT_GOAL := aide` ; l'aide s'affiche. |
|
||
| AFF-006 | « Valider le dépôt : `make verifier` » (README:91) | fonctionnelle | `make verifier` | ❌ | `make lint` (1re dépendance de `verifier`) **échoue rc=2** : ansible-lint rapporte « Failed: 33 failure(s) » (`name[play]` sur le `site.yml` généré, `risky-shell-pipe` dans `site.yml`/`valider.yml`, `name[template]`). `make verifier` ne passe donc **pas** sur un dépôt propre. |
|
||
| AFF-007 | « Inspecter … `make hote-afficher HOTE=web-frontal-01` » (README:98) | procédurale | `make hote-afficher HOTE=web-frontal-01` | 🟡 | La cible existe et fonctionne, mais l'hôte d'exemple `web-frontal-01` n'existe pas dans l'instance courante → l'exemple littéral échoue (exemple générique, pas garanti par instance). |
|
||
| AFF-008 | « Chaque groupe opérationnel doit avoir son playbook homonyme dans `playbooks/groupes/` » (README:120 ; AGENTS:316) | structurelle | `python3 scripts/inventory_host.py --inventaire instance/inventories/principal/hosts.yml verifier-playbooks --dossier-playbooks playbooks/groupes` | ✅ | rc=0. Les 30 groupes opérationnels ont leur playbook. Seuls `hotes_actifs`, `hotes_planifies`, `modeles_vm` (groupes méta/état) n'en ont pas — exclus par conception. |
|
||
| AFF-009 | « Les dépendances causales entre groupes sont dans `docs/dependances-groupes.yml` » (README:128 ; AGENTS:413) | structurelle | `python3 scripts/inventory_host.py … verifier-dependances …` | ✅ | rc=0. Aucune entrée ne référence un rôle/groupe inexistant. |
|
||
| AFF-010 | « Le runbook du DNS interne initial est dans `docs/dns-interne.md` » (README:130) | structurelle | `test -f docs/dns-interne.md` | ✅ | Fichier présent. |
|
||
| AFF-011 | « La nomenclature … est dans `docs/nomenclature-vm.md` » (README:132) | structurelle | `test -f docs/nomenclature-vm.md` | ✅ | Fichier présent. |
|
||
| AFF-012 | « Le catalogue des services … `docs/catalogue-services.md` » (README:126) | structurelle | `test -f docs/catalogue-services.md` | ✅ | Fichier présent. |
|
||
| AFF-013 | « `make creer-vm HOTE=… ` VMID/IP/VLAN/passerelle lus dans le plan » (README:138) | fonctionnelle | `python3 scripts/inventory_host.py … parametres-proxmox --hote <h>` | 🟡 | La dérivation existe (sous-commande `parametres-proxmox`), mais l'exécution réelle touche Proxmox → non testable localement (hors production). Mécanique de dérivation seule vérifiable. |
|
||
| AFF-014 | « Les déploiements de groupes ciblent automatiquement les hôtes actifs seulement » (README:171) | fonctionnelle | lecture `Makefile:261` : `--limit '$(GROUPE):&$(GROUPE_HOTES_ACTIFS)'` | ✅ | Intersection `groupe ∩ hotes_actifs` codée dans la cible `appliquer`. |
|
||
| AFF-015 | « Set-OPS est un logiciel libre … AGPLv3 … texte intégral dans `LICENSE` » (README:177-186) | structurelle | `test -f LICENSE` | ✅ | `LICENSE` présent. |
|
||
|
||
---
|
||
|
||
## 2. QUICKSTART.md
|
||
|
||
| ID | Affirmation (source) | Type | Commande de preuve | Statut | Écart constaté |
|
||
|---|---|---|---|---|---|
|
||
| AFF-020 | « Les modèles sont dans `exemples/modeles/` … Choisis : `socle`, `presence-web`, `forge`, `identite`, `observabilite`, `integral` » (QUICKSTART:25-26) | structurelle | `ls exemples/modeles/` | ❌ | Le dossier public ne contient que `socle` (+ `README.md`). Les 5 autres modèles sont dans un dépôt **privé** `Set-OPS-modeles` (correctement expliqué dans `exemples/modeles/README.md`, mais **pas** dans QUICKSTART). |
|
||
| AFF-021 | « `cp -r exemples/modeles/presence-web ../mon-instance` » (QUICKSTART:29) | procédurale | exécuter la commande | ❌ | La commande **échoue** : `exemples/modeles/presence-web` n'existe pas. C'est la commande centrale de l'étape 2 ; un opérateur suivant QUICKSTART à la lettre est bloqué immédiatement. Seule valeur valide : `socle`. |
|
||
| AFF-022 | « `instance/inventories/production/group_vars/all.yml` → `domaine_interne` » (QUICKSTART:36) | structurelle | `test -f exemples/modeles/socle/inventories/production/group_vars/all.yml` | ✅ | Le modèle `socle` fournit bien ce fichier sous `production/`. |
|
||
| AFF-023 | « Tous tes secrets … `instance/inventories/lab/group_vars/all/vault.yml` » (QUICKSTART:48-49) | procédurale | `ls exemples/modeles/socle/inventories/` | ❌ | Le modèle `socle` n'a **pas** d'inventaire `lab/` (uniquement `production/`). Le chemin de voûte annoncé n'existe pas dans le modèle public ; incohérent avec AFF-022 (`production/`). |
|
||
| AFF-024 | « `make instancier` (diff) puis `make instancier-appliquer FORCE=1` — 1re génération » (QUICKSTART:68-70) | fonctionnelle | `make instancier` ; cible `instancier-appliquer` (Makefile:582) | ✅ | Cibles présentes ; `FORCE` mappé sur `--force`. Diff-vide prouve le mécanisme (AFF-001). |
|
||
| AFF-025 | Étape 5 : `make preparer-modele` / `verifier-modele` / `nettoyer-modele CONFIRMER=true` (QUICKSTART:59-62) | procédurale | cibles Makefile:632-643 | 🟡 | Cibles présentes et gardes vérifiées ; l'exécution réelle exige une VM Debian 13 + Proxmox → hors production, non testable ici. |
|
||
| AFF-026 | « Valider à tout moment : `make inventaire-verifier` / `make verifier` » (QUICKSTART:98-101) | fonctionnelle | `make inventaire-verifier` ; `make verifier` | 🟡 | `make verifier` échoue (AFF-006). `make inventaire-verifier` appelle `ansible-inventory --list` qui **exige le mot de passe Vault** (`ERROR! Attempting to decrypt but no vault secrets found` sans `ANSIBLE_VAULT_PASSWORD_FILE`) — prérequis non rappelé à cet endroit. |
|
||
|
||
---
|
||
|
||
## 3. AGENTS.md
|
||
|
||
| ID | Affirmation (source) | Type | Commande de preuve | Statut | Écart constaté |
|
||
|---|---|---|---|---|---|
|
||
| AFF-030 | « RÈGLE D'OR : `…/production/hosts.yml` est un artefact GÉNÉRÉ » (AGENTS:43) | procédurale | `python3 scripts/instancier.py comparer` | ✅ | Diff vide : l'inventaire est reproductible depuis le plan. |
|
||
| AFF-031 | « `make instancier-appliquer` refuse si le diff n'est pas vide (`FORCE=1` sinon) » (AGENTS:47) | fonctionnelle | lecture `scripts/instancier.py appliquer` + Makefile:582-583 | ✅ | `appliquer` accepte `--force` (mappé `FORCE`) ; garde diff cohérente avec le comparateur. |
|
||
| AFF-032 | « VMID / IP / VLAN / passerelle sont dérivés de la `fonction` via la nomenclature » (AGENTS:49) | fonctionnelle | `python3 scripts/serveurs.py verifier` (réconcilie dérivation ↔ inventaire) | ✅ | « Registre des serveurs valide et réconcilié avec l'inventaire. » Dérivation confirmée. |
|
||
| AFF-033 | « garde-fous : … `node --check` du JS du GUI (`scripts/verifier_gui.py`, dans `make inventaire-verifier`) » (AGENTS:50) | fonctionnelle | `python3 scripts/verifier_gui.py` | ✅ | « JS du GUI : syntaxe valide (node --check). » |
|
||
| AFF-034 | « Chaque rôle qui utilise `notify` doit contenir son handler dans le rôle » (AGENTS:182) | structurelle | script de recoupement notify↔handlers sur tous les rôles | ✅ | « OK : tout `notify` pointe vers un handler existant dans le même rôle. » |
|
||
| AFF-035 | « Tout `notify` doit pointer vers un handler existant » (AGENTS:193) | structurelle | idem AFF-034 | ✅ | Aucun `notify` orphelin. |
|
||
| AFF-036 | « Playbooks … testables avec `--check` autant que possible » (AGENTS:214, 427) | fonctionnelle | `ansible-playbook … --check` sur cibles vivantes | ⚪ | Non testable hors flotte réelle (mission hors production). Recensement des rôles non-check reporté (nécessite des hôtes). |
|
||
| AFF-037 | État SSH attendu : `PasswordAuthentication no`, `AuthenticationMethods publickey` (AGENTS:538-542) | fonctionnelle | lecture `roles/ssh_baseline/defaults` + `templates/10-setops.conf.j2` | ✅ | Défauts = `no`/`no`/`yes` ; le template code `AuthenticationMethods publickey`. **Le code suit AGENTS.md.** (Contredit CLAUDE.md — voir AFF-050.) |
|
||
| AFF-038 | « Ne pas maintenir en parallèle `playbooks/socle/` ou `playbooks/durcissement/` » (AGENTS:278) | structurelle | `ls playbooks/` | ✅ | Ces dossiers n'existent pas ; socle/durcissement = groupes `serveur_debian`/`serveur_durci`. |
|
||
| AFF-039 | « Les playbooks peuvent être classés par domaine : groupes/ maintenance/ monitoring/ networking/ proxmox/ modeles_vm/ web/ database/ identity/ backup/ applications/ » (AGENTS:257-270) | structurelle | `find playbooks -maxdepth 1 -type d` | 🟡 | Seuls `groupes/`, `maintenance/`, `modeles_vm/`, `proxmox/` existent. Formulé au conditionnel (« peuvent ») → aspirationnel, pas une fausse affirmation, mais liste plus large que la réalité. |
|
||
| AFF-040 | Section « Comportement attendu de **Codex** » (AGENTS:650) | doctrinale | lecture | 🟡 | La section ne nomme que Codex alors qu'elle vaut pour tout agent (Claude inclus). Correctif de titrage prévu en Phase 2 (item 3). |
|
||
|
||
---
|
||
|
||
## 4. CLAUDE.md
|
||
|
||
| ID | Affirmation (source) | Type | Commande de preuve | Statut | Écart constaté |
|
||
|---|---|---|---|---|---|
|
||
| AFF-050 | « Pendant la construction du template : `PasswordAuthentication yes` » (CLAUDE.md § SSH) | fonctionnelle | `roles/ssh_baseline/defaults/main.yml` | ❌ | Le code déploie `PasswordAuthentication no` **dès la construction** (`ssh_baseline_password_authentication: "no"`, template `AuthenticationMethods publickey`). CLAUDE.md contredit **et** le code **et** AGENTS.md (qui fait autorité). Cause racine : duplication de doctrine. Cible Phase 2 (item 1). |
|
||
| AFF-051 | « Claude Code doit lire et respecter `AGENTS.md` avant toute modification ; en cas de contradiction, suivre `AGENTS.md` » (CLAUDE.md § Instruction principale) | doctrinale | — | ✅ | Cohérent avec AGENTS.md ; pas de commande de preuve (déclaration de gouvernance). |
|
||
| AFF-052 | CLAUDE.md redéclare la doctrine de template, SSH, pare-feu, cloud-init, handlers, actions destructives (dupliquée d'AGENTS.md) | structurelle | `diff` conceptuel CLAUDE.md ↔ AGENTS.md | 🟡 | Large duplication → source des dérives (AFF-050). Réduction à un pointeur mince prévue Phase 2 (item 2). |
|
||
|
||
---
|
||
|
||
## 5. SOLUTION.md
|
||
|
||
| ID | Affirmation (source) | Type | Commande de preuve | Statut | Écart constaté |
|
||
|---|---|---|---|---|---|
|
||
| AFF-060 | « On garde une seule structure : `inventories/ playbooks/ roles/ docs/` » (SOLUTION:11-18) | structurelle | `ls` racine | 🟡 | Réel : aussi `scripts/`, `filter_plugins/`, `exemples/`, `wiki/`, `instance/`. Description obsolète (antérieure au plan/GUI). |
|
||
| AFF-061 | Commande template : `ansible-playbook … debian13_proxmox_preparer.yml --ask-pass --ask-become-pass` (SOLUTION:24-25) | procédurale | comparaison avec la doctrine SSH clé-only | 🟡 | `--ask-pass` (mot de passe SSH) contredit l'accès **par clé dès le départ** d'AGENTS.md (AFF-037). SOLUTION.md décrit un flux périmé (mot de passe SSH) ; le flux réel = clé via cloud-init. |
|
||
| AFF-062 | « Le pare-feu `nftables` est installé et préparé, mais pas activé par défaut dans le template » (SOLUTION:60 ; AGENTS:559 ; CLAUDE.md) | fonctionnelle | `grep enabled roles/nftables_baseline/defaults/main.yml` | ✅ | `nftables_baseline_enabled: false`. `preparer-modele` inclut le rôle et affiche « nftables est installé mais désactivé par défaut ». |
|
||
|
||
---
|
||
|
||
## 6. Aide du Makefile (`make`)
|
||
|
||
| ID | Affirmation (source) | Type | Commande de preuve | Statut | Écart constaté |
|
||
|---|---|---|---|---|---|
|
||
| AFF-070 | « `make site-verifier` valide la cohérence couches/graphe » (Makefile aide:133) | fonctionnelle | `python3 scripts/orchestrer.py verifier` | ✅ | « Orchestration cohérente : 30 groupes classés, aucun cycle, aucune arête en arrière. » |
|
||
| AFF-071 | « `make flux` → `docs/registre-flux.md` + `instance/flux-genere/*.nft` » (Makefile aide:146) | fonctionnelle | `python3 scripts/resoudre_flux.py verifier` ; en-tête de `docs/registre-flux.md` | ✅ | « Flux cohérents : 29 rôles, 63 flux ». Le registre porte l'en-tête « GÉNÉRÉ par `scripts/resoudre_flux.py` ». |
|
||
| AFF-072 | « `make deployer-tout` — déploiement orchestré de la flotte ; garde `CONFIRMER` » (Makefile aide:138) | fonctionnelle | lecture Makefile:352-357 | 🟡 | Garde `CONFIRMER=true` vérifiée (refuse sinon, rc=2). Déploiement réel hors production → non exécuté. |
|
||
| AFF-073 | « `make wiki-publier` … refuse sans `WIKI_REMOTE` » (Makefile aide:151) | fonctionnelle | lecture Makefile:320-326 | ✅ | Garde présente : refus + message d'usage si `WIKI_REMOTE` vide. |
|
||
| AFF-074 | « `make devis-reseau` — dérivé des nomenclatures » (Makefile:309) | fonctionnelle | `python3 scripts/devis_reseau.py` | 🟡 | Dérive des instances fédérées `../*/plan/nomenclature.yml` (schéma `ip-miroir`) ; sortie dépend du voisinage de dépôts → vérifiable seulement dans un contexte fédéré. |
|
||
| AFF-075 | Cibles dépréciées `make hote-planifier / hote-ajouter / hote-groupes` renvoient vers le plan (README:118 ; Makefile:237) | procédurale | `make hote-planifier` | ✅ | Stub présent : message « Cible dépréciée … » + `exit 2`. |
|
||
|
||
---
|
||
|
||
## 7. docs/ — runbooks et cohérence des commandes
|
||
|
||
| ID | Affirmation (source) | Type | Commande de preuve | Statut | Écart constaté |
|
||
|---|---|---|---|---|---|
|
||
| AFF-080 | « `make help` — liste des cibles » (docs/config-proxmox.md:114) | procédurale | `grep -E '^help:' Makefile` | ❌ | Aucune cible `help`. La cible réelle est `aide` (défaut). Commande citée inexistante. |
|
||
| AFF-081 | « `make syntax-template` » (docs/modeles_vm/debian13-proxmox.md:77) | procédurale | `grep syntax-template Makefile` | ❌ | Aucune cible `syntax-template`. Réel : `syntaxe-modele`. Nom périmé. |
|
||
| AFF-082 | « `make syntax-template` » (docs/MISE-A-JOUR-CODEX-CLAUDE.md:146) | procédurale | idem | ❌ | Même nom périmé, second emplacement. |
|
||
| AFF-083 | Tous les docs cités par README/QUICKSTART/AGENTS existent (`plan-et-generation`, `positionnement`, `bindings-conception`, `flux-conception`, `couches-deploiement.yml`, `registre-flux.md`, `carte-set-ops`, `runbooks-exploitation`, `vm-lifecycle`, `procedure-template-…`, `dns-interne`, `nomenclature-vm`, `config-proxmox`, `catalogue-services`, `dimensionnement-ressources`, `exemples/vault.exemple.yml`, `exemples/instance.exemple.yml`) | structurelle | `test -f` sur chaque chemin | ✅ | 17/17 présents. |
|
||
| AFF-084 | « `docs/dependances-groupes.yml` — chaque groupe existant y figure, aucune entrée ne référence un rôle supprimé » (AGENTS:345,413) | structurelle | `verifier-dependances` (AFF-009) | ✅ | Validé ; graphe sans cycle, tri topologique réussi (via `orchestrer verifier`). |
|
||
| AFF-097 | Chemins d'inventaire `lab/` codés en dur pour la config/voûte **Proxmox** et le template, alors que `make config`/`cloner-vm` résolvent `lab > principal > production` (modèle `socle` = `production/`) | procédurale | `grep -rn 'inventories/lab/group_vars' docs playbooks` ; `scripts/config_proxmox.py:31` | 🟡 | **Découvert en Phase 3 (lot A).** Reste `lab/` codé en dur dans `docs/vm-lifecycle.md:171`, `docs/procedure-template-debian13-proxmox.md:741,747`, `docs/modeles_vm/debian13-proxmox.md:89`, `playbooks/proxmox/README.md:31,43,49,50`, `playbooks/proxmox/cloner_vm_debian.yml:45` (message). Non bloquant (l'outillage résout), mais trompeur pour le socle. **Différé** au lot « voûte Proxmox » (couplé à AFF-098). |
|
||
| AFF-099 | Le modèle public `socle` livre un `plan/domaines.yml` **invalide** : `exemple.internal` en `autorite: interne`, rejeté par le validateur (`auto-heberge`/`delegue`/`primaire-cache` attendus) | fonctionnelle | `SETOPS_INSTANCE=exemples/modeles/socle python3 scripts/domaines.py verifier` | ❌ | **Découvert Phase 5.** Un opérateur suivant QUICKSTART bute à la validation (étape 9 / `make inventaire-verifier`). `interne` = valeur périmée (déjà corrigée ailleurs en `auto-heberge`, cf. CHANGELOG 2026-07-07). |
|
||
| AFF-100 | `instancier.py`/`inventory_gui.py` résolvent `principal > production` mais **retombent sur `principal`** quand aucun `hosts.yml` n'existe encore ; le socle est en `production/` → 1ʳᵉ génération dans `principal/`, à côté des `group_vars` restés en `production/` (split-brain) | fonctionnelle | parcours QUICKSTART hors-ligne sur une copie du socle (`generer`→`appliquer`) | ❌ | **Découvert Phase 5.** `config_proxmox.py` détecte le répertoire existant (→ `production/`) ; `instancier`/GUI non → incohérence. QUICKSTART étapes 6-9 cassées pour le socle. |
|
||
| AFF-098 | Contradiction fonctionnelle voûte Proxmox : `make config` écrit le token dans la voûte unifiée `all/vault.yml` (et `config-proxmox.md` dit de **supprimer** `proxmox.vault.yml`), mais le clonage `cloner_vm_debian.yml` (lancé `-i localhost,`) ne charge le secret **que** depuis `proxmox.vault.yml`/`proxmox.local.yml` ou les variables d'env — **jamais** `all/vault.yml` | fonctionnelle | lecture `playbooks/proxmox/cloner_vm_debian.yml:11-12,51-64` vs `scripts/config_proxmox.py:35` | ❌ | **Découvert en Phase 3 (lot B).** Un opérateur qui suit la voûte unifiée met le token dans `all/vault.yml` → `make creer-vm` échoue l'assert (`proxmox_api_token_secret` vide), sauf variables d'env ou `proxmox.vault.yml` conservé. **Traitement B (code)** : faire lire `all/vault.yml` par le clonage, ou faire écrire `proxmox.vault.yml` par `make config`. À arbitrer dans le lot « voûte Proxmox ». |
|
||
|
||
---
|
||
|
||
## 8. wiki/
|
||
|
||
| ID | Affirmation (source) | Type | Commande de preuve | Statut | Écart constaté |
|
||
|---|---|---|---|---|---|
|
||
| AFF-090 | Le wiki pédagogique fournit des unités d'apprentissage par service (`wiki/*.md`) publiables dans Forgejo | structurelle | `ls wiki/*.md` | ✅ | 16 pages de contenu (+ `README.md` + `_Sidebar.md`) ; 17 publiées par `wiki-publier` (README exclu). |
|
||
| AFF-091 | Contenu conceptuel du wiki (OIDC, PKI, DNS, sauvegardes, idempotence, RBAC…) | doctrinale | — | ⚪ | Contenu pédagogique = affirmations conceptuelles, non rattachées à une preuve exécutable du dépôt. Hors périmètre de preuve automatisable. |
|
||
|
||
---
|
||
|
||
## 9. GUI (libellés)
|
||
|
||
| ID | Affirmation (source) | Type | Commande de preuve | Statut | Écart constaté |
|
||
|---|---|---|---|---|---|
|
||
| AFF-095 | « La vue **Inventaire** est en lecture seule ; vues éditables **Serveurs**, **Applications**, **Domaines** ; vues lecture seule **Réseau**, **Flux**, **Couches** » (README:41 ; AGENTS:48 ; CHANGELOG) | fonctionnelle | démarrage headless de `scripts/inventory_gui.py` + inspection des routes/onglets | 🟡 | Les routes backend et l'import des validateurs sont présents dans `scripts/inventory_gui.py` ; le rendu des onglets et le caractère « lecture seule » ne sont pas vérifiés sans lancer le serveur + un navigateur (non fait — pas de commande de preuve headless au registre). |
|
||
| AFF-096 | « GUI 100 % française » (CHANGELOG 2026-07-03) | structurelle | inspection des chaînes du GUI | ⚪ | Vérifiable seulement par revue exhaustive des libellés rendus ; non automatisé ici. |
|
||
|
||
---
|
||
|
||
## Décompte
|
||
|
||
Recompte exact par ID (numérotation à trous AFF-001 → AFF-096, **54 affirmations**).
|
||
|
||
| Statut | Nombre |
|
||
|---|---|
|
||
| ✅ prouvée | 30 |
|
||
| 🟡 partielle | 13 |
|
||
| ❌ fausse | 8 |
|
||
| ⚪ invérifiable localement | 3 |
|
||
| **Total** | **54** |
|
||
|
||
Détail :
|
||
|
||
- ✅ (30) : AFF-001, 003, 004, 005, 008, 009, 010, 011, 012, 014, 015, 022, 024, 030, 031, 032, 033, 034, 035, 037, 038, 051, 062, 070, 071, 073, 075, 083, 084, 090.
|
||
- 🟡 (13) : AFF-002, 007, 013, 025, 026, 039, 040, 052, 060, 061, 072, 074, 095.
|
||
- ❌ (8) : AFF-006, 020, 021, 023, 050, 080, 081, 082.
|
||
- ⚪ (3) : AFF-036, 091, 096.
|
||
|
||
> La Phase 4 (`make prouver`) rattachera chaque ✅ à sa section de preuve et figera le
|
||
> compte.
|
||
|
||
---
|
||
|
||
## Les dix écarts les plus graves
|
||
|
||
Classés par risque pour un opérateur qui suit la doc **à la lettre, sans IA**.
|
||
|
||
1. **AFF-021 / AFF-020 — QUICKSTART renvoie à un modèle inexistant.**
|
||
`cp -r exemples/modeles/presence-web ../mon-instance` échoue : seul `socle` est
|
||
public. **L'opérateur est bloqué dès l'étape 2** du guide de démarrage. Risque
|
||
maximal : c'est la toute première action concrète du parcours « zéro → écosystème ».
|
||
|
||
2. **AFF-006 — `make verifier` échoue sur un dépôt propre.**
|
||
`ansible-lint` rapporte 33 échecs (surtout `name[play]` sur le `site.yml` **généré**
|
||
par l'outil lui-même, + `risky-shell-pipe`). La commande de validation vantée par
|
||
README et QUICKSTART ne passe pas → l'opérateur croit son dépôt cassé, ou apprend à
|
||
ignorer l'échec (perte de confiance dans le harnais).
|
||
|
||
3. **AFF-050 — Contradiction SSH doc vs code (sécurité).**
|
||
`CLAUDE.md` prescrit `PasswordAuthentication yes` pendant la construction ; le code
|
||
et `AGENTS.md` imposent `no` + `AuthenticationMethods publickey`. Un opérateur qui
|
||
suit CLAUDE.md attend un accès mot de passe qui n'existe pas — et la doctrine de
|
||
sécurité affichée est contradictoire.
|
||
|
||
4. **AFF-023 — Chemin de voûte faux dans QUICKSTART.**
|
||
L'étape 4 place les secrets dans `inventories/lab/group_vars/all/vault.yml`, mais le
|
||
modèle public `socle` n'a pas d'inventaire `lab/` (seulement `production/`).
|
||
L'opérateur crée sa voûte au mauvais endroit → déchiffrement introuvable au déploiement.
|
||
|
||
5. **AFF-026 — `make inventaire-verifier` exige le Vault sans le dire.**
|
||
La validation « à tout moment » appelle `ansible-inventory --list` qui échoue
|
||
(`no vault secrets found`) sans `ANSIBLE_VAULT_PASSWORD_FILE`. Prérequis non rappelé
|
||
au point d'usage → échec surprenant pour qui n'a pas exporté sa clé.
|
||
|
||
6. **AFF-002 — Promesse « exploitable sans IA » entamée par 1–5.**
|
||
Le principe fondateur (AGENTS principe 10) est **partiellement démenti par les faits** :
|
||
le parcours documenté comporte au moins deux ruptures dures (modèle absent, `make
|
||
verifier` cassé). C'est le méta-risque : la doc ne mène pas seule au succès.
|
||
|
||
7. **AFF-080 / AFF-081 / AFF-082 — Commandes `make` périmées dans la doc.**
|
||
`make help` (→ `aide`) et `make syntax-template` (→ `syntaxe-modele`, cité 2×)
|
||
n'existent pas. L'opérateur tape une commande qui renvoie une erreur `make`.
|
||
|
||
8. **AFF-061 — SOLUTION.md décrit un flux SSH périmé.**
|
||
`--ask-pass --ask-become-pass` suppose un accès par mot de passe contraire au modèle
|
||
clé-only réel. Suivre SOLUTION.md pour construire le template mène à un flux qui ne
|
||
correspond plus au code.
|
||
|
||
9. **AFF-060 — SOLUTION.md décrit une arborescence obsolète.**
|
||
« Une seule structure : inventories/playbooks/roles/docs/ » ignore `scripts/`,
|
||
`instance/`, `filter_plugins/`, `wiki/`, `exemples/` — désoriente un nouveau lecteur
|
||
sur l'endroit où vivent le plan et le GUI.
|
||
|
||
10. **AFF-052 / AFF-040 — Doctrine dupliquée et titrage « Codex ».**
|
||
La duplication CLAUDE.md ↔ AGENTS.md est la **cause racine** de la contradiction n°3 ;
|
||
la section « Comportement attendu de Codex » sous-entend à tort qu'elle ne vise pas
|
||
Claude. Risque de gouvernance : deux sources d'autorité qui divergent avec le temps.
|
||
|
||
---
|
||
|
||
## Journal des traitements
|
||
|
||
Le tableau ci-dessus est le **snapshot d'audit Phase 1 (2026-07-20)** et n'est pas
|
||
réécrit. Les traitements appliqués ensuite sont consignés ici, datés et traçables.
|
||
|
||
### Phase 2 — 2026-07-20 (3 incohérences internes pré-cadrées)
|
||
|
||
- **AFF-050 (❌ → résolu)** — Doctrine SSH contradictoire. Vérifié que le code applique
|
||
déjà `PasswordAuthentication no` + `AuthenticationMethods publickey` dès la construction
|
||
(aligné sur `AGENTS.md`, cf. AFF-037). **Aucun correctif de code** ; la doctrine SSH a
|
||
été **retirée de `CLAUDE.md`**.
|
||
- **AFF-052 (🟡 → résolu)** — Duplication CLAUDE.md ↔ AGENTS.md. `CLAUDE.md` réduit à un
|
||
pointeur mince (autorité d'`AGENTS.md` + 5 règles absolues) ; cause racine d'AFF-050 supprimée.
|
||
- **AFF-040 (🟡 → résolu)** — Section « Comportement attendu de **Codex** » renommée
|
||
« …des agents IA » dans `AGENTS.md`, avec mention explicite qu'elle vaut pour tout agent.
|
||
|
||
Reste ouvert après Phase 2 : les 5 ❌ restants (AFF-006, 020, 021, 023, 080/081/082) et
|
||
les 🟡 relèvent de la **Phase 3 (arbitrage)**.
|
||
|
||
### Phase 3 — Lot A « doc de démarrage » — 2026-07-20
|
||
|
||
- **AFF-020/021 (❌ → résolu, A)** — `QUICKSTART.md` étape 2 : ne propose plus que le
|
||
modèle public `socle` (`cp -r exemples/modeles/socle …`) ; les modèles assemblés
|
||
renvoyés au dépôt privé `Set-OPS-modeles`, cohérent avec `exemples/modeles/README.md`.
|
||
- **AFF-023 (❌ → résolu, A + correctif d'exemple)** — Chemin de voûte corrigé
|
||
`lab/` → `production/` dans `QUICKSTART.md`, `exemples/vault.exemple.yml` et
|
||
`docs/config-proxmox.md`. **Piège corrigé** : le modèle `socle` livrait ses intrants en
|
||
`production/group_vars/all.yml` (forme fichier) ; ajouter `all/vault.yml` (forme dossier)
|
||
**masque silencieusement** le fichier `all.yml` (vérifié empiriquement : seul le dossier
|
||
est chargé). Le modèle a été converti en forme dossier (`all/10-intrants.yml`), alignée
|
||
sur l'instance prouvée `principal`. Validé : `ansible-inventory --host` charge bien
|
||
`domaine_interne` depuis la nouvelle disposition.
|
||
- **AFF-080/081/082 (❌ → résolu, A)** — Commandes `make` périmées corrigées :
|
||
`make help` → `make` (`docs/config-proxmox.md`) ; `make syntax-template` →
|
||
`make syntaxe-modele` (`docs/modeles_vm/debian13-proxmox.md`,
|
||
`docs/MISE-A-JOUR-CODEX-CLAUDE.md`).
|
||
- **AFF-097 (🟡, découvert)** — `lab/` codé en dur restant dans les docs template/clone
|
||
(étapes 5+). Consigné ci-dessus ; **non traité dans ce lot** (lot séparé à prévoir).
|
||
|
||
### Phase 3 — Lot B « doc (prose) » — 2026-07-20
|
||
|
||
- **AFF-026 (🟡 → résolu, A)** — `QUICKSTART.md` § « Valider à tout moment » : note ajoutée
|
||
que `inventaire-verifier`/`verifier` chargent l'inventaire complet et exigent
|
||
`ANSIBLE_VAULT_PASSWORD_FILE` (étape 4), sinon « no vault secrets found ».
|
||
- **AFF-039 (🟡 → résolu, A)** — `AGENTS.md` : note ajoutée sous la liste des sous-dossiers
|
||
`playbooks/` — seuls `groupes/`, `maintenance/`, `modeles_vm/`, `proxmox/` sont peuplés ;
|
||
les autres sont **prospectifs**.
|
||
- **AFF-060/061 (🟡 → résolu, A)** — `SOLUTION.md` : bannière « document historique » ajoutée
|
||
(supplanté par README/QUICKSTART/`make`) ; arborescence complétée (`scripts/`, `wiki/`,
|
||
`instance/`…) ; commande de construction `--ask-pass` (mot de passe) remplacée par
|
||
`make preparer-modele` (accès par clé, aligné `AGENTS.md`).
|
||
- **AFF-002 (🟡)** — « exploitable sans IA » : **pas de reformulation** (c'est un engagement
|
||
fondateur légitime, pas une sur-affirmation). Son seul écart résiduel est AFF-006
|
||
(`make verifier` casse) → bascule ✅ une fois AFF-006 traité (lot C, B). Aucune édition.
|
||
- **AFF-007 (🟡)** — `web-frontal-01` : **assumé** comme nom d'exemple/placeholder (usage
|
||
cohérent dans tout le README) ; aucune édition.
|
||
- **AFF-097 / AFF-098** — **différés** au lot « voûte Proxmox » : AFF-098 (contradiction
|
||
fonctionnelle `all/vault.yml` ↔ clonage, traitement B) est couplé à AFF-097 (mêmes
|
||
fichiers) ; les traiter ensemble évite un double passage.
|
||
|
||
### Phase 3 — Lot « voûte Proxmox » — 2026-07-20
|
||
|
||
- **AFF-098 (❌ → résolu, B, option a)** — Le clonage lit désormais la voûte **unifiée**.
|
||
`playbooks/proxmox/cloner_vm_debian.yml` : `all/vault.yml` ajouté à la liste des sources
|
||
de secrets Proxmox (chargé via le filtre `is search('vault')`, autoritaire car en
|
||
dernier). `Makefile` (`cloner-vm`) : la détection de voûte chiffrée cherche d'abord
|
||
`group_vars/all/vault.yml` puis `proxmox.vault.yml` (déclenche `--ask-vault-pass`).
|
||
Messages de tâche/rescousse/assert rendus génériques. **Validé** : `--syntax-check` OK,
|
||
`ansible-lint` 0 échec sur le playbook, et **test fonctionnel** (mini-instance en clair) —
|
||
le token est bien chargé depuis `all/vault.yml` et l'hôte depuis `proxmox.yml`
|
||
(assert vert). `proxmox.vault.yml` reste accepté en compatibilité.
|
||
- **AFF-097 (🟡 → résolu, A)** — `lab/` codé en dur retiré des docs Proxmox/template :
|
||
`playbooks/proxmox/README.md`, `docs/procedure-template-debian13-proxmox.md`,
|
||
`docs/vm-lifecycle.md`, `docs/modeles_vm/debian13-proxmox.md` → `production/` + voûte
|
||
unifiée. Plus aucune référence `inventories/lab/group_vars` dans les fichiers suivis
|
||
(hors `tmp/` gitignoré et la section *migration* de `config-proxmox.md`, intentionnelle).
|
||
|
||
### Phase 3 — Lot C « make verifier vert » — 2026-07-20
|
||
|
||
- **AFF-006 (❌ → résolu, B)** — `ansible-lint` passe de **33 échecs à 0** (profil monté
|
||
`min` → `production`), donc `make lint` **rc=0**. Trois causes traitées :
|
||
- **30× `name[play]`** sur le `site.yml` **généré** → `scripts/orchestrer.py` (`rendre_site`)
|
||
émet désormais `- name: Couche <c> — groupe <g>` avant chaque `import_playbook` ;
|
||
`site.yml` régénéré (`make site`). Logique d'orchestration inchangée (`orchestrer verifier`
|
||
OK, 30 groupes, syntax-check OK).
|
||
- **2× `risky-shell-pipe`** (`playbooks/valider.yml`) → `set -o pipefail;` +
|
||
`executable: /bin/bash` sur les deux tâches shell à pipe.
|
||
- **1× `name[template]`** (`playbooks/proxmox/supprimer_vm_debian.yml`) → Jinja déplacé en
|
||
fin de `name` (`… (VMID {{ … }})`).
|
||
- **Validé** : `make lint` rc=0 ; `make verifier` franchit lint + test (4) + `site-verifier`
|
||
+ `flux-verifier` + `syntaxe` (35 playbooks) — **toutes vertes**. Seule `inventaire-verifier`
|
||
exige la voûte de l'opérateur (`ANSIBLE_VAULT_PASSWORD_FILE`), prérequis documenté (AFF-026).
|
||
- **AFF-002 (🟡 → ✅)** — « exploitable sans IA » : ses deux écarts résiduels sont soldés
|
||
(parcours QUICKSTART, lot A ; `make verifier`/lint, ce lot). Bascule ✅, sous le prérequis
|
||
Vault désormais rappelé (AFF-026).
|
||
|
||
### Phase 5 — Boucle documentaire — 2026-07-20
|
||
|
||
Relecture de cohérence bout-en-bout (README, QUICKSTART, docs, wiki) contre le code final,
|
||
au regard du critère du principe 10 : *un opérateur sans IA exécute chaque procédure sans
|
||
commande morte, chemin faux ni étape manquante.*
|
||
|
||
- **Sweep commandes/chemins** : toutes les commandes `make` citées existent ; jetons périmés
|
||
(`presence-web` hors contexte, `syntax-template`, `make help`, `--ask-pass`, voûte `lab/`)
|
||
soldés (les occurrences restantes ne sont que dans `CHANGELOG.md`/`docs/audit`, historiques).
|
||
- **AFF-099 (❌ → résolu, B)** — `exemples/modeles/socle/plan/domaines.yml` : `interne` →
|
||
`auto-heberge`. Le modèle public valide désormais.
|
||
- **AFF-100 (❌ → résolu, B)** — `instancier.py` et `inventory_gui.py` : le repli sans
|
||
`hosts.yml` vise maintenant le **répertoire d'inventaire existant** (→ `production/` pour le
|
||
socle) avant de retomber sur `principal`. Instances existantes (avec `hosts.yml`) inchangées.
|
||
- **Cohérence GUI/doc** — `docs/intrants-communs.md` : `group_vars/all.yml` →
|
||
`group_vars/all/10-intrants.yml` (le GUI écrit déjà en forme dossier). `QUICKSTART.md`
|
||
étape 8 : exemple `serveur_postgresql` → `serveur_powerdns` (groupe présent dans le socle).
|
||
- **Preuve bout-en-bout (hors-ligne)** : parcours QUICKSTART rejoué sur une copie du socle —
|
||
`instancier generer`→`comparer`→`appliquer --force` **écrit `production/hosts.yml`**, diff
|
||
**vide** ensuite (idempotence), et les 4 validateurs verts (`serveurs` **réconcilié**).
|
||
Non-régression vérifiée sur l'instance réelle `principal` (diff vide, cible inchangée).
|
||
|
||
## Couverture par `make prouver` (Phase 4)
|
||
|
||
Chaque affirmation ✅ est soit **rejouée** par une preuve de `make prouver`
|
||
(`scripts/prouver.py` → `docs/audit/preuve-<date>.md`), soit **structurelle/doctrinale**
|
||
(vérifiée à l'audit, rien d'exécutable à rejouer en boucle).
|
||
|
||
| Affirmation ✅ | Preuve `make prouver` |
|
||
|---|---|
|
||
| AFF-001, 004, 030, 031, 032 | **P03** (diff-vide) |
|
||
| AFF-003 | **P06** (validateurs de registres) |
|
||
| AFF-008 | **P04** (groupes ↔ playbooks) |
|
||
| AFF-009, 084 | **P05** (dépendances) |
|
||
| AFF-010, 011, 012 | **P12** (existence des runbooks) |
|
||
| AFF-015, 022, 037, 038, 062 | **P13** (invariants structurels) |
|
||
| AFF-033 | **P07** (GUI node --check) |
|
||
| AFF-034, 035 | **P10** (handlers ↔ notify) |
|
||
| AFF-070 | **P08** (orchestration) |
|
||
| AFF-071 | **P09** (flux) |
|
||
| AFF-083 | **P11** (syntaxe) + **P12** |
|
||
| AFF-097 | **P14** (pas de `lab/` codé en dur) |
|
||
| AFF-002, 006 | **P01** (lint) — + parcours démarrage corrigé |
|
||
| AFF-030 (inventaire complet) | **P15** (voûte requise ; sauté sinon) |
|
||
|
||
**Structurelles/doctrinales, hors harnais récurrent** (vérifiées à l'audit) : AFF-005
|
||
(`make`=aide), AFF-014 (ciblage `groupe:&hotes_actifs`), AFF-024 (`instancier-appliquer`,
|
||
couvert indirectement par P03), AFF-051 (autorité d'`AGENTS.md`), AFF-073/075 (gardes
|
||
`make wiki-publier`/`hote-planifier`), AFF-090 (comptage wiki).
|
||
|
||
**Déclarations d'intention (⚪ — assumées, jamais présentées comme prouvées)** : AFF-036
|
||
(`--check` réel), AFF-091 (contenu wiki), AFF-096 (GUI 100 % français), AFF-007
|
||
(placeholder `web-frontal-01`). Reprises dans la section dédiée de chaque `preuve-<date>.md`.
|
||
|
||
## Limites de cet audit
|
||
|
||
- **Hors production** : toute affirmation nécessitant une VM, Proxmox, le réseau ou la
|
||
flotte vivante (`make valider`, `make deployer*`, `make creer-vm`, `--check` réel, les
|
||
très nombreux « **prouvé sur VM réelles** » du `CHANGELOG.md`) est marquée ⚪ ou 🟡 —
|
||
**non rejouable localement par conception**. Le `CHANGELOG.md` n'étant pas une surface
|
||
publique listée, ses affirmations « prouvé » ne sont pas enregistrées ici ; à noter que
|
||
`AGENTS.md` (« pas encore exécuté contre des VM réelles », « ne jamais présenter un rôle
|
||
non déployé comme en production ») encadre correctement cette réserve.
|
||
- **GUI** : pas de preuve headless au registre (AFF-095/096 en 🟡/⚪).
|
||
- **Vault** : l'instance courante chiffre `group_vars/all/vault.yml` ; les commandes qui
|
||
chargent l'inventaire complet via Ansible exigent le mot de passe Vault, non fourni
|
||
pendant l'audit (les validateurs Python lisent `hosts.yml`/le plan directement et
|
||
n'en ont pas besoin — d'où leur usage ici).
|
||
- **Numérotation à trous** : les ID sautent (AFF-001…096) pour laisser de la place par
|
||
surface ; ce n'est pas une omission.
|