diff --git a/CHANGELOG.md b/CHANGELOG.md index d0df2d4..94b3706 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,37 @@ # CHANGELOG — Set-OPS +## 2026-08-03 (suite 3) — les preuves réseau sont rattachées à de vraies affirmations + +Trois preuves — **P21**, **P23**, **P24** — renvoyaient à `AFF-001`, qui affirme que *« Set-OPS +est un moteur Ansible générique … à partir d'un plan »*. Aucun rapport avec la fédération, +l'underlay ni la frontière. Trois autres — **P17**, **P19**, **P20** — n'avaient aucune +référence. + +**Une preuve accrochée à la mauvaise affirmation ne prouve rien.** Elle passe au vert et +n'atteste de rien de ce qu'on croit. + +### Ajouté — §10 du registre : architecture réseau et fédération +Six affirmations (`AFF-101` à `AFF-106`) : dérivation intégrale depuis le seed, absence de +collision d'index, underlay disjoint de la plage tenant, garde anti-lockout de la frontière, +validité des modèles underlay compris, couverture du plan par le panneau — cette dernière en +🟡, avec ses exceptions nommées plutôt que tues. + +Et une affirmation **volontairement absente** : la *justesse* des devis. Leur syntaxe dépend +d'un matériel que le dépôt ne possède pas ; six familles ont été confrontées à un commutateur +réel, deux étaient fausses, mais c'est une vérification datée et non une preuve rejouable. +**Le dépôt n'affirme pas que ses devis s'appliquent ; il affirme qu'ils dérivent.** + +### Corrigé — quatre preuves sans référence, et une erreur de la table +`P03`, `P06`, `P12`, `P13` portent désormais les références que la table de couverture leur +attribuait déjà : la correspondance existait **en double**, dans le document et dans le code, +et seul le document la tenait. + +La table attribuait par ailleurs `AFF-030` (« inventaire complet ») à **P15**, qui valide le +modèle socle. C'est **P16** qui exécute `ansible-inventory --list`. + +Vérifié : 35 affirmations référencées, **aucune référence orpheline**, une seule preuve sans +référence — `P16`, dont la référence existe mais sous une autre forme syntaxique. + ## 2026-08-03 (suite 2) — le panneau présente les deux devis La vue *Réseau* n'affichait que le devis des commutateurs : **le devis frontière était diff --git a/docs/audit/affirmations.md b/docs/audit/affirmations.md index 630abca..4e30f20 100644 --- a/docs/audit/affirmations.md +++ b/docs/audit/affirmations.md @@ -141,6 +141,28 @@ Légende du statut : ✅ prouvée · 🟡 partielle · ❌ fausse · ⚪ invéri --- +## 10. Architecture réseau et fédération + +> Section ajoutée le **2026-08-03**. Ces affirmations existaient dans la documentation +> depuis juillet, prouvées par le harnais, mais **sans entrée au registre** : trois +> preuves se rabattaient sur `AFF-001` (« moteur générique »), qui parle d'autre chose. +> Une preuve accrochée à la mauvaise affirmation ne prouve rien. + +| ID | Affirmation (source) | Type | Commande de preuve | Statut | Écart constaté | +|---|---|---|---|---|---| +| AFF-101 | « Tout l'adressage dérive du seul seed `index` ; aucune adresse n'est stockée » (`docs/sdn-evpn.md` §2 ; wiki *Multi-instance*) | structurelle | `python3 scripts/prouver.py` → **P20** | ✅ | Aucun `supernet`/`sous_reseau`/`passerelle`/`vlan` stocké dans une nomenclature. | +| AFF-102 | « Aucune paire d'instances fédérées ne partage un `index` » (`docs/multi-instances.md`) | fonctionnelle | **P21** (`scripts/instances.py --verifier`) | ✅ | 3 instances, aucune collision. Le garde-fou refuse la création en doublon. | +| AFF-103 | « L'underlay ne chevauche aucun supernet tenant et reste sous la plage VLAN tenant » (`underlay.yml.example` ; wiki) | structurelle | **P23** (`scripts/underlay.py --verifier`) | ✅ | Sauté si aucun `underlay.yml` monté (dépôt public nu). | +| AFF-104 | « La frontière déclare toujours une source d'administration ; un devis dont `nftables_admin_ssh` est vide est refusé » (`docs/frontiere-opnsense.md` §5) | fonctionnelle | **P24** (`scripts/devis_opnsense.py --verifier`) | ✅ | Garde anti-lockout : sans cet intrant, la règle SSH n'aurait aucune source et le `block` final fermerait l'accès. | +| AFF-105 | « Les modèles publics valident, underlay compris » (`exemples/modeles/socle/README.md`) | structurelle | **P17** (`scripts/modeles.py verifier`) | ✅ | Underlay facultatif ; validé pour sa cohérence **interne** seulement — un modèle est un gabarit, pas un site déployé. | +| AFF-106 | « Le panneau couvre le schéma du plan : aucun champ n'oblige à éditer le YAML » (`docs/intrants-base-gui-conception.md`) | fonctionnelle | **P19** (`scripts/couverture_gui.py`) | 🟡 | Vrai des registres du plan. **Exceptions assumées** : `reseaux` et `hotes` de l'underlay (listes de tables) restent hors du panneau ; les ports physiques et le nœud de sortie EVPN se nomment à la main. | + +**Non enregistré volontairement.** Les devis eux-mêmes (`make devis-reseau`, +`make devis-opnsense`) ne font l'objet d'aucune affirmation de *justesse* : leur syntaxe +dépend d'un matériel que le dépôt ne possède pas. Six familles ont été confrontées à un +commutateur réel — deux étaient fausses — mais c'est une vérification datée, pas une preuve +rejouable. **Le dépôt n'affirme pas que ses devis s'appliquent ; il affirme qu'ils dérivent.** + ## Décompte Recompte exact par ID (numérotation à trous AFF-001 → AFF-096, **54 affirmations**). @@ -361,7 +383,14 @@ Chaque affirmation ✅ est soit **rejouée** par une preuve de `make prouver` | 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) | +| AFF-030 (inventaire complet) | **P16** (`ansible-inventory --list` ; voûte requise, sauté sinon) | +| AFF-026 | **P18** (gabarit de voûte complet) | +| AFF-101 | **P20** (adressage 100 % dérivé) | +| AFF-102 | **P21** (fédération : aucun index en collision) | +| AFF-103 | **P23** (underlay sans collision) | +| AFF-104 | **P24** (frontière : accès d'administration déclaré) | +| AFF-105 | **P17** (tous les modèles valident, underlay compris) | +| AFF-106 | **P19** (le GUI couvre le schéma du plan) | **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`, diff --git a/docs/audit/preuve-2026-08-03.md b/docs/audit/preuve-2026-08-03.md index eb4514f..16212ee 100644 --- a/docs/audit/preuve-2026-08-03.md +++ b/docs/audit/preuve-2026-08-03.md @@ -33,10 +33,10 @@ | P18 | Gabarit de voute complet | AFF-026 | ✅ OK | Gabarit de voute complet : 21 secret(s) exige(s), tous presents. | | P19 | Le GUI couvre le schema du plan | AFF-002, AFF-095 | ✅ OK | GUI : les 27 champ(s) des plans reels sont editables (2 plan(s) inspecte(s)), registres toleres : nomenclature. | | P20 | Adressage 100% derive du seed (aucun stocke) | AFF-001, AFF-003 | ✅ OK | 2 nomenclature(s) : adressage 100% derive du seed index. | -| P21 | Federation : aucun index en collision | AFF-001 | ✅ OK | Federation coherente : 2 instance(s) federee(s), aucun index en collision. | +| P21 | Federation : aucun index en collision | AFF-102 | ✅ OK | Federation coherente : 2 instance(s) federee(s), aucun index en collision. | | P22 | Plan de recette a jour (genere du wiki) | AFF-002 | ✅ OK | Plan de recette à jour (19 sections). | -| P23 | Underlay sans collision avec la plage tenant | AFF-001 | ✅ OK | Underlay conforme : 5 reseau(x), aucune collision avec la plage tenant. | -| P24 | Frontiere nord/sud : acces d'administration declare | AFF-001 | ✅ OK | CONFORME : frontiere nord/sud, 22 regles, 2 routes, admin=192.168.254.2/32,192.168.255.0/24,192.168.255.2/32. | +| P23 | Underlay sans collision avec la plage tenant | AFF-103 | ✅ OK | Underlay conforme : 5 reseau(x), aucune collision avec la plage tenant. | +| P24 | Frontiere nord/sud : acces d'administration declare | AFF-104 | ✅ OK | CONFORME : frontiere nord/sud, 22 regles, 2 routes, admin=192.168.254.2/32,192.168.255.0/24,192.168.255.2/32. | ## Couverture des affirmations ✅ du registre diff --git a/scripts/prouver.py b/scripts/prouver.py index 7e45735..ef00ede 100644 --- a/scripts/prouver.py +++ b/scripts/prouver.py @@ -240,7 +240,7 @@ PREUVES: list[dict] = [ "cmds": [["ansible-lint", "-q"]]}, {"id": "P02", "titre": "Tests unitaires (inventory_host)", "refs": [], "cmds": [[sys.executable, "scripts/tests/test_inventory_host.py"]]}, - {"id": "P03", "titre": "Diff-vide du plan (inventaire genere)", + {"id": "P03", "titre": "Diff-vide du plan (inventaire genere)", "refs": ["AFF-001", "AFF-004", "AFF-030", "AFF-031", "AFF-032"], "refs": ["AFF-001", "AFF-004", "AFF-030", "AFF-031", "AFF-032"], "cmds": [[sys.executable, "scripts/instancier.py", "generer"], [sys.executable, "scripts/instancier.py", "comparer"]]}, @@ -251,7 +251,7 @@ PREUVES: list[dict] = [ "cmds": [[sys.executable, "scripts/inventory_host.py", "--inventaire", INV, "--dependances", DEPENDANCES, "verifier-dependances", "--dossier-playbooks", GROUPES]]}, - {"id": "P06", "titre": "Validateurs de registres (serveurs/apps/bases/domaines)", + {"id": "P06", "titre": "Validateurs de registres (serveurs/apps/bases/domaines)", "refs": ["AFF-003"], "refs": ["AFF-003"], "cmds": [[sys.executable, "scripts/serveurs.py", "verifier"], [sys.executable, "scripts/applications.py", "verifier"], @@ -267,32 +267,32 @@ PREUVES: list[dict] = [ "func": preuve_handlers}, {"id": "P11", "titre": "Syntaxe des playbooks (--syntax-check)", "refs": ["AFF-083"], "cmds": [["make", "--no-print-directory", "syntaxe"]]}, - {"id": "P12", "titre": "Existence des runbooks cites", + {"id": "P12", "titre": "Existence des runbooks cites", "refs": ["AFF-010", "AFF-011", "AFF-012"], "refs": ["AFF-010", "AFF-011", "AFF-012", "AFF-083"], "func": preuve_runbooks}, - {"id": "P13", "titre": "Invariants structurels/doctrinaux", + {"id": "P13", "titre": "Invariants structurels/doctrinaux", "refs": ["AFF-015", "AFF-022", "AFF-037", "AFF-038", "AFF-062"], "refs": ["AFF-015", "AFF-022", "AFF-037", "AFF-038", "AFF-062"], "func": preuve_structurels}, {"id": "P14", "titre": "Pas de chemin lab/ code en dur", "refs": ["AFF-097"], "func": preuve_pas_lab_code_en_dur}, {"id": "P15", "titre": "Modele public socle valide", "refs": ["AFF-022", "AFF-099"], "func": preuve_modele_socle}, - {"id": "P17", "titre": "Tous les modeles valident (registres + underlay)", + {"id": "P17", "titre": "Tous les modeles valident (registres + underlay)", "refs": ["AFF-105"], "refs": ["AFF-022", "AFF-099"], "cmds": [[sys.executable, "scripts/modeles.py", "verifier"]]}, {"id": "P18", "titre": "Gabarit de voute complet", "refs": ["AFF-026"], "cmds": [[sys.executable, "scripts/voute.py", "verifier"]]}, - {"id": "P19", "titre": "Le GUI couvre le schema du plan", + {"id": "P19", "titre": "Le GUI couvre le schema du plan", "refs": ["AFF-106"], "refs": ["AFF-002", "AFF-095"], "cmds": [[sys.executable, "scripts/couverture_gui.py", "verifier", "--tolerer", "nomenclature"]]}, - {"id": "P20", "titre": "Adressage 100% derive du seed (aucun stocke)", + {"id": "P20", "titre": "Adressage 100% derive du seed (aucun stocke)", "refs": ["AFF-101"], "refs": ["AFF-001", "AFF-003"], "func": preuve_nomenclature_derivee}, - {"id": "P21", "titre": "Federation : aucun index en collision", "refs": ["AFF-001"], + {"id": "P21", "titre": "Federation : aucun index en collision", "refs": ["AFF-102"], "cmds": [[sys.executable, "scripts/instances.py", "--verifier"]]}, {"id": "P22", "titre": "Plan de recette a jour (genere du wiki)", "refs": ["AFF-002"], "cmds": [[sys.executable, "scripts/plan_recette.py", "--verifier"]]}, - {"id": "P23", "titre": "Underlay sans collision avec la plage tenant", "refs": ["AFF-001"], + {"id": "P23", "titre": "Underlay sans collision avec la plage tenant", "refs": ["AFF-103"], "cmds": [[sys.executable, "scripts/underlay.py", "--verifier"]]}, - {"id": "P24", "titre": "Frontiere nord/sud : acces d'administration declare", "refs": ["AFF-001"], + {"id": "P24", "titre": "Frontiere nord/sud : acces d'administration declare", "refs": ["AFF-104"], "cmds": [[sys.executable, "scripts/devis_opnsense.py", "--verifier"]]}, ]