Première figure d'illustration de la doc : capture de la vue Serveurs du GUI
(docs/img/Set-OPS-Serveurs.png) + sa version annotée en SVG AUTO-CONTENU
(docs/img/Set-OPS-Serveurs-annote.svg) — le PNG y est intégré en base64, un
seul fichier portable (rend dans les .md, le wiki Forgejo, un navigateur).
8 repères aux couleurs Alliance Boréale + légende : inventaire actif & flotte,
onglets/registres, « Appliquer le plan », carte serveur dérivée, tuiles
VMID/IP/VLAN dérivées du seed, formulaire IDENTITE (édition du plan),
intégrations client_*, dépendances causales (garde-fou requiert/manquant).
À intégrer aux .md quand la série de captures sera complète.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Demande explicite et repetee de l'operateur : gerer les instances DEPUIS le GUI.
- Inventaire resolu DYNAMIQUEMENT : le serveur figeait l'inventaire au demarrage
(args.inventaire.resolve()). Il est desormais relu depuis le symlink instance/
a chaque requete (propriete Gestionnaire.inventaire) -> la bascule prend effet
sans redemarrer. Les FICHIER_* de plan suivaient deja le lien. SETOPS_INVENTAIRE
force encore un inventaire fixe (CI).
- POST /api/instance-utiliser + basculer_instance(nom) : repointe le symlink avec
les garde-fous de make instance-utiliser + validation STRICTE (nom doit etre une
instance decouverte -> pas de traversee de chemin ; ../etc refuse, teste).
- Vue Reseau : bouton « Activer » par instance dans la table de flotte. Confirme
(avertissement renforce si production), bascule, recharge -> toutes les vues et
les deploiements visent la nouvelle instance.
L'edition de federe reste au CLI (rarement change) ; la bascule est CLI ET GUI.
docs/carte-set-ops.md : la ligne Multi-instance du tableau des mecanismes documente
la decouverte (glob des dossiers freres, aucun registre) et le garde-fou P21.
Valide : node --check ; bascule testee de bout en bout (repoint -> inventaire
dynamique suit -> traversee refusee -> restauration) ; make verifier rc=0
CONFORME 21/21.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GUI (vue Réseau) :
- nouvelle vue FLOTTE (endpoint /api/instances) : liste les instances, marque
l'active (star), montre index / plage VLAN / statut federe-local / prod, et
affiche une banniere de COLLISION d'index — le pendant visuel de make instances
et de la preuve P21.
- le devis n'affiche plus que les instances FEDEREES (coherent avec le filtre
federe ; le labo local en est ecarte).
- retire les deux mentions perimees de « ip-miroir » (concept supprime a la
rupture ; la decouverte se fait desormais sur `index`).
La bascule d'instance et l'edition de `federe` restent au CLI (chirurgie de
symlink / drapeau rarement change) : plan de controle gele.
docs/multi-instances.md :
- section « Gerer la flotte » (make instances, bascule, les deux reflexes).
- section « Comment le moteur decouvre les instances » : convention de dossiers
freres (glob ../*/plan/nomenclature.yml), pas de registre.
- « Adressage federe » reecrit : il mentait encore (VMID compact 21101/1CSNN,
sandbox « sans index », plafond 9). Remplace par le modele derive du seed
(tableau des formules, VMID ip-miroir, drapeau federe: false, plafond reel 245).
- corrige les mentions residuelles de `supernet` a saisir (c'est `index`).
Valide : node --check du GUI, make verifier rc=0 CONFORME 21/21.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
La bascule d'instance existait deja (make instance-utiliser / instance-courante,
repointage du symlink). Manquaient la vue d'ensemble et le filet de securite.
- make instances (scripts/instances.py) : liste les instances de la federation
(depots freres avec plan/nomenclature.yml), marque l'active (*), montre index,
plage VLAN derivee, statut federe/local et production. Lecture seule.
- Detection de collision d'index entre instances FEDEREES (memes VLAN/VMID sur le
trunk) : le piege exact vecu (prod + labo tous deux a l'index 1) est desormais
crie. Mode --verifier -> rc=2 sur collision.
- Preuve P21 : cable ce garde-fou dans make prouver / make verifier. No-op quand
moins de deux instances federees sont presentes (comme P17 sans SETOPS_MODELES).
Valide : make instances liste les 3 instances (labo LOCAL, Technolibre + Chezlepro
federees, index 2 et 13) ; detection testee en synthetique (deux federees meme
index -> collision ; labo federe:false -> coherent) ; make verifier rc=0
CONFORME 21/21.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deux corrections, revelees quand Chezlepro a eu deux instances (labo index 1 +
prod index 13) decouvertes par le devis :
1. Collision de noms. prefixe() reduisait OPS-Chezlepro ET OPS-Chezlepro-lab au
meme "CHEZ" (retrait de -lab + troncature 4 lettres) -> deux VLAN "CHEZ-Frontiere"
et surtout deux ACL "CHEZ-ISOLATION", que le switch aurait FUSIONNEES (config
cassee). Les noms sont desormais qualifies par l'index (CHEZ1-*, CHEZ13-*,
TECH2-*) : uniques, et le tenant + son index se lisent dans le nom. Les numeros
de VLAN encodaient deja l'index ; les noms le font maintenant aussi.
2. Drapeau federe. decouvrir() saute toute nomenclature avec `federe: false`
(defaut true). Permet d'exclure un bac a sable LOCAL (labo, sans remote, pas sur
la fabric de production) : on ne provisionne pas ses VLAN sur les switches de
prod. Le labo genere toujours son propre inventaire.
Verifie : make devis-reseau -> labo (1011-1016) exclu, restent Technolibre
(1021-1026) et Chezlepro prod (1131-1136) ; SVI/ACL coherents (access-group ==
nom d'ACL) ; make verifier rc=0 CONFORME 20/20.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Principe : les valeurs de configuration se derivent des intrants, elles ne se
reecrivent pas a la main. La nomenclature dupliquait ce qu'index determine deja
(supernet, sous-reseaux, passerelles, VLAN). Corrige en rupture nette.
- inventory_rules : source unique de derivation — supernet_de, base3_de,
sous_reseau_de, passerelle_de, vlan_de. Modele 6 zones encode une fois
(2e octet = 10+index, 3e octet zone = 15+categorie, VLAN = 1000+index*10+zone).
deriver_nomenclature ne lit plus aucun adressage stocke ; mode compact supprime.
- devis_reseau : importe ces helpers (fin de la duplication) ; decouvre les
tenants sur `index` present (filtre vmid_schema retire).
- GUI : `index` devient un INTRANT (section Reseau). Il vit dans la nomenclature
(plan reseau uniforme, contrairement aux intrants des modeles heterogenes) et
le GUI l'ecrit chirurgicalement (une ligne, sans reformater). Le miroir JS
derive le VLAN du seed (fin de la lecture de c.vlan stocke).
- socle public : nomenclature au format maigre.
Preuve P20 (preuve_nomenclature_derivee) : aucune nomenclature ne stocke
d'adressage — garde-fou permanent, teste en negatif.
Valide : DIFF VIDE sur les 3 instances (la derivation reproduit exactement
l'adressage stocke), 7 modeles valident, devis_reseau genere les memes VLAN
(1011-1016 derives), make verifier rc=0 CONFORME 20/20, node --check du GUI OK.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le harnais ne verifiait qu'UNE instance et le seul modele socle. Tout ce qui vit
a cote du moteur echappait au controle. Trois preuves ferment ces angles morts :
- P17 (scripts/modeles.py) : TOUS les modeles valident, pas seulement socle.
SETOPS_MODELES=../Set-OPS-Modeles inclut les modeles assembles prives. A trouve
6 modeles invalides sur 7 (corriges dans Set-OPS-Modeles).
- P18 (scripts/voute.py) : le gabarit vault.yml.example couvre EXACTEMENT les secrets
que le plan exige (bases + roles actifs + group_vars). Ne dechiffre jamais la vraie
voute : compare des noms.
- P19 (scripts/couverture_gui.py) : tout champ present dans un plan reel est editable
par le GUI. A trouve applications.websocket (comble). Nomenclature toleree (trou connu).
GUI :
- champ « Liens (bindings) » dans l'inspecteur d'application : role -> cible en listes
deroulantes, les roles proposes = ceux que le role porteur accepte (meta/liens.yml).
Comble un manque : les bindings ne se declaraient qu'en editant le YAML a la main.
- champ « WebSocket » (Collabora).
- CHAMPS_ECRITS_PAR_GUI : declaration de ce que le GUI sait ecrire, verifiee par P19.
Garde-fou de fond : valider_applications refuse une application posee sur un hote non
declare (l'hote fantome exact qu'integral portait). Cable partout + POST du GUI.
liens_acceptes()/catalogue_liens() dans inventory_rules : source unique partagee par le
validateur, le GUI et instancier.py (dont la copie locale est retiree).
Valide : make verifier rc=0, CONFORME 19/19, ansible-lint 0 echec, 7 modeles valident,
DIFF VIDE, node --check du GUI OK. Piece justificative : docs/audit/preuve-2026-07-22.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Palette (promo/, les 4 pages) — les teintes rose, verte et violette etaient
trop presentes une fois etalees au tour precedent. Reduction d'environ 40 % :
rose .075 -> .044, vert .058 -> .034, violet .062 -> .036, arrets
intermediaires abaisses dans la meme proportion, opacite de la nappe .aurora
.44 -> .32. Geometrie inchangee : meme largeur, meme position, seule
l'intensite baisse. 0 conflit CSS entre les quatre pages.
forge-01 — la note precedente presentait comme une contradiction a trancher
le fait que le plan dise `etat: planifie` et que le CHANGELOG du 2026-07-03
dise le branding « prouve sur forge-01 ». Ce n'en etait pas une : l'hote a ete
cree, puis supprime. Le plan decrit l'etat COURANT, le CHANGELOG un etat PASSE
— les deux disent vrai. La preuve reste valable, simplement non rejouable tant
que l'hote n'est pas recree. roles/serveur_forgejo/README.md corrige.
Valide : equilibre accolades/parentheses du CSS, 0 conflit CSS,
prouver.py --verifier -> CONFORME 16/16.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Palette (promo/, les 4 pages) — ajoute --rose:#ff6fc4 (frange magenta) et
--vert:#5cff9d (vert fluo), uniquement dans les DÉGRADÉS FONCÉS : fond fixe du
corps, nappe .aurora dérivante, filets .rule. Opacités de 5,5 % à 8,5 %, une
teinte et non un motif. Le vert entre par la gauche et le rose sort par la
droite, comme une vraie aurore. --aurora (texte et boutons) est inchangé :
l'identité de marque ne bouge pas. Appliqué identiquement aux quatre fichiers,
0 conflit CSS après coup.
Thème Forgejo (alliance.css, 29 → 118 lignes) — la feuille étant injectée par
templates/custom/header.tmpl sur toutes les pages, le wiki est couvert sans
feuille distincte. Réorganisée en deux sections de risque explicite :
§1 Variables — couleurs officielles + ciel nocturne. Sûr, résiste aux
mises à jour. ÉPROUVÉ sur forge-01 (CHANGELOG 2026-07-03).
§2 Décor — fond aurore, filet sous les titres, citations, tableaux et code
en ligne de .markup. Fragile (classes internes). JAMAIS RENDU.
Supprimer §2 ramène au thème sobre. Le ciel nocturne ne s'applique qu'aux
thèmes sombres, pour ne pas casser le thème clair.
docs/theme-forgejo-hors-flotte.md — pose manuelle sur une instance Forgejo non
gérée par Set-OPS (la forge historique qui héberge ce dépôt et son wiki).
Forgejo n'ayant aucun réglage web pour le CSS, il faut déposer la feuille sur
le serveur. La procédure ne duplique aucun fichier : elle pointe vers ceux du
rôle. Inclut la détection du répertoire custom, un garde-fou pour ne pas
écraser un header.tmpl existant (ajout de ligne), la vérification curl et la
marche arrière.
Corrige deux affirmations fausses de ma part :
- « thème jamais rendu par un Forgejo réel » était faux pour §1, éprouvée.
Le statut est désormais donné section par section.
- Contradiction consignée sur forge-01 : le plan la dit `etat: planifie`, le
CHANGELOG 2026-07-03 dit le branding « prouvé sur forge-01 ». Les deux ne
peuvent pas être vrais ; l'écart est écrit dans le README du rôle, à trancher.
Validé : équilibre accolades/parenthèses du CSS, 0 conflit CSS entre les quatre
pages, lien de doc résolu, ansible-lint 0 échec sur 485 fichiers,
prouver.py --verifier → CONFORME 16/16.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Les pages ayant été écrites l'une après l'autre, six dérives s'étaient
installées entre elles. Passe de normalisation :
- Adresse au lecteur : index.html tutoyait (17 occurrences), les trois autres
vouvoyaient. Vouvoiement partout — ce sont des pages commerciales.
- Marque : trois pages affichaient « Alliance Boréale », tarifs affichait
« Chezlepro · tarifs ». Désormais « Set-OPS · Chezlepro » dans la barre et
« Chezlepro inc. · Saint-Bruno-de-Montarville, Québec » au pied.
- Navigation : quatre barres différentes (libellés et ordres distincts) →
Capacités · Offres · Tarifs · Valeur + « Nous parler », identique partout,
page courante marquée aria-current="page".
- Pieds de page : quatre structures → une seule, licence AGPLv3 incluse.
- Vocabulaire d'état : index utilisait .tag proven/soon, les autres
.st ok/wip/road. Un seul système : Éprouvé · En chantier · Feuille de route.
- CSS : 35 sélecteurs partagés avaient des déclarations divergentes → 0 conflit.
Deux étaient de vrais conflits de mise en page (.beats 4 colonnes contre 3,
.stats grille contre flex) ; passés en repeat(auto-fit,minmax(...)), une seule
règle qui s'adapte au nombre d'éléments.
Ajoute une section « Nos réserves » à index.html — seule page à en manquer,
alors que c'est celle qui affirme le plus de capacités. Les quatre assument
désormais leurs limites (mainteneur unique, épreuve de l'opérateur indépendant).
promo/README.md consigne les conventions communes en tableau et fournit le
script de détection des conflits CSS à lancer avant commit.
Validé : liens, balises, identifiants, équilibre CSS et node --check du JS sur
les quatre pages ; 0 conflit CSS ; prouver.py --verifier → CONFORME 16/16.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
promo/offres.html — les écosystèmes livrables, nommés par persona (Socle,
Identité, Maison OBNL, Cabinet, Atelier, Vigie, Intégral, Présence Web). Le
périmètre annoncé est tiré des modèles réels : le nombre de machines est celui
du plan, pas une estimation. Les états sont honnêtes — collaboration marquée
« en chantier », presence-web marquée « feuille de route, non vendable ».
promo/tarifs.html — grille tarifaire de Chezlepro inc., alignée sur les six
offres du site chezlepro.ca (diagnostic, socle opérateur, tenant portable,
audit-ready ops, exploitation gérée, observabilité) plutôt que sur les noms de
modèles Set-OPS. Diagnostic dès 4 500 $ et déductible, socle dès 18 000 $,
tenant dès 12 000 $ (7 500 $ les suivants), parcours combiné dès 38 000 $ au
lieu de 42 000 $, exploitation à 750/1 500/2 800 $ par mois. Trois postes,
aucune facturation par siège, licences à 0 $.
Montants = estimations de marché (taux effectif ~1 000-1 100 $/jour, firme
spécialisée québécoise), pas des prix validés par une vente réelle. Dollars
canadiens avant taxes. Le README le consigne, ainsi que le fait que cette
grille est publique et versionnée.
Corrige au passage une contradiction introduite : offres.html affirmait « un
prix affiché serait un prix inventé » ; son tableau porte désormais les prix de
départ et renvoie à tarifs.html, source de vérité.
Validé : node --check du JS des 4 pages, balises équilibrées, liens internes et
croisés vérifiés, prouver.py --verifier → CONFORME 16/16.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Page sœur de promo/index.html, même thème Alliance Boréale, liée dans les deux
sens. index.html s'adresse au sysadmin (« que puis-je faire ? ») ; valeur.html
s'adresse à la personne qui signe (« qu'est-ce que ça rapporte, et comment le
vérifier ? »).
Quatre pièces :
- calculateur de coût total interactif (personnes, abonnements, matériel, mise
en place, exploitation) sur 5 ans, avec point de bascule calculé ;
- tableau des équivalences : 11 briques, ce qu'elles remplacent, le libre qui
le fait, et leur état réel (Nextcloud/Collabora marqué « en chantier ») ;
- la preuve : make prouver 16/16, registre de 54 affirmations, et le fait que
le registre a le droit de perdre ;
- « Ce que nous ne prétendons pas » : seuil de rentabilité réel, besoin d'une
personne responsable, mainteneur unique, épreuve de l'opérateur indépendant
à venir — y compris si elle échoue.
Le calculateur affiche honnêtement le cas défavorable : sous ~40 personnes aux
valeurs par défaut, l'autohébergement ne se rembourse pas sur l'horizon retenu,
et la page le dit plutôt que de le cacher. Les valeurs par défaut sont des
ordres de grandeur à remplacer, pas des tarifs.
Validé : node --check du JS (rc=0), balises équilibrées, liens internes
résolus, prouver.py --verifier → CONFORME 16/16.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
AFF-002 (« Set-OPS s'exploite sans aucune IA ») était ✅ par inspection : ses
écarts bloquants soldés et le parcours relu, mais jamais exécutée par un
opérateur qui n'est pas l'auteur. Aucune commande locale ne peut la prouver.
Ajoute le protocole de l'épreuve humaine : départ à froid depuis le modèle
public `socle`, sur la grappe Proxmox de l'opérateur. Règle du silence
(N0 journalise / N1 déblocage après 30 min, consigné comme défaut / N2 arrêt
sécurité), interdits (aucune IA, aucun dépôt privé, aucune lecture de
docs/audit/ qui divulguerait les pièges connus), critères R1→R6 fixés
d'avance, périmètre matériel, gabarit de rapport.
Le registre peut perdre : la redescente d'AFF-002 en 🟡 ou ❌ selon le verdict
est explicitement prévue.
Le protocole ne nomme personne — il est réutilisable, et l'identité de
l'opérateur vit dans son rapport, sous réserve de consentement.
Validé : prouver.py --verifier → CONFORME 16/16. Aucun code touché.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Page web autonome (un seul fichier, zéro dépendance externe) présentant tout ce
qu'un sysadmin peut faire avec Set-OPS, sous l'identité Alliance Boréale (ciel
nocturne + aurore + constellation, reprise des thèmes Keycloak/Forgejo).
- 7 piliers (identité, PKI, DNS/réseau, données, courriel, edge TLS, observabilité)
+ socle transverse (durcissement, pare-feu, sauvegardes, plan/GUI) + forge.
- Console opérateur, cycle de vie VM, section preuve/souveraineté, feuille de route.
- Honnêteté prouvable : « éprouvé » vs « feuille de route » clairement distingués.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- prouver.py : nouveau mode --verifier — exécute toutes les preuves du registre
(verdict + code de sortie) sans écrire de rapport, pour ne pas écraser la pièce
justificative committée docs/audit/preuve-<date>.md.
- Makefile : make verifier se termine par `python3 scripts/prouver.py --verifier`
→ verifier échoue si une preuve échoue. make prouver seul écrit toujours le rapport.
- docs/audit/README.md : section « Rapport avec make verifier » mise à jour.
Vérifié : make verifier → CONFORME 16/16 (voûte), aucun churn du rapport ; make
prouver écrit toujours ; ansible-lint 0 failure.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 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>
Ajoute au make valider la preuve de RÉSILIENCE : pour chaque nœud client_backup,
restic restaure le dernier snapshot dans un dossier temporaire (lecture seule sur
le dépôt) et vérifie que des fichiers en sortent.
Éprouvé sur la flotte : 6 dépôts restaurables. La recette a débusqué un vrai trou
(collab-01/Nextcloud sans backup jobs -> service en échec, stockage fichier non
protégé) — corrigé côté instance.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ajoute au make valider la preuve fonctionnelle du service courriel souverain :
envoi via le MTA (sendmail -> postfix -> LDAP -> LMTP) puis vérification de la
remise dans le Maildir avec doveadm (compte testmail), message de test nettoyé.
Éprouvé sur la flotte vivante, sous pare-feu actif : remise confirmée.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Vérifie que les services FONCTIONNENT, pas juste qu'ils sont déployés — complète
les *-verifier (statiques, sur le plan) par une recette fonctionnelle vivante.
playbooks/valider.yml (lecture seule) :
- Prometheus : toutes les cibles de supervision UP (API /targets)
- Edge : les vhosts HTTPS exposés répondent (server_name réels filtrés sur
domaine_interne, statut sain 200/301/302/401/403)
Éprouvé sur la flotte : 7 cibles UP, 8 vhosts OK (sous pare-feu actif).
À venir : courriel bout-en-bout (envoi->IMAP), restauration de sauvegarde.
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>
Le public ne garde que le modèle générique 'socle' (preuve libre reproductible).
Les modèles assemblés (identite/observabilite/forge/collaboration/presence-web/
integral) = actif commercial, déplacés dans Set-OPS-modeles (privé). Le moteur
(rôles, machinerie) reste libre.
NB : ces modèles restent dans l'HISTORIQUE git de ce dépôt — mettre Set-OPS-Public
en visibilité privée sur le Forgejo, ou réécrire l'historique (git filter-repo).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Les rôles serveur_web_frontal/dorsal existent maintenant → presence-web passe de
« rôles à construire » à ✅. Apps frontal/dorsal exposées (site./app.<domaine>),
group_vars d'exemple (sites statiques + webapp Python). Instancie proprement.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Aligne sur la convention serveur_* de tous les rôles de service (vars incluses).
Le modèle presence-web (pré-existant) utilisait déjà ces noms -> il colle enfin.
Aussi : serveur_web_dorsal ne chown plus le code (reste root, lecture seule pour
l'app = plus sûr + git idempotent, fini le 'propriété douteuse' au pull).
Idempotence prouvée (2e passage changed=0). lint production.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Le garde 'creates:' sautait la ré-émission même quand les SAN voulus changeaient
(ex: nouvelle exposition -> client_pki_sans mis à jour). Contourné 3× à la main ce
soir. Corrigé : on lit les SAN du cert existant (openssl) et on ré-émet si le cert
est absent OU si un SAN voulu manque, puis on recharge les consommateurs
(client_pki_reload_services). Idempotent (SAN à jour -> sauté) + dérive détectée,
prouvés. ansible-lint production : 0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Runtime (venv/paquets) + service systemd + nginx local, derrière l'edge, ZÉRO
conteneur. Chaque app : git clone (depth 1) → venv + pip → unité systemd durcie
(app en localhost, user webapp, NoNewPrivileges/PrivateTmp) → vhost nginx local
qui la fronte. data_dir persistant pour l'état local (SQLite) ; BD réseau via
resoudre_base sinon.
Éprouvé bout-en-bout sur web-frontal-01 par le rôle : monregistraire (FastAPI+
uvicorn+SQLite) cloné de Forgejo, servi via l'edge en HTTPS step-ca, API OK.
Avec web_frontal, la plateforme webapp native est complète. lint production: 0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Chemin git prouvé de bout en bout : le rôle clone le site depuis le Forgejo
souverain (depth 1 — pas l'historique lourd) et le sert derrière l'edge.
Éprouvé sur web-frontal-01 (Alliance Boréale servi via edge depuis /srv/web,
cloné de Forgejo). ansible-lint production : 0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
nginx + sites statiques depuis un dépôt git souverain, derrière l'edge. Pas de
conteneur, pas de runtime, pas de BD — l'éthos libre/natif. Chaque site :
git clone → vhost (headers sécurité + CSP self-only, gzip, try_files). SAN edge
+ plancher auto-dérivés. meta/flux.yml (ingress 80 depuis edge).
Spike prouvé sur web-frontal-01 (site Alliance Boréale servi via edge, HTTPS
step-ca vérifié, CSP en place). NB : le chemin git-clone est codifié mais le
spike a servi via copie locale → à éprouver (pousser le site en Forgejo).
Les apps dynamiques (dorsal systemd) = rôle à venir. ansible-lint production: 0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ce qui manquait aux modèles = la collaboration (Nextcloud/Collabora), placeholder
'rôles à construire' du README, désormais bâti.
- exemples/modeles/collaboration/ : socle + identité + nœud collab (8 VM, zone
Collaboration VLAN 20) ; nextcloud+collabora exposés (cloud/bureau, websocket auto),
base nextcloud, client Keycloak nextcloud. SANs edge + plancher auto-dérivés.
- integral : + collab-01 (zone Applications), nextcloud/collabora/base/client — il
tient enfin sa promesse de « tout ».
- README : collaboration ✅.
Les deux modèles instancient proprement (collab dérivé, expositions auto).
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>
Conteneur collabora/code (restart always), publié sur localhost + IP LAN
(gotcha : bind localhost seul → 502 depuis l'edge), aliasgroup = domaine
Nextcloud, ssl.termination à l'edge, attente santé /hosting/capabilities.
meta/flux.yml (ingress 9980 depuis edge) alimente le registre des flux.
Docker (prouvé au spike) ; CODE natif = option future à spiker. Tag à épingler.
ansible-lint profil production : 0 échec.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Couche accès du zéro-confiance (complète le chiffrement). Chaque rôle possède
ses flux (comme meta/empreinte) : sens/port/protocole/pair/chiffrement/raison.
Résolu par le plan (pair→IP) → génère les règles nftables (default deny) ET le
registre d'audit. Doc de conception + 3 pilotes validés (résolveur-démo).
Séquence : schéma+pilote (fait) → résolveur → remplir les rôles → générer +
registre → activer nftables prudemment (action destructive).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Cœur de l'offre maison-obnl (OBNL/coops). Surface de config posée (BD via
resoudre_base, Redis, OIDC Keycloak, Collabora WOPI, exposé cloud.<domaine>,
sauvegarde Tier 1). tasks/main.yml VOLONTAIREMENT absent : attend le spike
empirique (éprouver l'outil avant le rôle) — déployer + prouver OIDC/WOPI/
fichiers sur un vrai nœud avant de codifier.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>