T8 Décisions, incidents et dette

Pourquoi c'est fait ainsi. À lire avant de vouloir simplifier.
Un repreneur retrouve le code, pas les raisons

Il voit une construction qui paraît compliquée, la simplifie, et reproduit l'incident qu'elle évitait. Chaque décision ci-dessous indique l'alternative écartée et pourquoi — la seule information vraiment irremplaçable.

Les cinq décisions structurantes

RetenuÉcartéPourquoi
Deux environnements figés
a et b, clés suffixées
Un modèle générique à N environnements, déclencheur unique qui se dédouble Le moteur n'émet qu'un message par sortie. Le modèle générique demandait exactement ce qu'il ne sait pas faire — 48 h de jetons interrompus. La forme retenue laisse l'environnement principal inchangé au caractère près.
Configuration par balise
site, source, modèle, métriques
Des défauts globaux, complétés balise par balise Les défauts produisaient des envois silencieusement faux. Mieux vaut ne rien envoyer et le dire (IOBASE_SKIP) qu'envoyer une donnée fausse.
Cockpit embarqué
sans dépendance externe
Une interface hébergée ailleurs, ou chargeant des ressources distantes On a besoin du cockpit précisément quand la liaison est coupée. D'où les graphiques en SVG écrits à la main : deux graphiques ne justifiaient pas une bibliothèque.
Statistiques à part
fichier dédié
Les ajouter à l'état des balises, déjà persisté Cet état porte le compteur et les réglages en cours ; sa sérialisation est écrite à la main. Un besoin d'affichage ne doit pas risquer l'état de service. Et l'état est écrit toutes les 2 min : y ajouter les trames aurait usé la flash.
La saisie prime
sur le fichier d'état
Laisser le fichier faire autorité, comme à l'origine Le fichier est un cache de survie, pas la source de vérité. Sans cette règle, une valeur corrigée revenait en arrière au redémarrage. Les jetons sont exclus : les figer empêcherait leur restauration.

Les cinq incidents

DateCe qui s'est passéCe qui a changé
6 juil. Ajout de capteur pendant un renouvellement → redémarrage → jeton à usage unique perdu. Passerelle hors service jusqu'à une intervention externe. L'ajout est refusé si un renouvellement est en cours, si un autre ajout est en vol, ou si le même équipement est récent.
29–31 août Un node émettant une liste a interrompu les jetons 48 h. Le cockpit l'affichait ; personne ne regardait, et l'alerte est tombée un week-end dans un canal non consulté. Motif interdit et vérifié automatiquement. Et surtout : les graphiques du tableau de bord, parce qu'un signal que personne ne regarde ne protège de rien.
29 août Un déploiement fondé sur un instantané ancien a supprimé une balise déclarée entre-temps. Le contrôle compare au flux en service et refuse tout envoi qui retirerait un node.
depuis le 29 août Le nom de l'API de recette ne résout plus. La passerelle va bien, chaque mesure est perdue. Une procédure trace la frontière en trois vérifications (E5).
4 sept. Le contrôle avant déploiement lisait la date du fichier d'état au lieu de l'horodatage qu'il contient : 4 h annoncées pour un jeton qui en avait 9. Il lit la valeur qui décide réellement. Un contrôle rassurant à tort est pire qu'aucun contrôle.
Leur fil commun

Aucun ne vient de code faux au sens habituel. Tous viennent de ce que quelque chose qu'on croyait vrai ne l'était pas, et que rien ne le disait : du code jamais exécuté cru éprouvé, un état affiché que personne ne lisait, un instantané cru à jour, un indicateur qui mesurait autre chose.

D'où l'orientation prise : préférer ce qui lit le réel à ce qui le décrit, et rendre visible ce qui manque. Les trois références produites depuis le flux, avec leur section « non décrit », viennent de là.

Dette connue

SujetÉtatCoût de correction
Rôles cosmétiques L'API n'exige le rôle admin que pour les variables globales. Un compte d'exploitation peut modifier une balise, en déclarer une, envoyer une commande. L'archivage est masqué dans l'interface mais accepté par l'API. Faible : un contrôle de rôle sur trois fonctions. Décision produit, pas contrainte technique.
Arriéré des journaux 63 fichiers, 13,9 Mo, certains d'il y a un an, pour une rétention de 15 jours. La rotation ne traite qu'un fichier par exécution. Nettoyage manuel. Sans urgence : partition à 29 %.
Second environnement non éprouvé Le routage est vérifié de bout en bout ; le renouvellement de son jeton ne l'est pas. Dépendance externe : un enrôlement réel. À demander tôt.
Réimportation d'un gabarit La configuration de la CloudGate se capture et s'inventorie, mais personne ne l'a jamais reposée sur une autre passerelle : il n'en existe qu'une. Dépendance externe : une CloudGate vierge. Le test se fait avant tout déploiement, sinon le gabarit est contaminé par le flux.

Trois entrées ont quitté ce tableau, et il vaut mieux savoir lesquelles que de les croire encore ouvertes. Les secrets en clair : le dépôt est reparti d'une base saine, les valeurs d'un site vivent dans des fichiers non versionnés, aucun script ne porte plus de mot de passe par défaut, et un contrôle échoue si un secret réapparaît dans le flux éclaté. La file orpheline : les cinq nodes qui pointaient vers une file inexistante ont été nettoyés le 11/09. Le chapitre Déploiement, qui mêlait la mise en service de l'appareil et le déploiement du flux : la scission est faite le 18/09, la page distingue la couche CloudGate de la couche applicative.

Ce qui n'est pas de la dette

Quatre constructions paraissent inutilement prudentes. Les simplifier rejouerait un incident déjà payé.

Le verrou sur le renouvellement Deux renouvellements simultanés perdent un jeton, et sa récupération passe par un tiers.
La garde des six heures Sans elle, chaque déploiement consommerait un jeton. C'est ce qui rend les déploiements fréquents possibles.
Le repli vers l'environnement principal Il rend le déploiement sans effet tant que les valeurs manquent — ce qui a permis de livrer sans attendre le client.
La répétition de restauration Elle prouve qu'on sait réparer l'état sans personne. C'est le filet.