Accéder au contenu technique
Retour à l’accueil

Stack technique

HansaChat est un chat d’entreprise européen doté d’une couche opérationnelle pour les équipes de terrain, conçu, développé et exploité par une seule personne. Cette page présente la technologie de chaque composant et la raison de ce choix.

Versions et chiffres vérifiés en octobre 2026.

Comptés dans les dépôts

services ConnectRPC totalisant 179 RPC, tous définis en Protobuf
18
binaires Go issus d’une seule base de code : API, worker, relais d’outbox, administration
4
plateformes à partir d’un seul client : web, macOS, Windows, Linux, iOS, Android
6
langues sur le site web public
22
langues d’interface dans l’application
23
scénarios Playwright de bout en bout sur une stack isolée
70

Comment les éléments s’articulent

Trois applications partagent une même couche edge et un même cluster. Le site web gère la facturation et le registre des espaces de travail, le backend Go gère tout ce qui se passe à l’intérieur d’un espace de travail, et l’application web communique avec le backend via des clients ConnectRPC générés.

Clients

Navigateur

Site web et application web

Tauri

Enveloppes bureau et mobile

hansa CLI

Scripts et agents

Edge

Bunny.net CDN

TLS, cache, protection DDoS

IONOS Managed Kubernetes, Allemagne

Traefik

Ingress pour chaque application

Application web Vue + Vite

Build Vue statique

API du chat

Go avec ConnectRPC

  • Worker
  • Relais d’outbox

Site web Laravel + FrankenPHP

Facturation, registre, provisionnement

NATS JetStream

Commandes et événements durables

Centrifugo

Diffusion WebSocket

Valkey Sentinel + HAProxy

Cache, présence, sessions

LiveKit

Flux média des appels

Données gérées chez IONOS

MariaDB

Une base de données par espace de travail, plus un registre central

Stockage objet S3

Fichiers et avatars

Services externes

ElevenLabs · LLM · Clef

Transcription, traduction, tri

Creem · EmailLabs

Paiements et e-mails

Hors du cluster

Cloudflare Workers D1

Vérifications de disponibilité externes

Bunny Storage restic

Sauvegardes chiffrées à Francfort et à Stockholm

Le parcours d’un message

  1. Le client appelle le service de messagerie via ConnectRPC.
  2. L’API n’accepte la requête qu’une fois la commande stockée de manière durable par NATS JetStream.
  3. Un worker écrit le message et un événement d’outbox dans la base de données de l’espace de travail, au sein d’une seule transaction.
  4. Le relais d’outbox publie l’événement validé vers NATS et Centrifugo.
  5. Chaque client ouvert le reçoit via WebSocket ; après une interruption, les clients rechargent l’état de référence depuis l’API.

Backend du chat

Tout ce qui se passe à l’intérieur d’un espace de travail s’exécute en Go : messages, canaux, fichiers, appels, temps réel, imports et le module opérationnel dédié au nettoyage. Le site web ne touche jamais aux données des espaces de travail.

Go 1.26

Quatre binaires issus d’une base de code modulaire : l’API, le worker de messages, le relais d’outbox et une commande d’administration protégée. Ils sont livrés sous forme de binaires statiques dans une seule image légère.

Pourquoi

Une bibliothèque standard solide, des performances prévisibles et une concurrence simple conviennent à un backend composé de workers à longue durée de vie. Un seul langage pour tout le cœur de l’espace de travail permet à une seule personne de le maintenir.

ConnectRPC + Protobuf connect-go 1.20 · buf 1.71

18 services et 179 RPC sont définis en Protobuf. buf génère le serveur Go et les clients TypeScript avec des plugins locaux, si bien qu’aucun schéma ne quitte la machine.

Pourquoi

Un seul contrat sert les clients web, bureau, mobile et en ligne de commande. Aucun chemin HTTP écrit à la main ni analyse manuelle des réponses, et une modification du contrat se manifeste par une erreur de compilation plutôt que par une panne à l’exécution.

Une base de données par espace de travail MariaDB · sqlc

Chaque espace de travail dispose de sa propre base de données MariaDB physique. L’API identifie l’espace de travail à partir de son domaine et ouvre le pool correspondant ; les workers l’identifient à nouveau eux-mêmes et ne font jamais confiance à un nom de base de données reçu dans un message de file d’attente. Les requêtes sont du SQL simple compilé en Go typé avec sqlc.

Pourquoi

L’isolation est structurelle, et non un filtre ajouté à chaque requête. L’export, l’import, la restauration et la suppression se font par entreprise.

NATS JetStream 2.10

Des streams durables pour les commandes, les tâches et les événements, ainsi qu’un stream de lettres mortes. Les écritures de messages s’exécutent dans 64 partitions ordonnées.

Pourquoi

