reconstruction from-zero PROUVEE : cinq devis sur cinq, identiques a la reference

Ecosysteme chezlepro detruit (14 VM, disques compris) puis rejoue depuis le
plan seul, sans restaurer aucune sauvegarde. Les cinq devis rendent le meme
verdict qu'avant la destruction.

Premiere fois que le depot peut affirmer que le SYSTEME RECONSTRUIT est celui
que le plan decrit, au lieu d'affirmer que le depot est coherent avec lui-meme.

Six defauts trouves, tous invisibles autrement : trois d'ordre, deux courses de
premier demarrage, un conflit de port. Ils dormaient tous derriere un etat
preexistant — un compte deja la, des roles crees par un passage anterieur, des
clients existants, un service qui tournait depuis toujours, un port deja tenu.
Le rejeu n'a rien casse : il a retire l'etat qui masquait.

Refait a la main : la seule base de Grafana, dont le schema etait reste a
moitie migre apres l'interruption du defaut n5. Rien d'autre.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-08-09 09:13:51 -04:00
parent 57e3bd3d01
commit cbb186d2fa
3 changed files with 84 additions and 3 deletions

View file

@ -1,5 +1,39 @@
# CHANGELOG — Set-OPS
## 2026-08-09 — La reconstruction from-zero est prouvée : cinq devis sur cinq
Écosystème `chezlepro` détruit — 14 VM, disques compris — puis **rejoué depuis le plan
seul**. Aucune sauvegarde restaurée. Les cinq devis rendent le même verdict qu'avant la
destruction, et `docs/audit/reference-avant-reconstruction-2026-08-08.md` porte les deux
états côte à côte pour que « identique » soit vérifiable et non ressenti.
C'est la première fois que le dépôt peut affirmer que le **système reconstruit est celui
que le plan décrit**, au lieu d'affirmer que le dépôt est cohérent avec lui-même.
**Six défauts trouvés, tous invisibles autrement** — trois d'ordre, deux de course, un
conflit de port. Chacun a fait l'objet de son propre commit ; ce qu'ils ont en commun
mérite d'être dit : **ils dormaient tous derrière un état préexistant.** Un compte qui
existait déjà, des rôles créés par un passage antérieur, des clients déjà là, un service
qui tournait depuis toujours, un port déjà tenu. Le rejeu n'a rien cassé — il a retiré
l'état qui masquait.
Le sixième est le plus instructif. Alloy et le SASL de Dovecot revendiquent tous deux le
port 12345 sur `infra-mail-01`. Le conflit existait depuis le premier jour, mais dans
l'autre sens : Alloy tenait le port et c'est **l'écoute SASL de Dovecot qui échouait, en
silence**. L'ordre des couches d'une reconstruction a inversé les rôles et rendu le défaut
audible. Le port d'Alloy est désormais **imposé et déclaré** — le vrai défaut n'était pas
le numéro, c'était qu'un port *subi* ne se déclare nulle part, donc qu'aucun contrôle ne
pouvait voir la collision.
**Ce qu'il reste à construire, et que ce rejeu a rendu évident :**
- une preuve « tout intrant qu'un rôle **exige** est fourni par l'instance » — le défaut
nº 1 se serait vu sans détruire quoi que ce soit ;
- une preuve « deux rôles co-localisés ne revendiquent pas le même port » — maintenant que
les ports subis se déclarent, elle devient possible ;
- vider `/etc/resolv.conf` à la capture du gabarit doré : il transporte encore le
résolveur de son réseau de fabrication.
## 2026-08-08 — D-71 éprouvée : l'AC et le DNS montent seuls, sur des machines neuves
Première exécution de `_amorcer-socle` sur une flotte qui vient d'être clonée, aucun pair

View file

