Méthode, octobre 2026
Prouver qu'une mise en production a eu lieu
Une intégration continue verte dit que le code a passé ses contrôles. Elle ne dit pas que l'adresse publique sert ce code. Sur ce site, l'écart a d'abord laissé une version en attente sans que rien ne le signale, puis il a trompé la vérification ajoutée pour le fermer. La sonde qui le ferme désormais se lit à deux adresses que chacun peut ouvrir.
Un merge qui ne déploie rien
Ce site est servi par Cloudflare Pages, et le projet n'est relié à aucun dépôt Git. L'API de Cloudflare le confirme, ses déploiements portent le déclencheur ad_hoc. Fusionner une branche ne construit donc rien. Le seul chemin vers la production est une étape de l'intégration continue, qui envoie le dossier construit à Cloudflare après chaque push surmain.
Fin août 2026, cette étape n'a pas tourné. Le compte GitHub avait atteint son plafond de dépense et les tâches ne démarraient plus. La fusion, elle, s'est faite sans erreur. J'ai attendu un déploiement qui ne pouvait pas partir, pendant que l'adresse publique servait l'ancienne version. Aucun voyant n'était rouge, parce que rien n'avait échoué. Rien n'avait commencé.
Une preuve qui répond oui dans les deux cas
La première parade a été une preuve en fin de déploiement. Astro donne à la feuille de style un nom qui contient une empreinte de son contenu. L'intégration continue lit ce nom dans la page qu'elle vient de construire, puis interroge l'adresse publique jusqu'à le retrouver. Le raisonnement était simple. Si la page servie contient un nom qui n'existait pas avant ce build, elle vient de ce build.
Il tenait pour le cas visé et tombait sur le cas le plus courant. Le 8 septembre, j'ai réécrit le chapeau de l'accueil sans toucher à la feuille de style. L'empreinte n'a pas bougé, et la preuve l'aurait trouvée dans l'ancienne page aussi bien que dans la nouvelle. Le 29 septembre, même constat sur une autre version, avec un nom de feuille identique avant et après. Dans les deux cas, la vérification aurait conclu au succès, que le déploiement ait eu lieu ou non.
Ces deux jours-là, une lecture à la main a tranché. Elle cherchait dans la page servie une phrase qui n'existait pas avant le changement, avec un paramètre ajouté à l'adresse pour passer le cache.
Le site dit lui-même quel commit il sert
La sonde actuelle prend la question dans l'autre sens. Au lieu de chercher une trace du build dans la page, le site déclare son commit. Pendant la construction, la page/deploye.json reçoit l'identifiant du commit et l'heure du build. Elle ne fait rien d'autre.
Reste à connaître la tête de main sans confier au site un jeton GitHub. Un workflow tourne à chaque push sur main et poste le commit au site, authentifié par le jeton OIDC que GitHub délivre à chaque exécution. Le site le range dans un espace KV de Cloudflare, avec l'heure à laquelle main a commencé à porter un commit non servi. Aucun secret n'est stocké des deux côtés.
La page /health compare les deux. Quand le commit servi est la tête demain, elle écrit « a jour ». Quand main porte depuis plus de 24 heures un commit que la production ne sert pas, elle passe en attention. Le délai court depuis le premier commit non servi et ne repart pas à chaque fusion. Deux fusions par jour sur un déploiement cassé ne doivent pas garder la sonde verte une semaine.
La même réponse juge les pages du site sur leur contenu, puis chaque fichier qu'elles chargent et les polices que la feuille demande. Un parcours cassé la met en rouge, avec la raison écrite dans la réponse.
La lecture se refait en une minute
Ouvrir /health sur ce site donne le commit servi, l'heure du build et le jugement. Le même champ existe sur mes autres sites. Celui de cleanpoker.dev renvoie le commit complet, et son code est public. Coller cet identifiant dans l'adresse du dépôt suffit à lire le code qui tourne à cet instant, sans me croire sur parole.
Des agents IA écrivent une partie du code de mes produits, et sur plusieurs dépôts ils fusionnent eux-mêmes leurs changements. Cette sonde est l'étape qui leur dit si leur travail est en ligne. Elle doit donc pouvoir répondre non, et elle le fait sans qu'un humain relise quoi que ce soit.
Les limites
La sonde dit quel commit est servi. Elle ne juge pas sa qualité. Un commit fautif mis en ligne à l'heure est « a jour ». Les tests et la relecture restent le seul rempart contre lui.
Elle ne sait rien d'un build fait hors de l'intégration continue. Un déploiement lancé à la main, depuis un poste, écrit « inconnu » dans /deploye.json, et la sonde le dit au lieu de deviner.
Elle ne remplace pas non plus la lecture d'une phrase neuve après un changement de texte. Le commit prouve que la nouvelle version est servie. Il ne prouve pas que la page qu'un lecteur reçoit a quitté le cache d'un nœud du réseau. Après chaque mise en ligne de ce site, je lis donc /health, puis la page modifiée deux fois, dont une avec un paramètre qui contourne le cache.