CHANGELOG : les trois entrees manquantes des 13 et 14 aout
Regle 5 — « rien n'est pret sans l'entree CHANGELOG correspondante ». Trois commits
etaient passes sans la leur, dont le plus instructif de la serie.
- 2026-08-14, la PORTEE de la frontiere : `underlay.tenants`, le defaut silencieux qui
aurait pose trente objets de Chezlepro sur la frontiere de Technolibre. La note dit
aussi ce qui n'est PAS corrige : `devis_sdn` et `devis_reseau` partent du meme
`decouvrir()`.
- 2026-08-13, le formulaire encode : `hasPost()`, le `{"result":"failed"}` NU, et la
regle qui reste vraie quelle que soit la version — un refus sans validation n'est pas
un refus, c'est une absence. Le point ouvert (re-eprouver apres mise a jour) est ecrit.
- 2026-08-13, le runbook d'implantation sur un site neuf : les six phases, et surtout ce
que lui seul porte (adressage cible d'emblee, le piege `make flux`, le site a un noeud).
Aucun code touche. make test 0 ; prouver 37/37 (invocation directe).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
7339cc64b4
commit
29148831bf
1 changed files with 139 additions and 0 deletions
139
CHANGELOG.md
139
CHANGELOG.md
|
|
@ -1,5 +1,144 @@
|
|||
# CHANGELOG — Set-OPS
|
||||
|
||||
## 2026-08-14 — Une frontière ne police que les tenants de **son** site
|
||||
|
||||
Premier `make frontiere-plan` sur le second site. Le devis voulait poser sur la frontière
|
||||
de Technolibre les règles **et** les routes de **Chezlepro** : trente objets de plus, dont
|
||||
six routes vers des sous-réseaux `10.17.x` qui n'existent pas là-bas.
|
||||
|
||||
### Le défaut est de portée, et il est silencieux
|
||||
|
||||
Les devis partaient de `devis_reseau.decouvrir()`, qui rend **toute la fédération** — tout
|
||||
dossier frère portant une nomenclature avec un index. C'était juste tant qu'il n'y avait
|
||||
qu'un site : l'hébergeur unique portait bien tous les tenants. Dès le second, c'est faux.
|
||||
|
||||
Et rien ne l'aurait dit. Le boîtier aurait **accepté** ces trente objets ; aucun n'aurait
|
||||
jamais correspondu à un paquet ; aucune erreur, aucun avertissement. Une politique qui a
|
||||
l'air complète et ne protège rien — encore le **chèque vert sur un périmètre vide**.
|
||||
|
||||
### Le correctif : l'hébergeur nomme ce qu'il porte
|
||||
|
||||
```yaml
|
||||
underlay:
|
||||
tenants: [OPS-Technolibre] # les tenants HÉBERGÉS ici, pas la fédération
|
||||
```
|
||||
|
||||
`devis_opnsense` s'y limite (`underlay.tenants_du_site()`). **Clé absente = ancien
|
||||
comportement**, toute la fédération : un site unique n'a rien à déclarer, c'est le second
|
||||
qui doit se nommer. Un nom déclaré qu'aucun dossier frère ne fournit est **signalé**, pas
|
||||
ignoré silencieusement ; et si le filtre ne retient aucun tenant connu, le devis refuse
|
||||
plutôt que de rendre une politique vide.
|
||||
|
||||
**Même hypothèse ailleurs, non corrigée** : `devis_sdn` et `devis_reseau` partent du même
|
||||
`decouvrir()`. À traiter le jour où ils serviront sur un second site — dit ici pour ne pas
|
||||
le redécouvrir.
|
||||
|
||||
### Au passage, un défaut du document écrit la veille
|
||||
|
||||
Le squelette d'`underlay.yml` d'[`implanter-un-tenant-sur-un-site.md`](docs/implanter-un-tenant-sur-un-site.md)
|
||||
omettait `index`. Sans cette clé, `make underlay` refuse le réseau de gestion en le prenant
|
||||
pour le supernet d'un **autre** site : message déroutant, cause triviale. Trouvé en s'en
|
||||
servant, moins de vingt-quatre heures après l'avoir écrit.
|
||||
|
||||
`prouver` 37/37, `make test` 0.
|
||||
|
||||
> **Ce qui marche avec un seul écosystème n'est pas prouvé.** Comme les six défauts moteur
|
||||
> qu'avait révélés le second tenant, celui-ci n'existait que parce qu'un second **site**
|
||||
> existe enfin. Une hypothèse implicite ne se voit qu'au moment où elle cesse d'être vraie.
|
||||
|
||||
|
||||
## 2026-08-13 — La frontière poste en formulaire encodé : `hasPost()` et le `failed` nu
|
||||
|
||||
Mesuré sur un OPNsense **24.7** (version ancienne, mise à jour depuis) : **toute écriture**
|
||||
du moteur y échouait. Alias, règles, NAT, routes — `make frontiere-appliquer` n'aurait rien
|
||||
posé sur ce boîtier. Ce n'est donc pas un défaut universel du moteur : il écrit correctement
|
||||
sur la frontière de Chezlepro, plus récente. C'est un problème de **compatibilité**, et le
|
||||
correctif vaut surtout comme garantie de **portabilité** — le jour où l'on arrive sur un
|
||||
site dont on ne choisit pas le firmware, ce qui est exactement le cas.
|
||||
|
||||
### Le symptôme mérite d'être retenu, lui, quelle que soit la version
|
||||
|
||||
Le contrôleur d'OPNsense lit ses champs avec `hasPost(<racine>)`. Si le corps arrive en
|
||||
`application/json` et que le boîtier ne le décompose pas en variables de POST, ce test est
|
||||
**faux** :
|
||||
|
||||
```
|
||||
HTTP 200 {"result":"failed"} ← nu : aucune redirection, aucune validation
|
||||
```
|
||||
|
||||
Le contrôleur ne dit pas quel champ manque, **parce que de son point de vue il n'y avait
|
||||
aucun champ**.
|
||||
|
||||
Trois fausses pistes avant la bonne : valeur invalide (un corps **vide** échouait pareil),
|
||||
racine de payload erronée (elle était juste), privilèges de la clé (la lecture passait). Ce
|
||||
qui a tranché : *un corps vide aurait dû produire des validations.* Leur absence disait que
|
||||
le contrôleur n'avait rien reçu.
|
||||
|
||||
### Le correctif
|
||||
|
||||
`Frontiere` poste désormais `racine[champ]=valeur` — la forme que poste **l'interface web
|
||||
elle-même**. Aucune version d'OPNsense ne la refuse, alors que le JSON dépend du boîtier.
|
||||
Tous les corps du moteur sont des dicts plats de chaînes (alias, `rule`, `route`) : un seul
|
||||
niveau d'imbrication suffit.
|
||||
|
||||
**Éprouvé sur le boîtier, dans les deux sens** : `addItem` d'un alias sonde → `saved`,
|
||||
`delItem` → `deleted`, aucune trace laissée, lecture intacte (11 alias). **Reste ouvert** :
|
||||
ré-éprouver après la mise à jour, pour vérifier que le formulaire reste bon sur la version
|
||||
récente.
|
||||
|
||||
> **Un `failed` sans validation n'est pas un refus, c'est une absence.** Quand un contrôleur
|
||||
> ne nomme aucun champ fautif, cesser de chercher le mauvais champ : il n'a rien reçu.
|
||||
|
||||
|
||||
## 2026-08-13 — Implanter un tenant sur un site neuf : le runbook de l'intervention
|
||||
|
||||
Le dépôt couvrait déjà « l'hébergeur prépare son matériel » et « un tenant **vivant** change
|
||||
d'hébergeur, sans coupure ». Il manquait le troisième cas, qui est celui qu'on s'apprête à
|
||||
faire : un tenant dont le plan existe déjà **prend corps sur un site qui n'a jamais rien
|
||||
porté**. Rien à migrer, rien à interrompre — donc ni la séquence de gel/bascule de
|
||||
`migration-tenant.md`, ni le bootstrap du QUICKSTART.
|
||||
|
||||
[`docs/implanter-un-tenant-sur-un-site.md`](docs/implanter-un-tenant-sur-un-site.md),
|
||||
**six phases**, chacune fermée par une commande qui **interroge le système** :
|
||||
|
||||
```
|
||||
0 bureau index du site = index du tenant, dépôt hébergeur, gabarit, voûte
|
||||
1 reconnaître make underlay, make placement-plan
|
||||
2 frontière make frontiere-plan
|
||||
3 gabarit convertir en template — un clone de VM vivante en ferait 14 copies
|
||||
4 composer les DEUX symlinks (D-80) + les 4 valeurs de placement
|
||||
5 matérialiser make sdn-appliquer, puis make reconstruire
|
||||
6 recette devis, restauration éprouvée, supervision
|
||||
```
|
||||
|
||||
### Ce que le runbook porte et qu'aucun autre document ne dit
|
||||
|
||||
- **Un site neuf se bâtit d'emblée dans l'adressage cible** (D-77/D-78). Le site historique
|
||||
est encore en `10.0.x` et migrera par les runbooks §6 ; sur un site vierge, la cible ne
|
||||
coûte rien. Deux sites en `10.0.0.0/24` rendraient la **reprise mutuelle impossible** :
|
||||
deux plans de gestion identiques ne peuvent pas s'atteindre.
|
||||
- **L'ordre de `reconstruire`, ligne à ligne**, dont le piège `make flux` : sans lui,
|
||||
nftables tombe en `policy drop` **sans aucune règle** — la flotte monte, SSH répond, et
|
||||
tout le reste est mur (trouvé le 2026-08-10).
|
||||
- **Un site à un seul nœud** : ce nœud est aussi nœud de sortie, aucun pont ne peut être
|
||||
partiel, aucune haute disponibilité. À dire, pas à laisser supposer.
|
||||
- **PVE 9 n'a jamais été éprouvé ici** : tout écart est inconnu jusqu'à mesure.
|
||||
- **« Ce qui n'est PAS fait en repartant »** — resserrer le compte d'API, le lien
|
||||
inter-sites, le gabarit des deux côtés, la voûte hors de son propre site.
|
||||
|
||||
**En annexe**, les squelettes d'`underlay.yml` et de `proxmox-hebergeur.yml` pour un site à
|
||||
un nœud, à remplir depuis la **reconnaissance** et jamais de mémoire — c'est en recopiant
|
||||
des listes chez chaque tenant qu'elles avaient divergé.
|
||||
|
||||
Sixième porte dans la table de routage du README. Les 21 cibles `make` citées ont été
|
||||
vérifiées comme existantes. `prouver` 37/37 (dont P34 : 40 documents déclarent leur
|
||||
lecteur), `make test` 0.
|
||||
|
||||
> **La règle qui commande tout l'ordre du document** : *rien n'est fait tant que ce n'est
|
||||
> pas mesuré sur place.* Une valeur transmise par courriel, une liste relevée dans
|
||||
> l'interface web, un `vmbr` cité de mémoire — chacun des trois a déjà produit une panne ici.
|
||||
|
||||
|
||||
## 2026-08-13 — La machine d'épreuve jetable existait, et n'était écrite nulle part
|
||||
|
||||
L'exploitant a découvert par hasard, en creusant l'intrant « pont réseau », qu'on peut
|
||||
|
|
|
|||
Loading…
Reference in a new issue