Commit graph

113 commits

Author SHA1 Message Date
5e7534d87f pare-feu proxmox : la procedure d activation prouvee entre au depot
eprouver_parefeu.py, make proxmox-fw-eprouver et proxmox-fw-activer-vm :
matrice du devis, flux observes, avant/apres, Icinga ; sans objet derive de
ce qui ecoute, VMID du bon locataire.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:09:22 -04:00
4f5a0b5696 pare-feu proxmox : poser les objets, puis activer VM par VM
--objets-seulement et --vm <vmid> : aucune des 26 VM des locataires n avait son
pare-feu actif ; tout activer d un coup ouvrait 26 pannes possibles a la fois.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 13:25:29 -04:00
4855cda294 voutes : elles sortent du poste, dans leur propre archive, relues
exporter_voutes.py et make voutes-exporter : les six voutes (gitignorees, sur
aucune forge) sont sur la cle USB, a cote des cles ; restauration eprouvee.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 12:53:14 -04:00
f5adffb0de sondes conditionnelles : attendues seulement la ou elles sont posees
seulement_si dans meta/supervision.yml, lu par le gabarit Icinga des sondes ;
garde test_sondes_conditionnelles. journaux-frontiere ne rougit plus a vie chez
les locataires ; Technolibre sans critique.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 12:31:17 -04:00
185b000c60 icinga : un service passif qui n a jamais rien recu passe au rouge
Gabarit setops-rapport-attendu : actif, dummy critique, check_interval = le
ttl que le noeud envoie. Prouve a t+60 s sur site-mon-01, deploye sur les trois
Icinga ; la garde test_fraicheur_icinga lie seuils et ttl.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 12:05:15 -04:00
7ef7ca196a depots perimes : ce qui n'existe qu'ici ne se detruit pas depuis ici
serveur_ops clone ce que le plan declare et ne retire rien : le runner de
Chezlepro-locataire portait encore le clone de SITE-Chezlepro, la carte de son hebergeur,
longtemps apres que son plan ait cesse de la declarer.

Le retrait n'entre pas dans le role. Un role qui efface des dossiers a chaque passage est
une grenade degoupillee : une faute de frappe dans serveur_ops_depots suffirait a perdre du
travail local. C'est donc un geste separe, qui regarde par defaut et n'efface que sur
CONFIRMER=true. Trois choses ne sont jamais retirees, meme confirmees : ce qui n'est pas un
depot git, ce qui porte des modifications non validees, ce qui porte des commits qu'aucun
distant ne porte.

La garde a servi au premier essai : le releve a nomme SITE-Chezlepro et venv, et venv a ete
ecarte parce que ce n'est pas un depot git. Une version naive aurait efface l'environnement
Python du runner en se disant satisfaite.

Passe deux fois sur le runner reel : regarder (changed=0), puis confirmer (changed=1) avec
relecture. Le runner ne porte plus que Set-OPS-public et OPS-Chezlepro ; sa console rend
portee=tenant, materialiser=False, fabric=False — le pouvoir de LIRE la fabric est tombe
avec la carte, et c'est juste.

Valide : syntax-check du playbook, runbooks.py verifier a 0 ecart (la cible neuve est portee
par le runbook Filiation), make test a 0 echec. P02 reste en echec pour la raison anterieure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 20:18:59 -04:00
4188cf5b6f la console mesure le pouvoir sur la voute, pas sur la carte
Le document des responsabilites attache chaque pouvoir a une voute : calculer n'en demande
aucune, configurer demande celle du tenant, materialiser celle du site. Le code lisait les
symlinks, c'est-a-dire les cartes. Le runner de Chezlepro-locataire montait la carte du
site sans en avoir jamais eu la voute : sa console se declarait poste et offrait 126 etapes
sur 126. Ces gestes seraient partis puis tombes sur un secret vide — un echec au milieu du
chemin, la ou un refus net aurait dit la verite avant de commencer.

contexte() derive desormais les pouvoirs des voutes presentes, et la portee decoule des
pouvoirs au lieu de les preceder. On ne prouve pas qu'une voute s'ouvre, le mot de passe se
tape a l'execution ; mais son absence est decisive et se mesure sans rien ouvrir. Lire une
carte reste permis : le pouvoir fabric suit toujours le symlink, consulter un miroir n'est
pas engendrer.

serveur_ops retire aussi le lien quand la fabric n'est plus declaree — il ne retirait rien,
et un runner gardait le pouvoir que son plan ne lui donnait plus. Il ne retire qu'un lien,
jamais un fichier : une vraie carte a cette place n'a pas ete ecrite par ce role, et il le
dit plutot que de detruire ce qui n'est pas le sien.

Valide : syntax-check et ansible-lint sur le role (profil production, 0/0), make test a 0
echec, P81 et P83 vertes. Six tests montent quatre faux disques et exigent la portee qui
leur revient, dont le defaut lui-meme : carte presente, voute absente, portee tenant.

Limite : P02 reste en echec pour la raison anterieure deja consignee.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 20:12:18 -04:00
f33b5be151 assistants : cent trente-deux cibles, et aucune ne disait dans quel ordre
La console offrait des boutons sans sequence. Rien n'y apprenait que site-creer precede
forge-amorcer, que le premier passage de site-deployer-tout s'arrete sur une forge vide
sans que ce soit un echec, ni que rien n'est pret avant valider : cet ordre vivait en
prose dans des documents que la console ne porte pas.

La vue Assistants conduit 17 runbooks et 126 etapes. Les 132 cibles documentees y sont,
chacune portee par un assistant ou exemptee avec son motif — une exemption muette est
refusee. Le registre ne recopie pas le Makefile : il declare l'ordre, la nature, la portee
et le pourquoi, et le libelle de chaque etape est lu dans le Makefile au moment de servir.

P83 est ecrite en meme temps que la liste, pas apres, parce qu'une liste qui suit une
autre prend du retard. Onze tests lui presentent des registres faux, un par forme de
retard, et exigent qu'elle les refuse.

Le navigateur ne nomme pas une commande, il nomme une place : la route lance ce que le
registre declare a cet index-la, avec les seules variables declarees. L'index compte, le
premier jour d'un site jouant site-deployer-tout deux fois. Une etape qui ecrit attend que
la precedente ait reussi ; une mesure reste toujours offerte, parce que mesurer apres un
echec est exactement ce qu'on fait ensuite.

Valide : runbooks.py verifier a 0 ecart, make test a 0 echec, les 83 preuves rejouees, et
la console lancee pour de vrai — 17 runbooks servis, six requetes malformees refusees une
a une, une etape de mesure executee de bout en bout avec son journal.

Limite, anterieure a ce travail : P02 (test_ecriture_plan) echoue sur domaines.yml, a
l'identique sur une copie de HEAD. Ajouter ou retirer un domaine public depuis la vue
Domaines leverait a l'enregistrement. Non corrige ici.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 16:31:16 -04:00
d90513ca91 acces d'administration : un tunnel WireGuard nominatif, pas le runner en rebond
Le runner detient la voute et les cles SSH : en faire la porte des humains reunirait deux
pouvoirs que le depot separe. Instance `admins` a cote du tunnel site-a-site, un pair par
personne et par appareil, cles publiques seules au plan. Le reseau du tunnel est un reseau
d'administration : pare-feux d'hote, contrat des locataires et regles de bordure en derivent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 14:42:48 -04:00
712ad9f630 DNSSEC : le locataire signe, avec la cle de sa voute
Cle CSK ECDSA P-256 tiree dans la voute du locataire, importee par le role, DS calcule
sans la machine. Refus de changer la cle ou de retirer la signature tant qu'un DS est
publie. SOA-EDIT EPOCH : INCEPTION-EPOCH aurait laisse expirer les signatures du site.
CAA sur chezlepro.ca, sonde des signatures au site, P18 deplie vault_dnssec_<zone>.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 22:09:21 -04:00
63780645a7 zones publiques : le courriel dans la zone, et un devis avant de basculer
Une zone publique ne portait que des A d'exposition ; basculer chezlepro.ca aurait coupe
son MX, son SPF et son DMARC. Les enregistrements se declarent au plan, valides et rendus ;
le serveur de noms porte le nom que le site declare (dns1.chezlepro.ca), parce que
ns1.chezlepro.ca existe deja en production. make dns-bascule-devis compare le plan au DNS
en service : 0 perdu sur les deux zones, deux prealables restants.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 21:54:49 -04:00
0cbb9fdb4a remise au client : deux temps, un outil, une garde
Livrer se terminait par une phrase — tes cles te seront remises separement — et
rien n ecrivait la suite. Temps 1 l identite (sa cle de voute, sa voute, sa racine
d AC), temps 2 la machine a echeance (sa cle entre, la notre sort, voute re-cletee,
secrets tournes). scripts/remise.py refuse une destination interne, un paquet sans
racine d AC, et tout ce qui n est pas l ecosysteme monte. Le registre remise.yml
declare enfin le responsable designe (D-18). P80 refuse un registre incomplet, un
second temps echu, un second temps declare fait sans revocation au plan, et un
secret dans un fichier versionne.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 11:16:27 -04:00
baa9d12054 wiki : WIKI_REMOTE etait documente cinq fois et jamais lu
La cible lisait $$remote — une variable de shell que rien ne definit — au lieu
de $(WIKI_REMOTE). L echappatoire que le message d erreur proposait lui-meme
n existait pas.

WIKI_BRANCHE, deux cibles plus bas, etait ecrit correctement depuis le debut.
Une option qui se lit autrement que sa voisine est l endroit ou regarder.

