Commit graph

24 commits

Author SHA1 Message Date
ce84d0e1ea frontiere : l'administration (P89) ; serveur_ops ne declare plus le 8006
La face reseau dit quelles entrees publiques sont ouvertes au poste ;
verifier_administration confronte gestion, VPN et tunnel. La sortie 8006
de serveur_ops vers externe ne laissait passer aucun paquet (hyperviseurs
en plages privees) et affirmait un pouvoir qu aucun locataire n a.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 03:14:14 -04:00
56033afd00 serveur_ops : retirer la sortie 443 vers voisins_site (passage inter-locataires)
Ecrite quand la forge du genome vivait chez un voisin ; elle est au site.
Vue d un locataire, voisins_site designe les autres locataires : la
frontiere ouvrait le 443 de chaque runner vers le supernet de l autre.
Le clonage passe par la regle de serveur_forge_site.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 01:38:18 -04:00
5340220192 vigie : vues métier par clientèle interne, dérivées du plan
- metier: sur chaque sonde (47) ; catalogue des vues et services dans
  serveur_icingaweb2 ; vues Mes outils / Services rendus / Exploitation
- contrôles calculés comme serveur_icinga (sauvegardes, socle, matériel,
  frontière) ; vue vide non posée ; ancien exemple supervision retiré
- CHANGELOG 71

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 02:26:11 -04:00
34bfd43e06 flux : seulement_si — un flux peut dependre d'un reglage de l'ecosysteme
La vigie (8080) et la console (8090) n'ecoutent sur le reseau qu'en mode
locale ; en SSO, nginx est lie a 127.0.0.1 et la regle ne menait a rien.
Evaluee par ecosysteme dans les trois generateurs (nftables, Proxmox,
frontiere). Locataires : 8 regles Proxmox et 4 nftables en moins. Site :
inchange.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 10:45:48 -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
c0f610be33 patient 0 efface : l index 29 est libere, et le site n ouvre plus rien a 10.29.0.0/16
Ses machines n existaient plus depuis le 2026-09-06 (D-83), mais son plan
restait sur disque : la federation lui reservait l index 29 et quatre machines
du site lui ouvraient SSH, apt, DNS et HTTPS. Les commentaires et documents
vivants gardent leur lecon sans le nommer ; les archives restent telles quelles.

Pas encore sur le reseau : les regles regenerees attendent le runner du site.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 21:55:27 -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
f9a20b0870 console des runners : le code sur le disque n'est pas le code servi
Les trois consoles portaient le moteur du jour et servaient celui du 16 septembre. Le
clone du genome ne notifiait rien et la tache de service demande state: started, qui ne
fait rien quand le service tourne deja ; inventory_gui.py lit son code au demarrage, et
seulement la. Le role retient desormais si le MOTEUR a avance — designe par
serveur_ops_depot_moteur, jamais un chemin recopie — et redemarre la console dans ce seul
cas : un plan qui avance ne coupe pas les pages ouvertes.

La sonde console-ops criait au vestibule ouvert sur les deux runners de locataire, sur
des consoles fermees. Elle frappait la boucle locale, seul endroit d'ou un 200 est le
resultat attendu en mode oidc, ou nginx est reduit a 127.0.0.1 pour qu'on ne contourne
pas la passerelle SSO. Elle connait maintenant son mode : en locale le verdict ne bouge
pas, en oidc la serrure mesuree est l'adresse d'ecoute. Le refus de la passerelle reste
l'affaire de la sonde passerelle de serveur_oauth2_proxy, sur le meme hote.

Valide : --syntax-check sur playbooks/groupes/serveur_ops.yml, ansible-lint sur le role
(profil production, 0 echec, 0 avertissement, 14 fichiers), le gabarit rendu dans ses deux
modes sans reste Jinja et bash -n propre, le filtre d'ecoute eprouve sur cinq formes
d'adresses, l'expression du when sur cinq cas dont le mode check. Le role est applique aux
trois runners, failed=0, et la sonde rejouee sur chacun rend 0.

