diff --git a/CHANGELOG.md b/CHANGELOG.md index a6005e4..c90c556 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/docs/decisions-architecture.md b/docs/decisions-architecture.md index d25c898..c175ce3 100644 --- a/docs/decisions-architecture.md +++ b/docs/decisions-architecture.md @@ -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` | --- diff --git a/docs/devis-services.md b/docs/devis-services.md index a07f84b..a523a35 100644 --- a/docs/devis-services.md +++ b/docs/devis-services.md @@ -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