Wiki publie sur eregion : 95 pages, les huit fiches neuves portent leur sonde —
verifie en clonant la forge, pas en lisant le temoin.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-14 15:46:43 -04:00
8574b7b540 wiki : chaque runner publie pour SA forge
J allais centraliser — un controleur poussant vers N forges, un temoin portant
une liste. Ca aurait demande un acces sur chaque forge depuis un seul poste, et
fait du temoin un fait global que personne ne detient.

Le modele suit la ligne du reste : chacun sert les siens. Sans WIKI_REMOTE,
l adresse se derive du nom que le plan monte expose pour serveur_forgejo.

Deux notions a ne pas confondre : la forge AMONT ou l on LIT le genome, et MA
forge ou l on SERT les siens. Le runner d un locataire lit chez son hebergeur et
sert chez lui.

WIKI_REMOTE l emporte toujours : le poste du mainteneur n est le runner d aucun
ecosysteme et publie vers le domicile public du projet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-14 14:26:29 -04:00
1b71884871 make fiches : les 68, et la cible qui les regenere
Une preuve a mordu : un script qu aucune cible n appelle est du code mort. Elle
avait raison.

68 fiches generees. Le vide y est une information — la carte de ce qui reste a
faire, tenue a jour toute seule.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-14 13:14:01 -04:00
8eb482e0c6 site-deployer-tout : l orchestration existait, rien ne la lancait
playbooks/site.yml ordonne les couches pour n importe quelle instance. Mais
deployer-tout ne vise que l inventaire d un locataire, et le site n avait que
site-appliquer GROUPE=<un seul>.

Un hebergeur qu on ne peut remonter qu en enchainant onze groupes de memoire
n est pas reconstructible : il est reparable par quelqu un qui se souvient.

Et quatre gardes que --check rendait folles, toutes de la meme famille : une
garde qui compare contre ce qu une tache du meme play vient de produire n a rien
a dire tant que rien n a ete ecrit. Sept machines en echec sur un site sain, en
suivant le conseil du Makefile lui-meme.

Apres correction : 7/7, 0 echec, de 174 a 309 taches par machine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-14 11:02:37 -04:00
220e1e3e28 deployer-tout : le genome est-il a jour avant de poser quoi que ce soit
Un runner tire ce qu on pousse, il ne le recoit pas. Trois fois ce soir un
genome perime a menace de rebatir un etat depasse — et aucun des deux runners
n aurait echoue : un deploiement depuis un genome perime REUSSIT. Il applique
fidelement un etat qui n a plus cours, et se presente en vert.

En retard : refus. En avance ou diverge : note et on continue. Forge
injoignable : note et on continue — une forge en panne ne doit pas immobiliser
une exploitation, le silence serait la faute.

FORCE=1 passe outre. Eprouvee dans les trois sens.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-13 23:32:16 -04:00
db1cb652b7 insemination : le runner verifie SA cle avant de partir
La cle d amorcage du plan est une transcription de la cle publique du runner du
site. Reconstruire le runner lui donne une paire neuve ; la transcription, elle,
ne bouge pas. Meme algorithme, meme commentaire, materiel different : rien ne
distingue les deux a l oeil.

La garde ne demande rien au reseau — le runner du site EST la machine qui
insemine, sa cle est sous sa main. Elle ne compare que si les deux cles nomment
le meme hote : lancee depuis le poste d un exploitant, elle se tait.

Elle dit aussi ce que la correction seule ne suffit pas a reparer : une machine
deja creee porte la cle perimee, il faut la RECREER.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-13 22:04:41 -04:00
bd0e40753b memoire : ce que l hote a le droit de reprendre, et pourquoi il ne le pouvait pas
61 Go declares a 21 machines, 12 reellement utilises. balloon valait 0 partout,
ce qui ne desactive pas le ballooning : cela RETIRE le peripherique de la ligne
de commande QEMU. Le moniteur repond "No balloon device has been activated".

Le moteur derive desormais un plancher par machine sur les deux chemins de
creation, et le playbook de clonage le pose a cote de memory.

La table des planchers a ete corrigee deux fois par la mesure : shared_buffers
vaut 128 Mo et non une part de la RAM, une JVM tient 605 Mo, Redis 16 Mo. Ces
machines tiennent du cache de pages, pas un jeu de donnees.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-13 19:57:11 -04:00
025776064a intrants du site : ce qu un locataire doit savoir pour l habiter, derive
Un locataire ECRIT les adresses des services de son site — resolveur, cache, forge,
depot de sauvegarde, plan d administration, sortie. Une copie se perime, et deux
l avaient fait en deux jours avec la meme forme : `serveur_ops_forge_amont` visait
10.0.33.11 quand la forge sert en 10.37.33.11, et `ac-racine-site.crt` portait la
racine d avant la reconstruction du site. Rien ne les relisait.

`make site-intrants` lit le plan du site et rend le contrat — sept valeurs, toutes
derivees. `make site-intrants-verifier` les confronte a ce que le locataire declare,
et P73 en fait une preuve. Elle a trouve le defaut de la forge des sa premiere
execution.

Le contrat se DERIVE du plan du site, pas d une liste tenue a part : ajouter un
service prete au site l ajoute au contrat, sans qu on ait a y penser.

P69 RESTREINTE AU COUPLE MONTE. Elle balayait tous les depots OPS-* et les comparait
au site monte. Elle avait raison tant qu un seul site existait : une adresse en
10.x.3z ne pouvait designer que lui. Deux sites decoupent leurs zones de la meme
facon — c est le but, un locataire doit pouvoir habiter l un ou l autre sans se
renumeroter. Le troisieme octet a cesse de distinguer « mon site » d « un autre
site » : 10.31.34.11, juste pour un locataire de TechnoLibre, etait declare faux
parce que Chezlepro etait monte.

Un locataire n appartient a aucun site — il en habite un, choisi par le symlink au
deploiement. La seule paire jugeable est celle qui est montee. Meme portee que P73.

Une marche payee : la premiere version de site_intrants recopiait la resolution
d instance au lieu de la partager. P41 a mordu — neuf modules avaient deja porte
chacun leur copie, et cinq defauts en etaient sortis en cinq jours.

make prouver : 72 OK, 0 echec, 1 saute. ansible-lint : 0 failure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-13 16:18:12 -04:00
db4223904d pools : le genome ne nait plus chez un locataire
`Chezlepro-17` contenait VINGT ET UNE VM : les quatorze du locataire ET les sept du
genome. `OPS-Chezlepro` et `OPS-Technolibre`, crees a la main, etaient vides.

La cause : `site-creer` appelle `cloner-vm`, qui derive son pool par `--pool-actif`,
c est-a-dire le pool du TENANT lie. Les machines du site heritaient du locataire
courant. Range a la main, ca se serait defait au prochain `site-creer` — sans un mot,
parce que la VM est bien creee, bien nommee, bien adressee. Seule son appartenance
est fausse, et rien ne la regarde.

- `--pool-site` rend le nom invariable du pool du genome. Option DISTINCTE, pas un
  drapeau sur la premiere : une fonction qui repond aux deux questions finit par se
  tromper d appelant.
- `cloner-vm` accepte une surcharge POOL= ; `site-creer` la nomme. Substitution au
  niveau MAKE, pas shell : POOL arrive du sur-make comme variable make, et $${POOL}
  ne l aurait jamais vue.
- P71 exige que `site-creer` nomme son pool. Eprouvee dans les deux sens : passe sur
  le Makefile sain, tire des qu on retire l argument.

Applique au cluster : Site-OPS 9 VM (7 du site + 2 gabarits), OPS-Chezlepro 14,
OPS-Patient0 5. Chezlepro-17, Patient0-29 et Set-OPS supprimes une fois vides. Les
pools anterieurs a Set-OPS et les quinze VM hors pool n ont pas ete touches.

make prouver : 70 OK, 0 echec, 1 saute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-13 04:12:27 -04:00
bef0655112 le site reconstruit depuis zero : 7/7, 0 echec, et seize corrections
SITE-Chezlepro n avait jamais ete rase. La limite qu on repetait partout —
l infrastructure d accueil n a jamais ete reconstruite depuis zero — se
lisait comme de la prudence. C etait seize defauts que rien d autre n aurait
pu reveler.

Un locataire naît dans un monde deja peuple : le site lui fournit paquets,
noms, genome, heure et depot. Un site n a personne au-dessus, sauf sa
frontiere. Onze des seize murs viennent de la.

DEUX CAPACITES QUI N EXISTAIENT PAS. make site-raser — rien ne detruisait les
machines du site, donc la limite etait un trou d outillage. make
forge-amorcer — la forge naît vide et le runner y clone ; l amorcage part du
poste, seul endroit qui detienne alors le genome.

TROIS GARDES QUI VERIFIAIENT LA FORME. La plus couteuse des familles : elles
donnent l apparence d une verification. Le resolveur comparait des adresses
au lieu de mesurer si la resolution aboutit, et protegeait ainsi l etat
casse. L administration etait reconnue a son port. Un flux a deux paires
n obtenait qu une branche.

UN ECART DE SECURITE. Le PostgreSQL du site servait le certificat auto-signe
de Debian, sans reseaux autorises ni hostssl — invisible tant qu aucun client
n exigeait la verification. Le defaut n a pas casse la construction : la
construction a revele le defaut.

UN ACCES ACCIDENTEL. Celui de l exploitant tenait au chevauchement d
adressage que le renumerotage a supprime. Separer les index n a pas cause le
probleme, il a retire le hasard qui le masquait.

La sequence du premier jour est ecrite : runbooks §9, avec les seize murs et
ce que chacun enseigne.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-12 19:08:31 -04:00
0c55aafc40 le site prend l index 37, et la capacite de le raser existe enfin
SITE-Chezlepro passe de 10.0.31-36 (tapes a la main, derives de rien) et
10.17.0.0/24 (emprunte au supernet du locataire) a son PROPRE index : gestion
en 10.37.0.0/24, zones en 10.37.31-36. OPS-Chezlepro garde 17.

