HENUSSE Rendre votre entreprise lisible par l’IA. Dehors, et dedans.

Méthode opérationnelle · Sous le capot

Comment nos systèmes sont construits.

Cette page est écrite pour la personne qui ouvrira le capot avant de signer : votre directeur technique, votre prestataire informatique, ou vous. Elle dit de quoi nos systèmes sont faits, ce qui y est déterministe et ce qui est confié à un modèle, où un humain signe, ce qui se passe quand une brique tombe, et ce que vous recevez si nous disparaissons. Les systèmes eux-mêmes sont décrits ici.

Ce dont c’est fait

Python 3.13, sans framework lourd. Environ 1 900 modules et 1 090 fichiers de test dans le dépôt de la maison, exécutés en local avant chaque commit par des gardes de pré-commit. Tout le code est sous Git, moteur et thèmes de sites compris : chaque changement est un commit, et chaque déploiement part d’un commit. Il n’y a pas d’intégration continue hébergée : les tests tournent sur la machine qui déploie, et un commit qui les casse ne part pas.

Les données vivent dans SQLite, une base par client, en mode journal (WAL), avec verrou d’écriture explicite. Les journaux d’événements sont des fichiers JSON en ajout seul : une ligne par fait, jamais réécrite. Les files d’attente sont mises à jour par copie puis remplacement atomique, jamais en place.

Côté sites, WordPress reste le support des pages et des articles, pour que le client garde un outil ordinaire et transférable. La livraison passe par un plugin PHP de la maison ; le portail de validation client est une application séparée, sur son propre serveur, avec sa propre base.

Les modèles de langage ne sont pas les nôtres. Nous utilisons ceux d’OpenAI, d’Anthropic et de Google par leurs outils officiels. Nous n’entraînons aucun modèle et n’en affinons aucun : notre travail est autour du modèle, pas dedans.

Les briques en service aujourd’hui

Systèmes : Debian sur le serveur de la maison, Arch sur le poste de travail, qui a aussi servi de banc d’essai aux miroirs WordPress, un serveur virtuel Scaleway pour le portail client, l’hébergement mutualisé des clients chez OVH et HostSilo. Le réseau privé entre machines est Tailscale ; le crawl sort par un espace réseau WireGuard séparé ; Caddy sert de porte d’entrée avec ses certificats automatiques ; Samba partage les fichiers vers un NAS.

Exécution : Docker Compose pour les miroirs WordPress de préproduction, les bases et les applications clientes, une trentaine de conteneurs en service ; systemd pour les services et minuteries de la maison, vingt-six unités pour le moteur seul ; cron pour les rails planifiés.

Langages : Python 3.13 pour le moteur, les pipelines et les applications ; PHP 8.4 pour huit extensions WordPress maison et un module PrestaShop ; Node 22 avec TypeScript, Vite et Preact pour les interfaces qui en ont besoin ; Go pour un outil réseau ; Bash pour la colle.

Données : SQLite quand une base par client suffit ; PostgreSQL 16 quand il faut plus, y compris pgvector pour la recherche par similarité ; MariaDB derrière WordPress ; Valkey comme cache ; des journaux JSON en ajout seul pour les faits.

Documents et images : OCR Tesseract et lecture par modèle de vision pour les factures photographiées, pypdf pour lire les PDF, ReportLab et WeasyPrint pour en produire, Pillow pour les images, Playwright et Chromium pour piloter un navigateur dans nos relevés, prendre les captures et jouer les tests de bout en bout, ffmpeg et MediaPipe pour la vidéo.

Intégrations : Telegram comme canal opérateur, courrier par SMTP et IMAP, API Search Console et PageSpeed de Google, DataForSEO, API REST de WordPress, dépôt par FTPS et SFTP chez les hébergeurs. Modèles : OpenAI, Anthropic, Google et Perplexity par leurs API et leurs outils officiels, avec un bac à sable bubblewrap pour le texte non fiable.

Sauvegardes : état interne et copie hors site par des outils dédiés, instantané avant chaque changement, base PostgreSQL vidée chaque nuit sur le NAS avec trente jours de rétention, copies horodatées des bases SQLite, et un exercice de restauration planifié chaque trimestre.

Des agents écrivent, une personne décide

Deux personnes ne tiennent pas 1 900 modules à la main. Le code est écrit et relu par des agents de programmation pilotés en ligne de commande : Codex d’OpenAI, Claude Code d’Anthropic, Gemini de Google, et Hermes, un agent ouvert que nous faisons tourner nous-mêmes. Ils travaillent en parallèle dans des sessions tmux nommées, jusqu’à vingt-quatre à la fois, chacun sur une tâche écrite, avec un orchestrateur qui tient le contexte, distribue, et vérifie.

La règle est la même que pour nos clients : l’agent propose, la personne décide. Rien n’entre dans le dépôt sans les gardes de pré-commit et les tests ; rien ne part en production sans un instantané et un chemin de retour. Les revues sont adverses : un second agent cherche à réfuter le travail du premier avant qu’une personne ne tranche, et une vague n’est close que lorsque la revue revient vide.

Les agents n’ont pas les clés. Le texte venu d’un tiers est lu dans un bac à sable sans droit d’outil, les accès aux modèles sont renouvelés par des minuteries système et non stockés dans le code, et un assistant qui n’est pas sur la liste autorisée est refusé.

Ce qui est vérifié sans aucun modèle

Dans le pipeline éditorial, treize contrôles sont du code pur, sans appel à un modèle : liens internes, balisage, données structurées, méta-données, intégrité et couverture des citations, affirmations datées, empreinte de voix, fluidité de lecture, position taxonomique, certification avant publication, vérification des résultats enrichis, score final. Un modèle n’intervient que là où le jugement est nécessaire : rédaction, polissage, contrôle des faits, relecture éditoriale.

