audit : les preuves réseau étaient accrochées à la mauvaise affirmation

P21, P23 et P24 renvoyaient à AFF-001 — « Set-OPS est un moteur Ansible
générique » — sans rapport avec la fédération, l'underlay ni la frontière.
P17, P19 et P20 n'avaient aucune référence. Une preuve accrochée à la
mauvaise affirmation passe au vert et n'atteste de rien de ce qu'on croit.

Ajouté §10 du registre : six affirmations (AFF-101..106) pour l'architecture
réseau et la fédération. La couverture du plan par le panneau est en 🟡, avec
ses exceptions nommées — listes de tables de l'underlay, ports physiques,
nœud de sortie.

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 au
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é aussi : P03, P06, P12 et P13 portent maintenant les références que la
table leur attribuait déjà — la correspondance existait en double et seul le
document la tenait. Et la table attribuait AFF-030 (« inventaire complet ») à
P15, qui valide le modèle socle ; c'est P16 qui exécute
`ansible-inventory --list`.

35 affirmations référencées, aucune référence orpheline.

Preuves : 24 OK, 0 échec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-08-03 09:36:30 -04:00
parent 39fab4c465
commit 1917545126
4 changed files with 75 additions and 14 deletions

View file

@ -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

View file

@ -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`,

View file

@ -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

View file

@ -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"]]},
]