CE QUE L OPERATION A REVELE. Il n existait aucun moyen de raser le site :
raser.py ne vise que l instance active, un locataire. Ce n est donc pas que
personne n avait essaye de le reconstruire depuis zero — l outil n en offrait
pas le moyen, et la limite se lisait partout sans que sa cause soit nommee.
make site-raser reprend les quatre verrous de raser.py.

TROIS FOIS LE MEME DEFAUT, attrape par l exploitant. La declaration decrit la
CIBLE pendant que l outillage s en sert pour joindre l EXISTANT : renumeroter
le rebond avant de bouger la patte a rendu le site injoignable. Regle posee :
le renumerotage declaratif vient APRES la derniere operation qui a besoin de
l ancienne infrastructure.

nftables_admin_ssh etait une liste a la main qui devait suivre le plan
d administration. Elle a pris du retard le jour meme.

Le plan de frontiere n a propose AUCUNE creation ni suppression de regle —
seulement douze contenus d alias. Les regles visent des alias par leur nom :
un renumerotage complet se reduit a changer ce que les noms designent.

Routes des trois hyperviseurs refaites, declarees ET vives, avec sauvegarde
de /etc/network/interfaces.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-12 16:32:06 -04:00
989398f3cf expositions-etat : le certificat SERVI, pas celui du disque
Renommer une exposition touche cinq choses. Quatre suivent au deploiement ;
la cinquieme est celle que le navigateur regarde. serveur_nginx pose le vhost
et laisse le SAN en arriere — c est client_pki qui reemet, et rien ne le
reclame. Mesure deux fois le 2026-09-10.

Le controle compare trois listes : les expositions du plan, les noms du
certificat servi, et le code que rend le vhost. Dans les deux sens : un nom
reste dans le SAN apres avoir quitte le plan continue d etre authentifie.

Piege trouve en l ecrivant : client_pki met toujours le FQDN et le nom court
de la machine dans le SAN. Les compter comme vestiges faisait crier le
controle a chaque execution — et un controle qui crie toujours ne se lit plus.

Deux formes de terminaison, une seule question : le locataire termine sur un
edge, le site sur la machine elle-meme. Le porteur se derive de l une ou de
l autre.

Ce n est pas une preuve : rien de statique ne peut lire un certificat servi.
Les quatre controles a la demande n etaient nommes nulle part comme famille ;
ils ont maintenant leur section dans les runbooks.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-11 10:21:19 -04:00
5abf20102d le site surveille enfin sa fabric
La supervision du site voyait ses sept VM et rien d autre. Au depart, depuis
site-mon-01, les trois hyperviseurs, les neuf pattes de la frontiere et sa
PROPRE passerelle par defaut rendaient tous 100 pourcent de perte au ping.

  16 hotes UP sur 16       dont 9 pattes de frontiere en controle ACTIF
  11 cibles Prometheus     dont 3 hyperviseurs, job fabric separe

LE PARTAGE. Les hyperviseurs portent node_exporter - D-48 l autorise - et
exposent 1005 unites systemd avec leur etat, soit ce que la sonde sante
mesurait, plus la charge et le disque. Ils n entrent PAS dans le socle :
leur appliquer serveur_durci reecrirait le pare-feu, le SSH et les sysctl
de la machine qui tient tout le reste. La frontiere, elle, n accueille
aucun agent : controle actif, une entree par PATTE, parce qu une interface
eteinte coupe une zone pendant que les autres vont bien.

ON TIRE, ON NE POUSSE PAS. J avais propose du passif et il avait ete
valide ; la mesure a dit non. Un hyperviseur envoie vers un routeur qui ne
connait pas les reseaux du site, et sa route par defaut est GELEE (D-57).
Le porteur de sante y expirait en 20 s.

LE VRAI DEFAUT ETAIT UNE LISTE QUI N A PAS SUIVI. Le mecanisme de routage
existait deja sur vmbr0, avec un commentaire du 2026-08-26 tenant
exactement le raisonnement qu on venait de refaire. Sa liste s arretait a
10.0.34.0/24 quand le site en declare six : les zones sauvegarde et
supervision sont nees, les routes n ont pas suivi. Le symptome ne
ressemblait pas a une route manquante - il ressemblait a un pare-feu, puis
a un probleme de reseau chez l exploitant.

make routes-fabric-etat compare desormais TROIS choses : zones declarees,
routes declarees dans /etc/network/interfaces, routes vivantes dans le
noyau. Le cas le plus traitre est vivante mais non declaree : tout
fonctionne, la supervision est verte, et la panne attend la prochaine
maintenance. Eprouvee dans les deux sens.

Deux defauts trouves en construisant. bifrost-2 est un nom RESERVE, pas un
boitier - l underlay le disait en prose, illisible par le moteur ; il porte
desormais etat: reserve. Et un service passif n existe que pour un hote qui
peut POUSSER : l appartenance a un groupe sert deux choses qui ne
coincident pas toujours, a qui l on deploie et de qui l on attend un
rapport.

Les commutateurs restent dehors, choix de l exploitant, coherent avec D-48.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-10 18:50:43 -04:00
4ef3a1d553 D-86 mis a l epreuve : Chezlepro rasee et refaite depuis zero
Quatorze machines detruites, quatorze refaites. 1 h 08, 0 injoignable.

D-86 TIENT, et la mesure le dit : 30 resultats de controle recus a
12:20:41 alors que la reconstruction ne s est terminee qu a 12:35:29.
Trente services rapportaient leur etat pendant que Keycloak, Forgejo et
Nextcloud montaient encore.

Sa limite, dite franchement : D-86 affirme que le DNS peut rester en
couche 6 grace au plancher /etc/hosts. Or _amorcer-socle monte
infra-dns-01 EN ENTIER d abord. Le DNS etait debout, le plancher n a rien
eu a porter, et la partie la plus audacieuse de la decision reste non
testee.

LE PLACEMENT DES VM N ETAIT DECLARE NULLE PART. Les quatorze vivaient sur
asgard depuis toujours, mais SETOPS_NOEUD valait le vide : ce placement
n existait que dans l etat d execution de Proxmox. Sans cible, le clone
reste sur le noeud du gabarit - vishnu, qui a 14 Go libres et heberge
eregion et site-forge-01. Le defaut avait survecu a la reconstruction du
2026-09-02 parce que les VM existaient deja et que le clone les sautait.
Il faut un from-zero VRAI pour voir ce genre de chose.

LE CLONAGE ETAIT 45 FOIS TROP LENT, et pas a cause du reseau : source et
destination etaient sur le meme stockage. C est le LVM epais qui interdit
a Proxmox tout clone autre que complet. Gabarit deplace sur CephNVMe,
mesure 480 s -> 8 s. On garde les clones complets : le clone lie descend
a 1 s mais enchaine chaque VM a l image de base pour toujours.

Un champ stockage: entre au gabarit, branche en quatre points - declare,
expose, consomme par le Makefile, garde par gabarit_etat. Declarer sans
consommer, c est decorer.

ICINGA NE POUVAIT PAS FAIRE SES PROPRES CONTROLES : icinga2 n apporte
aucun greffon, et la supervision etant passive, le manque etait masque.
Quatorze ping4 muets d une seule cause. monitoring-plugins-basic entre au
role. Le site l avait deja - pose A LA MAIN, jamais declare : troisieme
occurrence du jour d un etat qui ne survivrait pas a une reconstruction.

Trois defauts laisses ouverts : le cache apt attendu pendant l amorcage,
la regression D-85 sur /etc/cloud - qui a fait decrocher deux hotes de la
tache deposant icinga-ca.crt, rendant leurs sondes muettes en silence - et
auditd sans regles dans le gabarit.

Mesure finale : Icinga 93 OK sur 98, site 51/51, Prometheus 15/15,
prouver 64 OK, lint 0 defaut. Les quatre non-OK restants sont des
sauvegarde dont le minuteur nocturne n a pas encore visite une flotte nee
il y a deux heures.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-10 13:06:45 -04:00
36aba37200 wiki : les deux forges servent le meme wiki (origin rattrape)
CE QUE JE DISAIS ETAIT FAUX. « Il n y a rien sur origin » — le DEPOT y
est, et a jour, exactement notre HEAD. C est le WIKI qui etait vide. Je
l avais recopie d une session precedente sans le remesurer.

LA GARDE AVAIT RAISON DE REFUSER, ET TORT DE S ARRETER LA. wiki-publier
refuse un wiki vide parce que publier y inventerait un nom de branche.
Son message renvoyait a l interface Forgejo — injoignable depuis ce poste,
et ce n est pas une panne : la forge du site n accepte le 443 que des
machines qui declarent le flux.

Forgejo DECLARE pourtant la reponse : wiki_branch, dans son API. Interroge
depuis ops-01 — machine qui a le flux — il repond main. On ne devinait
pas : on ne demandait pas. WIKI_BRANCHE= ajoute a la recette, le refus
reste le defaut. Les deux cotes eprouves.

Resultat : 26 pages sur les deux forges, contenu identique au fichier pres.

LECON D INSTRUMENT. Trois sondes fausses avant la bonne : connect() direct
rend TimeoutError (politique, pas route manquante) ; un tunnel par la
frontiere ne repondait pas ; et git ls-remote fonctionnait tres bien, parce
que ~/.ssh/config passe par un ProxyJump que la sonde ignorait.

