doctrine : D-68 et D-69 — relire ce qu'on ecrit, pas « toujours l'API »

Question de l'exploitant apres deux pannes causees par kcadm. La reponse est
non, et elle se fonde sur la mesure : sur six familles de defauts du jour,
deux seulement viennent d'un CLI ; un module Ansible (ldap_entry) a commis la
meme faute, et trois autres viennent d'un grep de fichier, de la precedence
Ansible et de mon propre comparateur.

D-68 — ecrire, puis relire et comparer, quelle que soit l'interface ; choisir
celle dont le chemin de lecture parle le meme langage que celui d'ecriture.
Une API est souvent preferable parce qu'elle rend la ressource ENTIERE, ce qui
permet le patron de chaque devis. Mais la plupart de la flotte n'a pas d'API,
et postconf -h / -e sont parfaitement symetriques.

D-69 — sur Keycloak : l'API pour toute map ou collection, kcadm ailleurs
(vocabulaire de la doc du produit, donc lisible sans IA).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Daniel Allaire 2026-08-08 11:45:31 -04:00
parent 44ee6d4d36
commit c9d84e48d9
3 changed files with 61 additions and 0 deletions

View file

@ -1,5 +1,33 @@
# CHANGELOG — Set-OPS
## 2026-08-08 — D-68 / D-69 : la règle n'est pas « toujours l'API »
Question de l'exploitant après deux pannes causées par `kcadm` : ne devrait-on pas toujours
utiliser une API quand il en existe une ?
Non — et la journée le montre mieux qu'un principe. Sur six familles de défauts, **deux**
seulement viennent d'un CLI ; un module Ansible (`ldap_entry`, qui crée sans jamais
modifier) a commis exactement la même faute, et trois autres viennent d'un `grep` de
fichier, de la précédence Ansible, et de mon propre comparateur. Le facteur commun n'est pas
l'interface : c'est d'avoir **écrit sans relire**.
**D-68** — on écrit, puis on relit et on compare, quelle que soit l'interface ; on choisit
celle dont le chemin de *lecture* parle le même langage que le chemin d'*écriture*. Une API
est souvent préférable pour une raison précise — elle rend la ressource entière, ce qui
permet le patron de chaque devis : *fusionner l'attendu dans le réel ; si rien ne change,
c'est conforme*. Mais la plupart de la flotte n'a pas d'API (Postfix, Dovecot, nginx, slapd,
nftables), et `postconf -h` / `postconf -e` sont parfaitement symétriques.
**D-69** — sur Keycloak en particulier : l'API pour toute map ou collection (`smtpServer`,
`attributes`, `config`), où `kcadm -s` sort en succès sans rien écrire ; `kcadm` ailleurs,
parce que c'est le vocabulaire de la documentation du produit — donc lisible par un
sysadmin sans IA.
Deux raisons de ne pas systématiser l'API méritent d'être dites : le CLI est souvent le
**contrat du fournisseur** et encode des invariants (`occ user:resetpassword` hache
correctement), et chaque appel d'API demande un jeton, donc du secret manipulé dans chaque
tâche.
## 2026-08-08 — Déconnexion OIDC : Keycloak valide une SECONDE liste d'URI
Nextcloud se connectait parfaitement et échouait à la déconnexion, sur un

View file

