- prouver.py : la preuve P16 (ansible-inventory --list) devient une fonction qui
parse le JSON et rapporte « N hôtes, M groupes » au lieu de la dernière ligne
brute (`}`).
- docs/audit/preuve-2026-07-20.md : régénéré voûte exportée — 16 OK, 0 échec,
0 sautée (P16 inclus : 14 hôtes, 29 groupes).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le dépôt fait / explique / prouve ce qu'il affirme, vérifiable en une commande.
- Phase 1 : docs/audit/affirmations.md — 54 affirmations publiques tracées vers
une commande de preuve et un statut (✅/🟡/❌/⚪).
- Phase 2 : CLAUDE.md réduit à un pointeur mince ; contradiction SSH levée (le
code applique déjà PasswordAuthentication no + AuthenticationMethods publickey,
conforme à AGENTS.md) ; section AGENTS « Codex » → « agents IA ».
- Phase 3 : parcours démarrage réparé (QUICKSTART renvoyait à un modèle absent,
chemins de voûte faux, commandes make périmées) ; make verifier vert
(ansible-lint 33 → 0 : site.yml généré nommé, pipefail, name[template]) ;
voûte Proxmox unifiée lue par le clonage (all/vault.yml).
- Phase 4 : make prouver → docs/audit/preuve-<date>.md, harnais rejouable qui
rappelle l'outillage existant (aucune validation réimplémentée).
- Phase 5 : parcours QUICKSTART prouvé hors-ligne sur le socle ; modèle socle
rendu valide (autorite interne → auto-heberge) ; split-brain d'inventaire
corrigé (repli sur le répertoire existant, pas principal/).
make prouver : 15 OK, 0 échec, 1 sautée (voûte). ansible-lint : 0 failure.
Écarts découverts en cours de traitement (AFF-097..100) : tous résolus.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nouvel onglet lecture seule affichant le devis make devis-reseau (VLANs+SVIs+ACLs)
via GET /api/devis-reseau, avec bouton Copier. node --check OK, endpoint eprouve
(2 tenants, 121 lignes). Un operateur genere et transmet la config sans CLI.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
scripts/devis_reseau.py decouvre les instances federees (ip-miroir) et emet
VLANs + SVIs + ACLs d'isolation inter-tenant, derives des nomenclatures.
Plus jamais saisi a la main. Eprouve sur Chezlepro + Technolibre.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Quand une action échoue, un encadré résume les tâches en erreur (étape ·
hôte · type · message clair), avec un bouton Copier pour transmettre à un
humain — au lieu d'obliger à lire le dump Ansible.
Backend _extraire_echec : parse fatal:/UNREACHABLE!, privilégie stderr sur le
générique 'non-zero return code', gère no_log (secret masqué) et injoignables.
Marqueur __RESUME__ streamé, rendu côté JS. Éprouvé sur les 4 échecs réels du
from-zero du jour. node --check OK, smoke serveur OK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le registre des domaines publics — seul sans éditeur — a désormais son onglet :
ajouter/retirer une zone, autorité (sélecteur), edge, DNSSEC, mail, secondaires,
et affichage des expositions (FQDN) sous la zone. Backend : route /api/domaines,
ecrire_domaines, validation valider_domaines (rejette une autorité inconnue).
Éprouvé : round-trip backend (valide/écrit/rejette interne), node --check, smoke serveur.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Chaque action (creer-vm/verifier/deployer) écrit un journal horodaté
<instance>/logs/<hote>-<action>-<date>.log en plus du streaming live.
Si le navigateur se déconnecte, l'exécution continue et le log est capturé
jusqu'au bout (au lieu d'être interrompue). node --check OK, serveur HTTP 200.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SECRETS_ATTENDUS listait 16 secrets ; en manquaient 8 (OIDC des 3 clients,
cookie oauth2, restic, clé SSH sauvegarde, + nextcloud admin/oidc/bd). Le
panneau Intrants du GUI montre désormais la vraie liste (noms seulement, jamais
de valeur — la garde d'écriture des secrets reste inchangée).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deux onglets qui rendent visibles dans l'interface deux registres jusque-là
en CLI seulement :
- Flux : matrice d'audit réseau (rôle/sens/port/pair/chiffrement coloré/raison,
depuis les meta/flux.yml), + légende chiffrement dans le panneau latéral.
- Couches : ordre de reconstruction (socle -> pki -> services -> apps -> agents),
groupes triés topologiquement par couche.
Alimentées par resoudre_flux/orchestrer via l'API inventaire. Éprouvé :
node --check OK, smoke test serveur (63 flux, 6 couches servis, boutons présents).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le panneau « Intrants de base » expose désormais nftables_admin_ssh (type liste,
section Sécurité) — la garde anti-lockout du pare-feu, éditable en fichier mais
absente du GUI. Retrait de vault_step_ca_fingerprint des secrets attendus
(empreinte du root CA dérivée dynamiquement maintenant). node --check OK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reconstruction complète prouvée (14 VM + sauvegardes + AC supprimées, puis
`make myDay` rebâtit tout ; `make valider` entièrement vert). Bugs corrigés :
- client_pki : empreinte du root CA dérivée dynamiquement de l'autorité
(au lieu d'une valeur figée en Vault) — une AC régénérée a une empreinte neuve.
- serveur_keycloak : assignation de rôle tolérante aux utilisateurs absents
(annuaire vide sur un from-zero).
- serveur_prometheus : ne scrute que les hôtes ACTIFS (client_metrique ∩ hotes_actifs).
- nftables résolu : compatible Docker — remplace la seule table setops_flux (pas de
flush ruleset, préserve les tables Docker) + forward autorise docker0/established.
Sans ça, forward policy drop coupait Collabora (conteneur).
Ajoute playbooks/proxmox/supprimer_vm_debian.yml (suppression par VMID, garde-fous).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sur un trunk convergé (tenants partagent l'infra), les VLAN doivent être uniques
GLOBALEMENT. deriver_nomenclature (ip-miroir) dérive VLAN = index×10 + zone : chaque
tenant son bloc de 10, 1-9 réservés à l'infra partagée. Le VLAN contenant le tenant,
le VMID mène avec le VLAN (VLAN·octet·seq, ≤ 9 chiffres Proxmox). compact (lab)
inchangé. GUI (miroir) + validation 1-4094 : compatibles.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Élimine 3 gotchas du spike Nextcloud/Collabora :
- instancier dérive sans_exposition par edge (FQDN exposés du plan) → le cert edge
(client_pki_sans) se met à jour tout seul, plus de liste manuelle en group_vars ;
- champ 'websocket' sur une application → le vhost d'exposition ajoute la map
$http_upgrade + en-têtes Upgrade/Connection + timeout long (Collabora, éditeurs live) ;
- (plancher /etc/hosts : le mécanisme d'alias existait déjà, publier_expositions=true).
Prouvé sur le lab : cert edge couvre les 6 expositions, bureau 200 en WebSocket.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fin des dernières poches de 'codé en dur' liées à l'instance d'origine :
- realm SSO centralisé sur l'intrant identite_realm (defaut chezlepro,
retro-compatible) ; les 4 rôles (keycloak/forgejo/grafana/oauth2_proxy)
en dérivent. Expose dans la GUI (panneau Intrants).
- vars brandees renommees generiques : chezlepro_timezone -> fuseau_horaire,
chezlepro_organisation -> organisation (chrony, openldap, GUI, docs).
Aucune reference fonctionnelle aux anciens noms. Le moteur ne porte plus le
nom d'un tenant. Technolibre a son propre realm (technolibre).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nouveau schema VMID 'ip-miroir' (vmid_schema dans la nomenclature) : 9 chiffres
I·VVV·HHH·NN = index·VLAN·octet-hote·sequence. Le VMID contient l'IP
(10.(10+index).VLAN.hote) + le tenant → lecture directe. Defaut 'compact'
(retro-compatible) : les instances existantes (lab) gardent leurs VMID.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Audit des boutons : « Pousser » était surchargé — servait à cloner la VM
(🖥 Pousser = creer-vm) ET à déployer (= make deployer, identique à
« Déployer »). Corrigé :
- 🖥 Pousser -> « 🖥 Créer la VM » (il clone) ;
- tous les Pousser/Déployer -> « Déployer » (une action = un mot) ;
- dry-run obligatoire AUSSI sur le déploiement des pieds (évite un
déploiement à l'aveugle ; cohérent avec un seul « Déployer ») ;
- titres/messages/console : Poussée -> Déploiement.
Chaque bouton fait désormais ce qu'il dit. GUI déjà entièrement francisée.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Une application déclare ses liens ([{vers, role}]) dans applications.yml ;
chaque rôle décrit les liens acceptés dans meta/liens.yml. instancier
résout la cible (FQDN interne dérivé de la nomenclature) et injecte les
variables en host_vars du consommateur.
Migration prouvée : les liens mail Postfix→Dovecot (mailstore) et
Postfix→rspamd (milter) passent de group_vars codés en dur à des liens
déclaratifs — make instancier donne DIFF VIDE (mêmes vars générées).
Cf. docs/bindings-conception.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Les groupes etaient deployes en ordre alphabetique -> client_pki (c)
passait AVANT serveur_debian (s), donc avant que hosts_statiques ne pose
/etc/hosts. Sur un noeud frais, client_pki ne pouvait pas resoudre l'AC
interne (« no such host ») et echouait au bootstrap.
L'ordre force desormais le socle en tete (serveur_debian, serveur_durci)
puis le reste : socle -> client_* -> services. Trouve en deployant un
noeud identite frais (client_pki avant socle).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- TLS LDAPS/STARTTLS : pont du cert step_ca (client_pki, root:root 600)
vers /etc/ldap/tls lisible par openldap ; script + unité path systemd
qui re-synchronise et recharge slapd au renouvellement ; olcTLS* dans
cn=config ; SLAPD_SERVICES expose ldaps://. Dégrade proprement sans cert.
- Organisation : intrant chezlepro_organisation (remplace « Exemple Inc »).
Validé statiquement (ansible-lint, syntax) ; déploiement réel à suivre.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Une voûte chiffrée group_vars/all/vault.yml fait échouer
ansible-inventory --list (comparaison du plan) sans mot de passe →
« Appliquer le plan » cassé dès qu'une voûte existe. instancier utilise
maintenant ~/.config/setops-vault-pass si ANSIBLE_VAULT_PASSWORD_FILE
n'est pas déjà fourni. Validé : plus d'exit 4.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sans lui, le dry-run ne peut pas déchiffrer les secrets → les rôles à
secrets (step_ca, etc.) échouaient au Vérifier même avec des secrets
présents, et une voûte chiffrée aurait bloqué TOUT Vérifier. La modale
autorise un mot de passe vide (hôtes sans secrets = comportement actuel).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bug racine : /api/instancier appelait « instancier appliquer » SANS
--force → refus silencieux dès que le plan divergeait de l'inventaire.
Après une édition (disque, état, auto-actif), l'inventaire n'était jamais
régénéré → compteurs figés (« 0 actifs » alors qu'un hôte était actif au
plan). Le clic « Appliquer » = intention explicite → on force.
Aussi :
- après matérialisation (creer/deployer/pousser), le frontend régénère
l'inventaire (appliquerPlan) au lieu d'un simple rechargement ;
- compteur « vivantes » dans l'en-tête (depuis la sonde).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le badge planifié/actif = intention du plan, pas existence de la VM.
- Sonde de vie : /api/sondes teste la joignabilité SSH de chaque hôte
(parallèle, non bloquant) → point ● vivante/injoignable sur les tuiles
et dans le détail (« Plan : … · Réel : … »).
- Auto-actif : un hôte cloné (creer) ou déployé passe actif dans le plan
automatiquement (matérialisé = actif).
Répond au constat « serveur planifié alors qu'il est vivant ».
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Chaque objet du détail se matérialise sur son hôte, en streaming console
(vault + confirmation prod) :
- Serveur → 🖥 Pousser clone la VM (make creer-vm), même sur un planifié —
comble le trou : le GUI ne clonait pas.
- Application → Pousser déploie l'hôte porteur.
- Base → Pousser déploie l'hôte du serveur de BD (crée la base).
Nouveaux modes creer/pousser dans executer_flux + routes /api/creer et
/api/pousser. Flux complet : éditer → Appliquer → Pousser → Vérifier →
Déployer, sans quitter le navigateur.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Depuis la fusion maître-détail, elle ne répétait que le socle (universel),
les rôles des applications (déjà listées) et les intégrations (déjà
cochées). Le prérequis bloquant — son seul signal unique — est désormais
nommé dans le pied. Code mort retiré (renduGroupe, detailGroupe,
titreGroupe, CSS .groupe*).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le VMID n'est plus codé 9CSNN en dur : il prend le préfixe d'un `index`
déclaré en tête de plan/nomenclature.yml. Convention : supernet =
10.(index*10).0.0/16, VMID = index·CSNN. Permet à N écosystèmes de
coexister sans collision (Chezlepro=1, Technolibre=2). Sans index →
9CSNN (rétro-compatible, bacs à sable en 172.19.x). deriveServeur JS
mort retiré. Doc multi-instances.md mise à jour.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
make instance-utiliser NOM=… repointe le symlink 'instance' (prod ↔ bac à
sable) ; make instance-courante affiche le montage. Le panneau Intrants lit
l'identité dans group_vars/all/10-intrants.yml de l'inventaire monté (réel
ou symlink partagé), donc compatible avec la séparation par instance comme
avec l'ancien partage lab/production.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le déploiement réel est permis sur TOUTE instance (un bac à sable déploie
sur son infra lab : isolé ET fonctionnel). Le drapeau ne bloque plus ;
il marque la PROD pour exiger une confirmation renforcée (badge/bouton
rouge, re-saisie du nom d'hôte). executer_flux ne refuse plus selon le
drapeau. Badge « PROD » / « bac à sable » dans l'en-tête.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le moteur ne code plus en dur inventories/lab|production : un inventaire
par instance, détecté de façon rétro-compatible (principal > production >
lab) et surchargeable par SETOPS_INVENTAIRE. Makefile (définitions seules,
pas les 47 usages), inventory_gui, instancier, config_proxmox, serveurs,
applications. Les instances lab/production existantes marchent à
l'identique ; les nouvelles adoptent inventories/principal/.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le droit de déployer ne dépend plus du nom de l'inventaire mais d'un
drapeau explicite setops_production dans group_vars/all/ de l'instance
(true = prod, false = bac à sable). Le GUI (champ "production" de l'API) et
executer_flux le lisent ; rétro-compatible (à défaut, ancien repère
"inventaire production"). Première pierre de la séparation par instance.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fini les voûtes éparpillées : tous les secrets (token Proxmox + vault_*)
vivent dans group_vars/all/vault.yml, un seul fichier chiffré, un seul mot
de passe. Gabarit committé exemples/vault.exemple.yml (17 clés). make config
écrit/édite cette voûte (semée depuis le gabarit si absente). .gitignore
durci (**/vault.yml). Docs : config-proxmox.md (+ migration), intrants-
communs.md §H, QUICKSTART. Le GUI ne stocke aucun secret.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
L'intrant de base global chezlepro_timezone était défini mais jamais
appliqué : le rôle chrony règle désormais le fuseau horaire (chrony_timezone,
vide = ne pas toucher). Nettoyage du CSS/HTML devenu mort après la refonte
maître-détail (.message, .chip-f, .onglet*, .base-ligne, .ch-grp*, etc.).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Toutes les vues adoptent le même motif que l'Inventaire : tuiles à
gauche, détail + saisie à droite, panneau droit contextuel (fin du
panneau figé au changement de vue). Applications et Bases passent en
maître-détail ; liens cliquables entre objets.
Les vues Inventaire (hôtes) et Serveurs (plan) faisaient doublon : elles
sont fusionnées en une vue Serveurs unique — tuile avec statut de
réconciliation, détail réunissant identité éditable, dérivés, groupes,
applications/bases hébergées et Vérifier/Déployer. Navigation clavier et
filtre rebranchés sur les serveurs ; bandeau « Comment lire ce parc ».
Code mort retiré (carte, renduChaine, ONGLETS, champLecture, sélection
d'hôte, chips de filtre).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Son contenu (renduChaine) est déjà accessible, par hôte, dans l'onglet
« Chaîne » du détail de la vue Inventaire ; la vue ne faisait que le
répéter pour tous les hôtes. Retire le bouton, le rendu dessinerArbre et
le CSS .arbre-* ; raccourcis clavier ramenés à 1-4. La chaîne reste
consultable hôte par hôte.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Les champs libres deviennent des sélections alimentées par les paramètres
globaux : Nœud et Stockage puisent dans de nouveaux catalogues
proxmox_noeuds / proxmox_stockages (vide = défaut global), Intégrations
liste les rôles client_* disponibles (scan roles/client_*). Les catalogues
(Nœuds/Stockages/Ponts) sont des intrants de classe « Catalogue » éditables
dans le panneau Intrants ; ajout du type `liste` (chaîne virgulée → liste
YAML dédoublonnée) et de integrations_disponibles dans l'API.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Notifications empilées (toasts) au lieu d'une bannière écrasée, durée
d'exécution en direct sur les opérations longues, navigation clavier
(1-5 / j-k / v / d / Ctrl+S contextuel), validation inline des champs du
plan (vue Serveurs), garde-fou beforeunload, bouton Sauvegarder contextuel
(fin de l'impasse 409).
Convertit le détail de la vue Inventaire (cartes) en inspection lecture
seule : la vue annonçait « généré depuis le plan » tout en exposant une
surface d'édition non persistable. Retire les contrôles orphelins
(+ Hôte, ✕, bascule d'état, ✨ Proposer, champs et groupes éditables) et
le code mort associé ; conserve Vérifier / Déployer et les onglets. CSS
inutilisé nettoyé. L'édition reste dans Serveurs / Applications / Bases.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Nouveau panneau « ⚙ Intrants » pour saisir d'un endroit unique les
valeurs communes à l'écosystème, avec distinction constantes (non
surchargeables) vs défauts (surchargeables dans les instances). Les
secrets ne sont jamais saisis ni affichés (garde INTRANTS_CLES_INTERDITES
+ filtrage par schéma) ; un domaine_interne vide est refusé et son
changement demande confirmation. Ajoute aussi les info-bulles d'aide au
survol des champs. domaine_interne/chezlepro_timezone consolidés en une
source partagée (inventories/partage/intrants-identite.yml).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Les cœurs/RAM/disque d'une VM sont estimés depuis l'empreinte des rôles
hébergés (roles/<rôle>/meta/empreinte.yml) sommée au socle SE, au lieu
d'hériter des specs du golden template. Le générateur écrit
proxmox_coeurs/memoire/disque_taille ; le clonage les passe à Proxmox
(omit si absent → aucune régression). Override par hôte dans le plan.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>