From f307a23345537288df708160a164cf02ce867956 Mon Sep 17 00:00:00 2001 From: Daniel Allaire Date: Mon, 14 Sep 2026 14:41:23 -0400 Subject: [PATCH] le wiki suit le genome : un locataire n en est pas depositaire MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Decision : seuls les SITES portent la forge, le cache APT et les artefacts. Meme geste que le retrait de serveur_artefacts d un plan de locataire, un cran plus loin — le site fournit tout ce dont un tenant a besoin pour venir au monde. La generalisation de forge_amorcer a un locataire est revenue en arriere : elle implementait le modele ecarte, et la garder en ferait un piege. ma_forge ne derive plus MA forge mais la forge qui porte MON genome. Le signal est deja au plan : serveur_ops_forge_externe dit je lis mon genome ailleurs. Qui le declare consulte, il ne republie pas. Reste vrai : une forge de locataire peut exister pour LE CODE DE SES GENS — c est l offre Atelier. Ce n est pas l endroit ou vit le moteur. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Crgis8CxCWkAGFA1ecBz3q --- CHANGELOG.md | 38 ++++++++++++++++++++++++++++++++++++++ scripts/ma_forge.py | 29 ++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9af86e1..198a1ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,43 @@ # CHANGELOG — Set-OPS +## 2026-09-14 (11) — Le wiki suit le genome, et un locataire n'en est pas depositaire + +Decision de l'exploitant : **seuls les SITES portent la forge, le cache APT et les +artefacts.** Un locataire n'a pas besoin de sa propre forge pour le moteur — il le lit +chez son hebergeur, comme il y prend ses paquets et son gabarit. + +C'est le meme geste que le retrait de `serveur_artefacts` du plan d'un locataire, un cran +plus loin, et la meme phrase le porte : *le site fournit tout ce dont un tenant a besoin +pour venir au monde*. + +### Ce que la soiree avait deja chiffre + +Une forge par locataire, c'est une organisation, des depots, un mot de passe d'admin en +voute, un mecanisme d'amorcage, un wiki, un miroir a tenir synchrone, et une preuve qu'il +ne derive pas. Mesure du 2026-09-14 sur TechnoLibre : forge servie en `https=200`, cle du +runner acceptee, **zero depot**. La chaine n'existait pas — pour UN locataire. + +### La distinction qui reste vraie + +« Un locataire n'a pas besoin d'une forge **pour le genome** » n'est pas « un locataire n'a +jamais de forge ». L'offre **Atelier** vend precisement une forge a des equipes qui +developpent : depots, tickets, revues, pour LEUR code. Ce n'est simplement pas l'endroit ou +vit le moteur. + +### Ce qui a ete defait, et pourquoi + +La generalisation de `forge_amorcer.py` a un locataire est **revenue en arriere** : elle +implementait le modele ecarte. La garder en ferait du code mort au mieux, un piege au pire +— quelqu'un finirait par le lancer. + +`ma_forge.py` change de regle : il ne derive plus « MA forge » mais **la forge qui porte +mon genome**. Le signal est deja au plan — `serveur_ops_forge_externe: true` dit « je lis +mon genome ailleurs ». Un ecosysteme qui le declare ne publie pas : il consulte, la ou le +genome vit. + + OPS-Technolibre -> refus : lit son genome sur 10.37.33.11 + SITE-Chezlepro -> forge.genese.internal + ## 2026-09-14 (10) — Le temoin du wiki pointait une forge VIDE En publiant les fiches de role, `make wiki-publier` a refuse : le wiki vise par le temoin diff --git a/scripts/ma_forge.py b/scripts/ma_forge.py index 2c29a99..aa0cd82 100755 --- a/scripts/ma_forge.py +++ b/scripts/ma_forge.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""L'adresse du wiki de MA forge — celle de l'ecosysteme monte. +"""L'adresse du wiki de la forge QUI PORTE MON GENOME. CHAQUE RUNNER PUBLIE POUR SA FORGE (decide le 2026-09-14). @@ -20,6 +20,19 @@ DEUX NOTIONS A NE PAS CONFONDRE, et c'est ce qui a rendu le sujet trouble : Le runner d'un locataire lit sur la forge du SITE et sert sur la SIENNE. Les deux adresses different, et le wiki appartient a la seconde. +LE WIKI SUIT LE GENOME (decide le 2026-09-14). Un locataire ne porte PAS le moteur : il le +lit sur la forge de son hebergeur, comme il y prend ses paquets et son gabarit. Lui faire +publier la documentation du moteur sur SA forge reviendrait a l'en rendre depositaire — +donc a lui imposer l'organisation, les depots, le miroir a tenir synchrone et la preuve +qu'il ne derive pas. Pour un service qu'il ne rend a personne. + +LE SIGNAL EST DEJA AU PLAN : `serveur_ops_forge_externe: true` dit « je lis mon genome +ailleurs ». Un ecosysteme qui le declare ne publie pas — il consulte, la ou le genome vit. + +CE QUI RESTE VRAI D'UNE FORGE DE LOCATAIRE : elle peut exister, et servir LE CODE DE SES +GENS — depots, tickets, revues. C'est l'offre « Atelier ». Ce n'est simplement pas +l'endroit ou vit le moteur. + CE QUI N'EST PAS DERIVABLE, ET C'EST DIT PLUTOT QUE DEVINE : le poste du mainteneur n'est le runner d'aucun ecosysteme. Il publie vers le domicile PUBLIC du projet, qui n'est la forge d'aucun plan. La, `WIKI_REMOTE` reste explicite — et il l'emporte toujours. @@ -53,6 +66,20 @@ def ma_forge() -> tuple[str | None, str]: except (OSError, ValueError) as e: return None, f"plan illisible ({e.__class__.__name__})" + # UN ECOSYSTEME QUI LIT SON GENOME AILLEURS NE LE PUBLIE PAS. Le wiki suit le genome : + # il vit la ou le moteur vit, et un locataire n'est pas son depositaire. + gv = Path(inst) / "inventories" / "principal" / "group_vars" / "serveur_ops.yml" + if gv.is_file(): + try: + import yaml + d = yaml.safe_load(gv.read_text(encoding="utf-8")) or {} + except (OSError, yaml.YAMLError): + d = {} + if d.get("serveur_ops_forge_externe"): + amont = d.get("serveur_ops_forge_amont") or "sa forge amont" + return None, (f"{Path(inst).resolve().name} lit son genome sur {amont} — " + "le wiki s'y consulte, il ne s'y republie pas d'ici") + # LE NOM DU SERVICE, PAS CELUI DE LA MACHINE. Un FQDN expose survit au demenagement du # service ; `forge-01` non. C'est la meme regle que partout ailleurs dans ce depot. for nom, app in (apps.items() if isinstance(apps, dict) else []):