Un message n’est accepté qu’après un accusé de réception durable. Les messages d’un même canal restent dans l’ordre, tandis que les canaux indépendants sont traités en parallèle.

Outbox transactionnelle

Les lignes métier et l’événement sortant sont validés dans la même transaction. Un relais publie les événements validés vers NATS et Centrifugo, dédupliqués par identifiant d’événement, et consigne les échecs pour les relancer.

Pourquoi

Aucun événement perdu ni fantôme lorsqu’un processus s’arrête entre l’écriture en base et la publication.

Centrifugo v5

Diffusion WebSocket des messages, de la présence, des indicateurs de saisie et de l’état des appels. Les clients s’abonnent avec des jetons de courte durée propres à chaque canal, que l’API n’émet qu’après avoir vérifié l’appartenance à l’espace de travail.

Pourquoi

Un serveur temps réel dédié tient les connexions de longue durée à l’écart du processus de l’API, et chaque jeton désigne à la fois l’espace de travail et l’utilisateur, de sorte que des identités issues de bases distinctes ne peuvent pas entrer en collision.

Stockage objet compatible S3 aws-sdk-go-v2

Les fichiers et les avatars sont stockés dans l’Object Storage d’IONOS dans l’UE et distribués via des liens signés de courte durée.

Pourquoi

Le stockage des fichiers évolue indépendamment des bases de données et il est chiffré au repos côté serveur.

LiveKit 1.9

Un serveur média WebRTC auto-hébergé pour les appels en messages directs et les appels de canal centrés sur l’audio, avec caméra et partage d’écran.

Pourquoi

Open source et auto-hébergeable, si bien que les flux média des appels transitent par une infrastructure exploitée par HansaChat.

ElevenLabs Scribe

Reconnaissance vocale pour les messages vocaux. La transcription est rattachée au message, consultable par la recherche et traduisible comme n’importe quel texte.

Pourquoi

Les équipes de terrain parlent plus qu’elles n’écrivent.

Traduction par LLM

Traduction propre à chaque lecteur via une API compatible OpenAI. Chaque message est traduit à la demande, mis en cache une seule fois par langue cible et ignoré lorsque le lecteur partage déjà la langue.

Pourquoi

Une équipe multilingue travaille dans une même conversation tandis que chaque membre lit dans sa propre langue. Le fournisseur reste remplaçable derrière une interface unique.

Cloudflare Clef

Un modèle de décision classe les messages opérationnels par catégorie, urgence et niveau de confiance. Il renvoie des probabilités pour des questions fixes, pas du texte généré. Actuellement en phase pilote.

Pourquoi

Il n’y a aucune sortie en texte libre à analyser. Les responsables voient ce qui demande leur attention ; la suite à donner reste toujours une décision humaine.

go-pdf 0.9

Les feuilles de temps et les rapports d’intervention au format A4 sont générés sur le serveur.

Pourquoi

Une bibliothèque écrite entièrement en Go garde l’image du backend légère et sans navigateur headless.

Sentry + slog

Les erreurs et les traces partent vers Sentry, les logs sont du JSON structuré produit par la bibliothèque standard, et les workers exposent des métriques au format texte de Prometheus.

Pourquoi

Peu de pièces mobiles à exploiter, et chaque défaillance arrive avec son contexte.

Applications et CLI

Un seul client Vue sert le web et est empaqueté par Tauri pour le bureau et le mobile. Le client en ligne de commande utilise la même API publique que les applications.

Vue 3 + TypeScript Vue 3.5 · TS 5.9 · Pinia 3

Un client unique avec 118 composants monofichiers, des stores Pinia, vue-router et vue-i18n en 23 langues d’interface, testé avec Vitest.

Pourquoi

Un modèle de composants mature et lisible ainsi qu’un TypeScript strict rendent un gros client maîtrisable pour une très petite équipe.

Vite + Tailwind CSS Vite 8 · Tailwind 4

L’outil de build et la couche de style : Tailwind CSS 4 avec un thème clair et un thème sombre.

Pourquoi

Des builds rapides et des design tokens qui suivent la même palette documentée que le site web.

Tauri 2.10

Empaquette le même client web pour macOS, Windows, Linux, iOS et Android, avec notifications natives, liens profonds et mises à jour signées sur ordinateur.

Pourquoi

Une seule interface partout, en s’appuyant sur la webview du système au lieu d’embarquer un moteur de navigateur dans chaque application.

Clients Connect générés connect-web 2.1 · protobuf-es 2

Des clients TypeScript générés à partir du Protobuf du backend et copiés dans l’application web. Ils ne sont jamais modifiés à la main.

Pourquoi

Une modification du contrat devient une erreur de type dans le client plutôt qu’une surprise en production.

centrifuge-js + livekit-client 5.7 · 2.20