make prouver : CONFORME, 62 OK, 0 echec, 1 saute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-09 13:50:06 -04:00
0eaceb1048 schema du plan : la forme des registres devient derivee, et gardee
Etape 2 du chantier « l UI reflete fidelement la structure ». Le GUI porte
CHAMPS_ECRITS_PAR_GUI, une liste tenue A LA MAIN de ce qu il sait ecrire, que
P19 confronte au reel. C est une copie — gardee, donc honnete, mais une copie :
quelqu un doit penser a l allonger.

`make schema` produit docs/audit/schema-plan.json : six registres, 42 champs,
leurs types, leurs enumerations et ce qui est requis.

CE QUE LE SCHEMA EST, ET CE QU IL N EST PAS

  schema       -> la FORME      -> generera les champs du formulaire
  validateurs  -> la COHERENCE  -> refusent une saisie incoherente

Un JSON Schema ne sait pas dire qu un `consommateur` designe une application
inexistante, ni qu une integration universelle recopiee au plan est un defaut.
Vouloir l y mettre creerait la seconde source de verite que tout ce depot
refuse. Les valider_* restent l autorite.

LES ENUMERATIONS SONT IMPORTEES, JAMAIS RECOPIEES

ETATS_SERVEUR, PORTEES_BD et AUTORITES_DNS viennent des constantes que les
validateurs appliquent. Une enumeration recopiee diverge — c est la lecon des
neuf resolutions d instance que P41 garde depuis.

CE QUE L ETAPE 1 AVAIT TROUVE, ET QUE P61 A CONFIRME

Le recensement montrait `categorie` et `service` presents dans TOUS les plans et
absents de CHAMPS_ECRITS_PAR_GUI, dont la ligne `nomenclature` est vide : le GUI
ne sait pas les editer, l operateur doit ouvrir le YAML. P61 a refuse le premier
schema pour cette raison exacte. Les trois tables imbriquees de la nomenclature
sont donc DECRITES et non resumees en « object ».

31 champs observes dans l instance courante, 42 decrits par le schema. La
difference n est pas du bavardage : observer une instance n est pas un schema.
`noeud`, `stockage` et `coeurs` sont legitimes et simplement inutilises ici — un
schema derive de l observation les INTERDIRAIT.

P61, EPROUVEE DANS LES DEUX SENS

  fichier genere perime                -> REFUSE
  champ du plan absent du schema       -> REFUSE
  champ decrit mais inutilise au plan  -> COMPTE, pas refuse

Le troisieme point est delibere : refuser obligerait a retirer du schema un
champ valide des que plus personne ne s en sert. Meme mesure que les lacunes
nommees de P29.

UN DEFAUT DE MON INSTRUMENT, PAYE EN ROUTE

P61 comparait des noms a plat quand couverture_gui aplatit les tables
imbriquees : elle criait sur un schema correct. L instrument mesurait autre
chose que la cible. On aplatit desormais des deux cotes.

make prouver : CONFORME, 60 OK, 0 echec, 1 saute.

Prochaine etape : generer les formulaires depuis ce schema, et retirer
CHAMPS_ECRITS_PAR_GUI.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-08 15:19:20 -04:00
cbdc6c523d wiki-publier : un wiki vide se clone tres bien, et le garde-fou ne le voyait pas
Some checks are pending
verifier / verifier (push) Waiting to run
En rattrapant origin, sa forge s est revelee porter un wiki VIDE — jamais
publie. Avant de viser la forge, la manoeuvre a ete eprouvee contre un depot
bare local, comme la premiere fois.

LE DEFAUT

Le garde-fou ne testait que l ECHEC du clone, alors que son message parle du cas
vide : « le wiki doit exister (creer une 1re page dans Forgejo) ». Or un depot
vide se clone parfaitement. La recette allait donc au bout et creait une branche
`master` — parce que init.defaultBranch vaut master sur ce poste — alors que le
wiki deja en service vit sur `main`.

Le nom de branche etait DEVINE, et il divergeait d une forge a l autre. Un wiki
publie sur la mauvaise branche est un wiki que Forgejo peut ne pas afficher :
la publication reussit, la page reste introuvable, et rien ne l explique.

LE CORRECTIF

Refuser un wiki sans commit, plutot que de choisir a la place de Forgejo. Creer
une premiere page dans son interface initialise le wiki avec LA branche qu il
attend — il n y a plus rien a deviner.

EPROUVE DANS LES DEUX SENS

  depot bare vide      -> REFUSE, avec le geste a faire
  depot bare non vide  -> publie
  forge eregion reelle -> « deja a jour », temoin depose

Le troisieme essai compte autant que le premier : remplacer un defaut par un
blocage aurait ete un autre defaut.

CE QUE CA LAISSE OUVERT

Le wiki d origin reste vide : l initialiser demande une action humaine dans
l interface de la forge, que cette cible refuse desormais de contourner.

Et le temoin ne nomme qu UNE forge. P60 prouve que le depot n a pas bouge depuis
la derniere publication — pas que toutes les forges sont a jour. Tant qu il n y
en a qu une de publiee, la distinction ne coute rien ; a deux, il faudra que le
temoin porte une liste.

make prouver : CONFORME, 59 OK, 0 echec, 1 saute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-08 12:56:21 -04:00
e2935edd3d wiki : publie, et le temoin le prouve — P60 passe au vert
Some checks are pending
verifier / verifier (push) Waiting to run
La forge servait le wiki du 2026-08-10 : deux unites jamais publiees, vingt et
une differentes. Toute la revision de documentation n existait pas pour qui lit
la forge plutot que le depot.

Publie. Verifie en reclonant : 26 pages sur 26, aucune differente, aucune en
trop, 8 figures. La forge porte 4da68c7, source c9d31e9.

DEUX DEFAUTS DANS MON PROPRE AJOUT, PAYES A L EXECUTION

1. `@#` au milieu d un bloc shell continue. Le prefixe @ appartient a make, pas
   au shell : bash a cherche une commande nommee « @# ». La publication avait
   REUSSI, et le temoin n a pas ete ecrit — erreur 127 apres coup.

2. Plus grave, et invisible au premier essai : le temoin n etait ecrit que dans
   la branche « il y a des changements ». Or « deja a jour » est PRECISEMENT le
   cas ou il doit dire que la forge est au niveau du depot. Sans lui, P60
   restait rouge apres une publication reussie — une preuve qui refuse un etat
   sain, donc une preuve qu on apprend a ignorer.

   C est la seconde execution qui l a montre : elle est passee par cette branche
   justement parce que la premiere avait publie. Le defaut se corrigeait en se
   revelant.

Les deux tiennent dans la meme lecon : une garde qu on n a pas vue dire OUI ne
vaut pas mieux qu une garde qu on n a pas vue dire non.

make prouver : CONFORME, 59 OK, 0 echec, 1 saute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-08 12:49:40 -04:00
c9d31e9a60 preuves : trois gardes pour ce que ma lecture ne tiendra pas
Une revision de documentation vieillit comme le reste. Ce qui tient, c est ce
qu une machine verifie — et trois lacunes etaient nommees sans etre gardees.

P58  HABILITATIONS. autorisation.md posait la regle (un service nomme un
     GROUPE, jamais une personne, D-66) et meta/acces.yml la portait ; rien ne
     la verifiait. P29 gardait les POSITIONS d authentification, personne ne
     gardait les DROITS.

     Le controle qui porte la preuve est un croisement : une entree
     porte_par: role-realm affirme que l habilitation voyage par un role de
     realm projete depuis un groupe LDAP. P58 le confronte a serveur_keycloak.
     Sans ca, un service annonce une habilitation que rien ne transporte, et l
     ecran reste vide sans que personne sache pourquoi.

     CE QU ELLE N EXIGE PAS, et c est le point le plus important : que les
     groupes nommes existent dans l annuaire. Ce serait contredire le regime du
     paragraphe 2 — le depot AMORCE un acces et se retire, les appartenances
     appartiennent a une personne. dev et personnel n existent dans aucun code,
     et ce n est pas un defaut.

P59  ENUMERATIONS ANNONCEES. Les deux ecarts trouves a la main pendant la
     tournee — cinq portes annoncees devant une table de six, huit lignes
     renvoyees vers une fiche qui en compte dix — etaient d une forme que P57
     ne voit pas.

     Ma premiere version a signale CINQ ecarts, et les cinq etaient du bruit :
     dans « reprise dans les deux devis : », le nombre qualifie autre chose que
     la liste. Cent pour cent de faux positifs — la preuve qui crie sur un cas
     sain et qu on apprend a ignorer. Resserree aux deux formes ou le nombre ne
     peut compter rien d autre. Etroite et vraie plutot que large et devineuse.

P60  WIKI PUBLIE. Le wiki est publie DEPUIS le depot ; rien ne mesurait l ecart,
     et il s est creuse de VINGT-SEPT JOURS en silence. Deux unites jamais
     publiees, vingt et une differentes : pour qui lit la forge plutot que le
     depot, toute la revision n existait pas.

     Le harnais est STATIQUE, zero appel reseau — cloner la forge romprait la
     seule propriete qui fasse qu une preuve vaille hors de ce poste. La mesure
     passe donc par un TEMOIN que make wiki-publier depose. Amorce avec la
     valeur MESUREE : le wiki d eregion porte b6167f2, dont le message dit
     source: ac85278.

     Ce qu elle ne prouve pas : un temoin dit ce qui est PARTI, jamais ce qui
     est ARRIVE.

LES TROIS SONT EPROUVEES DANS LES DEUX SENS

Douze essais negatifs, douze refus : groupe non projete, acces.yml disparu,
personne au lieu d un groupe, mecanisme invente, raison manquante, compte
revenu a cinq, septieme porte ajoutee sans toucher au compte, renvoi croise
fausse, temoin absent, temoin d un autre depot. Une garantie qu on n a jamais vu
dire non n est pas une garantie, c est une habitude.