Limite : le redemarrage automatique ne s'est pas declenche, les clones etant deja au
niveau de la forge — la tache s'est correctement abstenue. La preuve du declenchement
viendra au prochain genome pousse.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 15:27:50 -04:00
e93e8f4c1d console chez les locataires, collision de noms, et un fichier ecrase
Les deux locataires declarent leur console derriere oauth2-proxy. En oidc le
vestibule n ecoute que la boucle locale : le gabarit annoncait cette protection
en s en remettant au pare-feu, qui ouvrait le port depuis l edge — la console
etait joignable sans passer par la passerelle.

COLLISION REELLE : serveur_oauth2_proxy est mono-instance par machine, et la
table des noms publics etait indexee par GROUPE. La passerelle de la vigie se
croyait la console ; son URL de retour OIDC aurait vise l autre machine. Une
application nomme un COUPLE (machine, role). P67 ne le voyait pas parce qu elle
indexait comme la derivation qu elle garde — une garde qui reproduit le
raisonnement qu elle verifie ne verifie rien.

ET J AI ECRASE group_vars/serveur_ops.yml sans le regarder : 68 lignes
detruites, deux preuves tombees, et une explication fausse construite dessus. Le
git diff qui m avait rassure portait un glob developpe par le shell parent : il
n a rien matche et n a rien dit. Une commande qui ne trouve rien et une commande
qui trouve que rien n a change rendent le meme silence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-15 11:47:50 -04:00
627ef00ec7 la console d exploitation devient un service, et elle n avait aucune serrure
Le GUI n a aucune authentification : GET / sert la page a qui la demande, jeton
ecrit dedans, et POST /api exige ce jeton que la page vient de donner. Le jeton
garde contre le CSRF, pas contre un visiteur — la seule serrure est
--hote 127.0.0.1. Ce qu il offre a qui entre : deployer, creer, raser, editer le
plan. La fabric entiere.

Le service reste donc sur la boucle locale. Ce qui est publie est un nginx local
qui authentifie d abord : oidc par defaut (oauth2-proxy, donc un groupe
d annuaire qu on revoque sans deploiement), locale en repli pour un ecosysteme
sans annuaire. L authentification est posee au niveau du server, pas d un
location.

La sonde console-ops mesure une SERRURE : une requete anonyme doit etre REFUSEE.
Un 200 y est la pire des reponses, et il ne fait echouer personne.

P54 a attrape une contrainte ratee : serveur_ops est insemine par le SITE, qui
ne detient pas la voute du locataire. Le role ne nomme donc aucune voute — il
declare un parametre, et la couche qui detient le secret le remplit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-14 19:27:28 -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
84b5ecc71d frontiere posee, et cinq sondes qui disaient faux
Application de ce que l entree precedente avait prepare : 49 regles creees,
5 retirees. Cibles Prometheus 2/8 -> 8/8, hotes dans Loki 1/7 -> 7/7.

Puis correction de ce que l application a revele. Cinq defauts, tous de la
meme famille : un reglage qui ne suit pas l interrupteur dont il depend.

  - la sonde de Loki interrogeait en HTTPS un Loki servant en clair ;
  - la sonde de la forge visait http:// sur un port 443 chiffre, puis
    validait un certificat emis pour le FQDN en interrogeant 127.0.0.1 ;
  - la sonde du runner comparait six depots a UNE branche quand le plan en
    declare une par depot. Elle contredisait la declaration qu elle etait
    censee verifier : elle n accusait pas la machine, elle s accusait
    elle-meme.

Le tenant restait juste dans les cinq cas. C est le site, qui deploie ces
roles autrement, qui les a tous reveles d un coup.

La sonde des journaux, elle, avait deux defauts a la naissance. Elle criait
une perte deja reparee, faute de dire sur QUELLE fenetre - un ecart sans sa
fenetre n est pas une mesure, c est un nombre. Et elle alertait sur la
cicatrice plutot que sur la plaie : le compteur d Alloy est cumulatif, donc
six machines restaient orange pour toujours. Ce qui alerte est desormais la
CROISSANCE. En echange, un cas muet leve maintenant : zero envoi et zero
rejet n est pas la sante, c est un agent qui ne fait rien.