Les bibliothèques clientes pour le temps réel de Centrifugo et les appels LiveKit.

Pourquoi

La reconnexion, la reprise et la gestion des médias proviennent des projets qui développent les serveurs.

TipTap 3.22

L’éditeur de messages, avec mentions, liens et blocs de code avec coloration syntaxique.

Pourquoi

Un éditeur structuré plutôt qu’une manipulation fragile de chaînes de caractères.

hansa CLI Go 1.26 · Cobra

Un client en ligne de commande sans état pour les personnes, les scripts et les agents LLM. Sortie JSON par défaut, identifiants dans le trousseau du système d’exploitation et sommes de contrôle des versions signées avec Minisign.

Pourquoi

Il utilise la même API publique que les applications. Ses contrats Protobuf sont copiés depuis le backend et verrouillés par des empreintes SHA-256, de sorte que toute divergence est détectée en CI.

Site web, facturation et registre

Laravel fait tourner le site public, la documentation client, le paiement, les abonnements et le registre central des espaces de travail. Il crée un espace de travail en appelant le backend Go via HTTP authentifié, sans code partagé ni files d’attente partagées.

Laravel + PHP Laravel 12 · PHP 8.5

Le site web public, la documentation client, le paiement, les abonnements, les coupons, les notifications de cycle de vie et le registre central des espaces de travail et des domaines.

Pourquoi

La facturation, les e-mails, la planification, les files d’attente et les formulaires sont les points forts de Laravel. Le chat reste en Go, et la frontière entre les deux est une seule interface HTTP authentifiée.

FrankenPHP 1.13

Le serveur d’applications PHP intégré à l’image de conteneur, construit sur une image de base partagée qui épingle PHP, ses extensions et ses outils par digest.

Pourquoi

Un seul processus sert l’application, et reconstruire le même commit produit le même environnement d’exécution.

Blade + Alpine.js + Tailwind CSS Alpine 3.15 · Tailwind 3.4 · Vite 7

Des pages rendues côté serveur avec de petits composants Alpine.js, stylées avec Tailwind CSS et regroupées par Vite.

Pourquoi

Les pages de contenu se chargent rapidement sans embarquer de framework d’application monopage.

22 langues

Chaque page publique existe dans 22 langues de l’UE, avec des URL préfixées par la langue, des liens hreflang et un sitemap localisé. Un test échoue si une langue omet une clé ou affiche du texte en anglais.

Pourquoi

Un produit européen doit être lisible dans la langue de l’acheteur dès la première page.

Creem

Paiement, taxes, factures et abonnements, synchronisés via des webhooks signés.

Pourquoi

Le paiement, les taxes et la facturation restent confiés à un prestataire spécialisé, tandis que le site web conserve une copie rapprochée de chaque abonnement.

EmailLabs

E-mails transactionnels et de service, comme les invitations, les liens de mot de passe et les notifications.

Pourquoi

Un fournisseur d’e-mail européen pour un produit européen.

Pest 4.4

Plus de 130 fichiers de tests couvrent les routes, la facturation, le provisionnement, les traductions et le SEO, y compris des tests dans le navigateur.

Pourquoi

Des tests rapides et lisibles, exécutés à chaque modification.

Plateforme et exploitation

La production et la préproduction tournent chez IONOS en Allemagne. Chaque application est livrée sous forme d’image de conteneur avec son propre chart Helm et déployée par un job GitLab déclenché manuellement.

IONOS Managed Kubernetes

Clusters de production et de préproduction, MariaDB géré et Object Storage compatible S3, le tout exploité par un fournisseur allemand en Allemagne.

Pourquoi

Un fournisseur européen soumis au droit de l’UE, et non la région européenne d’un cloud non européen.

Helm + Traefik

Chaque application est livrée avec son propre chart. Traefik route le trafic à l’intérieur du cluster, et les migrations des bases de données des espaces de travail s’exécutent sous forme de hook avant chaque déploiement du backend.

Pourquoi

Chaque déploiement est versionné, reproductible et facile à annuler.

Bunny.net

CDN, DNS et protection DDoS devant le cluster, ainsi que le stockage des sauvegardes chiffrées.

Pourquoi

Une entreprise européenne exploite la couche edge et conserve les copies de sauvegarde, si bien qu’aucune des deux ne dépend d’un cloud non européen.

Valkey + Sentinel + HAProxy Valkey 9.1

Trois réplicas avec bascule gérée par Sentinel et un proxy HAProxy qui pointe toujours vers le primaire actuel. Il sert au cache, aux sessions, à la présence et au broker temps réel.

Pourquoi

Une bascule ne nécessite aucune modification de l’application, car chaque service continue de s’adresser à la même adresse.

restic 0.18