ETAT : NON CONFORME, 58 OK, 1 echec, 1 saute.

P60 est rouge, et c est le comportement voulu : le registre a le droit de
perdre. Le retard qu elle signale est reel et anterieur a elle. Une commande le
ferme, et elle vient ensuite.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-08 12:47:18 -04:00
5bc3bceac1 documentation : la tournee des 74 documents, parce qu un balayage ne lit pas
Some checks failed
verifier / verifier (push) Has been cancelled
La revision a commence par un balayage par motifs — chemins morts, cibles make
absentes, comptes derives. Il a trouve une trentaine d ecarts et rate presque
tout le reste : un motif ne voit que ce qui s exprime en motif.

make hote-planifier en est l exemple. La cible EXISTE, donc le controle passait
au vert. C est une cible depreciee qui refuse et sort en 2, recommandee par
AGENTS.md, et qui contredit la REGLE D OR du meme fichier trois ecrans plus
haut. Il fallait lire pour la voir.

74 documents lus un par un. 66 corriges, 8 exacts.

CE QUI ETAIT FRANCHEMENT FAUX

AGENTS.md, la source d autorite, annoncait la flotte pas encore executee contre
des VM reelles. Elle a ete rasee et remontee depuis zero trois fois.
ecosysteme-chezlepro.md, le document montre a un client, portait la meme
phrase : il se sous-vendait gravement.

courriel-conception.md s ouvrait sur aucun role n est encore ecrit, au-dessus de
son propre paragraphe 1 qui les nomme. autorisation.md se terminait sur rien n
est construit alors qu il rapporte des mesures datees du role en fonctionnement.
hebergeur-exploitation.md disait rien n est fait d un depot qui existe.
filiation-emancipation.md se contredisait a deux ecrans de distance.

DES MODELES DECRITS D APRES UN MONDE ANTERIEUR

Le resolveur : cinq documents decrivaient un Unbound par VM en opt-in, trois le
donnaient en exemple d integration FACULTATIVE — il est universel depuis le
2026-08-24. L adressage de nomenclature-vm.md : reseau unique, VLAN 11-15, VMID
a cinq chiffres. Le nommage SDN de sdn-evpn.md contre le code : c est le wiki
qui avait raison.

CE QUI CASSE AU PREMIER ESSAI

Le nom du gabarit dore etait faux a quatre endroits, dont la procedure qui le
FABRIQUE et le critere R2 de l epreuve d operateur independant.
preparer-un-site-hebergeur.md avertissait qu une VM faite a la main serait
detruite : raser derive du plan, il ne la detruira jamais — le risque est l
inverse. Un mot de passe d essai en clair dans un depot public.

DEUX PREUVES ETENDUES, ET UNE QUI SE TROMPAIT ELLE-MEME

P57 couvre les groupes : elle a signale aussitot 29 groupes annonces au-dessus d
un tableau qui en cite 40. P29 confronte le tableau de authentification.md aux
declarations reelles : 12 annonces, 21 reels.

Et P57 imposait un chiffre faux — 56 preuves alors que le depot en porte 57, la
conditionnelle vivant hors de tout comptage. Un garde-fou qui fait respecter une
erreur ajoute l assurance a l erreur.

CE QUI RESTE, ET QU AUCUNE PREUVE NE TIENT

Deux comptes trouves a la main. Et une lacune reelle : rien ne garde les
meta/acces.yml — ni qu un service web-sso en porte un, ni que le groupe qu il
nomme existe. P29 tient les positions d authentification, personne ne tient les
habilitations.

make prouver : CONFORME, 56 OK, 0 echec, 1 saute. 0 lien mort.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-06 16:18:23 -04:00
00cee67f02 depot hors site : trois pieges payes en une manoeuvre
Some checks are pending
verifier / verifier (push) Waiting to run
1. ansible -e cle=valeur DECOUPE SUR LES BLANCS — c est ainsi qu on passe
   plusieurs variables. Un chemin avec une espace y perd tout ce qui suit le
   premier blanc, et l erreur parle d un repertoire introuvable au nom tronque.
   Passage en JSON. Le depot avait deja appris ca pour le clonage de VM ; la
   lecon ne s etait pas propagee. Quatrieme fois.

2. /srv/restic est en 0711 — traversable, NON listable, pour qu un locataire
   n apprenne pas qui d autre depose ici. La consequence tombe sur rsync :
   opendir Permission denied, un message qui accuse un droit sans dire lequel.
   --rsync-path=sudo rsync fait lire la SOURCE en root.

3. rsync_opts ne protege pas ses elements : le shell coupait
   --rsync-path=sudo rsync en deux. Guillemets internes.

Resultat mesure : COPIE FIDELE, 233 fichiers, 95,7 Mo, empreintes identiques
une a une — comparees entre la source et la copie, pas supposees.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-05 16:33:26 -04:00
9a823a5ea2 depot hors site : sortir du site ce que le site garde pour tout le monde
Some checks are pending
verifier / verifier (push) Waiting to run
Le depot heberge la racine de l AC, la forge du genome, et l etat de CHAQUE
locataire — 109 Mo sur une seule machine, dans un seul batiment. C est le
probleme du filet range dans la flotte qu il protege, un etage plus haut.

On emporte AUSSI les depots des locataires : si le site brule, ils perdent
leurs sauvegardes avec lui, et eux ne peuvent rien y faire. Ils ont depose chez
l hebergeur, c est a l hebergeur de tenir cette promesse.

La copie est OPAQUE — chiffree cote client, illisible par qui la porte. C est
ce qui permet de la deposer chez un pair sans lui demander autre chose que de
la disponibilite.

L empreinte est prise A LA SOURCE avant la copie, puis recalculee sur la copie
et comparee une a une. Sans ca on rentre chez soi avec un repertoire.

Un pipe sans pipefail masque l echec de tout ce qui n est pas le dernier
maillon : ici sed, qui reussit toujours. Une empreinte vide des deux cotes
aurait passe la comparaison.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-05 14:20:19 -04:00
dcbb57db69 cles : la cle USB se suffit a elle-meme, et la restauration est prouvee
Some checks are pending
verifier / verifier (push) Waiting to run
Le jour ou l on s en sert, le poste est mort — et cloner le depot demande la cle
SSH qui est dans l archive qu on essaie d ouvrir. Une procedure rangee dans le
depot serait inaccessible exactement quand elle sert.

L export depose donc restaurer_cles.py et un LISEZ-MOI a cote de l archive. La
cle ne demande plus que gpg, python3 et la phrase de passe.

Le script remet chaque fichier a sa place selon son NOM (machine neuve, parfois
autre compte), repose les droits a 0600 — ssh refuse une cle privee lisible par
d autres, et son message ne dit pas qu il s agit d un droit — et refuse d
ecraser une cle presente, en regardant AVANT d ecrire.

Le LISEZ-MOI porte les trois commandes manuelles. Un outil peut avoir un defaut ;
gpg et tar seront la.

EPROUVE : export vers une cle, poste neuf vide, restauration depuis la cle SEULE,
empreintes comparees — identiques 4 sur 4, droits 700/600, et le refus d ecraser
tire. Le filet manuel passe au meme test separement, identiques 4 sur 4.

make cles-restaurer refusera puisque les cles sont en place — et ce refus est la
preuve que l archive s ouvre et que la phrase de passe est la bonne.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-05 13:33:31 -04:00
bebdb84212 cles : sortir du poste ce qui n existe qu au poste
Some checks are pending
verifier / verifier (push) Waiting to run
Le code est replique trois fois (eregion, forge du site, patient 0) et les
voutes chiffrees y sont aussi — le coffre est solide. Les CLES qui l ouvrent
vivaient dans neuf fichiers, 1644 octets, sans copie ailleurs.

Poste seul : les mots de passe restic restent lisibles sur les machines vivantes,
donc recuperable mais douloureux. Poste + une machine : l etat de cette machine
devient illisible. Poste + site : terminal.

make cles-recenser montre ce qui sortirait sans rien ecrire — nom, taille,
empreinte, JAMAIS le contenu. make cles-exporter chiffre en AES256 puis
REDECHIFFRE ce qu il vient d ecrire et compare les empreintes une a une : une
sauvegarde de cles qu on n a pas rouverte n est pas une sauvegarde.

A lancer par l exploitant lui-meme : gpg demande une phrase de passe, elle ne
doit passer ni par un journal ni par le contexte d un assistant.

Trois refus, eprouves en les faisant echouer : destination dans l infrastructure
(un coffre dont la cle est dedans), archive existante (elle est peut-etre la
seule), archive illisible (supprimee). Le premier essai du premier refus etait
faux — le shell developpait HOME avant que je le remplace, l instrument mesurait
ailleurs que la cible.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-05 09:42:01 -04:00
42becd0c02 paquets tiers : passer par le cache du controleur, plus par Internet
Some checks are pending
verifier / verifier (push) Waiting to run
Trois depots tiers etaient en HTTPS, et client_artefacts pose
Acquire::https::Proxy DIRECT — sans quoi le cache du site refuse les tunnels et
aucun depot tiers n est joignable. La ligne est juste ; sa consequence ne l avait
pas ete vue : ces trois depots CONTOURNENT le cache, et chaque VM neuve allait
les chercher sur Internet a sa naissance.

step-cli et alloy sont poses par des integrations UNIVERSELLES. Sans lien, une
machine neuve n obtenait ni son client d autorite ni ses metriques — elle n
entrait dans aucun flux chiffre. Dernier obstacle a une reconstruction hors
ligne, et il tenait dans un mot.