Enfin, le runner ne pouvait plus cloner le genome. Defaut PREEXISTANT,
revele par le redeploiement et non cause par lui - le diff des regles
generees le montre. generer_nftables(site=True) lisait le plan du TENANT :
derive se resolvait donc a 3000, le port que Forgejo ecoute derriere un
edge, alors que le plan du site dit 443 et explique pourquoi. La forge
ouvrait un port que personne n ecoute et laissait 443 ferme a toute la
flotte.

Mesure finale : Icinga 51/51, Prometheus 8/8, Loki 7/7, prouver 64 OK,
lint 0 defaut sur 82 fichiers. Controles negatifs sur des COPIES des
sondes : les quatre rendent CRITICAL.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-10 10:27:12 -04:00
6120e6f006 sondes : quatorze, une par role, derivees en objets Icinga
boites (dovecot) · cache-apt (artefacts) · certificat (client_pki, 14/14)
collaboration (nextcloud) · collecte (prometheus) · file-courriel (postfix)
forge (forgejo) · identite (keycloak) · ingestion (loki) · moteur (icinga)
resolution (resolveur) · runner (serveur_ops) · tableaux (grafana)
voute (ops_tenant) — toutes vertes, sans une ligne ecrite dans Icinga.

DEUX PRINCIPES QUE LA PREMIERE SONDE A IMPOSES.
Une sonde doit pouvoir etre mise en defaut PAR PARAMETRE : cible et seuils
sont des variables du role, on prouve le rouge avec un port ferme ou un
seuil impossible, sans rien casser. Et la sonde vit LA OU VIT LA VERITE :
« ce noeud est-il collecte ? » appartient a prometheus, pas au client —
une seule y voit les N noeuds, et surtout elle voit le cas SILENCIEUX.

ON DEMANDE AU SERVICE CE QU IL PENSE DE LUI-MEME quand il sait le dire
(healthz, /ready, status.php, decouverte OIDC). Quand il ne sait pas, on
va chercher la verite de terrain : « moteur » ne regarde ni le service ni
le port, il demande a la base depuis combien de temps elle n a pas ete
rafraichie — la lecon des sauvegardes appliquee a la supervision.

QUATRE FOIS J AI ECRIT LA SONDE AVANT DE MESURER, QUATRE FOIS ELLE A EU
TORT. La forge : port et chemin des depots inventes, elle ecoute en 3000
derriere l edge et n a legitimement aucun depot. Loki : « panne
persistante » conclue sur deux lectures a quelques secondes d intervalle
juste apres un redemarrage — deux mesures rapprochees ne distinguent pas
un etat d un instant. Keycloak : vise en 8443, il ecoute en 8080. Le
runner : git en root refuse un depot d un autre proprietaire. A chaque
fois le remede est le meme — lire la verite du role, ne pas la supposer.