@ -105,6 +105,8 @@ sont les seules vérifiables.
| **D-28** | Le mandat de migration est **signé par le tenant**, pas convenu entre hébergeurs | il n'y a pas de registre central pour arbitrer ; une organisation n'est pas la propriété de son hébergeur | `migration-tenant.md` §2 | — |
| **D-33** | Une intégration **universelle** est déclarée par le **rôle**, jamais recopiée par serveur | 28 des 57 lignes du plan disaient oui à ce qui vaut pour tous : elles n'existaient que pour être oubliées — et quatre l'avaient été | `integrations-vm.md` §Politique | P26 |
| **D-34** | Une **exemption** se dérive du **service rendu** (`sauf_role`), jamais d'un nom d'hôte | l'AC ne s'enrôle pas auprès d'elle-même ; l'exemption doit suivre step-ca si on le déplace | `roles/client_pki/meta/integration.yml` | P26 |
| **D-68** | On **écrit, puis on relit et on compare** — quelle que soit l'interface ; on choisit celle dont le chemin de **lecture** parle le même langage que le chemin d'**écriture** | « toujours préférer l'API » n'aurait prédit aucune des pannes du 2026-08-08 : sur six familles de défauts, deux venaient d'un CLI, une d'un module Ansible (`ldap_entry` crée sans jamais modifier), une d'un `grep` de fichier, une de la précédence Ansible, une de mon comparateur. Le facteur commun est d'avoir écrit sans relire. Et la plupart de la flotte n'a **pas** d'API — Postfix, Dovecot, nginx, slapd, nftables : `postconf -h` / `postconf -e` sont symétriques, c'est tout ce qu'on demande | `devis-services.md` | les 5 devis |
| **D-69** | Sur Keycloak : **l'API pour toute map ou collection** (`smtpServer`, `attributes`, `config`), `kcadm` pour les scalaires et les créations | `kcadm -s` sur une map accepte la commande, **sort en succès et n'écrit rien** — mesuré deux fois le 2026-08-08 (`smtpServer` resté vide après deux déploiements verts, puis `post.logout.redirect.uris`). Le CLI reste préféré ailleurs : c'est le vocabulaire de la documentation du produit, donc lisible sans IA | `roles/serveur_keycloak/tasks/` | `make identite-plan` |
---

View file

@ -126,6 +126,37 @@ révèle que le courrier ne bouge pas.
Le routage local se fait par **identifiant** (`uid`), pas par l'attribut `mail` — voir le
gabarit `ldap-mailboxes.cf.j2` pour la raison et le coût assumé.
## La règle dont ces devis découlent (D-68)
> **Écrire, puis relire et comparer** — quelle que soit l'interface. Choisir celle dont le
> chemin de *lecture* parle le même langage que le chemin d'*écriture*.
Ce n'est pas « toujours préférer l'API ». Cette règle-là n'aurait prédit aucune des pannes
du 2026-08-08. Sur six familles de défauts ce jour-là, **deux** venaient d'un CLI :
| Ce qui a menti | Interface |
|---|---|
| `kcadm -s` sur une map : succès, rien d'écrit | CLI |
| `grafana-cli` : « password changed ✔ » dans une base fantôme | CLI |
| `ldap_entry` : crée, ne modifie jamais | module Ansible |
| `grep postgresql.conf` : valeur fausse (surcharge `conf.d`) | lecture de fichier |
| `include_vars` : le devis rapportait le défaut, pas le réel | précédence Ansible |
| le comparateur d'expositions : un 502 compté comme vivant | mon propre code |
Le facteur commun n'est pas l'interface, c'est d'avoir **écrit sans relire**. Et la plupart
de la flotte n'a pas d'API du tout — Postfix, Dovecot, nginx, slapd, nftables. `postconf -h`
et `postconf -e` sont parfaitement symétriques : lecture et écriture dans le même
vocabulaire, c'est tout ce qu'on demande.
Une API est souvent préférable, mais pour une raison précise : elle rend la ressource
**entière**, ce qui permet le patron qu'on retrouve dans chaque devis — *fusionner
l'attendu dans le réel ; si rien ne change, c'est conforme*. Une interface qui n'accepte
que des écritures ne peut pas le soutenir.
**Les cinq devis sont cette relecture**, faite après coup et par une autre main que celle
qui a écrit. C'est ce qui les distingue d'un déploiement : `make deployer` réconcilie, les
devis constatent.
## Un piège de construction, à connaître avant d'écrire le prochain
`include_vars` au niveau du *play* **prime sur les `group_vars`**. Charger les défauts d'un