make cacher-paquets tire les 21 deb aux versions epinglees, empreinte SHA256
verifiee depuis l index du depot. Le role partage paquets_tiers les depose et les
installe EN UN SEUL appel a apt — il sait resoudre un ensemble de fichiers locaux
qui se dependent, la ou paquet par paquet echouerait sur l ordre (Icinga en
apporte dix-sept). Six roles branches ; chacun retombe sur le depot distant pour
ce que le cache n a PAS fourni, et rien d autre.

Eprouve pour de vrai : packages.smallstep.com renvoye vers 127.0.0.1, step-cli
desinstalle, cache local efface. Le role rejoue installe 0.30.6-1 depuis le cache
et la machine obtient ses certificats. Zero echec.

Deux defauts de mon propre outil, trouves en le construisant : Smallstep sert son
index NON COMPRESSE (404 sur .gz) donc step-cli n etait jamais mis en cache ; et
un depot injoignable faisait continue AVANT d incrementer le total, si bien que
le script rapportait 20 sur 20 alors qu il en manquait un. Une garde qui ne peut
pas echouer ne garde rien — troisieme fois cette semaine. Corrige puis eprouve en
le faisant echouer.

Reste hors ligne : NTP externe, et l expedition des alertes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-05 08:22:14 -04:00
53c5f41a1a durcissement : le site recoit enfin serveur_durci
Some checks are pending
verifier / verifier (push) Waiting to run
Les six machines du SITE — racine de l AC, forge, cache, resolveur, depot de
sauvegarde, runner — ne recevaient que serveur_debian. Ni auditd, ni fail2ban,
ni apparmor, ni sysctl, ni pare-feu. Le commentaire au-dessus de GROUPE_SOCLE
affirmait pourtant le contraire, ce qui rendait l ecart invisible.

Le pare-feu du site n avait aucune des trois pieces qui le rendent applicable :
- aucune regle generee (resoudre_flux lit un hosts.yml ; le site a un inventaire
  dynamique) -> commande nftables-site, branchee sur make flux
- le chemin du jeu de regles sortait du depot (inventory_dir vaut scripts/ pour
  un inventaire dynamique) -> host_var explicite
- aucun nftables_admin_ssh : l exploitant administre PAR REBOND, la connexion
  arrive avec l adresse de la patte de frontiere DANS LA ZONE VISEE. Le
  generateur refuse desormais de produire des regles sans cet intrant.

Defaut attrape en LISANT le jeu de regles avant de l appliquer : la regle DNS de
site-dns-01 omettait 10.17.0.0/16. _supernets_voisins retire l instance montee —
juste chez un tenant, faux du cote du site, ou ca retire le locataire qu on
pilote. L appliquer aurait prive de DNS les quinze machines reconstruites la
veille.

MaxStartups du depot passe en host_var : dans le meta du role, il ne portait que
dans son play, et le passage de serveur_durci le remettait au defaut sans rien
dire. Un reglage qui depend de l ordre des plays revient en arriere.

Verifie depuis un locataire a travers le nouveau pare-feu : cache, forge, depot
(2 snapshots) et resolveur repondent ; l AC du site refuse, et c est correct.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-02 10:31:21 -04:00
4abf875e5f gabarit : q35 n est pas un reglage, c est la raison de la procedure manuelle
Some checks are pending
verifier / verifier (push) Waiting to run
CONSTAT DE L EXPLOITANT, PAYE EN ANOMALIES : convertir une machine deja installee
d `i440fx` a `q35` produit une serie de pannes dont chacune ressemble a autre chose
qu a sa cause. Ce n est pas une correction, c est une transplantation.

LE MECANISME, ECRIT POUR QU ON NE LE REDECOUVRE PAS : `i440fx` est un chipset PCI,
`q35` est PCIe. La topologie des bus change, donc les NOMS D INTERFACES
PREDICTIBLES changent avec le chemin PCI (enp0s3 -> enp1s0) et la machine perd le
reseau ; les chemins de disques bougent ; l ordre d enumeration suit.

C EST AUSSI POURQUOI SET-OPS N UTILISE PAS L IMAGE CLOUD OFFICIELLE DE DEBIAN :
`genericcloud` est livree configuree pour `i440fx`. Une machine nait `q35`, ou elle
ne le sera jamais proprement — et c est ce que l installation depuis l ISO garantit.

Ces deux lignes de la procedure n etaient qu une ligne de tableau. Elles portent
maintenant leur pourquoi, et le SITE les declare comme DONNEES (cle `gabarit`),
plus seulement comme prose.

`make gabarit-etat` compare le gabarit reel a ce que le site declare de lui.

ON VERIFIE LA SOURCE, PAS CHAQUE COPIE. Ma premiere version gardait le CLONAGE : la
propriete s herite, donc verifier chaque clone coute a chaque creation sans rien
dire de plus que verifier le gabarit une fois. Retiree.

TROIS FOIS J AI DEVINE LA FORME DE LA REPONSE AU LIEU DE LA REGARDER — regex_search
a groupe qui rend None, proxmox_vm_info sans `config: current` qui ne rend que
l etat. La garde a declare « ? » sur une VM parfaitement conforme : une garde qui
crie toujours est pire qu aucune, on apprend a l ignorer.

A la demande et non dans `make prouver` : ce controle exige le cluster, que le
harnais ne suppose pas joignable. Meme nature que genome-etat et underlay-plan.
Controle negatif verifie : declarer i440fx fait echouer, rc=1.

make verifier : vert. make prouver : CONFORME, 56 OK, 0 echec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-01 14:42:58 -04:00
9aef3614ab gabarit : refabrique, minimal, et puise aux ressources du SITE
Some checks are pending
verifier / verifier (push) Waiting to run
REFABRIQUE (VMID 9006, modeleSetOPS-minimal). Quatre roles au lieu de dix-sept :
qemu_guest_agent, cloud_init, sudo_ansible, ssh_baseline — des conditions
d existence, pas des choix d efficacite. Tout le reste vient du socle, et P56 refuse
qu un role retire ne soit repris par personne.

FABRIQUE CHEZ LE SITE, ET C EST LA DECISION QUI COMPTE. « Les ressources du SITE
font autorite pour tous ses artefacts ; elles servent les tenants jusqu a ce qu ils
s emancipent. »

Il se fabriquait DEHORS : `-i "<ip>,"` ne porte aucun group_vars, donc ni mandataire
ni resolveur. L ancien gabarit allait chercher ses paquets chez Debian et resolvait
chez l ancien LAN — 192.168.10.10, lu sur la VM 99998. Le site avait son cache et
son resolveur, et son propre artefact les ignorait.

Desormais la fabrication DERIVE ses ressources du plan du site (underlay --adresses)
et tourne sur le reseau du genome. PROUVE : dix requetes de 10.0.33.31 servies par
site-cache-01, resolveur pose a 10.0.34.11.

L IDENTITE DU GABARIT VIENT DU SITE, PLUS DU TENANT. `proxmox_clone_vmid_modele`
vivait dans les group_vars de l ecosysteme : deux tenants pouvaient cloner deux
gabarits differents sans que rien ne le dise, et un tenant decidait d un objet dont
descend chaque VM de chaque ecosysteme. Meme mouvement que l INDEX (2026-08-25) : le
site ALLOUE, le tenant RECOIT. Cle `gabarit` du plan du site, lue par
underlay --gabarit.

PIEGE FERME EN CHEMIN : creer-vm passait VMID_MODELE="$SETOPS_VMID_MODELE" a
cloner-vm, or inventory_host.py n emet PAS cette variable. Elle valait donc le VIDE,
et ce vide ECRASAIT la valeur derivee — le gabarit du tenant reprenait la main sans
bruit.

ET UN PIEGE DEJA DOCUMENTE, PAYE UNE TROISIEME FOIS : le chemin du controleur
contient une espace, et `lookup('pipe', ...)` le decoupait. Guillemets.

EPROUVE DE BOUT EN BOUT : VM clonee du gabarit minimal — nom, adresse, machine-id
neuf, cle d hote regeneree, agent invite actif ; puis socle applique dessus,
changed=5, 0 echec, auditd compris. VM d essai retiree.

make verifier : vert. make prouver : CONFORME, 56 OK, 0 echec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-01 13:46:31 -04:00
0b653170fa emancipation : l instrument de la quatrieme ligne — couper, pas sonder
Some checks are pending
verifier / verifier (push) Waiting to run
docs/filiation-emancipation.md decrit quatre temps et n en outillait que trois. Le
quatrieme est celui qu on oublie : « une emancipation non prouvee est une
emancipation non faite ».

SONDER NE PROUVE RIEN. Verifier que le service local repond ne dit pas si l amont
sert encore — le depot le disait deja du cache : « tant qu internet repond, un apt
update qui reussit ne dit pas d ou vient l octet ». L instrument COUPE donc l amont
et refait marcher la chose.

LE MEME ESSAI REND LES DEUX VERDICTS, et c est ce qui le rend honnete :

    coupe, la fonction marche  ->  EMANCIPE, et c est prouve
    coupe, la fonction casse   ->  PAS EMANCIPE, dependance prouvee REELLE

Le second n est pas un echec de l outil, c est son CONTROLE NEGATIF rendu par la
meme commande. Une preuve d emancipation incapable de montrer la dependance qu elle
mesure ne prouverait rien le jour ou elle passerait au vert.

UN TEMOIN PRECEDE LA COUPURE : la fonction marchait-elle seulement avant ? Sans lui,
une panne preexistante se lirait comme une dependance.

LA COUPURE EST GARANTIE REVERSIBLE : une TABLE nftables dediee, jamais une regle
glissee dans une table existante — elle se retire d un geste et ne peut pas laisser
d etat partiel. Le bloc `always` la retire meme si la mesure echoue ou si le play
est interrompu, et une tache verifie ensuite qu elle a bien disparu.

