CHAMPS_ECRITS_A_LA_MAIN est vide. Serveurs et applications, les deux plus gros, sont passes au generateur — chargement, rendu et sauvegarde. L EPREUVE QUI COMPTE. Ouvrir chaque vue et enregistrer sans rien toucher doit renvoyer exactement le plan qu on vient de lire : 14 serveurs, 25 applications, 2 domaines, 4 bases, IDENTIQUE partout. C est ce qui separe un formulaire genere d un formulaire qui en a l air — un champ visible a l ecran et perdu en silence a l enregistrement serait le pire des deux mondes. test_rendu_gui.py le mesure a chaque make prouver. TROIS DEFAUTS TROUVES EN CHEMIN. Le formulaire annoncait des defauts INVENTES : 2048 Mo, 2 coeurs, 16G. Il n existe aucun defaut fixe — deriver_ressources calcule depuis les roles portes (1024 et 1 pour infra-pki-01, 5632 et 4 pour collab-01). Un repere faux fait croire qu on connait la valeur. Le schema nomme le champ derive, et l ecran montre la valeur reelle de cet hote. L option vide d un select dit desormais ce qu elle produira : « (defaut : asgard) ». Une SECONDE occurrence du defaut d hier dormait dans sourceDeValeurs : elle lisait encore data.nomenclature. Elle n avait jamais leve parce que la vue Serveurs, seule a emprunter cette source, avait un formulaire ecrit a la main. Elle a leve a la seconde ou le generateur l a prise. Le banc ne voit que les chemins vivants : verifier_gui.py fait donc aussi une verification STATIQUE, qui voit ce qui dort. La validation client s accrochait a data-v, pose a la main sur trois champs. Le formulaire genere l aurait perdu et la validation serait passee au vert sur ZERO champ. Le generateur marque chaque controle, et la sauvegarde refuse si elle n en inspecte aucun. DEUX CHAMPS GARDENT LEUR EDITEUR, et le schema le dit (x-editeur) : la matrice des integrations montre les universelles et les exemptions, et l editeur de liens contraint le role a meta/liens.yml. Le generateur s efface plutot que de remplacer un editeur qui en sait plus que lui. LIMITE : je n ai toujours pas ouvert ces pages dans un navigateur. make prouver : CONFORME, 61 OK, 0 echec, 1 saute. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q
172 lines
9.4 KiB
Markdown
172 lines
9.4 KiB
Markdown
# Le GUI (console d'exploitation)
|
||
|
||
> **Unité d'apprentissage.** Moule : ① concept → ② Set-OPS → ③ transférable → ④ à toi de jouer.
|
||
|
||
---
|
||
|
||
## ① Le concept *(générique)*
|
||
|
||
Un moteur d'infrastructure a besoin d'une **interface humaine** — sinon il n'est utilisable que
|
||
par son auteur (ou une IA). Le principe fondateur : **un opérateur doit tout piloter seul**, sans
|
||
l'auteur et sans IA (« exploitable sans IA »).
|
||
|
||
Une bonne console d'exploitation obéit à trois règles :
|
||
|
||
- **Elle édite la SOURCE, pas l'artefact.** On modifie le *plan* (l'état voulu), jamais l'inventaire
|
||
généré. La console montre la vérité, elle ne la contourne pas.
|
||
- **Elle prévisualise avant d'agir.** *dry-run* (voir ce qui changerait) avant *apply* (changer).
|
||
- **Elle empêche l'invalide.** Le meilleur garde-fou n'est pas un message d'erreur : c'est une
|
||
interface où l'erreur est **impossible à saisir**.
|
||
|
||
---
|
||
|
||
## ② Comment Set-OPS le fait
|
||
|
||
`make inventaire-ui` lance une console web **locale** (`127.0.0.1`, protégée par un jeton). Ses vues :
|
||
|
||
| Vues **éditables** (le plan) | Vues **dérivées** (lecture seule) |
|
||
|---|---|
|
||
| Serveurs · **Intégrations** · Applications · Bases · Domaines · **Nomenclature** · **Intrants** | Flux · Couches · **Réseau** (flotte + devis) |
|
||
|
||
Le flux d'exploitation, de bout en bout :
|
||
|
||
1. **Éditer** une vue du plan → **Sauvegarder** ;
|
||
2. **« Appliquer le plan »** → régénère l'inventaire (VMID/IP/VLAN **dérivés**) ;
|
||
3. **Vérifier** (dry-run) sur un hôte → prévisualise sans rien changer ;
|
||
4. **Déployer** → applique les rôles (confirmation **renforcée** si l'instance est en **PROD**) ;
|
||
5. **Créer la VM** → clone sur Proxmox depuis le plan.
|
||
|
||
**L'erreur rendue impossible.** Le champ « Hôte » d'une application est un `<select>` qui ne
|
||
propose que des **hôtes réels** : impossible de pointer vers un hôte fantôme. La console couvre le
|
||
schéma du plan — et la preuve **P19** le vérifie.
|
||
|
||
**Les formulaires sont GÉNÉRÉS.** Depuis le 2026-09-08, **les six registres** — serveurs,
|
||
applications, bases de données, serveurs de BD, domaines et nomenclature — ne portent plus de
|
||
formulaire écrit à la main : ils le construisent depuis `docs/audit/schema-plan.json`, lui-même
|
||
dérivé des constantes du moteur (`make schema`). Un champ ajouté au plan apparaît donc à l'écran
|
||
**sans qu'on touche à l'interface** — et il arrive au fichier, parce que la sauvegarde dérive du
|
||
même schéma. Ouvrir une vue et enregistrer sans rien toucher renvoie **exactement** le plan qu'on
|
||
vient de lire ; c'est mesuré à chaque `make prouver`.
|
||
|
||
Deux champs gardent volontairement leur propre éditeur, et le schéma le déclare : la **matrice des
|
||
intégrations** (elle montre aussi les universelles, non décochables, et les exemptions) et
|
||
l'**éditeur de liens** (il contraint le rôle à ce que `meta/liens.yml` accepte). Le générateur
|
||
s'efface plutôt que de remplacer un éditeur qui en sait plus que lui.
|
||
|
||
Deux preuves tiennent le schéma : **P61** refuse qu'un champ des plans réels
|
||
manque au schéma, ou que le schéma décrive une *forme* que les plans n'ont pas ; **P62** refuse
|
||
qu'un champ accepté par les *validateurs du moteur* manque au schéma — sans quoi le formulaire ne
|
||
saurait pas offrir une fonctionnalité que Set-OPS possède déjà.
|
||
|
||
**Sauvegarder n'efface plus les commentaires du plan.** Les registres portent la mémoire écrite des
|
||
décisions — pourquoi `backup-01` a été retiré, dans quel ordre les rôles du runner s'appliquent.
|
||
Jusqu'au 2026-09-08, chaque « Sauvegarder » en détruisait **quarante lignes**. Les quatre écrivains
|
||
passent désormais par une fusion ligne à ligne : un aller-retour sans modification laisse le
|
||
fichier **identique à l'octet**.
|
||
|
||
**La flotte, dans la vue Réseau.** Voir toutes les instances, **basculer** (« Activer »), **créer**
|
||
une instance depuis un modèle, repérer une **collision** d'index. Cf.
|
||
[Multi-instance & fédération](Multi-instance-et-fédération).
|
||
|
||
### Les vues, annotées
|
||
|
||
Chaque figure porte ses **repères** (pastilles + légende). Les vues **éditables** d'abord (le plan),
|
||
puis les vues **dérivées** (lecture seule) :
|
||
|
||
**Serveurs** *(éditable)* — inventaire actif et état de la flotte ; cartes serveur et tuiles
|
||
VMID/IP/VLAN **dérivées** du seed ; formulaire **Identité** = le seul endroit où l'on édite le plan.
|
||
|
||

|
||
|
||
**Nomenclature** *(éditable)* — le **modèle** dont tout l'adressage dérive : zones de sécurité,
|
||
fonctions (catégorie · service), réservations. Chaque fonction montre **ce qu'elle dérive** — zone,
|
||
VLAN, sous-réseau, bloc d'hôtes — et les VM qui la portent ; on ne retire pas une fonction encore
|
||
portée. L'`index` y est **affiché mais pas éditable** : il est *alloué par le site*, pas décidé par
|
||
le tenant (cf. l'en-tête de `plan/nomenclature.yml`), et s'édite depuis le panneau **Intrants**.
|
||
|
||
**Applications** *(éditable)* — catalogue des applis, éditeur (rôle · hôte · port · FQDN exposé),
|
||
relations déclaratives (requiert · liens · bases), dépendances causales.
|
||
|
||

|
||
|
||
**Bases — serveur** *(éditable)* — les moteurs SGBD et les bases applicatives « nom @ serveur »,
|
||
avec les bases hébergées sur chaque serveur.
|
||
|
||

|
||
|
||
**Bases — fiche** *(éditable)* — portée · consommateur · serveur, **secret Vault** (jamais en clair,
|
||
un pointeur seulement) et le **DSN dérivé** (secret masqué).
|
||
|
||

|
||
|
||
**Domaines** *(éditable)* — zones DNS publique vs interne, autorité · edge · DNSSEC, expositions.
|
||
|
||

|
||
|
||
**Intégrations** *(éditable)* — la **matrice serveurs × intégrations**. Les colonnes ✓ vertes
|
||
sont la **politique des rôles** : elles s'appliquent à tout hôte et ne se décochent pas ; un `—`
|
||
barré signale une **exemption dérivée du service rendu** (l'AC ne s'enrôle pas auprès d'elle-même).
|
||
Les autres colonnes sont de vrais choix, cochables ici. La ligne **couverture** ne juge pas — elle
|
||
rend le motif visible : c'est au lecteur de savoir si les manquants sont des décisions ou des oublis.
|
||
|
||
> Cette vue existe parce que la fiche de détail ne montrait les intégrations que **d'un serveur à
|
||
> la fois**. Deux serveurs sans supervision ni journaux sont restés invisibles jusqu'à ce qu'un
|
||
> devis de pare-feu les énumère : l'information était à l'écran, répartie sur quatorze clics.
|
||
|
||
**Flux** *(dérivée)* — la **matrice d'audit** : la source de nftables *et* la justification lisible
|
||
de chaque flux (sens ingress/egress, chiffrement).
|
||
|
||

|
||
|
||
**Couches** *(dérivée)* — l'**ordre de déploiement** en 6 couches, du socle aux agents ; celui que
|
||
`make deployer-tout` déroule.
|
||
|
||

|
||
|
||
**Réseau** *(dérivée)* — la **flotte multi-instances** : adressage dérivé du seed, bascule
|
||
d'instance, devis de configuration des switches.
|
||
|
||

|
||
|
||
> Chaque figure est un **SVG auto-contenu** (la capture y est intégrée) : un seul fichier portable
|
||
> qui rend tel quel dans le wiki, un `.md` du dépôt, ou un navigateur.
|
||
|
||
---
|
||
|
||
## ③ Pourquoi c'est transférable
|
||
|
||
| Set-OPS | Équivalents ailleurs |
|
||
|---|---|
|
||
| GUI au-dessus d'Ansible | **AWX** / Ansible Automation Platform, **Semaphore** |
|
||
| éditer la source de vérité | l'UI de **NetBox** (IPAM/DCIM), une CMDB |
|
||
| dry-run → apply | `terraform plan/apply`, tout panneau IaC |
|
||
| l'invalide impossible à saisir | *validation à la source*, formulaires contraints |
|
||
|
||
Tu as appris **la console d'exploitation, éditer-la-source, dry-run-avant-apply, la validation à la
|
||
saisie** — pas « le GUI de Set-OPS ».
|
||
|
||
---
|
||
|
||
## ④ À toi de jouer
|
||
|
||
1. **Lance-la.** `make inventaire-ui`, ouvre l'URL affichée. Repère l'inventaire actif et l'état de
|
||
la flotte (en haut), les onglets, « Appliquer le plan », « Sauvegarder ».
|
||
2. **Édite → prévisualise.** Vue **Serveurs**, change la mémoire d'un hôte, **Sauvegarder**,
|
||
**Appliquer le plan**, puis **Vérifier** (dry-run) : tu vois ce qui *changerait* avant d'agir.
|
||
3. **Répare un hôte fantôme (l'erreur impossible).** Si une appli pointe un hôte inexistant, ouvre
|
||
la vue **Applications**, sélectionne-la : le `<select>` « Hôte » ne montre **que des hôtes
|
||
réels**. Choisis le bon, **Sauvegarder**, **Appliquer**. Tu ne *peux pas* re-saisir le fantôme.
|
||
4. **Bascule d'instance.** Vue **Réseau**, bouton **« Activer »** sur une autre instance. Toutes
|
||
les vues suivent, sans redémarrer.
|
||
5. **Sens le garde-fou.** Essaie de sauvegarder un plan incohérent (ex. une base dont le
|
||
consommateur n'existe pas) : la console **refuse** avec une raison. L'invalide ne passe pas.
|
||
6. **Casse & répare.** Édite `hosts.yml` à la main, reviens dans la GUI, « Appliquer le plan » : ta
|
||
modification est **écrasée** par le plan. La source de vérité, c'est le plan — pas l'inventaire.
|
||
|
||
---
|
||
|
||
## Pour aller plus loin *(dépôt)*
|
||
- Lancer : `make inventaire-ui` ; le code : `scripts/inventory_gui.py`.
|
||
- Ce que le GUI sait écrire (et la preuve) : `scripts/couverture_gui.py` (P19).
|
||
- Le flux plan → apply : unité **[Infra as Code & idempotence](Infra-as-Code-et-idempotence)**.
|
||
- La flotte : unité **[Multi-instance & fédération](Multi-instance-et-fédération)**.
|