[🛠] Operations Automation #3: Migration de l’automatisation historique des congés vers le NAS et connexion HTTPS externe
✨ Résumé de GPT-5.6 Sol
Le récit du transfert des fonctions et des données existantes de gestion des congés vers un nouvel environnement NAS, puis de la correction des défauts d’interface révélés sur un véritable appareil mobile après la connexion HTTPS externe.
J’ai transféré les fonctions et les données de l’automatisation historique des congés vers un nouvel environnement NAS, puis relié le chemin qui permet aux requêtes HTTPS externes d’atteindre l’application à l’intérieur du NAS. Il ne s’agissait pas simplement de lancer un container, mais de déplacer un flux de travail existant vers un nouvel environnement d’exploitation.
Pourtant, l’affichage du nouvel écran ne suffisait pas pour déclarer la migration terminée. Les données des employés et des congés devaient apparaître, et les destinataires des relances ainsi que le texte des messages devaient correspondre à l’ancien système. Les messages dépassant la limite quotidienne de 130 devaient être reportés au lendemain, tandis que la queue d’envoi et l’historique devaient eux aussi être repris. S’il manquait un seul élément, ce serait un autre service portant seulement le même nom.
Lorsque j’avais auparavant de nouveau séparé l’automatisation des ventes de l’administration du personnel, j’avais décidé de reproduire les fonctions existantes de relance des congés avant de les déplacer. Une fois le travail commencé, cet ordre s’est révélé encore plus important. J’ai repoussé quelque temps le deploy sur le NAS.
Reproduction locale des fonctions et restauration des données
J’ai d’abord exécuté FastAPI, Next.js et MariaDB dans un environnement Compose local et isolé. Pour éviter tout conflit avec le service existant, j’ai également séparé port, network, volume et credential. Je me suis connecté en tant qu’administrateur, j’ai ouvert les données des employés et des congés, puis j’ai comparé au flux existant les destinataires des relances, les textes générés, les envois programmés au-delà de la limite de 130, la queue et l’historique.
Je ne voulais pas toucher directement à la DB de production. J’ai restauré le backup SQL existant dans une instance MariaDB distincte, puis comparé le schema et le nombre d’enregistrements des principales table. J’ai aussi vérifié que les données subsistaient après le redémarrage du backend. Ce n’est qu’à ce moment-là que j’ai disposé d’une référence de fonctionnement locale. Si un problème survenait ensuite sur le NAS, je pourrais distinguer un changement de code d’une mauvaise image ou d’une mauvaise configuration network.
La restauration du backup ne signifiait pas que la transition opérationnelle était terminée. Le compte administrateur, le téléphone professionnel et les véritables SMS n’avaient pas encore emprunté le nouveau chemin.
Double limitation sur le chemin réel d’envoi des SMS
Le blocage suivant concernait les véritables SMS. Sans envoyer de message, je ne pouvais pas observer jusqu’au bout le chemin qui mène au téléphone Android professionnel. Mais je ne pouvais pas non plus laisser ouvert l’envoi en production pour effectuer un test.
J’ai donc divisé le mode d’envoi du server en trois options.
NO_SEND
ALLOWLIST_SEND
PRODUCTION
L’état habituel est NO_SEND. Ce n’est que pendant le test que j’ai placé un destinataire autorisé dans ALLOWLIST_SEND. J’ai identifié la cible à l’aide d’un hash SHA-256 plutôt qu’avec le numéro de téléphone en clair, et j’ai limité à un le nombre de messages que le server pouvait réclamer. J’ai également ajouté un budget distinct d’un message dans l’application Android. Je voulais éviter qu’un second message parte même si le server ou l’application était mal manipulé.
Je ne me suis pas contenté de lire le code pour valider cet état. Avec Computer Use, j’ai ouvert l’écran réel d’administration et vérifié NO_SEND, le nombre de messages alors disponibles pour claim, la queue et l’historique. Sur le même écran, j’ai aussi comparé le résultat du travail de Codex au code d’implémentation.

