preuve : P34 — chaque document declare son lecteur (D-74)
La refonte de ce matin posait une convention. Une convention qu'on n'outille pas tient tant que quelqu'un y pense : c'est le raisonnement de D-70, applique au corpus documentaire. Etat de depart mesure : 2 documents sur 34 declaraient leur lecteur. Les 32 autres disaient leur SUJET — ce qui avait enfoui le runbook de reprise le plus utile du depot au §6 de autorisation.md. Les 38 le declarent desormais, lecteur determine document par document et non colle au gabarit : l'exploitant (devis, migration de tenant, cycle de vie, gabarit d'or), le mainteneur (conceptions, registres, carte), le lecteur externe (ecosysteme-chezlepro), l'agent IA (MISE-A-JOUR-CODEX-CLAUDE). Deux exemptions DERIVEES, pas listees — un chemin en dur aurait vieilli a la premiere page ajoutee : un document qui s'annonce genere, et un fragment sans titre. Les 13 exemptes verifies un par un ; aucun document ecrit a la main n'est exempte par accident. La preuve ne lit que l'EN-TETE, ce qui empeche frontiere-opnsense.md et plan-et-generation.md — qui parlent de generation dans leur corps — d'etre exemptes a tort. Eprouvee dans les deux sens. Elle a echoue seule des sa premiere execution en nommant deux documents que mon inventaire avait manques (docs/audit/). Puis test negatif delibere : declaration retiree de meta-classe.md -> ECHEC la nommant ; restauree -> OK. Ce qu'elle ne teste pas : que le lecteur declare soit le BON. Ca se juge en revue ; elle garantit qu'on a du y penser. P01–P34. Comptes perimes corriges au passage (AGENTS.md et devis-services.md annoncaient encore 30 preuves). Verifie : prouver.py 0 (34 OK), plan-recette inchange. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
01ecea901b
commit
ac85278366
41 changed files with 185 additions and 4 deletions
|
|
@ -180,7 +180,7 @@ Si `ansible-lint` n’est pas disponible, le signaler clairement. Ne pas invente
|
||||||
## Écrire, puis relire (D-68)
|
## Écrire, puis relire (D-68)
|
||||||
|
|
||||||
`--syntax-check` et `ansible-lint` prouvent que le dépôt est cohérent **avec lui-même**.
|
`--syntax-check` et `ansible-lint` prouvent que le dépôt est cohérent **avec lui-même**.
|
||||||
C'est aussi ce que font les 30 preuves de `make prouver` : elles lisent le dépôt, sans le
|
C'est aussi ce que font les 34 preuves de `make prouver` : elles lisent le dépôt, sans le
|
||||||
moindre appel réseau. **Aucune ne demande au système déployé s'il ressemble à ce que le
|
moindre appel réseau. **Aucune ne demande au système déployé s'il ressemble à ce que le
|
||||||
dépôt annonce.**
|
dépôt annonce.**
|
||||||
|
|
||||||
|
|
|
||||||
44
CHANGELOG.md
44
CHANGELOG.md
|
|
@ -1,5 +1,49 @@
|
||||||
# CHANGELOG — Set-OPS
|
# CHANGELOG — Set-OPS
|
||||||
|
|
||||||
|
## 2026-08-10 — P34 : la convention « chaque document déclare son lecteur » devient une garde
|
||||||
|
|
||||||
|
La refonte de ce matin posait une convention. Une convention qu'on n'outille pas tient tant
|
||||||
|
que quelqu'un y pense — c'est exactement le raisonnement de **D-70**, et voici son
|
||||||
|
application au corpus documentaire. **D-74**, gardée par **P34**.
|
||||||
|
|
||||||
|
**L'état de départ, mesuré : 2 documents sur 34 déclaraient leur lecteur.** Les 32 autres
|
||||||
|
disaient leur *sujet*. C'est ce qui avait enfoui le runbook de reprise le plus utile du dépôt
|
||||||
|
au §6 de `autorisation.md`.
|
||||||
|
|
||||||
|
**Les 38 documents le déclarent désormais**, et le lecteur a été déterminé document par
|
||||||
|
document — pas collé au gabarit. Trois familles : l'**exploitant** (les devis, la migration
|
||||||
|
de tenant, le cycle de vie des VM, le gabarit d'or, `autorisation.md` §6…), le **mainteneur**
|
||||||
|
(les conceptions, les registres, la carte), et deux cas à part — `ecosysteme-chezlepro.md`
|
||||||
|
s'adresse au **lecteur externe**, `MISE-A-JOUR-CODEX-CLAUDE.md` à l'**agent IA** qui reprend
|
||||||
|
le dépôt.
|
||||||
|
|
||||||
|
**Deux exemptions, dérivées et non listées** — un chemin en dur aurait vieilli à la première
|
||||||
|
page ajoutée :
|
||||||
|
|
||||||
|
- un document qui **s'annonce généré** ne se lit pas, il se régénère. On le reconnaît à sa
|
||||||
|
propre en-tête (« Généré par », « ne pas éditer à la main ») : 13 documents, tous
|
||||||
|
réellement générés — vérifié un par un, aucun document écrit à la main n'est exempté par
|
||||||
|
accident ;
|
||||||
|
- un fragment sans titre `#` n'est pas un document.
|
||||||
|
|
||||||
|
**La preuve ne lit que l'en-tête**, jamais le corps : une mention de « Pour qui » perdue au
|
||||||
|
milieu d'une page ne serait pas une porte. C'est aussi ce qui empêche `frontiere-opnsense.md`
|
||||||
|
et `plan-et-generation.md` — qui parlent de génération dans leur corps — d'être exemptés à
|
||||||
|
tort.
|
||||||
|
|
||||||
|
**Éprouvée dans les deux sens, parce qu'une garantie qu'on n'a jamais vue dire *non* est une
|
||||||
|
habitude, pas une garantie.** Elle a d'abord échoué toute seule à sa première exécution, en
|
||||||
|
nommant deux documents que mon inventaire avait manqués (`protocole-operateur-independant.md`,
|
||||||
|
`reference-avant-reconstruction-2026-08-08.md` — tous deux dans `docs/audit/`, hors de mon
|
||||||
|
motif). Puis test négatif délibéré : déclaration retirée de `meta-classe.md` → **ÉCHEC** le
|
||||||
|
nommant précisément ; restaurée → **OK**.
|
||||||
|
|
||||||
|
**Ce qu'elle ne teste pas :** que le lecteur déclaré soit le *bon*. Ça se juge en revue. Elle
|
||||||
|
garantit qu'on a dû y penser — ce qui est précisément ce qui manquait.
|
||||||
|
|
||||||
|
`P01–P34`, et les comptes périmés corrigés au passage (`AGENTS.md` et `devis-services.md`
|
||||||
|
annonçaient encore 30 preuves).
|
||||||
|
|
||||||
## 2026-08-10 — Refonte documentaire : on n'arrive pas avec un sujet, on arrive avec une situation
|
## 2026-08-10 — Refonte documentaire : on n'arrive pas avec un sujet, on arrive avec une situation
|
||||||
|
|
||||||
La documentation était organisée **par sujet** — identité, courriel, DNS, PKI, sauvegardes.
|
La documentation était organisée **par sujet** — identité, courriel, DNS, PKI, sauvegardes.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Mise à jour pour Codex et Claude Code — Set-OPS
|
# Mise à jour pour Codex et Claude Code — Set-OPS
|
||||||
|
|
||||||
|
> **Pour qui :** l'**agent IA** qui reprend le dépôt — et le mainteneur qui relit ce qu'on lui dit.
|
||||||
|
|
||||||
## État du dépôt
|
## État du dépôt
|
||||||
|
|
||||||
`Set-OPS` est le moteur Ansible global d’exploitation d’écosystèmes numériques souverains.
|
`Set-OPS` est le moteur Ansible global d’exploitation d’écosystèmes numériques souverains.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Architecture Set-OPS
|
# Architecture Set-OPS
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — le survol du modèle. À lire avant `plan-et-generation.md`.
|
||||||
|
|
||||||
Set-OPS définit et construit l'écosystème numérique souverain. Il se
|
Set-OPS définit et construit l'écosystème numérique souverain. Il se
|
||||||
pilote par un **plan** : l'inventaire Ansible (`instance/inventories/production/hosts.yml`)
|
pilote par un **plan** : l'inventaire Ansible (`instance/inventories/production/hosts.yml`)
|
||||||
est **généré** depuis le plan, pas édité à la main.
|
est **généré** depuis le plan, pas édité à la main.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Audit de conformité — mode d'emploi
|
# Audit de conformité — mode d'emploi
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — comment le dispositif de preuve fonctionne, et comment l'étendre.
|
||||||
|
|
||||||
Ce dossier contient le dispositif qui garde Set-OPS **honnête** : il ne doit jamais
|
Ce dossier contient le dispositif qui garde Set-OPS **honnête** : il ne doit jamais
|
||||||
affirmer plus que ce qu'il prouve.
|
affirmer plus que ce qu'il prouve.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Registre des affirmations — Set-OPS
|
# Registre des affirmations — Set-OPS
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — chaque affirmation publique du dépôt, et la preuve qui la garde.
|
||||||
|
|
||||||
> **Phase 1 de la mise en conformité prouvable.** Ce document est un **audit**, sans
|
> **Phase 1 de la mise en conformité prouvable.** Ce document est un **audit**, sans
|
||||||
> aucun correctif de code ni de documentation. Chaque affirmation publique vérifiable
|
> aucun correctif de code ni de documentation. Chaque affirmation publique vérifiable
|
||||||
> du dépôt est tracée vers une commande de preuve reproductible, ou marquée comme
|
> du dépôt est tracée vers une commande de preuve reproductible, ou marquée comme
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
> [`docs/audit/affirmations.md`](affirmations.md).
|
> [`docs/audit/affirmations.md`](affirmations.md).
|
||||||
|
|
||||||
- **Instance** : `instance` — inventaire `instance/inventories/principal/hosts.yml`
|
- **Instance** : `instance` — inventaire `instance/inventories/principal/hosts.yml`
|
||||||
- **Verdict** : ✅ CONFORME (33 OK · 0 echec · 0 saute)
|
- **Verdict** : ✅ CONFORME (34 OK · 0 echec · 0 saute)
|
||||||
|
|
||||||
## Preuves
|
## Preuves
|
||||||
|
|
||||||
|
|
@ -46,6 +46,7 @@
|
||||||
| P31 | Documentation : tout ce que le depot FAIT est nomme | — | ✅ OK | 41 scripts expliques et atteignables, 90 cibles make documentees, 54 roles avec README. |
|
| P31 | Documentation : tout ce que le depot FAIT est nomme | — | ✅ OK | 41 scripts expliques et atteignables, 90 cibles make documentees, 54 roles avec README. |
|
||||||
| P32 | Intrants exiges par les roles : tous fournis | — | ✅ OK | CONFORME : 30 exigence(s) de role, toutes satisfaites (126 cle(s) declaree(s) par l'instance). |
|
| P32 | Intrants exiges par les roles : tous fournis | — | ✅ OK | CONFORME : 30 exigence(s) de role, toutes satisfaites (126 cle(s) declaree(s) par l'instance). |
|
||||||
| P33 | Aucune collision de port entre roles co-localises | — | ✅ OK | CONFORME : 32 revendication(s) de port, aucune collision entre roles co-localises (33 groupes). |
|
| P33 | Aucune collision de port entre roles co-localises | — | ✅ OK | CONFORME : 32 revendication(s) de port, aucune collision entre roles co-localises (33 groupes). |
|
||||||
|
| P34 | Chaque document declare son lecteur | — | ✅ OK | 38 document(s) declarent leur lecteur (13 genere(s) exempte(s)). |
|
||||||
|
|
||||||
## Couverture des affirmations ✅ du registre
|
## Couverture des affirmations ✅ du registre
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
# Protocole — épreuve de l'opérateur indépendant
|
# Protocole — épreuve de l'opérateur indépendant
|
||||||
|
|
||||||
|
> **Pour qui :** qui **fait passer l'épreuve** — et l'opérateur indépendant qui s'y prête.
|
||||||
|
> Le mainteneur n'y intervient pas : c'est tout l'objet du protocole.
|
||||||
|
|
||||||
Épreuve empirique de l'affirmation **AFF-002** : *« Set-OPS s'exploite entièrement à la
|
Épreuve empirique de l'affirmation **AFF-002** : *« Set-OPS s'exploite entièrement à la
|
||||||
main — la doc, `make` et le GUI suffisent, sans aucune IA »* (README:9 ; `AGENTS.md`
|
main — la doc, `make` et le GUI suffisent, sans aucune IA »* (README:9 ; `AGENTS.md`
|
||||||
principe 10).
|
principe 10).
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
# État de référence — avant reconstruction from-zero
|
# État de référence — avant reconstruction from-zero
|
||||||
|
|
||||||
|
> **Pour qui :** qui **compare après une reconstruction** — le témoin contre lequel se lit
|
||||||
|
> toute divergence. Historique : il ne décrit pas l'état courant.
|
||||||
|
|
||||||
> Figé le 2026-08-08, écosystème **chezlepro** (index 17, 14 VM), avant destruction et
|
> Figé le 2026-08-08, écosystème **chezlepro** (index 17, 14 VM), avant destruction et
|
||||||
> rejeu complet du plan. **Ce document existe pour que « identique » soit prouvable
|
> rejeu complet du plan. **Ce document existe pour que « identique » soit prouvable
|
||||||
> plutôt que ressenti.** Toute divergence après reconstruction se lit contre lui.
|
> plutôt que ressenti.** Toute divergence après reconstruction se lit contre lui.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Authentification : Keycloak devant, LDAP dessous, `sudo` en secours
|
# Authentification : Keycloak devant, LDAP dessous, `sudo` en secours
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — la doctrine d'authentification, avant de brancher un service.
|
||||||
|
|
||||||
> **Directive d'architecture du 2026-08-03.** Trois règles, décidées ensemble et
|
> **Directive d'architecture du 2026-08-03.** Trois règles, décidées ensemble et
|
||||||
> volontairement indissociables — chacune crée le problème que la suivante résout.
|
> volontairement indissociables — chacune crée le problème que la suivante résout.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Accès et habilitations : Set-OPS amorce, le sysadmin gouverne
|
# Accès et habilitations : Set-OPS amorce, le sysadmin gouverne
|
||||||
|
|
||||||
|
> **Pour qui :** l'**exploitant**, le jour de la reprise — le §6 est la partie utile. La doctrine qui précède (§1-5) s'adresse au mainteneur.
|
||||||
|
|
||||||
> **Directive d'architecture du 2026-08-07.** L'authentification dit *qui tu es*
|
> **Directive d'architecture du 2026-08-07.** L'authentification dit *qui tu es*
|
||||||
> (`authentification.md`). Ce document dit *ce que tu peux faire* — et surtout **qui en
|
> (`authentification.md`). Ce document dit *ce que tu peux faire* — et surtout **qui en
|
||||||
> décide**. La réponse n'est pas « le dépôt ».
|
> décide**. La réponse n'est pas « le dépôt ».
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Bindings — conception des relations entre applications, bases, serveurs et domaines
|
# Bindings — conception des relations entre applications, bases, serveurs et domaines
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** qui ajoute une relation service → service.
|
||||||
|
|
||||||
> Note de conception, 2026-07-02. Décision d'architecture à valider avant implémentation.
|
> Note de conception, 2026-07-02. Décision d'architecture à valider avant implémentation.
|
||||||
> Direction retenue : **liens déclarés côté application (le consommateur déclare ses besoins)**.
|
> Direction retenue : **liens déclarés côté application (le consommateur déclare ses besoins)**.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Catalogue des services
|
# Catalogue des services
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — les noms de groupes et de playbooks des services, existants et à venir, avec leur maturité.
|
||||||
|
|
||||||
Ce document fixe les noms de groupes et de playbooks pour les prochains services.
|
Ce document fixe les noms de groupes et de playbooks pour les prochains services.
|
||||||
|
|
||||||
La règle reste :
|
La règle reste :
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# `make config` — référence des paramètres Proxmox
|
# `make config` — référence des paramètres Proxmox
|
||||||
|
|
||||||
|
> **Pour qui :** l'**exploitant** qui raccorde le moteur à sa grappe Proxmox.
|
||||||
|
|
||||||
`make config` lance `scripts/config_proxmox.py`, l'assistant interactif qui écrit
|
`make config` lance `scripts/config_proxmox.py`, l'assistant interactif qui écrit
|
||||||
la connexion au cluster Proxmox et les valeurs de clonage par défaut. Il pose
|
la connexion au cluster Proxmox et les valeurs de clonage par défaut. Il pose
|
||||||
**16 paramètres non sensibles** puis propose de saisir les **secrets API**.
|
**16 paramètres non sensibles** puis propose de saisir les **secrets API**.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Conception — Service de courriel souverain (Chezlepro)
|
# Conception — Service de courriel souverain (Chezlepro)
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** du service de courriel.
|
||||||
|
|
||||||
> **Statut : CONCEPTION (cadrage).** Aucun rôle n'est encore écrit. Ce document fixe
|
> **Statut : CONCEPTION (cadrage).** Aucun rôle n'est encore écrit. Ce document fixe
|
||||||
> les décisions, les prérequis et la topologie avant toute implémentation.
|
> les décisions, les prérequis et la topologie avant toute implémentation.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Registre des décisions d'architecture
|
# Registre des décisions d'architecture
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — pourquoi les choses sont ainsi, et ce qui a été écarté.
|
||||||
|
|
||||||
> **À quoi sert ce document.** Les décisions sont écrites là où elles s'appliquent —
|
> **À quoi sert ce document.** Les décisions sont écrites là où elles s'appliquent —
|
||||||
> `frontiere-opnsense.md`, `sdn-evpn.md`, `migration-tenant.md`, `underlay.yml.example` — et
|
> `frontiere-opnsense.md`, `sdn-evpn.md`, `migration-tenant.md`, `underlay.yml.example` — et
|
||||||
> leur histoire vit dans le `CHANGELOG`. Ce registre ne les répète pas : il dit **quelles
|
> leur histoire vit dans le `CHANGELOG`. Ce registre ne les répète pas : il dit **quelles
|
||||||
|
|
@ -110,6 +112,7 @@ sont les seules vérifiables.
|
||||||
| **D-72** | Un `assert` de rôle est un **contrat d'intrant**, et l'instance doit l'honorer — vérifié hors ligne | la première reconstruction from-zero s'est arrêtée sur `amorcage_acces_courriel` : obligatoire depuis le matin, déclaré par aucun tenant, et invisible parce que le compte existait déjà — la garde n'avait jamais eu l'occasion de se déclencher. Un intrant est satisfait par un **défaut non vide**, un `set_fact` de résolveur, ou une déclaration de l'inventaire (fichier `hosts.yml` compris) | `scripts/verifier_intrants.py`, `make intrants-verifier` | **P32** |
|
| **D-72** | Un `assert` de rôle est un **contrat d'intrant**, et l'instance doit l'honorer — vérifié hors ligne | la première reconstruction from-zero s'est arrêtée sur `amorcage_acces_courriel` : obligatoire depuis le matin, déclaré par aucun tenant, et invisible parce que le compte existait déjà — la garde n'avait jamais eu l'occasion de se déclencher. Un intrant est satisfait par un **défaut non vide**, un `set_fact` de résolveur, ou une déclaration de l'inventaire (fichier `hosts.yml` compris) | `scripts/verifier_intrants.py`, `make intrants-verifier` | **P32** |
|
||||||
| **D-73** | Tout port **lié** se déclare, et deux rôles co-localisés ne peuvent pas revendiquer le même | un port n'appartient à personne : le premier démarré le prend, l'autre échoue — parfois **en silence**. Sur `infra-mail-01`, le SASL de Dovecot et l'interface d'Alloy se disputaient le 12345 depuis le premier jour, et c'est Dovecot qui perdait sans que rien ne le dise. Le contrôle n'était possible qu'une fois le port d'Alloy — un défaut amont **subi** — déclaré. `partage: true` distingue « j'ouvre cette écoute » de « je décris celle d'un autre » | `scripts/verifier_ports.py`, `make ports-verifier` | **P33** |
|
| **D-73** | Tout port **lié** se déclare, et deux rôles co-localisés ne peuvent pas revendiquer le même | un port n'appartient à personne : le premier démarré le prend, l'autre échoue — parfois **en silence**. Sur `infra-mail-01`, le SASL de Dovecot et l'interface d'Alloy se disputaient le 12345 depuis le premier jour, et c'est Dovecot qui perdait sans que rien ne le dise. Le contrôle n'était possible qu'une fois le port d'Alloy — un défaut amont **subi** — déclaré. `partage: true` distingue « j'ouvre cette écoute » de « je décris celle d'un autre » | `scripts/verifier_ports.py`, `make ports-verifier` | **P33** |
|
||||||
| **D-70** | La documentation **dit et explique tout ce que le dépôt fait** — et l'exigence est **outillée**, pas seulement énoncée | une exigence qu'on n'outille pas pourrit en silence : la carte annonçait « 28 décisions » quand il y en avait 66, et disait les accès « non construits » alors qu'ils tournaient en production. **P31** garde le couvert — chaque script s'explique et reste atteignable, chaque cible `make` porte son aide (sauf les internes préfixées `_`), chaque rôle a son README. Elle ne garde **pas** la qualité du « pourquoi » : ça se juge en revue, et ça vit dans `CHANGELOG.md` et ici | `devis-services.md`, `CHANGELOG.md` | **P31** |
|
| **D-70** | La documentation **dit et explique tout ce que le dépôt fait** — et l'exigence est **outillée**, pas seulement énoncée | une exigence qu'on n'outille pas pourrit en silence : la carte annonçait « 28 décisions » quand il y en avait 66, et disait les accès « non construits » alors qu'ils tournaient en production. **P31** garde le couvert — chaque script s'explique et reste atteignable, chaque cible `make` porte son aide (sauf les internes préfixées `_`), chaque rôle a son README. Elle ne garde **pas** la qualité du « pourquoi » : ça se juge en revue, et ça vit dans `CHANGELOG.md` et ici | `devis-services.md`, `CHANGELOG.md` | **P31** |
|
||||||
|
| **D-74** | **Chaque document déclare son lecteur** en tête — un lecteur et sa situation, pas une catégorie de sujet | la documentation était rangée par SUJET, ce qui est juste pour de la référence — mais personne n'arrive avec un sujet, on arrive avec une **situation**. Symptôme exact : `autorisation.md` portait le runbook de reprise le plus utile du dépôt, enfoui au §6, parce que son sujet est l'autorisation ; personne n'allait l'y chercher. Un document qui déclare son lecteur se range tout seul, et un intrus s'y voit. Deux exemptions, **dérivées et non listées** : un document qui s'annonce généré, et un fragment sans titre | `README.md`, `wiki/Reprendre-l-écosystème.md`, `docs/carte-set-ops.md` | **P34** |
|
||||||
| **D-71** | **Une PKI et un DNS fonctionnels avant toute chose** ; puis, par VM : socle → enrôlement PKI → enregistrement DNS (A **et** PTR) | `deployer-tout` déroule par COUCHES — correct, mais chaque VM réclame alors un certificat à une autorité pas encore debout, et l'échec se lit comme un défaut du rôle et non d'ordre. Les deux hôtes d'amorçage se **dérivent** de `applications.<step_ca\|powerdns>.hote` : déplacer l'autorité déplace l'amorçage. **Deux exceptions structurelles assumées** — l'AC s'auto-signe, le DNS pose son propre enregistrement | `Makefile` `_amorcer-socle`, `scripts/socle_amorcage.py` | — |
|
| **D-71** | **Une PKI et un DNS fonctionnels avant toute chose** ; puis, par VM : socle → enrôlement PKI → enregistrement DNS (A **et** PTR) | `deployer-tout` déroule par COUCHES — correct, mais chaque VM réclame alors un certificat à une autorité pas encore debout, et l'échec se lit comme un défaut du rôle et non d'ordre. Les deux hôtes d'amorçage se **dérivent** de `applications.<step_ca\|powerdns>.hote` : déplacer l'autorité déplace l'amorçage. **Deux exceptions structurelles assumées** — l'AC s'auto-signe, le DNS pose son propre enregistrement | `Makefile` `_amorcer-socle`, `scripts/socle_amorcage.py` | — |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Les devis de service : ce qui tourne correspond-il à ce qui est déclaré ?
|
# Les devis de service : ce qui tourne correspond-il à ce qui est déclaré ?
|
||||||
|
|
||||||
|
> **Pour qui :** l'**exploitant** qui veut savoir si ce qui tourne correspond à ce qui est déclaré.
|
||||||
|
|
||||||
> **Instrument ajouté le 2026-08-08**, après une série de défauts qu'aucun test n'avait
|
> **Instrument ajouté le 2026-08-08**, après une série de défauts qu'aucun test n'avait
|
||||||
> signalés. Lecture seule — il ne modifie rien.
|
> signalés. Lecture seule — il ne modifie rien.
|
||||||
|
|
||||||
|
|
@ -14,7 +16,7 @@ make frontiere-mesurer # ce qui n'est pas déclaré à la frontière est-il re
|
||||||
|
|
||||||
## Le trou qu'il comble
|
## Le trou qu'il comble
|
||||||
|
|
||||||
`scripts/prouver.py` porte 30 preuves. Elles sont toutes **statiques** : elles lisent le
|
`scripts/prouver.py` porte 34 preuves. Elles sont toutes **statiques** : elles lisent le
|
||||||
dépôt. Zéro appel réseau, zéro SSH, zéro `ansible`. Elles établissent que le dépôt est
|
dépôt. Zéro appel réseau, zéro SSH, zéro `ansible`. Elles établissent que le dépôt est
|
||||||
cohérent **avec lui-même** — que les handlers existent, que les intrants ont un
|
cohérent **avec lui-même** — que les handlers existent, que les intrants ont un
|
||||||
propriétaire, que rien n'est codé en dur.
|
propriétaire, que rien n'est codé en dur.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Dimensionnement dérivé des ressources VM
|
# Dimensionnement dérivé des ressources VM
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — comment les ressources d'une VM se dérivent des logiciels qu'elle porte.
|
||||||
|
|
||||||
Ce document décrit comment Set-OPS **estime les ressources d'une VM** (cœurs, RAM,
|
Ce document décrit comment Set-OPS **estime les ressources d'une VM** (cœurs, RAM,
|
||||||
disque) à partir des **propriétés des logiciels** qu'elle héberge et du **socle SE**,
|
disque) à partir des **propriétés des logiciels** qu'elle héberge et du **socle SE**,
|
||||||
plutôt que de laisser chaque clone hériter aveuglément des specs du golden template.
|
plutôt que de laisser chaque clone hériter aveuglément des specs du golden template.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# DNS interne
|
# DNS interne
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** du DNS interne.
|
||||||
|
|
||||||
Le service DNS interne est la premiere capacite de plateforme.
|
Le service DNS interne est la premiere capacite de plateforme.
|
||||||
|
|
||||||
> **Plancher de resolution independant du DNS.** Le socle (`hosts_statiques`, dans
|
> **Plancher de resolution independant du DNS.** Le socle (`hosts_statiques`, dans
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# L'écosystème numérique Chezlepro
|
# L'écosystème numérique Chezlepro
|
||||||
|
|
||||||
|
> **Pour qui :** le **lecteur externe** — client, partenaire, évaluateur. Ce n'est pas un document technique.
|
||||||
|
|
||||||
*Document de présentation — souveraineté et sécurité*
|
*Document de présentation — souveraineté et sécurité*
|
||||||
|
|
||||||
## En une phrase
|
## En une phrase
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Registre des flux réseau — conception
|
# Registre des flux réseau — conception
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** qui déclare un flux réseau dans `roles/*/meta/flux.yml`.
|
||||||
|
|
||||||
## But
|
## But
|
||||||
Set-OPS tient un **registre des flux** (qui parle à qui, sur quel port, dans quel sens, pourquoi)
|
Set-OPS tient un **registre des flux** (qui parle à qui, sur quel port, dans quel sens, pourquoi)
|
||||||
pour **deux usages** :
|
pour **deux usages** :
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# La frontière OPNsense (nord/sud)
|
# La frontière OPNsense (nord/sud)
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** de la bordure nord/sud.
|
||||||
|
|
||||||
> Le pare-feu de bordure de l'écosystème. Ce document fixe les décisions d'architecture
|
> Le pare-feu de bordure de l'écosystème. Ce document fixe les décisions d'architecture
|
||||||
> prises le **2026-07-29**, et décrit le devis **dérivé** qui en découle
|
> prises le **2026-07-29**, et décrit le devis **dérivé** qui en découle
|
||||||
> (`make devis-opnsense`). Il complète `docs/flux-conception.md` (le modèle des flux) et
|
> (`make devis-opnsense`). Il complète `docs/flux-conception.md` (le modèle des flux) et
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Les services d'exploitation de l'hébergeur
|
# Les services d'exploitation de l'hébergeur
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — quels services l'hébergeur se doit à lui-même, et de quoi chacun doit survivre.
|
||||||
|
|
||||||
> **Décision du 2026-08-04.** Tout ce qu'un hébergeur fait tourner n'appartient pas à un
|
> **Décision du 2026-08-04.** Tout ce qu'un hébergeur fait tourner n'appartient pas à un
|
||||||
> tenant. Ce document dit où va quoi, et pourquoi certains services ne peuvent pas vivre
|
> tenant. Ce document dit où va quoi, et pourquoi certains services ne peuvent pas vivre
|
||||||
> dans l'overlay qu'ils observent. **Rien n'est construit** : la décision est consignée,
|
> dans l'overlay qu'ils observent. **Rien n'est construit** : la décision est consignée,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Architecture d'identité et SSO
|
# Architecture d'identité et SSO
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — les deux couches de l'identité, avant de brancher quoi que ce soit dessus.
|
||||||
|
|
||||||
> **Décision arrêtée (2026-07-02).** Modèle **A** : OpenLDAP source de vérité,
|
> **Décision arrêtée (2026-07-02).** Modèle **A** : OpenLDAP source de vérité,
|
||||||
> Keycloak fédéré pour le SSO web, mail en bind LDAP direct.
|
> Keycloak fédéré pour le SSO web, mail en bind LDAP direct.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
# Intégrations des VM
|
# Intégrations des VM
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** qui ajoute une intégration à toutes les VM.
|
||||||
|
|
||||||
## Politique : le défaut est « oui », l'exception se justifie
|
## Politique : le défaut est « oui », l'exception se justifie
|
||||||
|
|
||||||
Une intégration est de l'un des deux genres, et ils ne se déclarent pas au même endroit.
|
Une intégration est de l'un des deux genres, et ils ne se déclarent pas au même endroit.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Note de conception — panneau « Intrants de base » du GUI
|
# Note de conception — panneau « Intrants de base » du GUI
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** du GUI.
|
||||||
|
|
||||||
But : saisir depuis **un endroit unique** les [intrants communs](intrants-communs.md)
|
But : saisir depuis **un endroit unique** les [intrants communs](intrants-communs.md)
|
||||||
de l'écosystème, en distinguant **constantes** et **défauts surchargeables**.
|
de l'écosystème, en distinguant **constantes** et **défauts surchargeables**.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Intrants communs de l'écosystème
|
# Intrants communs de l'écosystème
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — les valeurs partagées par tout l'écosystème, et qui les possède.
|
||||||
|
|
||||||
Recensement des **intrants communs** : les valeurs partagées par tout l'écosystème
|
Recensement des **intrants communs** : les valeurs partagées par tout l'écosystème
|
||||||
(par opposition aux valeurs propres à un seul hôte). Objectif : les saisir **une
|
(par opposition aux valeurs propres à un seul hôte). Objectif : les saisir **une
|
||||||
fois**, depuis un endroit unique, puis les laisser se **dériver** ou se **propager**.
|
fois**, depuis un endroit unique, puis les laisser se **dériver** ou se **propager**.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# La méta-classe — une définition, tout l'écosystème
|
# La méta-classe — une définition, tout l'écosystème
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — le concept qui explique pourquoi on écrit *un* plan et non onze serveurs.
|
||||||
|
|
||||||
Set-OPS se comporte comme une **méta-classe** : on n'écrit pas onze serveurs, on
|
Set-OPS se comporte comme une **méta-classe** : on n'écrit pas onze serveurs, on
|
||||||
écrit *une* **définition d'écosystème** (le plan déclaratif) ; l'instanciation
|
écrit *une* **définition d'écosystème** (le plan déclaratif) ; l'instanciation
|
||||||
engendre la flotte entière, cohérente. Le réseau, la taille des VM, les groupes, les
|
engendre la flotte entière, cohérente. Le réseau, la taille des VM, les groupes, les
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Migrer un tenant d'un hébergeur à un autre
|
# Migrer un tenant d'un hébergeur à un autre
|
||||||
|
|
||||||
|
> **Pour qui :** l'**exploitant** qui déplace un tenant d'un hébergeur à un autre.
|
||||||
|
|
||||||
> **Recette d'exploitation.** Elle décrit la séquence, les états et les gardes ; elle ne
|
> **Recette d'exploitation.** Elle décrit la séquence, les états et les gardes ; elle ne
|
||||||
> décrit pas encore un outil, parce que la séquence doit être éprouvée avant d'être figée
|
> décrit pas encore un outil, parce que la séquence doit être éprouvée avant d'être figée
|
||||||
> dans du code. Complète `docs/multi-instances.md` (la fédération) et
|
> dans du code. Complète `docs/multi-instances.md` (la fédération) et
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Golden template Debian 13 Proxmox
|
# Golden template Debian 13 Proxmox
|
||||||
|
|
||||||
|
> **Pour qui :** qui **fabrique ou audite le gabarit d'or** — ce que Set-OPS ajoute à une Debian 13 minimale, et pourquoi chaque ajout est là.
|
||||||
|
|
||||||
## Objet
|
## Objet
|
||||||
|
|
||||||
Ce document justifie les ajouts appliqués par Set-OPS à une installation Debian 13 minimale pour obtenir le golden template Proxmox.
|
Ce document justifie les ajouts appliqués par Set-OPS à une installation Debian 13 minimale pour obtenir le golden template Proxmox.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Multi-instances — un moteur, N écosystèmes
|
# Multi-instances — un moteur, N écosystèmes
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — la séparation entre le moteur et une instance.
|
||||||
|
|
||||||
Set-OPS sépare **le moteur** (ce dépôt : rôles, playbooks, scripts, GUI) de **l'instance**
|
Set-OPS sépare **le moteur** (ce dépôt : rôles, playbooks, scripts, GUI) de **l'instance**
|
||||||
(un dépôt distinct : le plan d'un écosystème + son inventaire généré + ses secrets). Un
|
(un dépôt distinct : le plan d'un écosystème + son inventaire généré + ses secrets). Un
|
||||||
seul moteur pilote **autant d'instances que voulu**.
|
seul moteur pilote **autant d'instances que voulu**.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Nomenclature des VM
|
# Nomenclature des VM
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** qui nomme une VM.
|
||||||
|
|
||||||
La nomenclature doit rendre lisible la fonction opérationnelle d'une VM sans l'enfermer dans un seul service. (« fonction » est le terme du plan ; « domaine » est réservé au DNS.)
|
La nomenclature doit rendre lisible la fonction opérationnelle d'une VM sans l'enfermer dans un seul service. (« fonction » est le terme du plan ; « domaine » est réservé au DNS.)
|
||||||
|
|
||||||
Un hôte peut porter plusieurs groupes Ansible et plusieurs applications. Le nom de VM représente donc une capacité ou une fonction, pas forcément un produit unique.
|
Un hôte peut porter plusieurs groupes Ansible et plusieurs applications. Le nom de VM représente donc une capacité ou une fonction, pas forcément un produit unique.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Le plan et la génération d'inventaire (méta-classe)
|
# Le plan et la génération d'inventaire (méta-classe)
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** — le plan et la génération de l'inventaire, à fond.
|
||||||
|
|
||||||
Set-OPS ne s'édite plus comme un inventaire à la main : on **décrit un plan**, et
|
Set-OPS ne s'édite plus comme un inventaire à la main : on **décrit un plan**, et
|
||||||
l'inventaire Ansible en est **généré**. Le dépôt est la définition ; chaque VM en
|
l'inventaire Ansible en est **généré**. Le dépôt est la définition ; chaque VM en
|
||||||
est une instance. Ce document décrit le modèle, les registres, les commandes et
|
est une instance. Ce document décrit le modèle, les registres, les commandes et
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Positionnement : ce que Set-OPS fait maison, et quand adopter l'existant
|
# Positionnement : ce que Set-OPS fait maison, et quand adopter l'existant
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur**, et quiconque arbitre une évolution : ce qui reste maison, et à quel seuil on adopte l'existant.
|
||||||
|
|
||||||
Ce document **acte une décision** pour ne plus la redébattre à chaque évolution :
|
Ce document **acte une décision** pour ne plus la redébattre à chaque évolution :
|
||||||
quelles parties de Set-OPS sont volontairement *maison*, pourquoi, et à partir de
|
quelles parties de Set-OPS sont volontairement *maison*, pourquoi, et à partir de
|
||||||
quel **seuil** il vaudra mieux adopter un outil du marché plutôt que continuer à
|
quel **seuil** il vaudra mieux adopter un outil du marché plutôt que continuer à
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Les pouvoirs de Set-OPS
|
# Les pouvoirs de Set-OPS
|
||||||
|
|
||||||
|
> **Pour qui :** qui **évalue le moteur** — ce qu'il sait faire, et ce qu'il ne sait pas encore.
|
||||||
|
|
||||||
> Bilan des capacités du moteur, au 2026-07-02.
|
> Bilan des capacités du moteur, au 2026-07-02.
|
||||||
> Fondé sur l'état réel du dépôt (≈50 rôles, ≈30 playbooks de groupe, le moteur de plan, la GUI).
|
> Fondé sur l'état réel du dépôt (≈50 rôles, ≈30 playbooks de groupe, le moteur de plan, la GUI).
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Procédure manuelle — VM Debian 13 vanille pour Proxmox
|
# Procédure manuelle — VM Debian 13 vanille pour Proxmox
|
||||||
|
|
||||||
|
> **Pour qui :** l'**exploitant** qui fabrique le gabarit d'or à la main, une fois.
|
||||||
|
|
||||||
## Objet du document
|
## Objet du document
|
||||||
|
|
||||||
Ce document décrit le travail manuel à effectuer pour créer une VM Debian 13 vanille dans Proxmox, jusqu’au moment où elle peut être prise en charge par Set-OPS.
|
Ce document décrit le travail manuel à effectuer pour créer une VM Debian 13 vanille dans Proxmox, jusqu’au moment où elle peut être prise en charge par Set-OPS.
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# SDN EVPN : le routage passe aux hyperviseurs
|
# SDN EVPN : le routage passe aux hyperviseurs
|
||||||
|
|
||||||
|
> **Pour qui :** le **mainteneur** du réseau overlay.
|
||||||
|
|
||||||
> **Décision d'architecture du 2026-08-02.** Elle remplace le routage inter-zone sur les
|
> **Décision d'architecture du 2026-08-02.** Elle remplace le routage inter-zone sur les
|
||||||
> commutateurs L3 par des zones EVPN de Proxmox SDN. Complète `docs/frontiere-opnsense.md`
|
> commutateurs L3 par des zones EVPN de Proxmox SDN. Complète `docs/frontiere-opnsense.md`
|
||||||
> (la bordure, inchangée) et `underlay.yml.example` (la fabric, très allégée).
|
> (la bordure, inchangée) et `underlay.yml.example` (la fabric, très allégée).
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Appliquer le thème Alliance Boréale à une forge Forgejo hors flotte
|
# Appliquer le thème Alliance Boréale à une forge Forgejo hors flotte
|
||||||
|
|
||||||
|
> **Pour qui :** l'**exploitant** d'une forge Forgejo *hors* de la flotte Set-OPS.
|
||||||
|
|
||||||
Procédure **manuelle**, pour une instance Forgejo qui n'est **pas** gérée par Set-OPS —
|
Procédure **manuelle**, pour une instance Forgejo qui n'est **pas** gérée par Set-OPS —
|
||||||
typiquement la forge historique qui héberge ce dépôt et son wiki.
|
typiquement la forge historique qui héberge ce dépôt et son wiki.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# Cycle de vie des VM
|
# Cycle de vie des VM
|
||||||
|
|
||||||
|
> **Pour qui :** l'**exploitant** — ce qu'une VM traverse, de l'installation à la conformité continue.
|
||||||
|
|
||||||
Ce document décrit le cycle normal d'une VM Debian, depuis l'installation minimale jusqu'à la conformité continue par Ansible.
|
Ce document décrit le cycle normal d'une VM Debian, depuis l'installation minimale jusqu'à la conformité continue par Ansible.
|
||||||
|
|
||||||
## Vue d'ensemble
|
## Vue d'ensemble
|
||||||
|
|
|
||||||
|
|
@ -399,6 +399,64 @@ def preuve_inventaire_ansible() -> tuple[bool, str]:
|
||||||
return True, f"{n_hotes} hotes, {n_groupes} groupes (inventaire dechiffre et parse)."
|
return True, f"{n_hotes} hotes, {n_groupes} groupes (inventaire dechiffre et parse)."
|
||||||
|
|
||||||
|
|
||||||
|
def preuve_lecteur_declare() -> tuple[bool, str]:
|
||||||
|
"""Chaque document de `docs/` declare son lecteur des sa premiere ligne.
|
||||||
|
|
||||||
|
La refonte du 2026-08-10 part d'un constat : la documentation etait rangee par SUJET,
|
||||||
|
ce qui est juste pour de la reference — mais personne n'arrive avec un sujet, on arrive
|
||||||
|
avec une SITUATION. Le symptome exact : `autorisation.md` contient le runbook de reprise
|
||||||
|
le plus utile du depot, enfoui au §6, parce que son SUJET est l'autorisation. Personne
|
||||||
|
n'allait l'y chercher.
|
||||||
|
|
||||||
|
D'ou la convention : un document declare son lecteur, pas sa categorie. Il se range
|
||||||
|
alors tout seul, et un intrus s'y voit.
|
||||||
|
|
||||||
|
CE QU'ELLE TESTE : la presence d'une ligne `> **Pour qui :** …` dans l'en-tete (avant
|
||||||
|
le premier titre de section), pour tout `docs/**/*.md`.
|
||||||
|
|
||||||
|
DEUX EXEMPTIONS, et elles sont DERIVEES, pas listees :
|
||||||
|
|
||||||
|
- un document qui se declare GENERE ne se lit pas, il se regenere. Il s'annonce
|
||||||
|
lui-meme (« Genere par », « ne pas editer a la main ») ; on le reconnait a ca,
|
||||||
|
et non par un chemin en dur qui vieillirait a la premiere page ajoutee ;
|
||||||
|
- un fragment sans titre `#` n'est pas un document.
|
||||||
|
|
||||||
|
CE QU'ELLE NE TESTE PAS : que le lecteur declare soit le BON. Ca se juge en revue.
|
||||||
|
Elle garantit seulement qu'on a du y penser — ce qui est exactement ce qui manquait :
|
||||||
|
32 des 34 documents n'en disaient rien.
|
||||||
|
"""
|
||||||
|
docs = sorted((RACINE / "docs").rglob("*.md"))
|
||||||
|
muets: list[str] = []
|
||||||
|
generes = 0
|
||||||
|
for f in docs:
|
||||||
|
lignes = f.read_text(encoding="utf-8", errors="ignore").splitlines()
|
||||||
|
# L'EN-TETE seulement : ce qui suit le premier `##` appartient au corps. Une
|
||||||
|
# mention de « Pour qui » perdue au milieu d'une page ne serait pas une porte.
|
||||||
|
entete = []
|
||||||
|
for l in lignes:
|
||||||
|
if l.startswith("## "):
|
||||||
|
break
|
||||||
|
entete.append(l)
|
||||||
|
tete = "\n".join(entete)
|
||||||
|
tete_bas = tete.lower()
|
||||||
|
if "genere par" in tete_bas or "généré par" in tete_bas \
|
||||||
|
or "ne pas editer a la main" in tete_bas or "ne pas éditer à la main" in tete_bas:
|
||||||
|
generes += 1
|
||||||
|
continue
|
||||||
|
if not any(l.startswith("# ") for l in entete):
|
||||||
|
continue
|
||||||
|
if "**Pour qui" not in tete:
|
||||||
|
muets.append(str(f.relative_to(RACINE)))
|
||||||
|
if muets:
|
||||||
|
return False, (
|
||||||
|
f"{len(muets)} document(s) ne declarent pas leur lecteur : "
|
||||||
|
+ ", ".join(muets[:6]) + ("…" if len(muets) > 6 else "")
|
||||||
|
+ " — ajouter `> **Pour qui :** …` sous le titre."
|
||||||
|
)
|
||||||
|
return True, (f"{len(docs) - generes} document(s) declarent leur lecteur "
|
||||||
|
f"({generes} genere(s) exempte(s)).")
|
||||||
|
|
||||||
|
|
||||||
def preuve_documentation_outillage() -> tuple[bool, str]:
|
def preuve_documentation_outillage() -> tuple[bool, str]:
|
||||||
"""Tout ce que Set-OPS FAIT s'explique et reste atteignable.
|
"""Tout ce que Set-OPS FAIT s'explique et reste atteignable.
|
||||||
|
|
||||||
|
|
@ -573,6 +631,8 @@ PREUVES: list[dict] = [
|
||||||
"func": preuve_documentation_outillage},
|
"func": preuve_documentation_outillage},
|
||||||
{"id": "P32", "titre": "Intrants exiges par les roles : tous fournis", "refs": [],
|
{"id": "P32", "titre": "Intrants exiges par les roles : tous fournis", "refs": [],
|
||||||
"cmds": [[sys.executable, "scripts/verifier_intrants.py"]]},
|
"cmds": [[sys.executable, "scripts/verifier_intrants.py"]]},
|
||||||
|
{"id": "P34", "titre": "Chaque document declare son lecteur", "refs": [],
|
||||||
|
"func": preuve_lecteur_declare},
|
||||||
{"id": "P33", "titre": "Aucune collision de port entre roles co-localises", "refs": [],
|
{"id": "P33", "titre": "Aucune collision de port entre roles co-localises", "refs": [],
|
||||||
"cmds": [[sys.executable, "scripts/verifier_ports.py"]]},
|
"cmds": [[sys.executable, "scripts/verifier_ports.py"]]},
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ Trois idées la portent :
|
||||||
|
|
||||||
- **Le registre** : `docs/audit/affirmations.md` — chaque affirmation du dépôt (README, docs,
|
- **Le registre** : `docs/audit/affirmations.md` — chaque affirmation du dépôt (README, docs,
|
||||||
aide `make`, GUI) reliée à une preuve et un statut (✅/🟡/❌/⚪).
|
aide `make`, GUI) reliée à une preuve et un statut (✅/🟡/❌/⚪).
|
||||||
- **Le harnais** : `make prouver` rejoue les preuves automatisables (**P01–P33**) et écrit
|
- **Le harnais** : `make prouver` rejoue les preuves automatisables (**P01–P34**) et écrit
|
||||||
`docs/audit/preuve-<date>.md`. `make verifier` les inclut : il **échoue** si une preuve échoue.
|
`docs/audit/preuve-<date>.md`. `make verifier` les inclut : il **échoue** si une preuve échoue.
|
||||||
- **Chaque preuve garde une classe d'erreur.** Extrait :
|
- **Chaque preuve garde une classe d'erreur.** Extrait :
|
||||||
|
|
||||||
|
|
@ -42,6 +42,7 @@ Trois idées la portent :
|
||||||
| P31 | une capacité du dépôt **non expliquée** (script muet, cible sans aide, rôle sans README) |
|
| P31 | une capacité du dépôt **non expliquée** (script muet, cible sans aide, rôle sans README) |
|
||||||
| P32 | un intrant qu'un rôle **exige** et que l'instance ne fournit pas |
|
| P32 | un intrant qu'un rôle **exige** et que l'instance ne fournit pas |
|
||||||
| P33 | deux rôles co-localisés qui **revendiquent le même port** |
|
| P33 | deux rôles co-localisés qui **revendiquent le même port** |
|
||||||
|
| P34 | un document qui ne **déclare pas son lecteur** — il finirait rangé par sujet, donc introuvable |
|
||||||
|
|
||||||
> **Ce que ces preuves ne font pas, et il faut le savoir avant de leur faire confiance.** Elles
|
> **Ce que ces preuves ne font pas, et il faut le savoir avant de leur faire confiance.** Elles
|
||||||
> sont toutes **statiques** : elles lisent le dépôt, sans un seul appel réseau. Elles établissent
|
> sont toutes **statiques** : elles lisent le dépôt, sans un seul appel réseau. Elles établissent
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue