Chapitre 14 / 39

Comment le système est construit

Le système tourne sur deux paliers de calcul, câblés ensemble par une seule règle : le code sur Cloudflare atteint le harness via des queues pull-based, jamais l’inverse.

Statut : En cours — le côté Cloudflare est en ligne. Le côté harness s’active dès que le Framework Desktop est installé à Gennevilliers.


Cloudflare — données, surface publique, le seul endpoint MCP

Cloudflare héberge tout ce qui bénéficie d’une distribution mondiale, d’un calcul serverless économique, et de Cloudflare Access comme porte d’identité :

  • D1 (l’entrepôt de données) — tous les chiffres de l’activité de Sodimo, y compris le miroir Sodiwin nocturne et la table run_ledger qui enregistre chaque invocation IA dans la stack.
  • R2 (stockage objet) — sauvegardes hors site depuis le NAS de Gennevilliers, artefacts générés, tout asset statique qui dépasse la taille raisonnable pour git.
  • Le Worker sodimo-core — le seul endpoint MCP pour toute la stack. Les outils pour les lectures ERP, les lectures et écritures CRM, les écritures dans le run-ledger, la rédaction d’emails, l’envoi d’emails, et les appels API externes vivent ici. Claude.ai l’atteint. Les agents planifiés l’atteignent. Rien d’autre ne prétend être un serveur MCP.
  • Le site CRM — une app TypeScript faite maison inspirée de Twenty et Pipedrive. Tourne sur Cloudflare Pages, lit et écrit dans D1.
  • Les tableaux de bord internes — de petites apps Cloudflare Pages que les membres de l’équipe déploient directement depuis Claude Code. Le tableau de bord de l’étude des économies en fait partie, en lisant depuis run_ledger.
  • Le webhook WhatsApp — un Worker qui réceptionne les messages entrants, délègue le travail IA à sodimo-core, et met en queue les réponses sortantes.
  • Les sites publicssodimo.eu et ses trois homologues.

L’accès à tout contenu interne passe par Cloudflare Access, conditionné à un compte Google Workspace sous @sodimo.eu.


Le harness — email, modèles locaux, archive, travaux planifiés

Le harness est la machine Fedora bootc dans la salle serveur de Gennevilliers. Il héberge tout ce qui appartient sur du matériel que Sodimo contrôle physiquement :

  • La stack mail — Postfix, Dovecot, rspamd, Piler.
  • L’inférence IA locale — llama.cpp fronté par llama-swap, exposé aux humains via OpenWebUI.
  • Paperclip — le runner d’agents planifiés.
  • L’ETL nocturne — lit l’export CSV de Florian depuis le NAS, charge D1.
  • Caddy, Cockpit, Tailscale — l’habituel entourage technique.

Le chapitre Le harness détaille chaque quadlet. Ce qui compte ici, c’est la frontière, pas l’inventaire.


La règle de câblage — pull-based, jamais entrant

Deux directions de trafic franchissent la frontière. Elles sont câblées de façon délibérément différente.

Harness → Cloudflare (sortant). L’ETL écrit dans D1 via l’API HTTP D1. OpenWebUI poste des enregistrements d’exécution vers l’endpoint run-ledger sur le Worker. Le Postgres interne de Paperclip se mirore vers run_ledger via un cron. Les sauvegardes transitent vers R2. Les connexions sortantes du harness vers Cloudflare sont du HTTPS ordinaire — rien d’exotique.

Cloudflare → Harness (entrant). Rien directement. Le harness n’expose aucun port entrant. À la place, le Worker écrit dans des Cloudflare Queues ; un petit service systemd sur le harness interroge ces queues et agit sur les messages. Le cas canonique est l’envoi d’email : le Worker reçoit un appel MCP email_send, écrit {to, from, subject, body} dans email_outbox, et retourne. Quelques secondes plus tard, un service Python sur le harness vide la queue, valide l’expéditeur, remet le message à Postfix, et acquitte.

Cette règle s’applique symétriquement. Le code tournant sur le harness qui a besoin d’envoyer un email — un agent Paperclip, une compétence de réponse automatique, n’importe quoi — appelle l’outil Worker email_send exactement comme Claude.ai le ferait. Il ne prend pas de raccourci vers le sendmail local. Fedora → Cloudflare → Fedora est intentionnel. Quatre propriétés en dépendent : un registre d’exécution unifié, une politique d’autorisation d’expéditeur unique, un schéma d’observabilité commun, et un rate-limiting centralisé avec une dead-letter queue.


La frontière MCP

Gennevilliers harness

Humans

Cloudflare

MCP over HTTPS

Cloudflare Access

MCP over HTTPS

HTTP pull

failed

HTTP

HTTP

cron mirror

sodimo-core Worker

D1

ERP mirror

run_ledger

R2

backups

email_outbox queue

email_dlq

Claude.ai

Sodimo staff

over Tailscale

email-drain

systemd

Postfix

OpenWebUI

Piler UI

Cockpit

Paperclip

nightly ETL

De gauche à droite. Les humains et les agents terminent tous les deux au Worker pour tout ce qui compte comme un effet de bord avec une piste d’audit. Les humains ont aussi un chemin séparé via Tailscale pour les interfaces on-prem — recherche Piler, chat OpenWebUI, admin Cockpit. Ces chemins sont réservés aux humains ; les agents ne les utilisent jamais.


Pourquoi pas les alternatives évidentes

Pourquoi pas une grande machine on-prem avec tout dessus ? Deux réponses. D1 est déjà là où vit le miroir ERP et où Claude.ai a besoin de lire. Le dupliquer on-prem doublerait la gravité des données et diviserait par deux la surface d’audit. Et la règle une-surface-MCP contourne un bug OAuth connu de Claude.ai avec les serveurs MCP self-hosted — une famille de bugs qui disparaît s’il n’y a pas de serveur MCP self-hosted.

Pourquoi ne pas pousser depuis Cloudflare vers le harness via un tunnel ? Un tunnel signifie que le harness expose un endpoint entrant sur internet, ce qui est une surface d’attaque que Sodimo devrait comprendre et défendre. Une pull queue signifie que le harness ouvre zéro port entrant. Si le harness est hors ligne, les messages sont mis en queue jusqu’à quatre jours et se vident à son retour — le Worker s’en moque.

Pourquoi ne pas laisser les agents on-prem appeler directement les services locaux ? Parce que la co-localisation physique est un fait, pas une autorisation architecturale. Chaque producteur d’un effet de bord contrôlé passe par le Worker. Un agent Paperclip qui appelle le sendmail local produit un envoi invisible : l’exécution de l’agent existe, l’email existe, le lien entre les deux n’existe pas. L’étude des économies se casse, la politique d’autorisation d’expéditeur dérive, et une boucle incontrôlée frappe Postfix à pleine vitesse au lieu d’une queue avec contre-pression.


Sauvegarde

Le harness sauvegarde sur le NAS chaque nuit. Le NAS réplique hors site vers R2. La restauration bare-metal s’effectue sur du matériel appartenant à Sodimo en moins de deux heures — parce que le harness est décrit par un dépôt de quadlets en texte brut, pas par l’état d’une machine en cours d’exécution.


Identifiants

Les identifiants sont autogérés. Les courants vivent dans un gestionnaire de mots de passe Google personnel. Ceux qui comptent — registrar de domaine, compte root Cloudflare, clés de récupération LUKS — sont écrits sur papier. Jack et Paul ont tous deux un accès d’urgence.