MESURE LE JOUR DE SA NAISSANCE, les deux verdicts sur du vrai materiel :
  obs-01 / resolveur   PAS EMANCIPE — plus aucune resolution des la coupure
  forge-01 / artefacts EMANCIPE — apt installe, cache du site coupe

Ce second verdict a ete DOUTE puis verifie : apt aurait pu reussir en rejouant des
listes fraiches. Refait avec un dossier de listes NEUF, amont coupe : reussit
quand meme. Le cache sert vraiment son contenu.

make verifier : vert. make prouver : CONFORME, 55 OK, 0 echec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-09-01 08:36:28 -04:00
90ea474745 inseminer : le geste sort de mes mains et entre dans le depot
Some checks failed
verifier / verifier (push) Has been cancelled
L insemination avait ete conduite A LA MAIN depuis le runner du site — hors du
depot, donc sans preuve. Elle a maintenant sa cible :

    make inseminer TENANT=OPS-Chezlepro

TENANT= PLUTOT QUE LE SYMLINK instance : le runner du SITE amorce PLUSIEURS
locataires ; pointer un lien global sur l un d eux le ferait se prendre pour ce
tenant. Il en NOMME un par commande. Ca borne aussi le couplage que creer-vm
imposait en silence — rien ne disait sur quels tenants ce lien pouvait pointer.

L HOTE SE DERIVE : celui qui porte serveur_ops_tenant. Meme critere que le flux
d insemination et que la cle SSH du runner — le meme mot borne les trois pouvoirs.

P54 GARDE LA LIGNE DE PARTAGE la ou elle glisserait sans bruit. Les deux couches
retenues sont les seules qui ne reclament aucun secret. Le jour ou l on en
ajouterait une, le deploiement echouerait chez le tenant sur une valeur vide, et ce
message ne dirait pas qu un POUVOIR a ete franchi. Controle negatif : ajouter
client_pki, la couche suivante, fait echouer la preuve.

UN GARDE-FOU EXISTANT A INTERCEPTE UNE INSEMINATION MAL DIRIGEE. Le make parent
exporte SETOPS_INVENTAIRE ; ma resolution en heritait et visait l inventaire d un
AUTRE ecosysteme. Le refus vient d inventory_rules, pas de la cible — exactement
l erreur qu un runner servant plusieurs locataires commettrait en silence.

make verifier : vert. make prouver : CONFORME, 54 OK, 0 echec, 0 saute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-08-28 17:14:37 -04:00
0595bf03c1 sonder : rapporter ce qui distingue, au lieu d un echec
Some checks are pending
verifier / verifier (push) Waiting to run
Trois faux diagnostics en une journee, tous dus a l instrument et aucun au
composant. curl et bash /dev/tcp ecrasent quatre causes incompatibles dans le meme
mot : ouvert, une POLITIQUE qui refuse, une machine ABSENTE, et la frontiere muette.

LE MEME CODE DIT DEUX CHOSES SELON LE DELAI, et c est la distinction qui a coute le
plus cher : EHOSTUNREACH immediat = pas de route ; le meme apres trois secondes =
il n y a pas de machine, c est l ARP qui renonce. Les confondre a fait appliquer un
pare-feu pour reparer un vide.  est pure, donc gardee par un test qui
exige que les deux ne se lisent jamais pareil.

LA GARDE ECHOUAIT DU COTE SILENCIEUX. L outil dit par quelle SOURCE le paquet part
et refuse de conclure sur une passerelle anycast — le piege qui m a fait declarer
muet un REJECT qui emettait bien ses RST. Ma premiere version rendait « pas
anycast » quand inventory_rules manquait, c est-a-dire sur un hyperviseur ou l on a
copie le seul fichier : precisement la ou le piege se produit. Une garde qui echoue
doit crier, pas se taire.

ET « NON CONCLUANT » EST UN RESULTAT : sur une source anycast et un silence, l outil
ne tranche pas, il dit quoi faire — compter les paquets du cote qui refuse, ou
sonder depuis une VM.

TCP seulement, et c est dit : UDP n a pas de poignee.

Valide contre le reel depuis ops-01 : trois cas sur quatre, le quatrieme attendant
deux machines vivantes dans un meme tenant.

make verifier : vert. make prouver : CONFORME, 53 OK, 0 echec, 0 saute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-08-28 17:02:20 -04:00
377462b141 voutes : une voute, une cle — separer avant de distribuer
Decision de l'exploitant : chaque runner est maitre de sa voute et en detient la
cle. C'est ce qui rend un runner autonome, donc ce qui rend l'emancipation
atteignable. Elle exigeait un prealable, mesure ce matin : UN SEUL mot de passe
ouvrait les SIX voutes de la flotte, celle de la fabric comprise.

DISTRIBUER AVANT DE SEPARER AURAIT ETE PIRE QUE LE STATU QUO : poser « la » cle
sur chaque runner rendait chaque runner capable d'ouvrir les autres. Compromettre
le plus petit locataire donnait les secrets de l'hebergeur.

Cinq cles, une par ecosysteme, sous ~/.config/setops-vault-<depot>. Verification
croisee apres rechiffrement : la diagonale, et rien qu'elle. L'ancienne cle
maitresse n'ouvre plus aucune des six.

UN SEUL MOT DE PASSE NE POUVAIT PLUS SUFFIRE, et pas pour la raison qu'on croit :
`cloner_vm_debian.yml` charge la voute du TENANT puis celle de l'UNDERLAY dans la
meme execution. `ANSIBLE_VAULT_IDENTITY_LIST` en porte plusieurs et les essaie
toutes — un seul export suffit pour les 28 appels a ansible-playbook, sans en
toucher un seul. La liste se derive dans scripts/voutes.py.

CE QUI BORNE LE POUVOIR N'EST PAS LA LISTE MAIS LA PRESENCE DES FICHIERS. Sur le
poste, toutes les cles sont la — c'est l'humain qui les detient toutes, et P03 lit
les inventaires de tous les freres. Sur un runner, une seule existe. Le code est
identique, le pouvoir ne l'est pas.

DEUX PREUVES ONT DIT CE QUI MANQUAIT. P03 est tombee des la separation : elle lit
les inventaires voisins, donc il lui faut leurs cles — c'est elle qui a etabli que
la liste devait couvrir le voisinage. P16 s'est mise a SAUTER : sa garde ne
connaissait que ANSIBLE_VAULT_PASSWORD_FILE. Une preuve sautee se lit trop
facilement comme une preuve passee.

COUT ASSUME : le chiffre et sa cle cohabiteront sur la meme machine des que les
runners recevront la leur. Le pari tient parce que le perimetre est borne.

Les six voutes sauvegardees avant rechiffrement. L'ancienne cle maitresse reste
sur le poste : la retirer est une decision, pas un nettoyage.

make verifier : vert. make prouver : CONFORME, 52 OK, 0 echec, 0 saute — sans
ANSIBLE_VAULT_PASSWORD_FILE.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-08-28 14:23:33 -04:00
ef832d11d6 insemination : la cle d'amorcage, bornee au meme groupe que le flux
Le flux etait declare et applique ; il manquait l'IDENTITE. Le runner du SITE
atteignait la porte de ops-01 sans avoir de cle.

LE PIEGE COMPTE PLUS QUE LE CORRECTIF. La cle s'injecte au CLONAGE, et `creer-vm`
cree TOUTES les machines d'un tenant. L'injecter a chaque clonage aurait donne a
l'hebergeur un acces SSH a la flotte entiere de chaque locataire, en silence — ca
aurait defait a la couche IDENTITE ce que le pare-feu venait de borner a la couche
RESEAU. Le meme critere gouverne donc les deux : porter `serveur_ops_tenant`.
`SETOPS_CLES_AMORCAGE` est vide partout ailleurs. Elle S'AJOUTE a celle de
l'exploitant, elle ne la remplace pas : c'est l'humain qui arme.

La cle vient du PLAN DU SITE, pas du disque local : materialiser depuis le poste
et depuis le runner doit produire la meme VM.

DEUX COUCHES MANGEAIENT LES ESPACES. Proxmox rendait `SSH public key validation
error` — message muet sur la cause. Isole par un CONTROLE (rejouer sans la cle :
la tache passe), puis par la mesure de ce qui arrivait au module :

    "sshkeys": "ssh-ed25519"     <- le premier mot, rien d'autre

J'ai accuse `make` d'abord ; c'etait `ansible-playbook -e cle=valeur`, qui decoupe
AU SHLEX. D'ou l'environnement pour le transport et `-e '{...}'` en JSON pour
l'entree. (Un scalaire YAML plie ne produit pas non plus de saut de ligne.)

TROIS TESTS QUI NE GARDAIENT RIEN. `test_inventory_host` inscrit ses tests dans une
liste explicite ; mes deux nouveaux n'y etaient pas — definis, jamais joues. La
garde d'exhaustivite ajoutee en a trouve un TROISIEME le jour meme,
`test_etiquette_vlan_repli_et_vide_explicite`, jamais inscrit depuis sa creation :
inscrit, il levait un KeyError sur une fixture qu'il lisait mal. Un test non
inscrit est pire qu'un test absent : on croit l'avoir.

PREUVE, AVEC SON CONTROLE NEGATIF :

    runner du SITE -> ops-01        ops-01  10.17.19.41/24   entre
    runner du SITE -> 10.17.19.21   Connection timed out     refuse

make verifier : vert. make prouver : CONFORME, 52 OK, 0 echec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-08-28 13:45:44 -04:00
6fe62f74e1 creer-vm : prouver la materialisation sans entrer chez le tenant
`creer-vm` confirmait son succes en attendant une reponse SSH. Le runner du SITE
materialise le terrain de TOUS les tenants, mais la frontiere lui refuse d'entrer
chez eux — c'est le sens meme de leur isolation. La premiere VM qu'il a creee a
donc ete declaree en echec apres 600 secondes alors qu'elle tournait, avec
l'adresse exacte que le plan lui destinait :

    Attente de SSH sur ops-01 ............ ECHEC: injoignable apres 600s.

