Set-OPS-Public/docs/runbooks-construction.yml
Daniel Allaire 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

881 lines
40 KiB
YAML

---
# LES RUNBOOKS DE CONSTRUCTION — l'ordre des gestes, et pourquoi celui-la.
#
# CE QUE CE FICHIER AJOUTE AU MAKEFILE, ET CE QU'IL NE REPETE PAS.
#
# Les 132 cibles documentees du Makefile disent chacune CE QU'ELLE FAIT. Aucune ne dit
# dans quel ORDRE, ni pourquoi maintenant, ni ce qu'il faut avoir mesure avant. Cette
# connaissance-la vivait en prose dans `docs/runbooks-exploitation.md`,
# `docs/implanter-un-tenant-sur-un-site.md` et `docs/preparer-un-site-hebergeur.md` — et
# la console offrait des boutons sans sequence.
#
# ON NE RECOPIE PAS LE LIBELLE D'UNE CIBLE. `scripts/runbooks.py` va le lire dans le
# Makefile au moment de servir. Un libelle recopie ici serait une seconde liste, et une
# liste qui suit une autre prend du retard sur elle. Ce fichier ne porte donc que ce que
# le Makefile ne peut pas porter : l'ordre, la nature du geste, la portee, le pourquoi.
#
# LA GARDE EST ECRITE AVEC LA LISTE, PAS APRES. `python3 scripts/runbooks.py verifier`
# (et P83) refusent qu'une cible documentee ne soit ni portee par un runbook ni exemptee
# avec un motif. Sans cela, la console cacherait des pouvoirs que le moteur possede.
#
# NATURE D'UNE ETAPE
# mesure n'ecrit rien, rejouable sans consequence, proposee meme apres un echec
# ecriture change l'etat du monde ; exige que l'etape precedente ait reussi
# destructif detruit ; exige une confirmation ecrite en plus de CONFIRMER=true
#
# PORTEE D'UN RUNBOOK — ce que la MACHINE porte, au sens de `contexte()` :
# tenant un ecosysteme est monte (`instance/`) : on le configure
# site une fabric est montee (`underlay.yml`) : on materialise
# poste les deux — l'atelier du mainteneur
# toute ni l'un ni l'autre n'est requis
#
# LA PORTEE SE PESE A L'ETAPE (2026-09-20). Un runbook donne le defaut ; une etape qui
# exige davantage le declare avec son propre `portee:`. Mesure faite sur la console de
# TechnoLibre : declaree au seul runbook, une unique etape qui materialise (`flotte-creer`,
# `creer-vm`) faisait basculer TOUTE la sequence en `poste` — et un locataire ne pouvait
# plus deployer sa propre flotte, ce qui est exactement son metier. Le locataire conduit
# donc sa sequence, et bute precisement la ou il faut : sur la machine a engendrer.
# CE QUE LA CONSOLE DOIT DEMANDER A L'EXPLOITANT. Une variable absente d'ici est refusee
# par la garde : la console ne saurait pas quoi afficher, et un champ libre sans invite
# est une invitation a se tromper.
variables:
HOTE:
invite: "La machine"
source: hotes # la liste vient de l'inventaire actif
GROUPE:
invite: "Le groupe (role)"
source: groupes
NOM:
invite: "Nom du dossier de l'ecosysteme"
exemple: "OPS-Machin"
MODELE:
invite: "Modele de depart"
source: modeles
INSTANCE:
invite: "Nom de l'ecosysteme a detruire (il doit etre ecrit en toutes lettres)"
SITE:
invite: "Depot du site a detruire (ecrit en toutes lettres)"
TENANT:
invite: "Dossier du locataire a amorcer"
exemple: "OPS-Machin"
DEPOT:
invite: "Un seul depot (vide = tous ceux que le runner porte)"
facultatif: true
VERS:
invite: "Repertoire de destination (une cle chiffree, hors du poste)"
ARCHIVE:
invite: "Fichier d'archive a restaurer"
CIBLE:
invite: "Hote ou adresse a sonder"
SERVICE:
invite: "Le lien dont on prouve la coupure"
valeurs: [artefacts, genome, resolveur]
ROLE:
invite: "Un seul role (vide = tous)"
facultatif: true
LIMITE:
invite: "Motif d'hotes"
facultatif: true
RECU_PAR:
invite: "Qui recoit la remise (nom complet)"
COURRIEL:
invite: "Courriel de la personne qui recoit"
DANS:
invite: "Jours avant le second temps"
facultatif: true
VMID:
invite: "Identifiant Proxmox de la VM"
DIALECTE:
invite: "Dialecte du commutateur"
valeurs: [cisco, binardat]
facultatif: true
PARALLELE:
invite: "Combien de VM a la fois"
facultatif: true
runbooks:
# ─────────────────────────────────────────────────────────────────────────────
- id: site-premier-jour
titre: "Le premier jour d'un site"
portee: site
doc: docs/runbooks-exploitation.md
but: >-
Faire naitre un site hebergeur depuis une fabric nue : les machines, puis le moteur,
puis la forge qui permettra aux locataires de se reproduire. L'ordre n'est pas une
preference — le premier passage s'ARRETE sur une forge vide, et c'est normal.
etapes:
- cible: underlay
nature: mesure
pourquoi: >-
La fabric declaree tient-elle debout toute seule ? Rien ne sert de creer des
machines sur un plan d'adressage qui se contredit.
- cible: underlay-plan
nature: mesure
pourquoi: >-
Le declare face au REEL, par l'API du cluster et une sonde TCP. C'est ici qu'on
apprend qu'un pont n'existe pas, pas au milieu de la creation des VM.
- cible: site-creer
nature: ecriture
fixes: {CONFIRMER: "true"}
duree: "~9 min"
pourquoi: >-
Les machines du site, depuis l'underlay. Elles naissent ; elles ne repondent pas
encore.
- cible: site-deployer-tout
nature: ecriture
fixes: {CONFIRMER: "true"}
duree: "~20 min"
pourquoi: >-
Premier passage. Il va jusqu'a `serveur_ops` et s'arrete sur la forge vide :
ce n'est pas un echec, c'est le maillon suivant.
- cible: forge-amorcer
nature: ecriture
fixes: {CONFIRMER: "true"}
duree: "~45 s"
pourquoi: >-
La forge tourne et n'a ni organisation ni depot. Sans cet amorcage, le runner
clone le vide et le deploiement ne finira jamais.
- cible: site-deployer-tout
nature: ecriture
fixes: {CONFIRMER: "true"}
duree: "~4 min"
pourquoi: >-
Second passage. Celui-ci doit finir a zero echec ; s'il n'y arrive pas, c'est
un vrai defaut, plus un maillon manquant.
- cible: genome-pousser
nature: ecriture
variables: [DEPOT]
pourquoi: >-
La forge du site FAIT AUTORITE : tant qu'elle est en retard, tout ecosysteme qui
s'y reproduit reproduit un moteur perime.
- cible: routes-fabric-etat
nature: mesure
pourquoi: >-
Les hyperviseurs routent-ils toutes les zones ? Une zone non routee ne se voit
qu'au moment ou un locataire y pose sa premiere machine.
- cible: gabarit-etat
nature: mesure
pourquoi: >-
Sans gabarit conforme, aucun locataire ne pourra cloner quoi que ce soit ici.
# ─────────────────────────────────────────────────────────────────────────────
- id: site-tenir
titre: "Tenir un site en etat"
portee: site
doc: docs/hebergeur-exploitation.md
but: >-
Les gestes reguliers de l'hebergeur : porter le genome a jour, appliquer un role aux
machines du site, et regarder ce que la fabric fait vraiment.
etapes:
- cible: genome-etat
nature: mesure
pourquoi: >-
Ce que la forge porte, face au poste. Un ecart ici se paie chez TOUS les
locataires qui clonent ensuite.
- cible: genome-pousser
nature: ecriture
variables: [DEPOT]
pourquoi: "Remettre la forge au niveau du poste, depot par depot si besoin."
- cible: site-appliquer
nature: ecriture
variables: [GROUPE]
pourquoi: >-
Rejouer un role sur les machines du site — c'est ainsi qu'un runner reprend le
genome courant, rien ne le tire tout seul.
- cible: site-decrire
nature: mesure
pourquoi: "Ce que l'underlay declare comme machines de l'hebergeur."
- cible: site-inventaire
nature: mesure
pourquoi: "L'inventaire dynamique du site, tel qu'Ansible le voit — pas tel qu'on l'imagine."
- cible: site-intrants
nature: mesure
pourquoi: "Ce que ce site expose a ses locataires, derive et non declare deux fois."
- cible: site-verifier
nature: mesure
pourquoi: "Le playbook du site correspond-il encore aux couches declarees ?"
- cible: site
nature: ecriture
pourquoi: "Regenerer playbooks/site.yml quand les couches ont bouge."
- cible: routes-fabric-etat
nature: mesure
pourquoi: "Une route de zone manquante est invisible jusqu'au premier invite qui la traverse."
- cible: site-raser
nature: destructif
variables: [SITE]
fixes: {CONFIRMER: "true"}
pourquoi: >-
Detruire les VM du SITE. A ne faire que sur un site de chantier : la
reconstruction est prouvee, elle n'est pas gratuite.
# ─────────────────────────────────────────────────────────────────────────────
- id: locataire-naitre
titre: "Faire naitre un ecosysteme de locataire"
portee: tenant
doc: docs/multi-instances.md
but: >-
Du modele au plan monte : creer le dossier de l'ecosysteme, le rendre actif, puis
generer son inventaire. Tout l'adressage descend du seed `index` — on ne l'ecrit
jamais a la main.
etapes:
- cible: instance-modeles
nature: mesure
pourquoi: "Quels modeles de depart existent, avant d'en choisir un."
- cible: instances
nature: mesure
pourquoi: >-
Les ecosystemes deja decouverts, et surtout les COLLISIONS d'index : deux
ecosystemes sur le meme seed se marcheraient dessus en silence.
- cible: instance-creer
nature: ecriture
variables: [NOM, MODELE]
pourquoi: "Le dossier de l'ecosysteme, depuis un modele, avec son index reserve."
- cible: instance-utiliser
nature: ecriture
variables: [NOM]
pourquoi: >-
Basculer le symlink `instance/`. C'est lui qui decide QUEL ecosysteme la console
configure — et quelle voute elle ouvrira.
- cible: instance-courante
nature: mesure
pourquoi: "Verifier vers quoi on pointe avant d'ecrire quoi que ce soit."
- cible: intrants-verifier
nature: mesure
pourquoi: >-
Tout intrant qu'un role EXIGE est-il fourni ? Un intrant manquant ne se voit
sinon qu'au milieu d'un deploiement.
- cible: ports-verifier
nature: mesure
pourquoi: "Deux roles co-localises qui reclament le meme port ne cohabiteront pas."
- cible: instancier
nature: mesure
pourquoi: >-
Generer hosts.yml depuis le plan SANS l'appliquer — on regarde le diff avant de
le prendre.
- cible: instancier-appliquer
nature: ecriture
pourquoi: >-
Prendre l'inventaire genere. `hosts.yml` est un ARTEFACT : on edite le plan, on
ne le corrige jamais a la main.
- cible: inventaire-verifier
nature: mesure
pourquoi: "L'inventaire se parse-t-il, voute dechiffree ? Sinon rien ne partira."
# ─────────────────────────────────────────────────────────────────────────────
- id: locataire-materialiser
titre: "Preparer le terrain d'un locataire sur la fabric"
portee: site
doc: docs/implanter-un-tenant-sur-un-site.md
but: >-
Tout ce que l'HEBERGEUR pose avant qu'un locataire puisse exister : le placement, les
pools, le SDN, les pare-feux et la frontiere. Chaque devis se mesure avant de
s'appliquer — un devis qu'on applique sans l'avoir lu est un pari.
etapes:
- cible: placement-plan
nature: mesure
pourquoi: >-
Le noeud, le stockage, le pont et le gabarit existent-ils VRAIMENT sur ce
cluster ? C'est la premiere chose qui manque, et la derniere qu'on regarde.
- cible: devis-proxmox-pools
nature: mesure
pourquoi: "Un pool par locataire, derive du plan — la cloison la plus simple."
- cible: devis-proxmox-pools-verifier
nature: mesure
pourquoi: "Le devis tient-il ses propres regles avant qu'on le pose ?"
- cible: devis-sdn
nature: mesure
pourquoi: "Zone, VNets et sous-reseaux, derives du seed de l'ecosysteme."
- cible: devis-sdn-verifier
nature: mesure
pourquoi: "Relire le devis SDN avant de toucher au reseau du cluster."
- cible: sdn-plan
nature: mesure
pourquoi: "L'ecart entre le SDN en service et ce devis — ce qui manque, ce qui est perime."
- cible: sdn-appliquer
nature: ecriture
fixes: {CONFIRMER: "true"}
pourquoi: >-
Reconcilier : creer ce qui manque et RETIRER ce qui est perime. Le retrait est la
moitie qu'on oublie.
- cible: flux
nature: ecriture
pourquoi: >-
Regenerer le registre des flux et les regles nftables depuis les `meta/flux.yml`
des roles. Tout ce qui suit en descend.
- cible: devis-proxmox-fw
nature: mesure
pourquoi: "Le pare-feu est-ouest intra-locataire, derive du registre des flux."
- cible: devis-proxmox-fw-verifier
nature: mesure
pourquoi: "Relire ce devis avant de le poser sur le cluster."
- cible: proxmox-fw-plan
nature: mesure
pourquoi: "L'ecart entre le pare-feu en service et le devis."
- cible: proxmox-fw-appliquer
nature: ecriture
fixes: {CONFIRMER: "true"}
pourquoi: "Poser IPSets, groupes et affectations — et retirer ce qui ne se declare plus."
- cible: proxmox-fw-eprouver
nature: mesure
variables: [TENANT, HOTE]
pourquoi: >-
Avant d'activer le pare-feu d'UNE VM : les regles du devis tiennent-elles face aux
flux que la VM recoit REELLEMENT ? Une VM reconstruite a perdu ses options.
- cible: proxmox-fw-activer-vm
nature: ecriture
variables: [TENANT, HOTE]
fixes: {CONFIRMER: "true"}
pourquoi: >-
Activer une VM a la fois, matrice avant et apres, Icinga lu. Chaque defaut du
2026-09-28 ne s'est montre qu'a l'activation d'UNE VM.
- cible: devis-opnsense
nature: mesure
pourquoi: "La frontiere nord/sud, derivee du meme registre de flux."
- cible: devis-opnsense-verifier
nature: mesure
pourquoi: "Relire le devis de frontiere : c'est la porte de l'exterieur."
- cible: frontiere-plan
nature: mesure
pourquoi: "Ce que la frontiere porte aujourd'hui, face a ce devis."
- cible: frontiere-appliquer
nature: ecriture
fixes: {CONFIRMER: "true"}
pourquoi: >-
Reconcilier la frontiere. Les routes creees ETEINTES ont deja coute une journee :
une route eteinte compte « posee » et ne route rien.
- cible: devis-reseau
nature: mesure
variables: [DIALECTE]
pourquoi: >-
Le devis des commutateurs physiques (VLANs, SVIs, ACLs). Il se pose a la main sur
le materiel — le moteur ne configure pas les switches.
- cible: frontiere-mesurer
nature: mesure
pourquoi: >-
La frontiere refuse-t-elle ce qui n'est pas declare ? Un connect() qui aboutit ne
prouve rien : seule la LIVRAISON compte.
# ─────────────────────────────────────────────────────────────────────────────
- id: locataire-deployer
titre: "Materialiser et deployer la flotte d'un locataire"
portee: tenant
doc: docs/vm-lifecycle.md
but: >-
Des VM au service rendu : creer les machines manquantes, deployer couche par couche,
puis mesurer. Rien n'est « pret » avant la recette.
etapes:
- cible: flotte-creer
nature: ecriture
portee: poste
variables: [PARALLELE]
fixes: {CONFIRMER: "true"}
pourquoi: >-
Les VM manquantes, clonees depuis le gabarit dore. VMID, IP et VLAN sont DERIVES
du plan : on ne les saisit nulle part.
- cible: deployer-tout
nature: ecriture
duree: "long"
fixes: {CONFIRMER: "true"}
pourquoi: >-
Toute la flotte, dans l'ordre des couches. L'ordre vient du graphe de
dependances, pas d'une liste tenue a la main.
- cible: deployer-groupe
nature: ecriture
variables: [GROUPE]
facultative: true
pourquoi: >-
Un seul role, sur toute la flotte. C'est le geste d'apres : quand un role a change
et qu'on ne veut pas tout rejouer.
- cible: appliquer
nature: ecriture
variables: [GROUPE]
facultative: true
pourquoi: >-
Appliquer un groupe a la flotte. Meme usage que `deployer-groupe`, par le chemin
court — sans le graphe des couches.
- cible: verifier-deploiement
nature: mesure
pourquoi: "L'etat de la flotte apres coup — avant de croire que c'est fini."
- cible: valider
nature: mesure
pourquoi: >-
La recette de validation sur la flotte. C'est elle qui autorise le mot « pret »,
pas l'absence d'erreur rouge.
# ─────────────────────────────────────────────────────────────────────────────
- id: machine-une
titre: "Ajouter ou reprendre une seule machine"
portee: tenant
doc: docs/vm-lifecycle.md
but: >-
Le cycle d'UNE machine, du plan au service : la voir derivee, la creer, la deployer,
la verifier. Le meme chemin sert pour une machine neuve et pour une machine a
reprendre.
etapes:
- cible: hote-afficher
nature: mesure
variables: [HOTE]
pourquoi: >-
Tout ce que le plan derive pour cette machine — avant de la creer, pour verifier
qu'on va bien poser ce qu'on croit.
- cible: creer-vm
nature: ecriture
portee: poste
variables: [HOTE]
duree: "~4 min 30"
pourquoi: "Cloner depuis le gabarit et ATTENDRE que la machine reponde."
- cible: deployer
nature: ecriture
variables: [HOTE]
pourquoi: "Les roles de cette machine, couche par couche, dans l'ordre du graphe."
- cible: verifier-hote
nature: mesure
variables: [HOTE]
pourquoi: "Le playbook de verification sur cette machine seule."
- cible: cloner-vm
nature: ecriture
portee: poste
variables: [HOTE, VMID]
facultative: true
pourquoi: >-
Cloner SANS passer par le plan. Chemin de reprise : a n'emprunter que lorsque le
plan ne peut pas encore deriver la machine.
# ─────────────────────────────────────────────────────────────────────────────
- id: flotte-refaire
titre: "Raser et reconstruire un ecosysteme"
portee: tenant
doc: docs/vm-lifecycle.md
but: >-
La preuve la plus dure du moteur : detruire un ecosysteme et le refaire depuis le
code seul. A ne lancer que sur un chantier — la prod vit ailleurs.
etapes:
- cible: raser
nature: destructif
portee: poste
variables: [INSTANCE]
fixes: {CONFIRMER: "true"}
pourquoi: >-
Detruire les VM derivees du plan. Le nom de l'ecosysteme s'ecrit en toutes
lettres : c'est le seul garde-fou qui resiste a un clic distrait.
- cible: reconstruire
nature: ecriture
portee: poste
duree: "long"
fixes: {CONFIRMER: "true"}
pourquoi: >-
Refaire tout depuis zero : les VM, puis le deploiement complet. Si le code ne
suffit pas, c'est ici qu'on l'apprend.
- cible: valider
nature: mesure
pourquoi: "Une reconstruction sans recette n'a rien prouve."
# ─────────────────────────────────────────────────────────────────────────────
- id: gabarit
titre: "Le gabarit dore"
portee: site
doc: docs/procedure-template-debian13-proxmox.md
but: >-
La VM de reference que toute la flotte clone. Elle nait en q35/OVMF et ne se convertit
jamais : convertir depuis i440fx casse interfaces et disques.
etapes:
- cible: gabarit-etat
nature: mesure
pourquoi: "Le gabarit porte-t-il ce que le SITE declare ? A regarder avant d'y toucher."
- cible: preparer-modele
nature: ecriture
duree: "long"
pourquoi: "Preparer la VM de reference, celle qui sera clonee pour chaque hote."
- cible: verifier-modele
nature: mesure
pourquoi: "Le gabarit tient-il ses promesses avant qu'on le capture ?"
- cible: nettoyer-modele
nature: destructif
fixes: {CONFIRMER: "true"}
pourquoi: >-
Nettoyer avant capture. Destructif pour la VM de reference : ce qui est efface ne
se retrouve pas.
# ─────────────────────────────────────────────────────────────────────────────
- id: mesurer
titre: "Mesurer sans rien ecrire"
portee: tenant
doc: docs/devis-services.md
but: >-
Les devis de service : ils confrontent ce que le plan derive a ce que le systeme rend
VRAIMENT, et sortent en erreur s'il y a un ecart. Une tache verte ne prouve pas qu'un
service rend son service.
etapes:
- cible: identite-plan
nature: mesure
pourquoi: "L'identite deployee face a ce que le plan derive."
- cible: certificats-plan
nature: mesure
pourquoi: >-
Les certificats sur disque face a ceux reellement SERVIS. Un cert renouvele mais
non recharge reste perime en memoire.
- cible: expositions-plan
nature: mesure
pourquoi: "Chaque exposition du plan repond-elle, depuis l'edge et depuis le poste ?"
- cible: expositions-etat
nature: mesure
pourquoi: "Chaque exposition est-elle servie sous un certificat qui la porte ?"
- cible: courriel-plan
nature: mesure
pourquoi: "La chaine Postfix → LDAP → Dovecot → IMAP, de bout en bout."
- cible: postgresql-plan
nature: mesure
pourquoi: "Le chiffrement impose et la portee reelle des acces."
- cible: mtu-mesurer
nature: mesure
pourquoi: "L'invite porte-t-il le MTU de sa zone ? Un MTU faux ne se voit qu'aux gros paquets."
- cible: versions-mesurer
nature: mesure
pourquoi: "De combien nos epinglages ont-ils vieilli face aux amonts ?"
- cible: ports-verifier
nature: mesure
pourquoi: "Deux roles co-localises revendiquent-ils le meme port ?"
- cible: intrants-verifier
nature: mesure
pourquoi: "Un intrant exige et non fourni est une panne differee."
- cible: flux-verifier
nature: mesure
pourquoi: "Le registre des flux correspond-il encore aux `meta/flux.yml` des roles ?"
- cible: site-intrants-verifier
nature: mesure
pourquoi: "Le locataire monte suit-il encore les intrants de son site ?"
- cible: sonder
nature: mesure
variables: [CIBLE]
pourquoi: >-
Sonder une cible et DIRE ce qui distingue absence, politique et frontiere. Un
« echec » nu ecrase ces trois causes et envoie chercher la panne ailleurs.
- cible: faits
nature: mesure
variables: [LIMITE]
pourquoi: "Les faits Ansible de la flotte, quand une hypothese demande un fait."
# ─────────────────────────────────────────────────────────────────────────────
- id: recette
titre: "La recette — avant de dire « pret »"
portee: tenant
doc: docs/audit/plan-de-recette.md
but: >-
Ce qui separe « ca a tourne sans erreur » de « c'est livrable ». Les preuves lisent le
depot ; la recette interroge la flotte. Il faut les deux.
etapes:
- cible: verifier
nature: mesure
pourquoi: "Rejouer les preuves sans reecrire le rapport — la verification rapide."
- cible: prouver
nature: mesure
pourquoi: >-
Executer les preuves et ECRIRE le rapport date. C'est le document qu'on montre,
et celui qu'on relit dans six mois.
- cible: valider
nature: mesure
pourquoi: "La recette de validation sur la flotte reelle."
- cible: verifier-deploiement
nature: mesure
pourquoi: "L'etat de la flotte, apres coup."
- cible: inventaire
nature: mesure
pourquoi: "L'inventaire se verifie et se montre — lab puis production."
# ─────────────────────────────────────────────────────────────────────────────
- id: acces-admin
titre: "L'acces d'administration (tunnel WireGuard)"
portee: site
doc: docs/acces-administration.md
but: >-
Un tunnel nominatif par locataire, declare par lui et borne a lui. Sans garde, un
ecosysteme s'ouvrirait un acces chez son voisin depuis son propre plan.
etapes:
- cible: vpn-admin-plan
nature: mesure
pourquoi: "Ce que la frontiere porte aujourd'hui, face aux pairs declares au plan."
- cible: vpn-admin-appliquer
nature: ecriture
fixes: {CONFIRMER: "true"}
pourquoi: "Poser l'instance et les pairs declares — et retirer ceux qui ne le sont plus."
# ─────────────────────────────────────────────────────────────────────────────
- id: dns-public
titre: "Le DNS public et sa signature"
portee: tenant
doc: docs/dns-interne.md
but: >-
Publier les zones du locataire, signees avant d'etre exposees. Les DS partent chez le
registraire : c'est le seul maillon que le moteur ne peut pas poser lui-meme.
etapes:
- cible: dnssec-verifier
nature: mesure
pourquoi: "Une cle en voute pour chaque zone signee, et des DS conformes au registre."
- cible: dnssec-ds
nature: mesure
pourquoi: >-
Les DS a remettre au registraire, calcules depuis la voute du locataire. A porter
a la main chez le registraire : aucun automate ne le fera.
- cible: dns-bascule-devis
nature: mesure
pourquoi: >-
Basculer nos serveurs de noms changerait-il quelque chose ? Le plan face au DNS
reellement en service, avant de toucher a la delegation.
# ─────────────────────────────────────────────────────────────────────────────
- id: filiation
titre: "Filiation, insemination, emancipation"
portee: tenant
doc: docs/filiation-emancipation.md
but: >-
D'ou vient cet ecosysteme, de quoi depend-il encore, et que faut-il couper pour qu'il
tienne seul. L'emancipation se mesure ; elle ne se decrete pas.
etapes:
- cible: genome
nature: mesure
pourquoi: "Les depots requis a la reproduction de cet ecosysteme, et leur etat."
- cible: genome-inscrire
nature: ecriture
pourquoi: "Inscrire la parente dans l'instance — sans quoi la filiation n'est qu'un souvenir."
- cible: genome-verifier
nature: mesure
pourquoi: "La parente inscrite tient-elle encore ? Le code de sortie repond."
- cible: inseminer
nature: ecriture
variables: [TENANT, HOTE]
pourquoi: >-
Le SITE amorce le runner d'un locataire, SANS ses secrets. Trois murs connus :
apt, pip, et le genome lui-meme.
- cible: depots-perimes
nature: destructif
fixes: {CONFIRMER: "true"}
# FACULTATIVE, SINON ELLE BARRE LA PREUVE QUI LA SUIT. La console
# debloque d'office une etape « mesure » ; toute autre attend que la
# precedente non facultative ait REUSSI dans la session. Un menage
# qu'on peut ne pas avoir a faire — aucun depot perime ce jour-la —
# rendrait alors l'emancipation injouable. Le ménage n'est pas un
# prealable a la preuve : il nettoie ce que la filiation a laisse.
facultative: true
pourquoi: >-
Un depot raye du plan reste sur le disque du runner, qui garde de quoi lire un
ecosysteme qu'il ne declare plus. Trois choses ne sont jamais retirees : ce qui
n'est pas un depot git, ce qui porte des modifications non validees, et ce qui
porte des commits qu'aucun distant ne porte.
- cible: emancipation-prouver
# ECRITURE, ET NON MESURE, MALGRE LE MOT « PROUVER ». La cible COUPE
# l'amont quelques secondes pour mesurer : elle refuse d'ailleurs sans
# CONFIRMER=true, et le dit. Le fait qu'elle rapporte un constat ne la
# rend pas inerte. Declarée « mesure », elle se serait offerte a tout
# outil qui ne propose que ce qui n'agit pas.
nature: ecriture
variables: [SERVICE, HOTE]
fixes: {CONFIRMER: "true"}
pourquoi: >-
Prouver qu'un lien est coupe, en le coupant. La coupure est retiree quoi
qu'il arrive, mais la fonction eprouvee peut echouer pendant ce temps.
La mesure instruit ; l'humain decide. Une emancipation automatique serait
une expulsion.
# ─────────────────────────────────────────────────────────────────────────────
- id: remise
titre: "La remise au client"
portee: poste
doc: docs/remise-au-client.md
but: >-
Deux temps qui ne se confondent pas : le paquet qu'on remet, puis le re-cle qui
mesure la revocation reelle. Tant que le temps 2 n'est pas fait, on detient encore
les cles de quelqu'un d'autre.
etapes:
- cible: remise-recenser
nature: mesure
pourquoi: "Ce qu'une remise emporterait, sans rien ecrire. A lire avant de fabriquer."
- cible: remise-paquet
nature: ecriture
variables: [VERS]
pourquoi: "Temps 1 : le paquet chiffre, et relu apres ecriture."
- cible: remise-inscrire
nature: ecriture
variables: [RECU_PAR, COURRIEL, DANS]
pourquoi: >-
Inscrire la remise chez le locataire : qui a recu, quand, et dans combien de
jours le second temps est du.
- cible: remise-verifier
nature: mesure
pourquoi: "Temps 1 fait ? Temps 2 du, ou echu ? La seule reponse qui compte est datee."
- cible: remise-recleer
nature: ecriture
fixes: {CONFIRMER: "true"}
pourquoi: >-
Temps 2 : mesurer la revocation REELLE, puis estampiller. On ne coche pas cette
case, on la mesure.
# ─────────────────────────────────────────────────────────────────────────────
- id: cles
titre: "Les cles hors du poste"
portee: poste
doc: docs/sortir-les-cles-du-poste.md
but: >-
Ce qui n'existe QUE sur le poste meurt avec lui : les CLES, et les VOUTES qu'elles
ouvrent (gitignorees, donc sur aucune forge). Les deux sortent, sur un support qu'on
relit — et on refait l'operation a chaque voute nouvelle ou modifiee.
etapes:
- cible: cles-recenser
nature: mesure
pourquoi: "Ce qui n'existe que sur ce poste, sans rien ecrire. La liste fait peur, c'est le but."
- cible: cles-exporter
nature: ecriture
variables: [VERS]
pourquoi: "Sortir les cles, chiffrees, et les RELIRE apres ecriture."
- cible: voutes-recenser
nature: mesure
pourquoi: "Les voutes de ce poste, et leur empreinte. Une voute en clair est refusee avant tout."
- cible: voutes-exporter
nature: ecriture
variables: [VERS]
pourquoi: >-
Sortir les voutes, deja chiffrees, dans leur propre archive, et la RELIRE. Sans
elles, les cles restaurees n'ouvrent rien (2026-09-28).
- cible: cles-compagnons
nature: ecriture
variables: [VERS]
pourquoi: >-
Deposer le script de restauration sur la cle. Une archive qu'on ne sait pas
rouvrir dans cinq ans n'est pas une sauvegarde.
- cible: cles-restaurer
nature: ecriture
variables: [ARCHIVE]
pourquoi: "Remettre les cles en place. A eprouver AVANT d'en avoir besoin."
- cible: depot-hors-site
nature: ecriture
variables: [VERS]
pourquoi: >-
Copier le depot de sauvegarde HORS du site. Le site heberge du chiffre et ne peut
pas le juger : la verification suit la cle.
# ─────────────────────────────────────────────────────────────────────────────
- id: lire-le-plan
titre: "Lire le plan et ce qu'il derive"
portee: tenant
doc: docs/plan-et-generation.md
but: >-
Tout ce qui se regarde sans rien changer : les registres du plan, leur validation, et
l'inventaire qui en descend. Le premier geste devant un ecosysteme qu'on ne connait pas.
etapes:
- cible: serveurs
nature: mesure
pourquoi: "Les serveurs declares au plan."
- cible: serveurs-verifier
nature: mesure
pourquoi: "Le registre des serveurs tient-il ses regles ?"
- cible: applications
nature: mesure
pourquoi: "Les applications declarees au plan."
- cible: applications-verifier
nature: mesure
pourquoi: "Le registre des applications tient-il ses regles ?"
- cible: bases
nature: mesure
pourquoi: "Les bases de donnees declarees au plan."
- cible: bases-verifier
nature: mesure
pourquoi: "Le registre des bases tient-il ses regles ?"
- cible: domaines
nature: mesure
pourquoi: "Les domaines declares au plan."
- cible: domaines-verifier
nature: mesure
pourquoi: "Le registre des domaines tient-il ses regles ?"
- cible: inventaire-lister
nature: mesure
pourquoi: "L'inventaire complet, en JSON — la verite generee."
- cible: inventaire-graphe
nature: mesure
pourquoi: "Le graphe des groupes : qui herite de quoi."
- cible: inventaire-hote
nature: mesure
variables: [HOTE]
pourquoi: "Les variables derivees d'une machine, telles qu'Ansible les verra."
- cible: inventaire-lab
nature: mesure
pourquoi: "Le graphe de l'inventaire de laboratoire."
- cible: inventaire-production
nature: mesure
pourquoi: "Le graphe de l'inventaire de production."
- cible: config
nature: mesure
pourquoi: "La configuration Proxmox telle que le moteur la lit."
# ─────────────────────────────────────────────────────────────────────────────
- id: depot-verifier
titre: "Verifier le depot avant de livrer"
portee: toute
doc: AGENTS.md
but: >-
Ce que le depot se doit a lui-meme : syntaxe, lint, tests, schema, fiches. Rien n'est
« pret » sans au moins la syntaxe du playbook touche et l'entree de CHANGELOG.
etapes:
- cible: syntaxe
nature: mesure
pourquoi: "La syntaxe de TOUS les playbooks. Jamais declarer pret si elle echoue."
- cible: lint
nature: mesure
pourquoi: "`ansible-lint` sur tout le depot."
- cible: test
nature: mesure
pourquoi: "Les tests unitaires de derivation — nomenclature et inventaire."
- cible: ci
nature: mesure
pourquoi: >-
Verifier le depot comme la CI, sur un modele public monte a l'ecart : sans jamais
toucher a l'ecosysteme monte.
- cible: schema
nature: ecriture
pourquoi: >-
Regenerer le schema du plan depuis les registres et les validateurs. C'est lui qui
construit les formulaires : un champ nouveau apparait sans toucher a l'interface.
- cible: fiches
nature: ecriture
variables: [ROLE]
pourquoi: "Regenerer la fiche de chaque role, depuis le role lui-meme."
- cible: plan-recette
nature: ecriture
pourquoi: "Regenerer le plan de recette depuis le wiki."
- cible: wiki-publier
nature: ecriture
pourquoi: "Publier le wiki vers la forge, une fois qu'il dit vrai."
# CE QUE LA CONSOLE N'OFFRE PAS, ET POURQUOI. Une exemption muette serait un oubli
# deguise : chaque ligne porte son motif, et la garde refuse une exemption vide.
hors_assistant:
aide: >-
Aide en ligne de commande. La console porte la meme information autrement — chaque
etape affiche le libelle lu dans le Makefile.
ansible-runtime: >-
Prerequis interne, appele par les cibles qui deploient. L'offrir seul donnerait un
bouton qui ne fait rien de visible.
inventaire-ui: >-
C'est cette console elle-meme. Un bouton qui la relance depuis elle-meme n'a pas d'objet.
syntaxe-modele: "Couverte par `syntaxe`, qui passe tous les playbooks d'un coup."
syntaxe-verification-modele: "Couverte par `syntaxe`."
syntaxe-nettoyage: "Couverte par `syntaxe`."
syntaxe-verification-hote: "Couverte par `syntaxe`."
syntaxe-groupes: "Couverte par `syntaxe`."
syntaxe-proxmox: "Couverte par `syntaxe`."
model-creer: >-
Fabrique un MODELE d'ecosysteme — un geste de mainteneur du moteur, pas d'exploitant.
Il se fait au poste, en connaissance du catalogue des modeles.
serveurs-bootstrap: >-
Chemin de REPRISE : reconstitue le plan depuis un inventaire existant. Il ecrit par
dessus le plan, et ne doit pas etre a un clic d'un exploitant qui explore.
applications-bootstrap: >-
Meme raison que `serveurs-bootstrap` : amorcage de reprise, pas geste courant.
cacher-paquets: >-
Se fait EN LIGNE depuis le poste, avant de partir sur un site hors ligne. Le runner,
lui, est deja derriere la frontiere : le bouton serait au mauvais endroit.
ca-racine: >-
Recupere la racine de l'AC pour l'installer sur un poste. L'empreinte doit etre
verifiee A LA MAIN avant installation — un bouton encouragerait a sauter ce controle.
ca-empreinte: >-
Le temoin de comparaison de `ca-racine`. Meme raison : il se lit, il ne se clique pas.