Sauvegardes chiffrées des bases de données toutes les 6 heures vers deux sites dans l’UE, avec des vérifications d’intégrité hebdomadaires et un exercice de restauration mensuel automatisé.

Pourquoi

Une sauvegarde ne compte qu’une fois sa restauration prouvée.

GitLab CI

Les tests, la construction des images et les vérifications des charts Helm s’exécutent en CI. Les déploiements en préproduction et en production sont des jobs distincts, déclenchés manuellement.

Pourquoi

L’automatisation se charge du travail répétitif ; une personne décide du moment où un changement atteint les clients.

Autour du produit

Les outils qui permettent à une entreprise d’une seule personne de rester observable, joignable et compréhensible.

Cloudflare Workers + D1

Une page de statut externe qui vérifie l’application et le site web toutes les cinq minutes et consigne les incidents.

Pourquoi

La disponibilité est mesurée depuis l’extérieur de l’infrastructure qu’elle décrit.

Umami 3.2

Une mesure d’audience auto-hébergée qui ne s’exécute qu’après que le visiteur a exprimé son choix de consentement.

Pourquoi

Les données des visiteurs restent sur l’infrastructure de HansaChat au lieu d’alimenter un réseau publicitaire.

Remotion 4.0

Les vidéos du produit sont enregistrées à partir de l’application réelle par l’exécuteur de tests de bout en bout et montées par le code avec une voix off générée par IA.

Pourquoi

Quand l’interface change, la vidéo est de nouveau générée au lieu d’être tournée à nouveau.

TwentyCRM + WireGuard

Un CRM auto-hébergé accessible uniquement via un VPN privé.

Pourquoi

Les données commerciales ne sont absolument pas exposées sur l’internet public.

Pratiques d’ingénierie

Les habitudes qui permettent à une seule personne de livrer un produit multi-locataire sans équipe QA ni équipe d’exploitation dédiée.

Les contrats sont générés, jamais écrits à la main

Protobuf est la source unique pour le serveur Go, les clients TypeScript et la CLI. Les générateurs sont épinglés à des versions exactes, et la CLI enregistre l’empreinte de chaque fichier de contrat qu’elle utilise.

Les migrations tiennent un registre

Chaque base de données d’espace de travail enregistre les migrations qu’elle a appliquées. Un hook de déploiement applique uniquement celles qui manquent et vérifie de nouveau après le déploiement. Le site web conserve ses migrations de base d’origine afin que les bases existantes ne les exécutent jamais deux fois.

Tests de bout en bout sur une stack isolée

Une seule commande démarre les bases de données, NATS, Valkey, Centrifugo et le stockage objet sur des ports libres, compile les binaires Go, lance l’application web et exécute 70 scénarios Playwright avec un espace de travail neuf pour chaque test.

Des tests à chaque couche

478 fonctions de test Go, dont des tests d’isolation entre deux espaces de travail, 109 fichiers Vitest dans le client et plus de 130 fichiers Pest sur le site web.

Garde-fous en CI

Vérifications de formatage, limite de 1 000 lignes par fichier Go et tests des charts Helm s’exécutent en CI aux côtés des suites de tests.

Validation manuelle des déploiements

La CI compile et teste automatiquement, mais les déploiements en préproduction et en production sont des jobs manuels distincts. La production déploie un tag de version qui n’est créé qu’après la fusion du changement.

Des sauvegardes prouvées par des restaurations

Chaque exécution de sauvegarde est surveillée, et un exercice automatisé restaure les bases de données chaque mois puis valide les tables et le nombre de lignes.

Un seul design system

Le site web et l’application partagent une palette documentée, une échelle typographique et des règles de composants, avec un thème clair et un thème sombre dans l’application.

Assisté par l’IA, validé par un humain

Les agents de programmation IA travaillent à partir d’un fichier d’instructions présent dans chaque dépôt, qui renvoie vers un dépôt central de documentation d’ingénierie. Les workflows répétables, comme l’exécution de bout en bout, sont empaquetés sous forme de skills d’agent. Chaque modification passe toujours les mêmes tests, et les déploiements restent manuels.

Management de la sécurité en préparation

HansaChat se prépare à la certification ISO/IEC 27001 avec un registre des risques, un registre des preuves et un journal des décisions. HansaChat n’est pas certifié à ce jour.

Ce que cette page affirme — et ce qu’elle n’affirme pas

Tout ce qui précède décrit ce qui est mis en œuvre aujourd’hui et a été compté dans les dépôts de code source. HansaChat ne revendique aucune certification de sécurité. Le tri des messages est en phase pilote, et les notifications push pour les applications fermées ne sont pas encore en service.

Des questions sur l’architecture ?

Les ingénieurs qui évaluent HansaChat obtiennent des réponses directes de la personne qui l’a construit.

Écrire au développeur