LA TENTATION ETAIT D'OUVRIR LE SSH du runner vers tous les tenants. Ca aurait
repare la mesure en detruisant ce qu'elle protege : une machine capable d'entrer
chez chaque locataire est precisement ce que cette architecture refuse d'avoir.

L'agent invite repond sans rien ouvrir — l'API des hyperviseurs est deja le flux
par lequel la VM vient d'etre creee, donc qui peut la creer peut la voir naitre —
et il PROUVE DAVANTAGE. « Quelque chose ecoute sur le port 22 » ne dit ni quel
systeme a demarre, ni si cloud-init a pose la bonne adresse. Sur ops-01 :

    10.17.19.41 portee sur asgard — Debian GNU/Linux 13 (trixie) 6.12.101

Ses echecs distinguent deux causes tres differentes : « la machine demarre mais
rapporte une AUTRE adresse — cloud-init, ou le pont sur lequel elle est posee »,
et « introuvable sur la fabric ».

ATTENDRE LA DISPONIBILITE A CHANGE DE MAIN. Guetter cloud-init et la liberation de
dpkg appartient a qui va CONFIGURER : `deployer` le fait desormais, la ou il se
contentait d'un `ping` unique. Il y gagne ce qu'il n'avait pas — attendre le verrou
APT, faute de quoi la premiere couche echouait dessus. Contrepartie assumee : un
nom d'hote errone patiente au lieu d'echouer vite ; echouer vite interdirait de
chainer creation et deploiement, le geste central d'une reconstruction.

P52 garde le couplage ferme. Deux controles negatifs verifies.

make prouver : CONFORME, 52 OK, 0 echec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 22:48:49 -04:00
87716cefc7 genome : la forge du SITE fait autorite (D-81), et make genome-etat le verifie
Some checks are pending
verifier / verifier (push) Waiting to run
Decision de l'exploitant : la forge du SITE fait autorite pour le genome. Toute
autre copie — y compris celle d'ou le moteur a ete pousse jusqu'ici — est un
MIROIR.

Un ecosysteme se reproduit depuis la forge de son site : c'est de la qu'il clone
son moteur, ses plans, ses modeles. Si l'autorite est ailleurs, cette forge
devient un cache qu'on croit a jour — et le 2026-08-26 elle etait quatre commits
en arriere sans que rien ne le signale, dont le correctif qui desarme le pare-feu
Proxmox.

UNE AUTORITE QU'ON NE VERIFIE PAS EST UNE AUTORITE QU'ON SUPPOSE.

`make genome-etat` confronte, depot par depot, ce que le poste porte a ce que la
forge porte. Il REFUSE en cas d'ecart plutot que de le signaler : un ecart connu
et tolere redevient un ecart oublie, et la commande qui le corrige tient en trois
mots. Il dit aussi quand la copie locale n'est pas propre — des commits pas
encore faits sont une autre forme de retard.

Mesure au passage, et traitee plutot qu'ignoree : le premier contact avec la
forge echoue une fois sur six — poignee TLS expiree, puis cinq reponses de suite.
Ce n'est pas le chemin, qui est prouve ; c'est l'acceptation TLS apres un temps
d'inactivite. Les deux cibles reessaient.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 09:17:24 -04:00
6a5a49f924 site : le runner travaille, et le genome remonte chez lui
Some checks are pending
verifier / verifier (push) Waiting to run
`serveur_ops` et `serveur_ops_site` sont deployes sur `site-ops-01` : le moteur,
les plans des trois tenants, les collections hors ligne, et la voute de
l'underlay deposee CHIFFREE. Le site a son runner.

DEUX FORMES DE RUNNER, ET UNE SEULE ETAIT PREVUE.

`serveur_ops` exigeait un depot `role: instance` et un `serveur_ops_instance` —
la forme d'un runner de TENANT, qui pilote un ecosysteme, monte son plan par le
lien `instance`, detient sa voute.

Un runner de SITE ne pilote rien : il MATERIALISE le terrain que d'autres
occuperont, et son inventaire est dynamique. Son plan declarait donc ses depots
de tenants en `role: tenant`, a dessein et avec ses raisons ecrites — et le role
le refusait au nom d'une exigence qui ne le concernait pas. Il exige desormais
que le runner pilote QUELQUE CHOSE, sans prescrire quoi.

Et il posait le lien quand meme : `serveur_ops_instance: ""` donnait
`instance -> /opt/setops/`, un repertoire qui n'est l'ecosysteme de personne. Un
lien qui existe et ne designe rien est pire qu'un lien absent : tout ce qui le
suit croit avoir trouve une instance.

LE CERTIFICAT COUVRE LES NOMS DU SERVICE.

`client_pki` ne mettait dans ses SAN que le FQDN, le nom court et l'IP. Le
clonage du genome a bute dessus : « certificate subject name
(site-forge-01.genese.internal) does not match target hostname
'forge.genese.internal' ». Le nom declare `expose:` etait publie partout —
plancher, zone DNS — et couvert nulle part.

Les expositions que cet hote SERT REELLEMENT entrent maintenant dans le
certificat. Un certificat qui revendiquerait le nom d'un service rendu ailleurs
serait une usurpation, pas une commodite.

`make genome-pousser` — LE RUNNER POUSSE, LE POSTE NE ROUTE PAS.

La forge du genome vit DANS le site, sur un reseau que le poste de l'exploitant
ne route pas. On ne perce pas un chemin pour lui : on lui retire le role. Le
poste emballe les commits dans un `git bundle` — un fichier, verifiable, qui ne
demande aucun reseau — et le runner verifie, avance EN AVANCE RAPIDE SEULEMENT,
puis pousse avec SA cle, autorisee en ecriture sur ces depots-la seulement.

Ce qui est pousse se DERIVE de `serveur_ops_depots`. `DEPOT=<nom>` en cible un
seul.

Trois pieges rencontres, tous inscrits dans le code : l'outil ne peut pas etre
supposé present sur le runner (il ne recevrait cette version qu'APRES la poussee
qu'elle sert a faire — le controleur le porte) ; la branche n'est pas toujours
`main` (deux depots vivent sur `master`, et le plan le declarait deja) ; le
dossier des depots freres contient un espace, d'ou `argv` et non `cmd`.

Le juge n'est pas le journal du playbook mais LA FORGE : on demande a son API ce
qu'elle porte, et on refuse si ca differe de ce que porte le runner. Six depots
verifies.

Pourquoi ca comptait : la forge du site etait restee quatre commits derriere le
poste, sans que rien ne le signale — dont le correctif qui desarme le pare-feu
Proxmox. Un ecosysteme qui se reproduit depuis une forge en retard reproduit ses
defauts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 08:52:37 -04:00
467b05cbc0 site : un ecosysteme complet — PKI, DNS, forge, cache, runner
Le site portait trois services sur les sept du modele `origine`. Sa forge servait LE
GENOME EN CLAIR et aucune de ses machines n'avait de certificat — donc aucun chiffrement
est-ouest, ce que la doctrine zero-confiance interdit. site-pki-01 (step-ca) et
site-dns-01 (PowerDNS + resolveur colocalises) rejoignent les trois autres.

Quatre defauts que le site a fait tomber, chacun invisible chez un tenant :

  - DNS bloque par notre propre default-deny. Un tenant a son resolveur DANS son reseau
    et ne traverse jamais la frontiere ; le site interroge la sienne. La regle est derivee
    de `site.dns_amorcage`, destination declaree, jamais `any`.
  - serveur_cache_site n'installe rien : il marque un cache et lit les variables de
    serveur_artefacts. Les defauts d'un role ne sont en portee que dans le play qui
    l'inclut — une dependance de role regle l'ordre ET la portee.
  - resoudre_idp partait meme avec OIDC desactive, et exigeait un plan. La resolution
    suit desormais l'usage.
  - le plancher /etc/hosts etait VIDE : `hotes_actifs` n'existait pas dans l'inventaire
    du site. Un role qui reussit en n'ecrivant rien est la pire forme d'echec.

Une machine du site peut desormais se configurer (`variables:`), appliquee en dernier :
ce qu'une machine declare d'elle-meme prime sur ce que le site declare pour toutes.

Verifie et non suppose : systemd disait `active` mais rien n'ecoutait sur 443 — step-ca
sert sur 8443. La zone souveraine resout et la recursion marche, mesurees sur la machine.

42 preuves vertes, ansible-lint profil production.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 12:00:17 -04:00
a6713ffdcd doctrine : patient 0 n'est pas un tenant — corriger la raison, garder le geste
Le commit dc92f01 justifiait le retrait des roles de site de patient 0 par « patient 0
est un tenant comme les autres, c'est meme tout ce qu'il prouve ». C'est FAUX.

Un tenant ordinaire existe POUR SES GENS : Chezlepro heberge de l'identite, du courriel,
de la collaboration. Patient 0 n'heberge que LA LIGNEE. Il est l'ecosysteme d'origine et
le detenteur du genome, et il le reste.

Ce qui le quitte, ce sont deux responsabilites de SITE qu'il tenait faute d'un SITE
capable de les porter — a l'epoque un site n'etait qu'un fichier de carte, sans machines.
Le SITE existe desormais comme objet a part entiere : le geste etait donc juste, seule sa
raison ne l'etait pas.

Le texte est corrige plutot qu'efface, dans le CHANGELOG comme dans les fichiers : une
doctrine juste appuyee sur une raison fausse finit toujours par se retourner.

42 preuves vertes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-25 09:34:02 -04:00