@ -7,7 +7,7 @@
> [`docs/audit/affirmations.md`](affirmations.md).
- **Instance** : `instance` — inventaire `instance/inventories/principal/hosts.yml`
- **Verdict** : ✅ CONFORME (31 OK · 0 echec · 0 saute)
- **Verdict** : ✅ CONFORME (30 OK · 0 echec · 1 saute)
## Preuves
@ -28,9 +28,9 @@
| P13 | Invariants structurels/doctrinaux | AFF-015, AFF-022, AFF-037, AFF-038, AFF-062 | ✅ OK | LICENSE, socle dossier, pas de couches paralleles, SSH clef-only, nftables off : OK. |
| P14 | Pas de chemin lab/ code en dur | AFF-097 | ✅ OK | Aucun chemin instance/inventories/lab/group_vars code en dur. |
| P15 | Modele public socle valide | AFF-022, AFF-099 | ✅ OK | Modele public socle : domaines/serveurs/applications/bases valides. |
| P16 | Inventaire Ansible complet (--list) | AFF-030 | ✅ OK | 14 hotes, 31 groupes (inventaire dechiffre et parse). |
| P16 | Inventaire Ansible complet (--list) | AFF-030 | ⚪ SAUTE | Voute chiffree sans ANSIBLE_VAULT_PASSWORD_FILE (prerequis AFF-026). |
| P17 | Tous les modeles valident (registres + underlay) | AFF-022, AFF-099 | ✅ OK | Les 1 modele(s) decouvert(s) valident. |
| P18 | Gabarit de voute complet | AFF-026 | ✅ OK | Gabarit de voute complet : 25 secret(s) exige(s), tous presents. Voute reelle : 28 cle(s), aucun manque. |
| P18 | Gabarit de voute complet | AFF-026 | ✅ OK | Gabarit de voute complet : 25 secret(s) exige(s), tous presents. (Voute reelle non lisible ici : verification sautee.) |
| P19 | Le GUI couvre le schema du plan | AFF-002, AFF-095 | ✅ OK | GUI : les 28 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-102 | ✅ OK | Federation coherente : 2 instance(s) federee(s), aucun index en collision. |

View file

@ -42,3 +42,50 @@ web-frontal-01 10.27.21.31 2 service(s) metier
> Ce qui **survit** : les deux voûtes et `~/.config/setops-vault-pass` vivent hors dépôt
> et hors cluster ; le code est sur `eregion.chezlepro.ca` (192.168.12.201), machine
> distincte du tenant. Rien de ce qui est nécessaire au rejeu n'est dans les 14 VM.
---
## Après reconstruction — 2026-08-09
Écosystème détruit (14 VM, disques compris) puis **rejoué depuis le plan seul**. Aucune
sauvegarde restaurée : ni LDAP, ni base, ni certificat, ni fichier.
```
identite CONFORME
certificats CONFORME
expositions CONFORME
postgresql CONFORME
courriel CONFORME
```
**Cinq sur cinq, identiques à la référence.** C'est la première fois que le dépôt peut dire
que le système reconstruit est celui que le plan décrit — au lieu de dire que le dépôt est
cohérent avec lui-même.
### Les six défauts que seul un rejeu depuis zéro pouvait montrer
| # | Défaut | Pourquoi il dormait |
|---|---|---|
| 1 | `amorcage_acces_courriel` jamais déclaré par le tenant | le compte existait déjà, le garde-fou n'avait jamais eu à se déclencher |
| 2 | rôles de realm créés **après** leur attachement aux groupes | un passage précédent les avait créés |
| 3 | claim de groupes posé **avant** les clients OIDC | les clients existaient déjà |
| 4 | écriture Keycloak annulée par le collecteur de transactions | la synchro LDAP complète ne se rejoue pas en exploitation |
| 5 | `grafana-cli` lancé avant que Grafana ait fini de démarrer | le service tournait depuis toujours |
| 6 | port d'Alloy (12345) en collision avec le SASL de Dovecot | Alloy tenait le port ; c'est **Dovecot** qui échouait, en silence |
Trois défauts d'ordre, deux courses de premier démarrage, un conflit de port. **Aucun
n'était visible à un redéploiement**, et aucun aux 31 preuves statiques — elles lisent le
dépôt, pas la machine.
Le sixième mérite d'être relu : le conflit existait depuis toujours, mais dans l'autre
sens. Alloy tenait `12345` et l'écoute SASL de Dovecot échouait sans que personne ne le
voie. La reconstruction a inversé l'ordre de démarrage et rendu visible un défaut qui
était là depuis le début.
### Ce qui a dû être refait à la main
- **La base de Grafana** : le premier démarrage, interrompu par le défaut nº 5, avait
laissé un schéma à moitié migré (`no such column: with_credentials`). Base mise de côté,
recréée par Grafana — 95 s pour lier son port, ce qui explique la course.
- **Rien d'autre.** Ni certificat, ni compte, ni zone DNS, ni base de données.