Et le meme piege Jinja qu avec client_sante : ${#tableau[@]} contient {#.
Le remede etait deja au depot ; je l ai reecrit au lieu de le chercher.

RESTE : client_smtp, client_artefacts, client_journal, icingaweb2 et
ops_site. Ce sont des chemins de report, dont la panne se voit deja par le
silence des sondes qu ils portent.

make prouver : CONFORME, 64 OK, 0 echec, 0 saute (P64 : 14 sondes).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
2026-09-10 03:00:21 -04:00
aca63011ea roues : pip par le meme chemin que les collections — le controleur telecharge, la cible n installe rien du dehors
LA DERNIERE DEPENDANCE QUI SORTAIT PAR ELLE-MEME. Les collections Ansible suivent
depuis longtemps l idiome de ce depot : le CONTROLEUR telecharge une fois puis
pousse par SSH, aucun flux nouveau depuis la cible, et l artefact devient
deployable hors ligne. pip sortait encore vers PyPI, en HTTPS et par nom.

Un tenant n a NI DNS SORTANT NI 443 vers l Internet, et c est voulu. Mesure sur
ops-01, premiere machine de la reconstruction de Chezlepro :

    ERROR: Could not find a version that satisfies the requirement ansible-core
    Echec temporaire dans la resolution du nom

PAS LE PAQUET DEBIAN : trixie propose ansible-core 2.19.4, hors de la plage
epinglee. Y aller demanderait de deplacer l epinglage vers une version majeure aux
changements de gabarits connus, trois jours apres l avoir pose pour cause de
portabilite.

--no-index EST LE POINT, PAS UNE OPTIMISATION. Sans lui, pip resterait capable de
sortir vers PyPI le jour ou le depot local serait incomplet : la reussite
dependrait d un flux que ce tenant n a pas le droit d avoir, et une lignee
autonome deviendrait une lignee qui a l air autonome.

LE CONTROLEUR ET LA CIBLE DOIVENT PARTAGER LEUR PYTHON, et ca ne se devine pas.
pyyaml porte du C compile ; une roue cp313 posee sur un python 3.12 ne s installe
pas, et l echec accuserait le depot local au lieu de l ecart entre deux machines.
Mesure et dit ici, ou on peut encore le nommer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019f91zs9SDdwSzL2CVei6on
2026-08-28 15:37:09 -04:00
5d0f82792a portabilite : declarer ce dont le moteur depend — quatre defauts reveles par le runner
Premiere materialisation d'une VM de tenant depuis le runner du SITE. Elle a
echoue quatre fois d'affilee, sur quatre dependances que le moteur ne declarait
nulle part. Chacune fonctionnait chez le mainteneur pour une raison DIFFERENTE,
et aucune de ces raisons n'existe sur une autre machine.

1. VERSIONS DES COLLECTIONS. `requirements.yml` les nommait sans les epingler. Le
   runner a recu `community.general` 13.3.0 quand le poste porte la 10.3.0 — et la
   11 a retire les modules Proxmox de cette collection.
       ERROR! couldn't resolve module/action 'community.general.proxmox_pool'

2. INSTALLATION EN AVANT. `ansible-galaxy` ne retrograde pas : declarer la 10.3.0
   ne suffisait pas a defaire une 13.3.0 deja posee. `--force`.

3. EMPLACEMENT. Le `Makefile` pose `ANSIBLE_HOME ?= $(CURDIR)/.ansible` : sous
   `make`, Ansible ne lit QUE `<moteur>/.ansible/collections`. Le role deposait
   dans `<racine>/.ansible/collections` — a cote, jamais lu. Invisible chez le
   mainteneur, ou les collections viennent du paquet systeme, toujours dans le
   chemin quel que soit ANSIBLE_HOME. Et le garde-fou d'installation suivait le
   DEPOT des archives : changer la destination ne le declenchait pas. Il mesure
   desormais la destination — meme piege qu'en 2026-08-24, deplace d'un cran.

4. BIBLIOTHEQUES PYTHON. Le venv recevait `ansible-core` et `pyyaml`, ecrits en
   dur. Les modules Proxmox tournent `delegate_to: localhost` et exigent
   `proxmoxer` SUR LE CONTROLEUR.
       La bibliotheque Python proxmoxer est absente

   Ne d'ici : `requirements-python.txt`, avec sa frontiere ecrite — il ne declare
   QUE ce qui tourne sur le controleur. `python-ldap` et `psycopg2` s'executent
   sur leurs cibles ; le poste du mainteneur ne les a pas et la flotte se deploie,
   ce qui prouve que la ligne est au bon endroit.

P51 garde les trois faiblesses de cette famille : une dependance utilisee sans
etre declaree (le defaut du 2026-08-24, `ansible.posix`), une dependance declaree
sans version, et `proxmoxer` absent alors que des playbooks Proxmox existent.
Quatre controles negatifs verifies.

RESULTAT : ops-01 materialisee par le runner du site. L'agent invite rapporte
`eth0 10.17.19.41/24`, Debian 13 trixie — l'adressage derive du plan, applique.

Un seul executant masque ces ecarts indefiniment ; un second les revele tous en
une soiree. Meme mecanique que le second tenant en aout.

make prouver : CONFORME, 51 OK, 0 echec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 22:38:35 -04:00
3fa6e4c3e1 collections : epingler les versions — le runner echouait la ou le poste reussissait
Premiere materialisation de VM depuis le runner du SITE :

    ERROR! couldn't resolve module/action 'community.general.proxmox_pool'

Meme depot, meme playbook, meme plan que chez le mainteneur. La difference tenait
a une seule chose que le moteur ne disait pas : la VERSION de ses collections.

Le poste porte `community.general` 10.3.0. Le runner, monte un jour plus tard, a
recu la 13.3.0 — et la version 11 a RETIRE les modules Proxmox de cette collection
(ils vivent desormais dans `community.proxmox`). `requirements.yml` nommait ses
collections sans dire lesquelles : chaque machine installait donc ce qui etait
courant le jour de son montage. Une dependance non epinglee n'est pas une
dependance, c'est un pari sur l'etat d'Internet a la date du deploiement.

TROIS CORRECTIONS.

`requirements.yml` epingle les trois collections aux versions eprouvees.

`serveur_ops` installe avec `--force`. Sans lui, ansible-galaxy laisse en place une
version SUPERIEURE a celle demandee : il ne retrograde pas. Un poste peut etre en
avance, pas seulement en retard, et le depot doit faire autorite dans les deux sens.

P51 garde les deux faiblesses de ce fichier — celle du 2026-08-24, une collection
utilisee sans etre declaree (`ansible.posix`), et celle d'aujourd'hui, declaree sans
version. La preuve ne lit que les fichiers de TACHES : un `defaults/main.yml` porte
`net.ipv4.ip_forward`, qu'un motif trop large prend pour un module.

MIGRATION CONNUE, PAS FAITE : passer les quatre modules Proxmox a
`community.proxmox` permettra de suivre `community.general` au-dela de la 11.

make prouver : CONFORME, 51 OK, 0 echec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-27 18:58:23 -04:00
8195d6b814 poste : l'outillage sur le chemin de celui qui l'exploite
Ansible vit dans un venv isole — c'est voulu, il est epingle. Mais rien ne le
mettait sur le PATH du compte d'exploitation : `make instancier` y echouait sur
« [Errno 2] No such file or directory: 'ansible-inventory' », un message qui
accuse un fichier manquant alors que le fichier est la, deux dossiers plus loin.

Mesure du 2026-08-26, en EPROUVANT la sequence depuis le runner du site. Un
exploitant y serait tombe exactement de la meme facon — et c'est precisement ce
qu'un outil « utilisable sans IA » ne doit pas faire.

Un fragment `profile.d` plutot qu'un `.bashrc` : il vaut pour toute session du
compte, `sudo -iu setops` compris, et se retire d'un seul geste.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-26 16:42: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
9c173f52ba forge du genome : mutualisee par site, avec une confiance limitee a une url
Une forge sert a deux choses que le meme logiciel confondait : porter le GENOME
-- meme contenu pour tous les tenants d'un site -- et heberger le TRAVAIL de ses
gens, qui est un service du tenant. La premiere se mutualise, la seconde non.

Lire le genome chez un voisin suppose de faire confiance a SON autorite. On ne
pose PAS cette racine dans le magasin systeme : `git config
http.<url>.sslCAInfo` limite la confiance a cette seule forge. Une porte, pas un
trousseau.

L'adresse est une IP : `forge.genese.internal` ne resout pas depuis un autre
tenant, et le certificat de l'edge porte l'IP dans ses SAN.

Effet de bord recherche : le genome devient disponible AVANT que la forge du
tenant soit debout. Un ecosysteme neuf n'attend plus sa propre forge pour se
remplir.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 18:55:44 -04:00
1363ebff59 acces : le runner peut enfin entrer, et trois silences fermes
ssh_baseline gere les cles d'administration declarees au plan, avec un `etat`
par entree : revoquer devient un changement de plan, pas une visite sur chaque
machine. Pas d'exclusive -- il effacerait la cle de cloud-init et fermerait la
flotte a tout le monde.

cloud-init reecrivait /etc/hosts a chaque demarrage et effacait le plancher de
resolution. Constate sur infra-dns-01 apres un redemarrage : six entrees
perdues, revelees deux jours plus tard par un apt update qui ne resolvait plus.

requirements.yml ne declarait pas ansible.posix ni community.docker, pourtant
utilisees. Ca marchait chez le mainteneur, pas sur un runner. Et le cache des
collections suivait l'existence du fichier au lieu de son contenu.

Enfin : deux `when` sur une meme tache, c'est un seul -- le dernier. Le
check-mode avait disparu en silence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 15:50:37 -04:00
f248bb084f filiation : nommer les trois ages d'un ecosysteme
Un ecosysteme nait fils, peut rester mutualise par choix, et s'emancipe quand il
le decide. Le moteur avait rencontre ce motif trois fois sans le nommer :
client_artefacts_actif, serveur_ops_forge_externe, client_backup_cible.

serveur_ops_forge_externe etait citee par le registre des dependances ET par le
README, definie nulle part : l'exemption ne pouvait jamais s'appliquer. Elle
existe maintenant, avec un amont obligatoire.

Consequence pour les modeles : quatre n'ont pas de forge, ce ne sont pas des
lacunes mais des ecosystemes au premier age. Ils le declarent.

Reste a faire : l'instrument qui PROUVE qu'une emancipation a coupe le lien.
Sans lui, on croirait s'etre emancipe en restant dependant.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 14:10:10 -04:00
e6c5f9f539 instancier : refuser une machine dont la fonction n'est pas declaree
deriver_nomenclature(...) or {} avalait l'echec : une fonction absente rendait
un dictionnaire vide, et la machine entrait dans l'inventaire avec
ansible_host: None. La generation se declarait reussie ; la panne serait
apparue au deploiement, sous une forme incomprehensible.

Revele en portant serveur_ops dans les modeles : presence-web range son socle
en zone 1 et n'a pas de categorie 4. Le defaut n'est pas apparu en ecrivant le
role ni en le deployant chez patient 0 -- il a fallu le porter ailleurs.

serveur_ops ne nomme plus patient 0 dans ses defauts : un ecosysteme distrait
aurait clone le genome d'un autre, en silence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 11:42:32 -04:00
d94fca490f poste : le second symlink, celui qui separe exploiter d'engendrer
Some checks are pending
verifier / verifier (push) Waiting to run
Le poste ne clonait que le moteur et son plan : il savait configurer des machines
existantes, pas en creer. Placer une VM demande de savoir sur quelle fabric la
poser.

Patient 0 n'a pas d'underlay a lui -- il est TENANT de SITE-Chezlepro. Son poste
porte donc les deux symlinks de D-80, et quatre depots : le moteur, son plan, la
fabric qui le porte, les modeles.

underlay.vault.yml reste hors du genome : le poste lit la CARTE du monde
physique, jamais ses cles. Mesure depuis ops-01 : `make instancier` rend un diff
vide sans aucun secret, `make underlay-plan` refuse faute de voute.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 12:24:28 -04:00
665b07ba82 serveur_ops : la difference entre une archive et une matrice
Some checks are pending
verifier / verifier (push) Waiting to run
Un ecosysteme pouvait DETENIR son genome sans savoir l'executer. Le poste
d'exploitation porte Ansible epingle, le genome clone depuis SA PROPRE forge, et
une cle SSH qui n'appartient qu'a lui. Il n'emporte ni la voute ni son mot de
passe : la structure se reconstruit depuis la forge, les secrets depuis la
sauvegarde. Deux sources qu'un meme incident n'atteint pas ensemble.

Une machine neuve traverse tout le moteur sans rien heriter, et revele ce qu'un
etat anterieur masquait. Deux defauts silencieux en sont sortis.

setops_plan_dir pointait le lien `instance` en dur : neuf roles lisaient donc le
plan d'une AUTRE instance. Le plancher de patient 0 portait les FQDN de
Chezlepro, et son edge publiait server_name forge.chezlepro.internal. La
variable suit desormais l'inventaire reellement charge.

Trois instances sur quatre declaraient les SAN d'exposition de leur edge ; la
quatrieme et le modele public ne les avaient pas. La forge de patient 0 etait
donc publiee derriere le certificat auto-signe de Debian, sans que rien ne le
signale -- `git clone` fut le premier a refuser, a juste titre. P42 le reclame
maintenant pour tout ecosysteme qui declare un edge.

Le harnais a ecrit la moitie de ce role : 5 echecs sur la piece neuve, aucun
n'empechait le code de tourner, tous la rendaient invisible a la carte, au
graphe et au lecteur. 42 preuves, 0 echec.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:58:10 -04:00