Le seuil est écrit : une note sous 60 rejette, entre 60 et 75 renvoie en révision, au-dessus de 75 passe. Un défaut de sévérité « erreur » rejette quelle que soit la note. Un contrôle des faits en échec dur bloque la publication sur tous les chemins. Un texte dans une langue non prévue, ou un scanner de langue qui échoue, met l’article en attente d’un humain au lieu de le laisser passer.

Les tirets cadratins, marque d’un texte écrit à la machine, sont retirés par une réécriture déterministe avant tout contrôle, et un moteur éditorial qui en renvoie un provoque une erreur.

La décision reste à la personne

Chaque publication client passe par une fenêtre de veto dont les états sont nommés : notice envoyée, en attente de relecture, approuvé, refusé, approuvé par silence, expiré sans réponse. Le module qui tient cette fenêtre ne publie jamais : à l’expiration, il enregistre une intention, et le déploiement réel se trouve derrière un interrupteur séparé, éteint par défaut.

Le portail de validation tient deux familles de tables : une projection écrite par le moteur seul (locataires, fenêtres, artefacts) et un grand livre écrit par le portail seul (décisions, consultations, demandes de lien). La base du portail se reconstruit entièrement depuis le moteur : la perdre ne perd rien de canonique.

Si le contenu d’un article change après son approbation, l’approbation tombe et une nouvelle est requise. C’est un état explicite, pas une convention.

Ce qui est prévu avant que ça arrive

Les appels aux modèles suivent un ordre écrit : l’outil OpenAI en premier, l’outil Anthropic en second, les API payantes en dernier. Les API payantes sont fermées par défaut : une clé stockée ne suffit pas, il faut un interrupteur explicite pour qu’elles servent. Après trois échecs consécutifs des deux premiers, ils sont écartés dix minutes. Un appel a un délai maximal (cinq minutes par l’outil, deux par l’API) et un budget mensuel : alerte à 80 %, refus à 100 %.

Une réponse qui n’est pas du JSON valide est traitée comme une absence de réponse, à chaque endroit où une réponse est lue. Un état corrompu sur disque est traité comme un état vide. Le texte fourni par un tiers (un client, un site) est lu dans un bac à sable isolé, avec un délai coupé de l’extérieur, par un bras de modèle séparé qui n’a pas le droit d’utiliser d’outils.

Deux exécutions ne peuvent pas se marcher dessus : un verrou par client, en base, avec délai. Les journaux sont en ajout seul et les files mises à jour par remplacement atomique, donc un travail relancé après une coupure ne compte rien deux fois. Ce qui échoue est écrit dans un journal des échecs par client ; un article bloqué par un contrôle est matérialisé dans un dossier « à relire » au lieu de disparaître.

Chaque client dans sa boîte

Chaque client est un utilisateur Unix distinct, sans connexion possible, dont le dossier est son domaine. Ses secrets sont dans un fichier lisible par lui et par son groupe seulement. Les services tournent avec les durcissements systemd : pas d’élévation de privilèges, système en lecture seule, dossiers personnels invisibles, répertoire temporaire privé.

Un travail lancé par le planificateur doit correspondre ligne à ligne à une liste autorisée : utilisateur fixé, dossier fixé, journal fixé. Un assistant qui n’est pas dans la liste est refusé avec un code d’erreur dédié. Les fragments sudo sont nommés et versionnés dans le dépôt.

Savoir ce qui s’est passé

Chaque client a ses journaux : exécutions planifiées, approbations, retraits, échecs, événements. Les secrets y sont caviardés avant écriture. Un tableau de bord opérateur, relancé automatiquement s’il tombe, expose la santé, les incidents, les coûts et l’activité.

Des rails de surveillance tournent à intervalles connus : battement de cœur chaque minute, contrôle de santé toutes les quinze minutes, veille de publication toutes les cinq minutes, veille des créneaux manqués, veille des relectures dues chaque semaine, synchronisation de l’index publié chaque nuit.

Revenir en arrière est un chemin écrit

Sauvegarde de l’état interne, sauvegarde hors site, instantané avant tout changement, et un exercice de restauration qui a son propre outil. Chaque vague de déploiement laisse derrière elle un script de retour nommé. Une publication peut être retirée par un outil dédié, et le plugin de livraison a sa propre procédure de retour.

Vingt-quatre procédures écrites couvrent les cas ordinaires : sauvegarde et restauration, réponse à incident, redémarrage d’un service, tâche planifiée bloquée, mise à jour, accueil d’un nouveau client.

Si nous disparaissons demain

Le dépôt commence par un document d’entrée, un document d’architecture, un lexique, et 205 décisions d’architecture datées, chacune expliquant ce qui a été choisi et pourquoi. Les procédures et les rapports de session sont au même endroit. Un développeur qui reçoit le dépôt et les secrets a de quoi faire tourner le système sans nous appeler.

Côté client, le cadrage produit un document de périmètre qui vous appartient, et la mission se termine par un inventaire de sortie : données, règles, documentation, accès. Les modalités de support et de maintenance disent ce qui est suivi dans le temps : dépendances, accès, flux de données, règles de métier, transférabilité.

Sur écran, pas sur diapositives

Un système en production, en direct : la base, les journaux, un article qui passe les contrôles et un autre qui y reste. Un paquet de passation d’un projet existant : l’architecture, les dépendances, l’inventaire des accès, la procédure de reprise. Et, avec l’accord du client, un système installé chez lui, sans ses données.

Demandez-le lors du premier échange. Ce sont les pièces que nous demanderions à votre place.

WhatsApp