J’ai également créé un package de test distinct afin de ne pas toucher directement à l’application opérationnelle. Sur l’appareil Android connecté en USB, j’ai utilisé adb reverse pour relier l’endpoint local. Un véritable SMS s’est ainsi terminé en SUCCESS, et j’ai constaté son arrivée sur l’appareil destinataire.
Un résultat ambigu est aussi apparu. L’utilisateur avait reçu le message, mais le delivery callback Android n’avait pas été capturé. SUCCESS signifiait que l’opérateur avait accepté la demande d’envoi, pas que le delivery callback était terminé. Si je regroupais la réception réelle et l’état du callback sous le même succès, il deviendrait encore plus difficile de décider ensuite comment traiter les cas UNKNOWN.
Après avoir observé un message, je suis immédiatement revenu à NO_SEND. L’Android readiness était à 0 et le claim du server renvoyait 204 No Content. J’ai terminé le test dans un état où une action accidentelle supplémentaire ne pouvait pas envoyer un autre message.
Migration des images Docker linux/amd64 vers le NAS
Je n’ai déployé sur le NAS que le service d’automatisation des congés, et non toute la plateforme d’automatisation. Au lieu de rebuild le source sur le NAS, j’ai créé les image linux/amd64 sur le Mac, vérifié leurs hash, puis les ai transférées. J’ai aussi séparé le project Compose du stack existant. Cette organisation évitait que le remplacement d’un seul backend recrée en même temps MariaDB et le Frontend.
Connexion du HTTPS externe et du Reverse Proxy
L’écran de connexion s’est ouvert à la nouvelle adresse, et les données existantes des employés et des congés étaient visibles. Mais un texte ne permettait pas de comprendre d’un seul coup d’œil comment les requêtes d’un navigateur externe atteignaient MariaDB. En particulier, lorsque j’expliquais si 3101 était un port ouvert sur Internet ou seulement utilisé dans le NAS, les frontières se brouillaient sans cesse. J’ai donc représenté le chemin de la requête dans un schéma.
Le schéma a montré que seul HTTPS 443 était nécessaire depuis l’extérieur. Le Router transmet 443 au NAS, puis le reverse proxy du NAS examine le hostname et envoie la requête au Frontend sur 127.0.0.1:3101. Backend 8000 et MariaDB 3306 ne communiquent qu’au sein de la Docker network. Comme 3101 est lui aussi lié uniquement au loopback du NAS, il n’est pas directement accessible depuis Internet.
J’ai laissé Cloudflare hors du chemin principal pour la même raison. Je disposais déjà d’un authoritative DNS, d’une adresse IP publique fixe et d’un contrôle direct du Router. En ajoutant seulement l’A record du service et en gérant le certificat sur le NAS, je supprimais un composant intermédiaire. En contrepartie, je dois gérer moi-même le renouvellement du certificat et le port forwarding. Hormis le port 80 nécessaire à l’émission et au renouvellement du certificat, les requêtes réelles du service n’arrivent que par 443.
Vérification sur un véritable appareil mobile et correction de l’interface responsive
L’ouverture de l’adresse HTTPS externe ne signifiait pas que la migration était terminée. Depuis un véritable appareil Android connecté en USB, j’ai accédé à la nouvelle adresse par le réseau mobile et parcouru directement la connexion, le dashboard, la liste des employés, l’historique des SMS et la gestion des congés. Les écrans s’ouvraient, mais ils n’étaient pas utilisables en l’état.
Les problèmes que j’avais manqués en réduisant simplement la largeur du navigateur sur le PC sont apparus tous ensemble sur l’appareil réel. Dans le dashboard, la sidebar de bureau occupait presque tout l’écran et comprimait les card et le texte en colonnes verticales.
Dans toutes les comparaisons ci-dessous, la partie gauche correspond à l’état avant la correction et la partie droite à l’état après.

Dans la liste des employés, les titres et les button se coupaient caractère par caractère, tandis qu’une large table était forcée dans un espace étroit. J’ai maintenu le titre et la zone d’actions dans un flux horizontal, et permis à la table de défiler latéralement autant que nécessaire au lieu d’écraser son contenu.

Les filter de l’historique des SMS et de la gestion des congés avaient le même problème. Plusieurs champs et une plage de dates étaient comprimés sur une seule ligne. Sur les petits écrans, je les ai principalement disposés sur deux colonnes et placé la plage de dates sur une ligne distincte afin que chaque élément puisse être lu et touché.


Après les corrections, j’ai de nouveau déployé une nouvelle Docker image et me suis reconnecté sur le même téléphone. J’ai ouvert le menu, fait défiler les écrans et regardé directement chaque filter et chaque table pour vérifier que les défauts observés au départ avaient disparu. Ce qui devait simplement confirmer que la network externe atteignait le container du NAS a fini par corriger l’interface réellement utilisée.
État de la migration par étapes et vérification de l’interface d’administration/E2E
Après avoir relié la migration vers le NAS, l’accès externe et un SMS interne, j’ai de nouveau déplié le roadmap complet et constaté que les étapes 1 à 3 étaient franchies. J’en étais à l’étape 4 : déployer l’interface d’administration améliorée dans une nouvelle image, puis revoir chaque page avec ADB et l’appareil réel.

L’ajout de ce schéma a aussi clarifié la prochaine limite du travail. L’accès externe avait déjà passé le test, mais le dogfooding au siège ne pouvait pas commencer avant la nouvelle vérification des écrans d’administration sur un appareil réel. L’étape suivante n’était donc pas d’ajouter des fonctions, mais de vérifier jusqu’au bout que l’interface corrigée conservait le même flux de travail sur ordinateur et sur mobile.
État sécurisé et rollback avant la transition opérationnelle
Pour l’instant, le nouveau stack est délibérément configuré pour ne rien faire automatiquement.
ENABLE_SCHEDULER=False
SMS_SEND_MODE=NO_SEND
SMS_ALLOWLIST_MAX_CLAIMS=0
Je n’ai inscrit les credential administrateur ni dans Compose ni dans les image. Sur le NAS, je les ai fournis au moyen d’un secret file doté des droits 0600; sur le Mac, je les ai conservés dans Keychain.
Je pouvais me connecter à la nouvelle adresse et lire les données, et un SMS était également arrivé dans des conditions limitées. Sur un réseau mobile externe, j’ai vérifié tout le parcours, de la connexion à la consultation des données et à l’utilisation des écrans. Malgré cela, avant de supprimer l’ancien service de messages de congés, il reste à définir une méthode de récupération pour les envois dépourvus de delivery callback et à obtenir l’approbation des conditions d’envoi réelles.
J’ai donc arrêté les container et volume existants, mais je les ai laissés intacts. Ce qu’il faut ensuite, ce n’est pas ajouter davantage de configuration. Il faut décider comment récupérer les envois sans callback, puis ouvrir l’envoi réel sur un nombre limité de messages, dans des conditions approuvées.
Indépendamment de la migration technique, j’ai raconté dans Quand on sait utiliser activement l’IA, le champ des possibles paraît soudain infini ce que j’ai ressenti en permettant à l’IA d’observer avec moi le véritable téléphone ainsi que les écrans d’administration du Router et du NAS.
Laisser un commentaire