Raccourcis clavier

Appuyez sur ← ou → pour passer d'un chapitre à l'autre

Appuyez sur S ou / pour rechercher dans la documentation

Appuyez sur ? pour afficher cette aide

Appuyez sur Échap pour masquer cette aide

Chatbotaurus en 5 minutes

Chatbotaurus - passerelle MCP souveraine UE

Chatbotaurus est une plateforme MGaaS (MCP Gateway as a Service) souveraine européenne, écrite en Rust : un backend Axum (forge-api) et un frontend Dioxus compilé en wasm (forge-ui). Elle réunit un agent conversationnel, une passerelle MCP et des fiches de connecteurs YAML.

Cette page montre un chemin court : lancer la pile en local, ouvrir l'application, poser une première question.

Chiffres du catalogue : 195 fiches YAML de connecteurs, mesurées le 3 octobre 2026 (connectors/*.yaml). Le nombre exact change à chaque ajout ; la source est le dossier, pas cette page.

Trois parcours de lecture

Ce livre se lit selon votre rôle. Chaque étape renvoie au chapitre qui la traite ; la page que vous lisez reste un chemin court pour lancer la pile en local.

Décideur (dirigeant, délégué à la protection des données, acheteur)

  1. Cas d'usage par secteur : ce que la plateforme fait pour votre métier
  2. Tarification et offres : les quatre offres et les capacités par plan
  3. SLA, support et niveaux de service : disponibilité, délais de support, pénalités
  4. Conformité RGPD : données personnelles, hébergement et sous-traitants dans l'UE
  5. Comparatifs : ce qui distingue une passerelle hébergée dans l'UE
  6. Limites et ce que la plateforme ne fait pas : le périmètre, dit sans détour

Délégué à la protection des données (répondre à une demande d'un utilisateur, documenter la sous-traitance) : Conformité RGPD, Paramètres (la page Compte porte l'export et la suppression), Journaux (chaîne d'audit) et Réponse aux incidents (notification d'une violation).

Utilisateur (responsable métier, équipe)

En production, l'application est sur app.chatbotaurus.eu (voir En production). En local, lancez d'abord la pile avec le chemin court plus bas.

  1. Prise en main guidée : du compte au premier workflow
  2. Tableau de bord : la première page après la connexion
  3. Workflows : l'éditeur, la palette de nœuds, les exécutions
  4. Chat : parler à un workflow déployé
  5. Connaissances : collections de documents et recherche ancrée (l'envoi de documents depuis l'application n'est pas encore branché)
  6. Questions fréquentes : les réponses courtes aux questions courantes

Pour brancher votre Odoo : Sécurité et identifiants (enregistrer les identifiants), puis Connecter Odoo à la passerelle MCP (un premier outil appelé, puis le chat).

Opérateur ou intégrateur (développeur, administrateur système)

  1. Installation de Chatbotaurus : compiler et lancer la pile
  2. Variables d'environnement : chaque variable lue par le code
  3. Déploiement avec Podman : deux plans, unités Quadlet en production
  4. Créer votre premier connecteur MCP : une fiche YAML, sans Rust
  5. Routes MCP (Streamable HTTP) : le transport, les sessions, le catalogue
  6. Supervision : points de santé et métriques en service

Une fois la pile en service : Sauvegarde et restauration, Gestion des conteneurs (mise à jour, dépannage) et Réponse aux incidents.

Pour appeler l'API depuis un script : Documentation Swagger (obtenir un jeton), puis Connecter Odoo à la passerelle MCP (un premier appel d'outil de bout en bout) et Gestion des erreurs (lire un code d'erreur).

Prérequis

OutilVersionUsage
Rust (rustup)1.91 ou plus (rust-version du workspace)Compiler forge-api et forge-ui
Dioxus CLI (dx)0.7Serveur de développement et bundler wasm
Git2.xRécupérer le dépôt
Podman4.x ou plusConteneurs d'infrastructure (PostgreSQL, Valkey, Qdrant, Ollama, entre autres)
podman-composeavec un tiretLancer les deux plans compose du dépôt
Cible wasmwasm32-unknown-unknownrustup target add wasm32-unknown-unknown, nécessaire à la compilation de forge-ui (étapes 3 et 6)

Installez le CLI Dioxus avec :

cargo install dioxus-cli --locked

1. Récupérer le dépôt

git clone <url-du-depot>
cd <dossier-du-depot>
cp .env.example .env

Éditez .env. Les valeurs secrètes de .env.example sont des gabarits CHANGE_ME_... : l'application refuse de démarrer avec elles. Générez les vôtres, par exemple avec openssl rand -hex 64.

Variables minimales (toutes lues par le code ; la liste complète est dans Variables d'environnement) :

DATABASE_URL=postgresql://<utilisateur>:<mot-de-passe>@localhost:5432/<base>
REDIS_URL=redis://localhost:6380
JWT_SECRET=<64 octets hexadécimaux>
QDRANT_URL=http://localhost:6334
OLLAMA_BASE_URL=http://localhost:11434
SMTP_HOST=<serveur-smtp>
SMTP_USER=<compte>
SMTP_PASSWORD=<mot-de-passe-applicatif>

Pourquoi le SMTP : le second facteur (FORCE_2FA, vrai par défaut) envoie un code par courriel. Sans SMTP configuré, le démarrage est refusé.

2. Lancer l'infrastructure

Le dépôt a deux plans compose (voir Déploiement avec Podman). Pour un premier essai, le plan chatbotaurus-vps1 suffit (PostgreSQL, Valkey, Qdrant, Ollama, Authentik, OpenBao, voix, observabilité) :

podman-compose -p chatbotaurus-vps1 -f podman-compose.yml up -d

Le plan mgaas-vps2 (passerelle et serveurs mcp-*) se lance de la même façon avec podman-compose.vps2.yml. Il n'est pas nécessaire pour ce tutoriel.

Téléchargez ensuite le modèle de dialogue souverain dans Ollama :

podman exec forge-ollama ollama pull cas/eurollm-1.7b-instruct-q8

3. Lancer le backend et le frontend

Appliquer les migrations :

cargo run -p forge-cli -- db migrate

Backend, port 3000 :

cargo run -p forge-api

Frontend, port 8080, dans un second terminal :

dx serve --platform web --port 8080 --package forge-ui

La première compilation wasm est longue. Ensuite le rechargement à chaud prend quelques secondes : ne relancez pas dx pour une modification.

Vérifiez que le backend répond (les autres sondes sont dans Diagnostics et signalement) :

curl http://localhost:3000/api/v1/health

La réponse est un JSON avec "status":"ok", le nom du service et la version.

4. Première conversation

  1. Ouvrez l'interface locale (http://localhost:8080). Sans session, elle vous renvoie vers l'écran de connexion (/auth/login).
  2. Créez un compte sur /auth/signup, puis connectez-vous sur /auth/login. Le code à usage unique arrive par courriel (/auth/verify-otp).
  3. Au premier accès, l'assistant d'accueil (/onboarding) vous demande votre secteur et un modèle de départ. Voir Prise en main guidée.
  4. Ouvrez /chat ou /orchestrator et posez une question, par exemple :
Quels connecteurs sont disponibles pour l'ERP ?

L'assistant s'appuie sur le catalogue de connecteurs de votre instance. La page est décrite dans Chat.

5. Interroger l'API

Les routes de l'API sont sous /api/v1. Le catalogue des connecteurs (contrat et authentification : Documentation Swagger) exige un jeton (Authorization: Bearer <jeton>), obtenu par la connexion (voir Authentification) :

curl -H "Authorization: Bearer <jeton>" \
  http://localhost:3000/api/v1/mcp/catalogue

Le transport MCP (JSON-RPC 2.0, HTTP streamable) est monté sur /api/v1/mcp, lui aussi authentifié. Voir Routes MCP.

Les passerelles (Routes des gateways et de la prédiction) se manipulent par /api/v1/mcp-gateway/*.

6. Vérifier

cargo test -p forge-replay
cargo build -p forge-ui --target wasm32-unknown-unknown --bin chatbotaurus

Pour regénérer ce livre en local : cargo run -p forge-docs. dx serve le sert ensuite sous /docs/.

En production

L'application publique est servie sur chatbotaurus.eu (site) et app.chatbotaurus.eu (application). Les prix publics sont sur la page /pricing : Starter 9 EUR, Pro 29,90 EUR, Enterprise 99,90 EUR par mois (HT), Souverain sur devis. Le détail des offres est dans Tarification.

Prochaines étapes

Voir aussi

Cas d'usage par secteur

Chatbotaurus propose 16 secteurs préconfigurés, plus une entrée « Autre » pour les métiers qui n'y figurent pas. Chaque secteur associe un jeu de connecteurs de départ à un vocabulaire métier. Cette page reprend ces associations telles qu'elles sont décrites dans l'application ; les pages /solutions/<secteur> du site présentent les mêmes secteurs.

Comment lire cette page

  • Dirigeant : repérez votre secteur dans le tableau et lisez la colonne « Pour quoi faire ».
  • Responsable métier : le tableau des cas d'usage, plus bas, montre ce qu'on peut demander au chat et avec quels outils.
  • Développeur : les connecteurs de départ du premier tableau sont ceux du catalogue (voir Vue d'ensemble des connecteurs). La colonne « Outils mobilisés » du second tableau cite aussi des services de la plateforme, par exemple CrowdSec, qui n'ont pas de fiche de connecteur.

Un secteur ne limite pas la plateforme : il choisit les connecteurs proposés par défaut. Vous pouvez ajouter ou retirer des connecteurs ensuite. Le secteur se choisit dans l'Orchestrateur (carte « Déployer les outils de votre métier »). L'assistant d'accueil le demande aussi (voir Prise en main guidée), mais le serveur n'en conserve rien aujourd'hui.

Les 16 secteurs

SecteurConnecteurs de départPour quoi faire
Thérapeute et bien-êtreOdoo, CalRS, Jitsi, CryptPadrendez-vous, suivi des consultations, téléconsultation, documents partagés
Consultant et servicesOdoo, CalRS, n8n, Mauticclients, missions, devis et factures, planification, relances
E-commerce et vente en ligneOdoo, Matomo, Mautic, Typesenseproduits, commandes, stock, audience du site, campagnes, recherche catalogue
Formation et e-learningChamilo, Jitsi, Odoocours, apprenants, classes virtuelles, inscriptions
Ressources humainesOdoo, CalRS, Authentikemployés, contrats, congés, recrutement, identité
Finance et comptabilitéOdoo, Paperlessfactures, paiements, comptabilité, documents comptables
Juridique et conformitéOdoo, Paperless, CryptPaddossiers, contrats, documents, rédaction partagée
Immobilier et agencesOdoo, CalRS, Nextcloudbiens, mandats, visites, fichiers des dossiers
Tourisme et hôtellerieOdoo, CalRS, Matomoréservations, séjours, activités, audience du site
Association et ONGOdoo, Listmonk, Discourseadhérents, bénévoles, cotisations, lettres d'information, forum
Industrie et productionOdoo, n8n, VictoriaMetricsproduction, maintenance, qualité, stocks, mesures machines
Logistique et transportOdoo, n8nlivraisons, entrepôts, expéditions, alertes
Créatif et médiaNextcloud, OnlyOffice, Mauticfichiers, documents collaboratifs, campagnes
Agriculture et viticultureOdoo, n8ncultures, récoltes, élevage, stocks, alertes
Médical et cliniquesOdoo, CalRS, OpenBaopatients, consultations, dossiers, secrets protégés
Mobilier et décorationOdoo, Nextcloudagencement, devis, livraisons, fichiers de projet

Chaque secteur est aussi relié à des catalogues de données publiques européennes (par exemple santé, énergie, industrie, agriculture, environnement) que le chat peut consulter en lecture (voir API-as-a-Service EU souverain).

Et si votre métier n'est pas dans la liste ?

L'entrée Autre décrit votre besoin et laisse l'équipe adapter les connecteurs, les workflows et la conformité à votre métier. Les secteurs de l'énergie, de l'informatique et de l'administration publique n'ont pas de parcours préconfiguré : ils passent par cette entrée, ou par le plan Souverain pour les exigences renforcées (voir plus bas).

Rappel pour les métiers de la santé

Les données de santé sont des données sensibles au sens de l'article 9 du RGPD. Les secteurs Thérapeute et Médical s'appuient sur des serveurs hébergés dans l'Union ; le secteur Médical ajoute un coffre de secrets (OpenBao et secrets) à ses connecteurs de départ. Le secrétariat de cabinet assisté ne fournit aucune aide au diagnostic et ne prend aucune décision médicale. Voir Conformité RGPD.

Les 13 cas d'usage transverses

Ces cas d'usage ne dépendent pas d'un secteur : chacun combine un modèle local (Fournisseurs de modèles), des connecteurs et, quand c'est utile, une base de recherche (Connaissances). Ils sont décrits sous /solutions/usecases/<cas>.

Cas d'usageOutils mobilisésSecteurs concernés
Support client assisté par chatOllama, n8n, Qdrant, Odoofinance, e-commerce, tourisme
Signalement d'anomalies et conformitéOllama, Qdrant, Odoo, VictoriaLogsfinance, e-commerce
Automatisation de workflowsn8n, Ollama, Odoo, Nextcloudconsultant, RH, industrie, logistique
Hygiène de sécurité assistéeCrowdSec, OpenBao, VictoriaLogs, Grafanafinance, médical, industrie
Aide à la décision sur vos donnéesOllama, Qdrant, Grafana, n8nfinance, consultant, industrie, RH
Recherche et synthèse documentaireOllama, Qdrant, Paperless, n8njuridique, médical, finance, RH
Marketing assistéMautic, Matomo, Ollama, n8ne-commerce, tourisme, créatif
Secrétariat de cabinet assistéOllama, Qdrant, OpenBao, CalRSmédical, thérapeute
Suivi de maintenanceOllama, n8n, VictoriaMetrics, Grafanaindustrie, logistique
Gestion locative assistéeOdoo, CalRS, Nextcloud, Ollamaimmobilier
Veille et synthèseOllama, Qdrant, n8n, Typesenseconsultant, finance, juridique
Logistique et stocks assistésOdoo, n8n, Ollama, Grafanalogistique, industrie, e-commerce
Formation assistéeMoodle, Chamilo, Ollama, Jitsiformation, RH

Ces cas d'usage assistent vos équipes : l'assistant propose, résume, alerte ; la décision, l'envoi et la validation restent à vos équipes. Une écriture sensible dans un outil (par exemple dans la comptabilité Odoo) passe par une approbation humaine (voir Workflows).

Exemple : un flux de commande en e-commerce

Avec le secteur E-commerce, un flux typique est le suivant :

  1. Vous demandez au chat de chercher une commande ou un produit : l'assistant interroge Odoo (outils comme sales_order_search).
  2. Vous lui demandez de créer un devis ou un contact : il propose l'écriture, que vous validez.
  3. Un workflow n8n peut déclencher la suite (notification, relance) ; Mautic prend les campagnes, Matomo mesure l'audience.

Chaque étape utilise un connecteur réel du catalogue ; ce que vous automatisez ensuite dépend de votre configuration.

Quel plan choisir ?

Les plans (Starter, Pro, Enterprise, Souverain) se distinguent par le nombre de connecteurs, le niveau de support (SLA, support et niveaux de service) et le mode de déploiement. Le plan Souverain, sur devis, vise les banques et l'État : infrastructure dédiée isolée, déploiement isolé du réseau possible. Les prix et le détail de chaque plan sont sur la page de tarification du site et dans Tarification, seule source à jour.

Voir aussi

Tarification et offres

Cette page décrit les quatre offres publiées sur la page Tarifs du site, état au 3 octobre 2026. Les prix sont hors taxes, mensuels et fixes. Le prix inclut la passerelle MCP, l'IA souveraine (Fournisseurs de modèles), les connecteurs MCP (Vue d'ensemble), la conformité UE (Conformité RGPD) et le support. Les outils métier (Odoo, n8n et autres) sont auto-hébergés par vos soins, ou disponibles en déploiement assisté, en option.

Le prix qui fait foi est celui de la page Tarifs et du contrat.

Les quatre offres

Chaque offre est décrite par son public et par ce qu'elle inclut.

Starter : 9 EUR par mois

Pour les TPE et les indépendants.

InclusDétail
IA souverainepilote vos outils métier
Connecteurs3 à 5 outils métier
Tutorielsauto-hébergement inclus
Conformitéconçue pour le RGPD et NIS2
Supportpar courriel
SLA99,5 % de disponibilité (objectif)

Pro : 29,90 EUR par mois

Pour les PME. C'est l'offre mise en avant sur la page.

InclusDétail
IA avancéelibellé de la page Tarifs : « raisonnement multi-étapes ». Les quatre moteurs de raisonnement du code (arbre de pensées, auto-cohérence, chaîne de vérification, MCTS) n'ont aucun appelant en production : ils sont en sommeil (Architecture)
Connecteurs10 outils métier et plus
Intégrationavec vos systèmes existants
Déploiement assistéde vos outils, en option
Supportprioritaire
SLA99,9 % de disponibilité (objectif)
Formationéquipes, 2 jours

Enterprise : 99,90 EUR par mois

Pour les ETI et les institutions.

InclusDétail
Infrastructuredédiée, connecteurs illimités
Déploiementsur site (on-premise) ou cloud privé dans l'UE
Code sourcecomplet et transférable
Supportprioritaire, avec un chargé de compte
SLA99,99 % de disponibilité (objectif)
Sécuritétest d'intrusion annuel et audit de conformité (programme cible : aucun exercice daté n'est encore publié)
Conseilstratégique, 12 jours par an

Souverain : sur devis

Pour les banques et l'État.

InclusDétail
Infrastructuredédiée et isolée
Cryptographie post-quantiqueML-KEM-768, disponible sur activation dédiée
ConformitéDORA, EUCS, Gaia-X : trajectoire et auto-évaluation, sans certification
Auditde conformité permanent (libellé de la page Tarifs ; aucun audit de conformité indépendant n'est publié, voir NIS2)
Chargé de comptedédié
SLA99,99 % et plan de continuité
Déploiementisolé du réseau possible

Les délais de réponse du support, par sévérité et par offre, sont dans la page SLA. Trois jeux de délais coexistent sur le site : la page Tarifs affiche 48 h, 4 h et 1 h (Starter, Pro, Enterprise) ; la page SLA donne, pour les incidents critiques, 48 h, 8 h et 2 h en heures ouvrées ; le tableau des conditions générales donne 48 h, 24 h et 4 h ouvrées. La page Tarifs parle en outre d'un support 24/7 pour Enterprise, que les deux autres textes ne confirment pas (heures ouvrées). Le contrat fait foi.

Capacités par offre

La page Tarifs publie aussi une table « Capacités par plan » : 20 lignes, chacune avec le plan minimum qui débloque la capacité. Elle compte six niveaux (Essentiel, Starter, Pro, Business, Enterprise, Souverain) ; la grille de prix n'en publie que quatre, et Essentiel et Business n'y ont pas de prix. Chaque palier supérieur conserve les capacités des précédents. Cette table est lue dans un registre unique du dépôt (docs/audit/capacites-par-plan.yaml) : ce livre ne la recopie pas, pour ne pas dériver. Les sections du menu visibles par plan sont dans Tableau de bord.

Les limites chiffrées de chaque offre (douze ressources, énumérées dans Limites) sont lues en base.

Essai gratuit

D'après les conditions générales de vente :

  • 14 jours, sans engagement et sans carte bancaire ;
  • accès à l'ensemble des fonctionnalités de l'offre Pro ;
  • à la fin, vous choisissez une offre ; sans souscription, le compte est désactivé et les données sont conservées 30 jours avant suppression définitive.

État du code au 3 octobre 2026 : ce parcours n'est pas câblé. L'inscription publique crée une organisation au plan « free » (un espace de travail, un workflow, un utilisateur et 100 conversations par mois), sans souscription ni essai de l'offre Pro. En terminant ou en passant l'assistant d'accueil, l'application pose pour une organisation sans souscription active une souscription simulée perpétuelle au niveau « essentiel » : jamais facturée, sans les fonctions de l'offre Pro. Tant que le code ne l'applique pas, lisez l'essai comme une promesse des conditions générales, pas comme une fonction de l'application.

Paiement et facturation

SujetRègle (conditions générales de vente)
Prixhors taxes ; TVA selon la législation applicable
Engagementmensuel ou annuel, avec 20 % de remise sur l'annuel
Moyens de paiementcarte bancaire, virement SEPA, iDEAL ou Bancontact, via Mollie (Pays-Bas)
Facturationà la souscription, puis à chaque date anniversaire
Renouvellementtacite ; vous pouvez le désactiver avant l'échéance
Retard de paiementpénalités de 3 fois le taux d'intérêt légal et indemnité forfaitaire de 40 EUR

Comment choisir

  • Indépendant ou TPE. Starter couvre l'essentiel avec 3 à 5 outils.
  • PME avec une équipe. Pro apporte 10 outils et plus, l'IA avancée annoncée par la page Tarifs (ses moteurs de raisonnement sont en sommeil, voir plus haut) et une formation.
  • ETI ou institution. Enterprise apporte une infrastructure dédiée et le code source transférable.
  • Banque ou administration. Demandez un devis Souverain (voir aussi Cas d'usage par secteur).
  • Vous hésitez. Les conditions générales prévoient un essai de 14 jours avec les fonctions de l'offre Pro (voir « Essai gratuit » plus haut : le code ne l'applique pas encore). Commencez par la prise en main guidée.

Le tarif agence est sur devis.

Voir aussi

SLA, support et niveaux de service

Cette page reprend la page publique « Accord de niveau de service » du site. Le texte qui fait foi est le contrat et les conditions générales de vente. En cas d'écart, ils priment sur ce livre.

Un SLA est ici un objectif contractuel sur les environnements de production sous contrat. Ce n'est pas une garantie sans condition.

Disponibilité

OffreDisponibilitéIndisponibilité maximale par moisPénalité (notation de la page SLA)
Starter99,5 %3 h 39 min5 % avoir / 10 % indispo
Pro99,9 %43 min10 % avoir / 10 % indispo
Enterprise99,99 %4,3 min15 % avoir / 10 % indispo
Souverain99,99 %4,3 min20 % avoir / 10 % indispo

La disponibilité est mesurée chaque mois par le système de supervision de la plateforme (voir Supervision). Les maintenances programmées, annoncées 72 heures à l'avance, sont exclues du calcul.

Les conditions générales plafonnent les pénalités à 30 % du montant mensuel de l'abonnement concerné. L'avoir est proportionnel au temps d'indisponibilité.

Temps de réponse du support

Les temps sont en heures ouvrées : du lundi au vendredi, de 9 h à 18 h (CET).

SévéritéDéfinitionStarterProEnterpriseSouverain
P1 critiqueservice indisponible48 h8 h2 h30 min
P2 majeurfonctionnalité dégradée72 h24 h4 h1 h
P3 mineurimpact limité5 jours48 h8 h4 h
P4 informationquestion, demande10 jours5 jours24 h8 h

L'offre Souverain relève d'un SLA personnalisé sous contrat. L'astreinte sur incidents P1 et P2 y est négociée au cas par cas.

L'assistant automatisé (niveau 1) est disponible à toute heure pour le premier tri. C'est un objectif : il suppose que l'API publique soit exposée.

Escalade

NiveauDélaiInterlocuteur
N1, support techniqueimmédiatéquipe support
N2, ingénierie+2 h (P1), +8 h (P2)ingénieur senior
N3, direction technique+4 h (P1), +24 h (P2)CTO
N4, direction générale+8 h (P1)CEO

Communication des incidents

  • La page de statut publique est /status.
  • Un courriel automatique part pour les incidents P1 et P2.
  • Un post-mortem est publié dans les 5 jours ouvrés suivant un incident P1 (voir Réponse aux incidents).
  • Une violation de données est notifiée à la CNPD et aux clients sous 72 heures (article 33 du RGPD, article 23 de NIS2).

Reprise après incident

MesureCibleRemarque
RTOmoins de 2 htemps de reprise après un incident majeur
RPOmoins de 24 hperte de données maximale ; sauvegardes quotidiennes, sans restauration à un instant précis
Sauvegardesquotidiennesconservation de 30 jours, tests mensuels
Exercice de reprisetrimestrielexercice complet

Ces cibles sont un programme, pas un constat. Aucune restauration chronométrée n'est encore publiée : le premier exercice daté fera passer la cible en résultat.

Le RPO de 24 heures vient du rythme des sauvegardes (Sauvegarde et restauration). Une perte allant jusqu'à une journée de données est donc possible.

Ce que le SLA ne couvre pas

  • Les services tiers que vous connectez (votre Odoo, votre n8n).
  • La force majeure, la maintenance programmée et l'usage non conforme.

Voir aussi

Comparatifs

Cette page compare Chatbotaurus à deux familles d'offres, sans nommer de tiers. Elle suit la page publique « Comparatif souverain » du site, état au 3 octobre 2026.

Deux règles :

  • on compare des critères que le code ou la configuration de la plateforme permettent de vérifier ;
  • quand une capacité d'une autre offre n'est pas documentée publiquement, on écrit « non documenté », pas « absent ».

Les deux familles

FamilleCe qu'elle faitOù elle est hébergée
Offres SaaS hors UEassistant d'IA généraliste, ou outil d'automatisation en lignechez un hébergeur sous juridiction hors UE
Outils d'automatisation auto-hébergésorchestration de flux que vous installez vous-mêmechez vous

Chatbotaurus est une passerelle MCP hébergée dans l'UE (voir Architecture Chatbotaurus), qui relie un assistant à vos outils métier (voir Vue d'ensemble). Ce n'est ni un assistant généraliste, ni un simple outil de flux.

Verdict critère par critère

CritèreChatbotaurusOffres SaaS hors UE
Hébergementdans l'UE ; test et production sur des serveurs européenshébergeur sous juridiction hors UE
FacturationMollie (Pays-Bas)prestataire de paiement hors UE
Courriel transactionnelProtonMail (Suisse, décision d'adéquation RGPD)messagerie transactionnelle hors UE
VoixLiveKit, Kokoro et Speaches, auto-hébergésvoix et synthèse tierces hors UE
Authentification uniqueAuthentik, open source européenSSO hébergé hors UE
ChiffrementAES-256-GCM ; ML-KEM-768, Schnorr et Shamir en optionAES-GCM uniquement
Vérification des sortiesgardes de sortie en cours (routes et outils)non documenté
AI Act, RGPD, NIS2documenté, avec Cedar et RLS (isolation en base)non documenté
Connecteurs195 fiches YAML (3 octobre 2026)non comparé
Prix agencesur devistarif public non comparé

« En option » veut dire désactivé par défaut. « En cours » veut dire prévu, pas livré.

Ce qui différencie la plateforme

  • Routage déterministe. EntityRouter choisit le connecteur par des règles. Aucune mesure de latence du routage n'est publiée.
  • Cryptographie en option. Quatre modules sont disponibles sur activation : ML-KEM-768 (canal hybride), compute-mode, preuves Schnorr, partage de secret de Shamir. Ils ne sont pas actifs par défaut (voir Glossaire, entrées PQC et Compute-mode).
  • Voix européenne. La reconnaissance vocale (Voix et Canaux) couvre 7 langues.
  • Catalogue de connecteurs. 195 fiches de connecteurs, dont le connecteur Odoo à 711 outils au registre.

Ce que la comparaison ne dit pas

  • Elle ne mesure ni la qualité des réponses, ni la vitesse d'un autre produit.
  • Elle ne compare pas les prix publics d'un tiers : ils changent et ne sont pas dans notre code.
  • Elle ne vaut pas certification. La plateforme est conçue pour répondre au RGPD, à NIS2 et à l'AI Act, et ne détient aucune certification à ce jour.

Voir aussi

Limites et ce que la plateforme ne fait pas

Cette page dit ce que Chatbotaurus fait, ce qu'il ne fait pas, et les limites mesurées dans le code. Les valeurs sont celles par défaut au 3 octobre 2026. Un opérateur qui héberge sa propre instance peut en régler certaines par variable d'environnement.

Ce que la plateforme fait

DomaineDétail
Automatisationworkflows visuels qui appellent vos outils métier
Assistantchat qui route vers vos connecteurs par des règles déterministes (EntityRouter)
IA localemodèles exécutés par la plateforme, dans l'UE (EuroLLM 1,7B, repli ministral-3:3b)
Connecteurs195 fiches YAML ; 175 cartes de serveurs dans l'application, dont 30 prouvées opérationnelles ; 108 entrées au catalogue public, dont 15 disponibles
Odoo711 outils au registre

Ce que la plateforme ne fait pas

  • Ce n'est pas un chatbot généraliste. Le chat de support répond aux questions sur la plateforme. Il ne tient pas de conversation libre sans contexte métier.
  • Ce n'est pas un ERP. Elle se connecte à Odoo ou à un autre outil ; les données métier restent dans cet outil.
  • Ce n'est pas un hébergeur web. Elle n'héberge ni site, ni application, ni base de données générique.
  • Ce n'est pas un stockage de fichiers. Les documents vivent dans les outils connectés.
  • Elle n'exécute pas de code JavaScript dans un workflow. Les nœuds « fonction personnalisée » sont refusés à l'exécution (doctrine Rust uniquement ; voir Migration depuis d'autres outils).
  • Elle ne route pas vers des services hors UE. À l'exécution, les identifiants de serveur de 25 services hors UE sont refusés, et seuls les serveurs de la liste autorisée sont appelés (voir Conception des connecteurs MCP).

Limites de débit

Le débit est limité par adresse IP. Au-delà, l'API répond 429 (format des erreurs : Documentation Swagger).

CheminLimite par défaut
/api/v1/*100 requêtes par seconde
/api/v1/stats/route-events30 par minute
/api/v1/prediction (chat public du site)20 par minute (la règle porte sur le préfixe : elle s'applique aussi à /api/v1/predictions)
autres chemins1 000 par minute

Le chat public du site a un seau à part, parce qu'une réponse coûte 20 à 36 secondes de calcul au modèle local (mesure du 3 octobre 2026).

La connexion a ses propres limites, par compte et par adresse : au-delà d'un nombre d'échecs, l'adresse est bloquée pendant un temps réglable (voir Sécurité).

Taille des requêtes

LimiteValeur par défaut
Corps de requête2 Mio
Fichier téléversé25 Mio

Au-delà, l'API répond 413.

Quotas par offre

Le code sait plafonner douze ressources : espaces de travail, workflows, utilisateurs, conversations par mois, connecteurs, serveurs MCP, connecteurs par gateway, appels d'API, stockage (en Go), minutes de voix, lignes d'appel concurrentes et enregistrements vectoriels. Les valeurs sont lues en base, par offre ; une valeur vide veut dire illimité.

  • Un quota atteint répond 402 avec le code QUOTA_EXCEEDED et un lien de montée en gamme.
  • Un quota que la plateforme n'a pas pu mesurer répond 503, jamais « illimité ».

La table des capacités par offre est sur la page Tarification.

Langues

ÉlémentLangues
Interfacefrançais et anglais (jeux complets de 1 610 clés)
Voix7 langues : français, anglais, allemand, espagnol, italien, néerlandais, portugais
Documentationfrançais

Limites de l'IA

  • Erreurs possibles. Un modèle peut se tromper. L'ancrage dans vos documents (RAG, voir Connaissances) réduit les erreurs, il ne les supprime pas. Vérifiez les informations critiques.
  • Latence. Sur processeur seul, une réponse du modèle local (Fournisseurs de modèles) peut prendre de 20 à 36 secondes (chat public, mesure du 3 octobre 2026).
  • Pas d'analyse d'images. Aucune analyse d'image ni de page scannée n'est annoncée. La recherche visuelle de pages est hors périmètre (spec 115).
  • Pas de GPU. L'inférence se fait sur processeur. Aucune tâche de spec ne prévoit de GPU ; tout achat de GPU est soumis à validation (spec 68, DEC-68-004).

Prévu

ÉvolutionSource
Kit de développement Python et JavaScriptspec 22, chantier 22.E (tâches 22.E.3 et 22.E.4)
Livraison du déploiement en un clic depuis le cataloguespec 16, tâche P5.5

Ce qui n'a pas de tâche dans une spec n'est pas annoncé ici.

Voir aussi

Installation de Chatbotaurus

Ce guide installe Chatbotaurus en développement local. La pile est écrite en Rust : forge-api (Axum, SeaORM) pour le backend et forge-ui (Dioxus 0.7) pour l'interface. Pour aller plus vite, voir le démarrage rapide.

Ce guide ne couvre pas l'installation sur un serveur : pour la production (réseaux, volumes, unités Quadlet, mise à jour), voir Déploiement avec Podman.

Prérequis

OutilVersionInstallation
Rust1.91 ou plus (rust-version du workspace)rustup.rs
dioxus-cli (dx)0.7cargo install dioxus-cli --locked
Cible wasmrustup target add wasm32-unknown-unknown
Git2.xgit-scm.com
Podman et podman-composePodman 4.x ou plusPodman Desktop

Le chemin de référence du dépôt est Windows (PowerShell) : les lanceurs de développement sont des scripts .ps1. Sous Linux ou macOS, utilisez les commandes cargo et dx ci-dessous.

1. Cloner le dépôt

git clone <url-du-depot>
cd <dossier-du-depot>

2. Compiler le workspace

cargo build --workspace

Le workspace compte 20 crates (forge-core, forge-api, forge-ui, forge-auth, forge-db, forge-mcp, forge-cli, forge-gateway, forge-voice, forge-ops, forge-audit, forge-docs, entre autres). Une première compilation à froid est longue.

3. Configurer l'environnement

cp .env.example .env

Les valeurs secrètes de .env.example sont des gabarits CHANGE_ME_... que l'application refuse au démarrage : remplacez-les. Pour générer un secret : openssl rand -hex 64.

Variables essentielles (chacune est lue par le code, voir crates/forge-core/src/config.rs) :

# Backend
PORT=3000
DATABASE_URL=postgresql://<utilisateur>:<mot-de-passe>@localhost:5432/<base>
REDIS_URL=redis://localhost:6380
JWT_SECRET=<secret-genere>
AT_REST_ENCRYPTION_KEY=<secret-genere>

# Vecteurs et secrets
QDRANT_URL=http://localhost:6334
BAO_ADDR=http://localhost:8200

# Modèles (Ollama)
OLLAMA_BASE_URL=http://localhost:11434

# Courriel (second facteur par code)
SMTP_HOST=<serveur-smtp>
SMTP_PORT=587
SMTP_USER=<compte>
SMTP_PASSWORD=<mot-de-passe-applicatif>
SMTP_FROM=<adresse-expediteur>

# SSO OIDC (Authentik), facultatif
AUTHENTIK_SERVER_URL=http://localhost:9000
AUTHENTIK_CLIENT_ID=<identifiant-client>
AUTHENTIK_CLIENT_SECRET=<secret-client>

# Journalisation
RUST_LOG=info,forge_api=debug

Notes (la liste complète des variables est dans Variables d'environnement) :

  • FORCE_2FA vaut vrai par défaut : le démarrage exige alors SMTP_HOST.
  • AT_REST_ENCRYPTION_KEY chiffre les identifiants stockés ; sans elle, la clé dérive de JWT_SECRET.
  • .env doit être lisible par dotenvy : une valeur contenant un espace doit être entre guillemets, sinon tout le fichier est ignoré.
  • Il n'existe pas de variables CSRF_SECRET ni TOTP_ISSUER.

4. Démarrer l'infrastructure

podman-compose -p chatbotaurus-vps1 -f podman-compose.yml up -d

Ce plan (détail dans Déploiement avec Podman) démarre PostgreSQL, Valkey, Qdrant, Ollama, Authentik, OpenBao, les services de voix et l'observabilité. Le second plan, mgaas-vps2 (podman-compose.vps2.yml), porte la passerelle et les serveurs mcp-*. Tout service futur y est ajouté dans ce fichier, jamais lancé à la main.

Vérifiez que les conteneurs tournent avec podman ps (voir Gestion des conteneurs). Si l'un d'eux manque, voir Problèmes connus. Téléchargez aussi les modèles de dialogue avant la première conversation (section « Modèles » plus bas).

5. Initialiser la base

Les migrations s'appliquent aussi au démarrage de forge-api. Pour migrer sans lancer le serveur :

cargo run -p forge-cli -- db migrate

6. Lancer en développement

Backend, port 3000

cargo run -p forge-api

Sous Windows, le lanceur de référence est scripts/dev/run-forge-api.ps1. Il copie le binaire avant de le lancer (la compilation reste possible pendant que le serveur tourne) et exige la variable ADMIN_PASSWORD (12 caractères ou plus) :

$env:ADMIN_PASSWORD = "<mot-de-passe-admin-12-caracteres-ou-plus>"
powershell -File scripts\dev\run-forge-api.ps1

scripts/dev/watch-forge-api.ps1 recompile et remplace le binaire à chaque modification du backend.

Routes principales (contrat complet : Documentation Swagger) :

  • GET /api/v1/health et GET /api/v1/healthz : état du service.
  • GET /api/v1/readyz : base et Valkey joignables.
  • POST /api/v1/predictions et POST /api/v1/predictions/stream : inférence.
  • GET /api/v1/mcp/catalogue : catalogue des connecteurs (authentifié).
  • POST /api/v1/mcp : transport MCP (authentifié).

Frontend, port 8080

dx serve --platform web --port 8080 --package forge-ui

Sous Windows : pwsh -File scripts\dev\run-dx.ps1. Ce lanceur utilise un répertoire de build séparé (target-dx) pour que cargo build ne bloque pas dx. dx recharge à chaud : ne le relancez pas pour un changement de code. pwsh -File scripts\dev\run-dx.ps1 -Status donne l'état du serveur.

Ouvrez l'interface locale (http://localhost:8080).

Autres plateformes

forge-ui se compile pour les cibles de Dioxus (web, desktop, android, ios, server, liveview), par exemple :

dx serve --platform desktop --package forge-ui

La cible web est la seule suivie en continu.

Ce livre

cargo run -p forge-docs               # construit le livre et le copie dans forge-ui/public/docs
cargo run -p forge-docs -- --clean    # purge book/ et public/docs/ avant de construire

dx serve sert ensuite le livre sous /docs/. L'option --serve (aperçu avec rechargement) n'existe pas : le binaire n'accepte que --src, --dst, --clean, --no-copy et --keep-html-urls.

Modèles

Le dialogue utilise EuroLLM 1.7B, avec ministral-3:3b en repli. Le modèle d'embedding (384 dimensions) est chargé par fastembed dans le processus forge-api : il ne passe pas par Ollama. Détails dans Fournisseurs.

podman exec forge-ollama ollama pull cas/eurollm-1.7b-instruct-q8
podman exec forge-ollama ollama pull ministral-3:3b

Vérification

curl http://localhost:3000/api/v1/health
cargo test -p forge-replay
cargo test -p forge-api

La première commande rend un JSON avec "status":"ok" (le même que dans le démarrage rapide) ; les deux suivantes doivent se terminer sans test en échec.

La CI (voir Contribuer) exécute aussi cargo clippy --workspace -- -D warnings et cargo fmt --check.

Prochaines étapes

Voir aussi

Prise en main guidée

Ce guide va de la création du compte au premier workflow. Chaque étape dit à qui elle s'adresse.

Quel est votre profil ?

  • Dirigeant ou décideur : étapes 1, 2 et 8.
  • Responsable métier : étapes 1 à 4, 6 et 7.
  • Développeur ou intégrateur : toutes les étapes, surtout 3, 5 et 6.
  • Administrateur système : étapes 3, 5 et 8, puis déploiement Podman.
  • Délégué à la protection des données : conformité RGPD.

Étape 1 : créer le compte

Tous les profils

  1. Ouvrez /auth/signup sur votre instance (en local : http://localhost:8080).
  2. Renseignez les champs demandés et validez.
  3. Connectez-vous sur /auth/login.
  4. Saisissez le code à usage unique reçu par courriel (/auth/verify-otp). Le second facteur est actif par défaut (FORCE_2FA).
  5. À la première connexion, l'assistant d'accueil s'ouvre (étape suivante). Si la connexion échoue, voir Questions fréquentes (« Comment me connecter ? »).

Les conditions générales prévoient un essai gratuit de 14 jours, sans engagement et sans carte bancaire. Il donne accès à l'ensemble des fonctionnalités de l'offre Pro. Sans souscription à la fin de l'essai, le compte est désactivé et les données sont conservées 30 jours avant suppression.

Étape 2 : l'assistant d'accueil

Tous les profils

À la première connexion, l'application ouvre /onboarding. L'assistant vous fait choisir :

RéglageChoix
Languefrançais, anglais, néerlandais ou allemand (seuls le français et l'anglais ont une interface complète ; le néerlandais et l'allemand n'ont que 26 clés traduites, le reste s'affiche en français)
Espace de travailun nom et un secteur parmi les 16 secteurs du catalogue
Odoofacultatif : l'adresse de votre serveur Odoo
Modèle de départSupport client IA, Chat confidentiel, ou workflow personnalisé (canvas vierge)

Terminer l'assistant vous amène au tableau de bord (/dashboard). Aujourd'hui, le serveur ne retient de l'assistant que le fait de l'avoir terminé ou passé : langue, secteur, adresse Odoo et modèle de départ ne sont pas enregistrés, et l'organisation reçoit le niveau « essentiel » si elle n'a aucune souscription (voir Tarification). Prenez cinq minutes pour parcourir les pages principales :

PageAdressePour qui
Tableau de bord/dashboardTous
Chat/chatTous
Orchestrateur/orchestratorTous
Workflows/workflowsMétier, développeur
Serveurs MCP/mcp-serversDéveloppeur, admin
Identifiants/credentialsDéveloppeur, admin
Intégration au site web/embedsDéveloppeur
Documents/documentsMétier, développeur
Facturation/billingDirigeant, admin
Paramètres/settingsAdmin, dirigeant

Étape 3 : enregistrer vos identifiants

Développeur, administrateur système, responsable métier

Les identifiants permettent à Chatbotaurus de se connecter à vos outils (la page est décrite dans Sécurité et identifiants).

  1. Ouvrez /credentials. Dans le menu, la page est dans la section Sécurité, visible à partir du plan Business ; sur un plan inférieur, ouvrez-la par son adresse (voir la section Navigation du Tableau de bord).
  2. Cliquez sur la carte du service voulu (Odoo, n8n, Matomo, Nextcloud, entre autres).
  3. Remplissez le formulaire : adresse du serveur, identifiant, clé d'API ou mot de passe applicatif selon le service.
  4. Enregistrez.

Les identifiants sont chiffrés au repos en base (clé AT_REST_ENCRYPTION_KEY). Ils ne sont jamais réaffichés en clair : en modification, un champ secret laissé vide ou inchangé conserve la valeur enregistrée. Voir aussi OpenBao et gestion des secrets pour les secrets d'infrastructure.

Pour Odoo, le parcours complet (les quatre champs à renseigner, puis un premier appel d'outil) est dans Connecter Odoo à la passerelle MCP.

Étape 4 : tester le chat

Tous les profils

  1. Ouvrez /chat.
  2. Posez une question simple : « Bonjour, que sais-tu faire ? »
  3. Observez la réponse. La page est décrite dans Chat.

Le chat parle à un workflow déployé : si le sélecteur de workflow est vide, créez d'abord un workflow (étape 6), puis revenez à cette étape.

Si un identifiant Odoo est enregistré, posez une question métier, par exemple « Combien de contacts dans le CRM ? ». Le registre d'outils Odoo compte 711 outils (mesure du 3 octobre 2026, odoo_tools_registry.rs).

Le modèle de dialogue par défaut est EuroLLM 1.7B, exécuté localement via Ollama, avec ministral-3:3b en repli. Il tourne sur le processeur : les réponses longues prennent quelques secondes. Pour utiliser un autre fournisseur, voir Fournisseurs.

Étape 5 : parcourir le catalogue de serveurs MCP

Développeur, administrateur système

Ouvrez /mcp-servers. Le catalogue se filtre par secteur et par catégorie (voir MCP et Orchestrateur). Le catalogue public compte 108 entrées dont 15 marquées « disponibles » (mesure du 3 octobre 2026) ; la page de l'application en liste 175.

Le déploiement en un clic n'est pas encore câblé. Les actions déployer, démarrer, arrêter et redémarrer un serveur du catalogue répondent 503 FEATURE_PENDING tant que l'adaptateur Podman n'est pas branché sur forge-api. C'est prévu (spec 16, tâche P5.5, route prévue ops/deploy). En attendant, un serveur se lance par le plan compose mgaas-vps2 (podman-compose.vps2.yml). Consulter le catalogue est possible dès maintenant (voir parcourir le catalogue de services).

Pour les dirigeants : cette étape relève de votre équipe technique.

Étape 6 : créer votre premier workflow

Responsable métier, développeur

Un workflow est une suite d'actions que vous assemblez sur un canvas (voir Workflows).

  1. Ouvrez /workflows et créez un nouveau workflow.
  2. Placez un nœud d'entrée (MCP Start) sur le canvas.
  3. Ajoutez un nœud agent.
  4. Ajoutez un nœud de sortie (MCP End).
  5. Reliez les nœuds en tirant des lignes.
  6. Configurez l'agent : modèle et consigne système.
  7. Enregistrez, puis testez depuis /chat.

Un nœud est une brique du workflow. Un agent est un nœud qui s'appuie sur le modèle. Un connecteur est un nœud qui parle à un outil externe (Odoo, n8n, entre autres). Voir le glossaire.

Étape 7 : intégrer le chat à votre site

Développeur, responsable métier

  1. Ouvrez /embeds : la page liste vos workflows.
  2. Choisissez celui à publier ; le générateur d'intégration s'ouvre.
  3. Réglez l'apparence (couleurs, message d'accueil).
  4. Copiez le code généré et collez-le dans votre site.

Le code est un extrait <script> qui s'ajoute à n'importe quel site. Voir aussi Voix et Canaux pour la page Marque (widget).

Étape 8 : passer à une offre payante

Dirigeant, administrateur

Les prix publics sont sur la page /pricing. Tous sont HT et mensuels.

OffrePrixPour qui
Starter9 EUR/moisTPE, indépendants : connecteurs pour 3 à 5 outils, RGPD et NIS2
Pro29,90 EUR/moisPME : connecteurs pour 10 outils et plus, IA avancée (moteurs de raisonnement en sommeil, voir Tarification), support prioritaire
Enterprise99,90 EUR/moisETI et institutions : infrastructure dédiée, code source transférable, support prioritaire avec gestionnaire de compte
Souverainsur devisBanques, État : infrastructure isolée, cryptographie post-quantique sur activation dédiée

Le détail des offres et des capacités par plan est sur /pricing et dans la page Tarification, les délais de support dans SLA. La gestion de l'abonnement est sur /billing (voir Paramètres).

Liste de contrôle

ÉtapeFait ?
Compte créé, code reçu par courriel
Assistant d'accueil terminé
Au moins un identifiant enregistré
Chat testé
Premier workflow créé ou testé
Équipe ajoutée (page /users, menu Gestion à partir du plan Business ; voir Paramètres)
Intégration au site (facultatif)

Et ensuite

Voir aussi

Fournisseurs de modèles

Chatbotaurus répond par défaut avec un modèle souverain européen exécuté localement. Un fournisseur supplémentaire se branche par un identifiant (voir Sécurité et identifiants) enregistré dans l'application, pas par une variable d'environnement globale.

Les trois modèles souverains

La liste est dans crates/forge-core/src/model_governance.rs (SOVEREIGN_LOCAL_MODELS). C'est l'unique source des défauts du code.

RôleModèleOù il tourne
Dialoguecas/eurollm-1.7b-instruct-q8 (EuroLLM 1.7B, environ 1,8 Go)Ollama
Repliministral-3:3bOllama
Embeddingparaphrase-multilingual-MiniLM-L12-v2, 384 dimensionsfastembed, dans le processus forge-api

Télécharger les deux modèles de dialogue (le conteneur Ollama vient du plan décrit dans Déploiement avec Podman) :

podman exec forge-ollama ollama pull cas/eurollm-1.7b-instruct-q8
podman exec forge-ollama ollama pull ministral-3:3b

Le modèle d'embedding n'est pas un modèle Ollama : ollama pull ne le concerne pas. fastembed le télécharge dans son cache au premier usage (le pipeline d'indexation est décrit dans Connaissances). La collection Qdrant du pipeline wiki est donc créée en 384 dimensions.

Ollama local (par défaut)

OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=ministral-3:3b
OLLAMA_EMBEDDING_MODEL=paraphrase-multilingual-MiniLM-L12-v2

Valeurs par défaut (crates/forge-core/src/config.rs) : OLLAMA_BASE_URL vaut http://localhost:11434 et OLLAMA_MODEL prend le modèle de repli de la liste souveraine. Le délai d'appel (OLLAMA_TIMEOUT_SECS) vaut 120 s.

Ajouter un autre fournisseur

La résolution du modèle de chat d'une organisation suit cet ordre (crates/forge-api/src/routes/llm_provider.rs) :

  1. le dernier identifiant de type IA enregistré par l'organisation ;
  2. l'ancienne configuration /llm-provider (compatibilité) ;
  3. EuroLLM en local.

Pour ajouter un fournisseur :

  1. Ouvrez /credentials (section Sécurité du menu à partir du plan Business, sinon par son adresse) et choisissez la catégorie des modèles de langage.
  2. Choisissez la famille (par exemple mistralApi pour Mistral AI, France, ou ollama pour votre propre serveur Ollama). Le formulaire préremplit l'adresse et le modèle.
  3. Pour un serveur auto-hébergé, indiquez son adresse de base. Pour un service en ligne, saisissez la clé d'API.
  4. Enregistrez. La carte active est signalée dans la liste.
  5. Vérifiez dans le chat : si le fournisseur est refusé, le chat répond avec EuroLLM (voir « Fournisseurs refusés » plus bas).

La clé n'est stockée qu'une fois, chiffrée en base. Le fournisseur choisi n'est utilisé que si son point d'accès est local ou européen (voir « Fournisseurs refusés »). Les variables LLM_PROVIDER et MISTRAL_API_KEY du fichier .env.example ne sont pas lues par le backend pour choisir le fournisseur de chat : n'en dépendez pas.

Les métadonnées du code (llm_provider_metadata.rs) décrivent Ollama et Mistral AI comme fournisseurs européens. Des fiches ollama et localai existent dans connectors/.

Fournisseurs refusés

Avant chaque appel à un modèle, le code applique deux contrôles (assert_llm_sovereign, crates/forge-core/src/agent/memory/sovereignty.rs) :

  1. le nom du modèle ne doit contenir aucun de ces huit noms : OpenAI, Anthropic, Azure, Google, AWS, Bedrock, Cohere, Groq (US_PROVIDERS) ;
  2. l'adresse du point d'accès doit être locale (boucle locale, réseau privé), se terminer par .eu, ou être celle d'un fournisseur européen connu (Ollama, Mistral AI et un hébergeur européen référencé dans le code).

Un appel qui échoue l'un des deux contrôles est refusé avant l'envoi du message. Quand le fournisseur choisi par l'organisation est refusé, le chat bascule sur EuroLLM. La liste de dix noms LLM_PROVIDER_US_BLOCKLIST (avec Together et Replicate) existe dans le code mais aucun chemin de production ne l'appelle.

La liste des familles proposées dans /credentials évolue : certaines familles passent par un agrégateur ou un service hors UE. Le formulaire affiche l'origine de chaque famille. Une famille dont le point d'accès n'est ni local ni européen s'enregistre, mais ses appels sont refusés par le contrôle ci-dessus.

Voir aussi

Utiliser les connecteurs MCP

Chatbotaurus utilise le Model Context Protocol (MCP) pour parler à des services externes. Un connecteur expose des outils que l'agent peut appeler.

Où vivent les connecteurs

EmplacementContenu
connectors/*.yaml (racine du dépôt)Fiches déclaratives : adresse de base, authentification, outils. Lues par crates/forge-mcp/src/connector/yaml_loader.rs.
crates/forge-mcp/src/connector/Code Rust commun : client HTTP, import OpenAPI, client XML-RPC Odoo, client CLI calrs.

Le dossier connectors/ compte 195 fiches YAML (mesure du 3 octobre 2026). Ajouter un outil HTTP se fait en ajoutant une fiche, sans écrire de Rust. Voir Créer votre premier connecteur MCP.

Exemples de fiches présentes

Chaque nom ci-dessous correspond à un fichier de connectors/.

DomaineFiches
ERP, gestionodoo, dolibarr, akaunting, invoiceninja
Automatisation, rendez-vousn8n, calrs
Analytique, recherchematomo, typesense, searxng
Communication, supportrocketchat, element, freescout, discourse, listmonk
Fichiers, codenextcloud, forgejo
Identité, secretsauthentik, openbao
IA, vecteurs, voixollama, localai, qdrant, kokoro-tts
Observabilitégrafana, victoriametrics, victorialogs
Données publiques UEcordis, eurostat, europeana, eurlex, enisa, europe-pmc, data-europa

Pour l'ERP, odoo porte un registre de 711 outils (mesure du 3 octobre 2026) et un client XML-RPC. Voir Connecter Odoo à la passerelle MCP et la vue d'ensemble des connecteurs.

Le nombre de fiches n'est pas le nombre de services prouvés. Le catalogue public compte 108 entrées, dont 96 avec une fiche et 15 marquées « disponibles » (mesure du 3 octobre 2026).

Identifiants

Un connecteur lit ses secrets au moment de la requête, depuis les identifiants enregistrés sur /credentials (chiffrés en base, voir Sécurité et identifiants). Ne placez jamais une clé dans une fiche YAML : une fiche référence une variable, par exemple ${NOM_DE_VARIABLE}.

Transport MCP

Le backend expose le transport HTTP streamable (voir Architecture Chatbotaurus). La version de protocole courante du code est 2025-03-26. La route est authentifiée :

POST   /api/v1/mcp   -> JSON-RPC 2.0 (initialize, tools/list, tools/call)
GET    /api/v1/mcp   -> flux SSE de notifications
DELETE /api/v1/mcp   -> fermer la session

La session est portée par l'en-tête Mcp-Session-Id. Le transport est actif si MCP_ENABLED et API_ENABLED le sont. Voir Routes MCP.

Consulter le catalogue par l'API

Le jeton s'obtient par la connexion : voir Authentification.

# Connecteurs chargés par l'instance (jeton requis)
curl -H "Authorization: Bearer <jeton>" \
  http://localhost:3000/api/v1/mcp/catalogue

# Une entrée
curl -H "Authorization: Bearer <jeton>" \
  http://localhost:3000/api/v1/mcp/catalogue/<identifiant>

La famille /api/v1/mcp-gateway/* (par exemple /mcp-gateway/servers) porte la passerelle (Routes des gateways et de la prédiction). Le catalogue d'applications métier (Routes du catalogue métier) est sous /api/v1/mcp/catalog-business.

Déploiement : pas encore. Les routes deploy, start, stop, restart, security et secrets de /api/v1/mcp/catalog-business/{id}/... répondent 503 FEATURE_PENDING avec un en-tête Retry-After à un administrateur (un autre rôle reçoit 403, sauf security qui répond 503 à tout rôle). Elles attendent l'adaptateur Podman de forge-api (spec 16, tâche P5.5). Il n'existe pas de route /mcp/gateways/<nom>/deploy. Pour lancer un serveur aujourd'hui, utilisez le plan compose mgaas-vps2.

Voir aussi

Tableau de bord

Le tableau de bord (/dashboard) est la première page après la connexion. Il résume l'activité de votre espace de travail : vos workflows, vos exécutions, vos premiers pas.

Se connecter

Toute page de l'application exige une session. Sans session, vous êtes renvoyé vers l'écran de connexion (/auth/login).

L'écran de connexion offre deux voies :

  • courriel et mot de passe, suivis d'un second facteur quand il est actif pour votre compte : code reçu par courriel, ou code de votre application d'authentification (TOTP, voir Paramètres) ;
  • le bouton « Authentik SSO » (connexion unique).

Voir SSO Authentik pour la configuration côté administrateur.

Ce que vous voyez, de haut en bas

BlocContenu
Titre et saisie de l'OrchestrateurUne zone de saisie. Envoyer un texte ouvre /orchestrator.
ActivitéExécutions réussies, en échec, en cours. Workflows déployés et brouillons. Liste des exécutions récentes. Lien « Voir tout » vers /executions.
Pour démarrerListe de quatre étapes : créer un workflow, ajouter un identifiant, déployer une gateway, importer un document. Elle s'affiche tant que l'espace n'est pas configuré.
À traiterRemplace la liste précédente une fois l'espace configuré : exécutions en échec, brouillons non déployés. Affiche « Tout est en ordre » sinon.
Leads / CRM et Voix / AppelsDeux cartes de synthèse : prospects de la semaine, gagnés, conversion ; appels terminés, abandonnés, durée moyenne.
Quatre compteursWorkflows, Identifiants, Documents, Gateway Projet UE. Chaque carte renvoie vers sa page.
Actions rapidesNouveau workflow, Gateway Projet UE, Gateways Business.
Parcours patient - Centre de rééducationCinq étapes cliquables : Orchestrateur, Médiathèque, Chat, Marque (image de marque et déploiement), Cockpit clinique.
Modèles de workflowUne grille de modèles prêts à déployer.
Workflows récentsLes derniers workflows, avec le badge Déployé ou Brouillon.

Un compteur ou une carte qui ne peut pas être lu affiche zéro ou un tiret : une seule lecture en échec ne vide pas toute la page.

La barre latérale et la barre haute affichent le même modèle : une catégorie par section, puis les pages de la section. Les sections visibles dépendent de votre plan.

PlanSections visibles (hors Paramètres)
EssentielPrincipal, Écosystème MCP (3 pages), Déployer, Connaissances (2 pages), Analytique (2 pages)
StarterPrincipal, Écosystème MCP (3 pages), Connaissances, Déployer (script d'intégration), Analytique (2 pages)
ProStarter, plus Canaux (marque, intégrations, campagnes) et Analytique complète
BusinessPro, plus voix et numéros, Sécurité, Gestion
Enterprise, SouverainTout, y compris Agence et Évaluations

Essentiel et Business sont des niveaux de la table des capacités par plan ; la page Tarifs ne publie pas de prix pour eux (voir Tarification). La section Paramètres est visible à tous les plans. Les pages d'administration /admin* n'apparaissent qu'aux comptes administrateur. Un plan inférieur peut encore ouvrir une page par son adresse : la limite porte sur le menu, et l'API applique ses propres refus (voir Limites et ce que la plateforme ne fait pas).

Source de ce tableau : docs/audit/nav-par-tier.yaml.

Voir aussi

Workflows

Un workflow est une suite de nœuds qui relie un message à des actions : appeler un outil, un modèle, un autre service. Les pages ci-dessous servent à les créer, les déployer et suivre leurs exécutions.

Les pages

PageAdresseRôle
Workflows/workflowsListe de vos workflows (vue cartes ou liste)
Éditeur/workflows/<id>Édition d'un workflow
Versioning/workflow-versionsÉtat de déploiement de chaque workflow
Exécutions/executionsJournal des exécutions

La page Exécutions n'a pas d'entrée dans la barre latérale. On l'ouvre depuis le lien « Voir tout » du tableau de bord, ou par son adresse.

Liste des workflows

Le bouton « Nouveau workflow » en crée un et ouvre l'éditeur. Le menu de chaque carte propose : modifier, dupliquer, générer le script d'intégration (voir l'étape 7, « intégrer le chat à votre site », de la prise en main guidée), supprimer.

Éditeur

L'éditeur a trois zones :

  • à gauche, la palette de nœuds, classée par catégorie ;
  • au centre, le canevas où l'on dépose et relie les nœuds ;
  • à droite, le panneau de propriétés du nœud choisi.

Vous pouvez enregistrer, déployer ou mettre en pause, supprimer, et annuler ou refaire (Ctrl+Z, Ctrl+Y). Un nœud choisi a une adresse partageable : /workflows/<id>/nodes/<nœud>.

Palette de nœuds

La palette compte 9 catégories et 74 nœuds. Un nœud grisé ne peut pas être déposé dans un workflow : il sert de brique interne à l'agent.

CatégorieExemples
MCP Gateway Flows (21)MCP Start, MCP End, MCP Gateway Agentic Workflow, MCP LLM, MCP Router, MCP Condition, MCP Loop, MCP Parallel, MCP Aggregator, MCP Fallback, MCP Retry, MCP Rate Limiter, MCP Cache, MCP Approval, MCP Audit Log
Formation (12)Parcours pédagogique, Vidéo, Image, Note audio, Quiz, Formulaire, Leçon, Carte, Carrousel, Rendez-vous
MCP Connectors EU (19)Un nœud par service (Odoo, n8n, Matomo, Nextcloud, entre autres)
MCP Security (6)Chiffrement, Sécurité FHE, Post-quantique, ZKP, SMPC, Audit SIEM
MCP Storage EU (5), MCP AI EU (3), MCP Data Processing (2), MCP Utilities (2)Briques internes de l'agent
Playbook (4)Say, Ask, Goto, Handoff

Deux précisions :

  • le nœud « MCP FHE Processor » et le nœud « MCP FHE Security » ne font pas de chiffrement homomorphe. Ils déchiffrent, calculent et rechiffrent en AES-256-GCM côté serveur. Le catalogue le dit lui-même ;
  • le nœud « MCP LLM » appelle un modèle de langage local (voir Fournisseurs de modèles). Son modèle par défaut est ministral-3:3b, modifiable dans ses propriétés. Le fournisseur refuse un modèle hors du périmètre souverain (voir Chat pour le modèle du chat).

Versioning

La page liste vos workflows avec leur type, leur état (déployé ou brouillon) et leurs dates de création et de mise à jour. Elle n'enregistre pas d'historique de versions et n'a pas de numéro de version : le serveur n'en garde aucun.

Exécutions

Le tableau a cinq colonnes : Statut, Gateway, Entrée, Durée, Date. Une recherche filtre la liste. Ouvrir une ligne montre le déroulé du graphe : pour chaque nœud, OK ou ECHEC, son nom et l'erreur éventuelle.

Connexion aux services

Les workflows appellent vos services par les connecteurs MCP (identifiants : Sécurité et identifiants). Le dépôt décrit 195 connecteurs (fichiers connectors/*.yaml). Tous ne sont pas déployés : un connecteur n'est dit « opérationnel » que s'il a été prouvé avec des données réelles. Voir la liste des connecteurs.

Pages annoncées, non disponibles

Les adresses /workflows/folders, /workflows/tags, /workflows/notes et /workflows/sharing affichent « Fonctionnalité v2.1 » : le dossier, l'étiquette, la note et le partage par workflow sont planifiés pour la v2.1. D'ici là, les droits se règlent au niveau de l'espace de travail (voir Paramètres).

Voir aussi

Chat

La page Chat (/chat) est l'endroit où vous parlez à un de vos workflows déployés. Il faut d'abord en avoir créé un : voir l'étape 6 de la prise en main guidée.

Une page, trois onglets

La page /chat porte trois onglets. Chacun a aussi sa propre adresse.

OngletAdresse directeContenu
Gateway Chat/chatLa conversation, avec la liste de vos conversations à gauche
Historique/chat-historyLes conversations passées
Messages Proactifs/proactive-messagesLes règles de messages proposés au visiteur

Gateway Chat

  • Choix du workflow : un sélecteur en haut choisit le workflow qui répond.
  • Liste des conversations : nouvelle conversation, recherche, favoris, dossiers, renommer, dupliquer, supprimer. Les favoris, dossiers et noms sont gardés dans votre navigateur.
  • Saisie : texte, ou micro pour dicter (la reconnaissance vocale est décrite dans Voix et Canaux).
  • Outils utilisés : quand l'agent appelle un outil, la réponse l'indique.
  • Export : une conversation s'exporte en JSON ou en Markdown.
  • Serveurs MCP : le menu du sélecteur propose six serveurs à activer ou non (Odoo, n8n, Matomo, un agenda, CryptPad, Jitsi).

Comment une réponse est produite

  1. Le routeur déterministe (EntityRouter) analyse votre message. Quand sa confiance atteint 0,80 ou plus, il appelle l'outil lui-même et formate le résultat. Aucun modèle de langage ne décide dans ce cas.
  2. Sinon, la question passe au modèle de langage local.
  3. Un outil irréversible ne s'exécute pas seul : le chat crée une demande d'approbation, qu'un humain décide ensuite.

Quel modèle

RôleModèleRemarque
DéfautEuroLLM 1.7B (q8), via Ollama, en localModèle européen.
Secoursministral-3:3b (Mistral AI, France), en localPrend le relais si le défaut échoue. L'administrateur peut le changer.
Choix du clientUn identifiant LLM enregistré dans votre espaceIl a la priorité sur le défaut, à une condition : son point d'accès doit être local ou européen (adresse locale, nom de domaine en .eu, ou fournisseur européen connu). Sinon l'appel est refusé avant l'envoi du message et le chat bascule sur EuroLLM. L'événement llm_provider_non_eu est tout de même inscrit au journal d'audit.

Le choix des outils, lui, reste celui du routeur déterministe. Pour brancher un autre fournisseur, voir Fournisseurs de modèles.

Contrôles de réponse

Un moteur anti-hallucination existe (validation multicouche, recherche de sources). Il démarre seulement si la recherche vectorielle (Connaissances) et Ollama sont disponibles. Le moteur de vérification factuelle « GroundingEngine » est dans le code mais n'est pas branché : /mgaas/engines le déclare « dormant ». N'attendez donc pas une vérification factuelle automatique de chaque réponse.

Historique

La page liste vos conversations et leurs messages. Elle sert aussi de page seule (/chat-history).

Messages proactifs

La page permet de créer, activer, modifier et supprimer des règles. Une règle porte un déclencheur (temps passé sur la page, profondeur de défilement, intention de sortie, inactivité, page visitée, horaire), une audience et un workflow. Le déclenchement côté visiteur n'est pas couvert par ce chapitre.

Voir aussi

Connaissances

La section Connaissances regroupe ce que votre agent peut retrouver : collections de documents, fichiers, outils personnalisés, wiki. Le principe du RAG est défini dans le Glossaire. Aujourd'hui, l'application affiche et gère les collections ; l'ajout de documents depuis l'interface n'est pas encore branché (détail plus bas).

Les pages

PageAdresseRôleÉtat
Collections/document-storesVos bases de connaissancesCréation, modification, duplication, suppression en service
Outils/toolsOutils personnalisés de l'agentCréation, modification, suppression en service
Vecteurs/vectorsCollections de la base vectorielleRéservée à l'opérateur de la plateforme (voir plus bas)
Fichiers/filesFichiers de votre espaceListe et suppression (l'envoi est prévu, voir plus bas)
Intents & NLU/intentsIntentions et entitésPage présente (non détaillée ici)
Wiki LLM/wikiÉtat de la synchronisation du wikiVoir plus bas
Médiathèque/mediathequeMédias par disciplinePage présente (non détaillée ici)
Formulaire pré-chat/pre-startFormulaire avant la conversationPage présente (non détaillée ici)

Les plans Essentiel n'affichent que Collections et Fichiers. Les autres pages apparaissent à partir du plan Starter (voir Tarification et offres).

Collections

La page liste vos collections avec quatre compteurs (collections, documents, morceaux, synchronisées). Une collection se crée, se modifie, se duplique, se supprime. Supprimer demande de retaper le nom.

Ouvrir une collection mène à /document-stores/<id>, une page à quatre onglets : Documents, Configuration, Preview, Vector Store. Cette page de détail est aujourd'hui une coquille avec des données d'exemple. Le bouton d'ajout de document propose cinq onglets (Fichier, URL, Sitemap, Table, Configuration), mais son envoi n'est pas branché.

Ce que l'API ne fait pas encore

Ces appels de l'API (Routes des ressources) répondent 503 FEATURE_PENDING : traiter un document (loader/process), l'envoyer par URL (loader/upload-url), l'envoyer en table (loader/upload-table), supprimer ou remplacer un document d'une collection.

Formats de fichier

FormatÉtat
Texte, Markdown, CSV, JSON, HTML, journauxLa fonction d'analyse du code (kb_parse.rs) les lit comme du texte
PDF, DOCX, XLSX, PPTXLa même fonction les refuse explicitement : l'analyse de ces formats n'est pas branchée
Pages web, sitemapsRoutes d'exploration présentes (scrape/page, scrape/sitemap, crawl)

Aucune route de l'API n'appelle encore cette fonction d'analyse : l'ingestion actuelle reçoit du texte déjà extrait (/rag/ingest). L'analyse des PDF et des documents Office est prévue : spec 115, tâches T-115-22 (admission des fichiers), T-115-23 (envoi), T-115-25 (branchement de l'analyse). Le crate d'extraction documentaire est en cours de livraison (T-115-31) ; il n'est pas branché sur l'API.

En attendant, l'API sait indexer un texte déjà extrait : voir « Indexer un texte » dans Routes des ressources.

Pipeline d'indexation

  1. Le texte est extrait.
  2. Il est découpé en morceaux. Le service de découpage intelligent propose cinq techniques, dont certaines appellent le modèle local ministral-3:3b.
  3. Chaque morceau reçoit un vecteur de 384 dimensions, calculé en local par paraphrase-multilingual-MiniLM-L12-v2 (fastembed, licence Apache-2.0 ; voir Fournisseurs de modèles).
  4. Les vecteurs sont rangés dans Qdrant (variables dans Variables d'environnement), dans des collections préfixées par l'identifiant de l'organisation. Ce cloisonnement est décrit dans Architecture Chatbotaurus.

Le suivi de progression en temps réel d'une ingestion n'est pas couvert par la page de détail actuelle.

Vecteurs

La liste des collections Qdrant est une vue de plateforme : elle exige une élévation d'opérateur et répond 403 sinon. La page décode un tableau alors que l'API rend un objet (engine, collections, total_vectors) : la liste ne s'affiche pas correctement. Les routes de lecture des enregistrements, de recherche et de synchronisation par collection (/vectors/<id>/...) n'existent pas dans l'API. Cette page est donc, pour un client, une page annoncée et non utilisable.

Fichiers

La page liste les fichiers de l'espace et permet d'en supprimer. L'envoi de fichiers depuis l'application, avec contrôle et chiffrement, est prévu : T-115-23 et T-115-24.

Outils

Un outil personnalisé a un nom, une couleur, une description, un schéma d'entrée (JSON Schema) et un corps de fonction. La page enregistre ces champs dans votre espace. L'exécution du corps de fonction par l'agent n'est pas couverte par ce chapitre.

Wiki LLM

Le wiki est un arbre de pages Markdown (format OKF : un fichier à en-tête type, l'identifiant est le chemin). Le serveur le lit depuis un dossier, un WebDAV ou un stockage S3. Aucun éditeur web n'est hébergé : on édite les fichiers dans le stockage. La page /wiki offre le bouton « Reindex now » et l'état de la synchronisation.

Voir aussi

Sécurité et identifiants

La section Sécurité gère les accès aux services externes et les accès à l'API. Elle apparaît dans le menu à partir du plan Business. Sur un plan inférieur, la limite porte sur le menu : voir la section Navigation du Tableau de bord.

Les pages

PageAdresseRôle
Conformité EU/compliance-dashboardMatrice de conformité (voir Analytique)
Identifiants/credentialsSecrets de connexion aux services externes
Variables/variablesValeurs réutilisables dans les workflows
Clés API/api-keysCréation et révocation de clés API (aucune route ne les accepte encore, voir plus bas)
Webhooks/webhooksAdresses notifiées, et réception des fournisseurs

Identifiants

Un identifiant contient les informations de connexion à un service (Odoo, n8n, Matomo, un fournisseur de paiement, entre autres). La page est un catalogue de cartes rangées en 21 catégories (IA, ERP/CRM, Automatisation, Paiements EU, Données EU, Sécurité, Connecteurs, entre autres). Chaque carte a ses propres champs. Les cartes OAuth portent un choix de portées et une durée de jeton.

Comment un secret est gardé

  • Il est chiffré en AES-256-GCM dans la base, avec une clé propre à chaque identifiant. La clé dérive d'une clé racine « au repos » (variable AT_REST_ENCRYPTION_KEY) distincte du secret de session quand elle est fournie. Sans elle, le secret de session sert de racine. Le détail des clés est dans Variables d'environnement.
  • La valeur en clair ne revient jamais dans une réponse de l'API : la liste montre un masque.
  • À la modification, la page recharge l'identifiant sans ses valeurs secrètes : chaque champ secret est remplacé par un marqueur avant d'entrer dans l'écran. Les champs secrets sont masqués, avec un bouton pour les afficher le temps de la saisie.
  • Un identifiant est lié à un espace de travail. Vous ne voyez que ceux de vos espaces.

Comment un connecteur le lit

Quand un connecteur appelle un service, le serveur déchiffre l'identifiant de l'organisation qui fait la requête, et d'elle seule. Ce mécanisme est décrit dans Conception des connecteurs MCP. Au démarrage, il peut aussi publier les identifiants d'un déploiement à locataire unique comme variables d'environnement.

OpenBao

OpenBao est optionnel. Une organisation peut y garder ses secrets de connecteurs : elle enregistre un identifiant d'AppRole nommé openbaoAppRole. Le serveur lit alors ses secrets dans le coffre, avec la priorité sur ceux de la base. Sans cet identifiant, OpenBao n'est jamais contacté. La carte « OpenBao Secrets » du catalogue sert à un client qui apporte sa propre instance à un connecteur.

Variables

La page a cinq onglets : Toutes, Système, Capture, Statiques, Runtime. Les variables système sont remplies par la plateforme et ne se modifient pas. Une valeur se masque et s'affiche d'un clic. On crée et on modifie les autres. Elles se consomment dans les workflows ; les routes correspondantes sont dans Routes des ressources.

Clés API

Une clé API se crée et se gère depuis cette page ; à ce jour aucune route de l'API ne l'accepte à la place du jeton de session (l'extracteur existe dans le code, sans route consommatrice) : un appel programmatique passe par le jeton obtenu à la connexion, décrit dans Swagger. Le formulaire demande un nom et un espace de travail. La page montre la clé une seule fois à la création, puis, dans la liste, un extrait (8 premiers et 4 derniers caractères) jusqu'au rechargement de la page, et ensuite ****. Supprimer une clé la révoque. L'extracteur prévu à cet effet attend l'en-tête X-Api-Key. Voir aussi Documentation Swagger pour l'authentification de l'API.

La clé est gardée sous forme hachée. La page n'offre ni choix de portées, ni rotation automatique.

Webhooks

La page permet de créer un webhook (nom, adresse, événements parmi 12), de l'activer, de le modifier, de le supprimer et d'envoyer un test. Les 12 événements proposés : conversation démarrée ou terminée, message reçu ou envoyé, intention détectée, transfert demandé, prospect créé, workflow démarré, terminé ou échoué, appel démarré ou terminé.

Ce qui est branché, ce qui ne l'est pas :

  • Envoi de test : réel. Le serveur appelle l'adresse (avec un filtre contre les adresses internes) et note la date.
  • Émission automatique des événements : non branchée. Le code qui lit la table des webhooks se limite à la gestion et à l'envoi de test.
  • Livraisons récentes : aucun journal de livraison n'est enregistré.
  • Régénérer le secret : répond 503 FEATURE_PENDING.

En sens inverse, le serveur reçoit les notifications de fournisseurs : paiement (Mollie, PayPlag, Adyen, Stripe, Lyra, SlimPay, Wero), LiveKit, et une entrée générique. Seul Mollie sert à la facturation de la plateforme (voir Tarification) ; les autres routes de paiement existent dans le code.

Voir aussi

MCP et Orchestrateur

La section « Écosystème MCP » regroupe l'assistant qui construit vos workflows et les catalogues de serveurs MCP.

Les pages

PageAdresseRôle
Orchestrateur/orchestratorAssistant qui construit un workflow avec vous
Gateway Business/mcp/gateways/businessUne carte par métier
Marketplace/marketplaceModèles de workflow à déployer
Console Admin MCP/mcp/adminInventaire des services (voir l'état, plus bas)
Gateway Projet UE/mcp/gateways/projet-ueCatalogues de données européennes
Serveurs MCP Business/mcp/servers/businessCatalogue de serveurs métier
Serveurs MCP Projet UE/mcp/servers/projet-ueServeurs des catalogues européens
Démo Crypto/crypto-demoSimulation pédagogique

Selon votre plan (voir Tarification et offres), le menu montre les trois premières pages seulement (Orchestrateur, Gateway Business, Marketplace). Les cinq autres apparaissent aux plans Enterprise et Souverain. Les anciennes adresses (/mcp-admin, /mcp-servers-business, /mcp-gateway-business) redirigent vers les adresses du tableau.

Orchestrateur

L'Orchestrateur ouvre sur deux cartes :

  • « Déployer les outils de votre métier » : vous choisissez un ou plusieurs métiers, puis l'assistant prépare l'ensemble ;
  • « Déployer un parcours support (pédagogique) » : un parcours pour accompagner une personne (explications, vidéos, exercices, questions).

Puis une conversation s'ouvre. Elle est portée par une session de l'API (/orchestrator/sessions). Une carte de progression montre cinq étapes :

  1. Accueil
  2. Secteur
  3. Template
  4. Validation (confirmation et identifiants)
  5. Déploiement (sauvegarde, puis ouverture du chat)

Le serveur utilise des noms de phase plus fins (coaching, discovery, identification, credentials, tels qu'ils sont écrits dans le code). L'écran les ramène à ces cinq étapes.

Gateway Business

La page montre 16 métiers (détaillés dans Cas d'usage par secteur) : thérapeute, consultant, mobilier, e-commerce, formation, juridique, immobilier, médical, logistique, industrie, agriculture, créatif, association, tourisme, RH, finance. Chaque carte donne le nombre de serveurs inclus par palier. Elle ouvre la page du métier (/mcp/gateways/business/<metier>).

Gateway Projet UE

La page présente 26 catalogues de serveurs MCP pour des données publiques européennes (par exemple CORDIS, OpenAIRE, Eurostat, EPO). Les 26 sont marqués « disponibles ». Les compteurs de la page (serveurs, endpoints, opérationnels) sont calculés depuis le catalogue, pas écrits à la main. Ces sources sont décrites dans API-as-a-Service EU souverain.

Serveurs MCP Business

Cette page est un catalogue de 175 cartes de connecteurs. Elle ne décrit pas votre infrastructure. Le même catalogue, lu par l'API, est dans parcourir le catalogue de services.

  • Une carte porte la mention « Déployé » seulement si le serveur figure à l'inventaire des serveurs prouvés : un outil de lecture y a rendu des données réelles. À la date du 2026-10-03, ce sont 30 serveurs sur 175. Les autres affichent « Bientôt disponible » (une seule carte affiche « Disponible » à cette date).
  • Le bouton « Déployer » (info-bulle « Déployer ce serveur et ouvrir son workflow ») crée un workflow pour ce serveur et ouvre l'éditeur. Sur une carte « Bientôt disponible », il est désactivé et se lit « En préparation ».
  • Vous pouvez chercher, filtrer par catégorie ou certification, et n'afficher que les serveurs déployés.

Ce qui n'est pas encore branché

Le cycle de vie des conteneurs n'est pas relié à l'API (le format des erreurs de l'API est dans Gestion des erreurs). Les appels suivants répondent 503 FEATURE_PENDING à un administrateur (un autre rôle reçoit 403) : déployer, démarrer, arrêter, redémarrer un serveur, enregistrer ses secrets, déployer un profil. La lecture du profil de sécurité répond 503 à tout rôle. L'analyse de sécurité Trivy avant déploiement n'est donc pas disponible depuis cette page. Les secrets de vos connecteurs se saisissent dans la page Sécurité et identifiants, pas par ces boutons.

Voir la référence API Catalogue Business.

Console Admin MCP

La console est prévue pour lister les services Podman (Core, MGaaS), leur santé, et pour lire leurs journaux. Elle n'est pas reliée à l'infrastructure : l'API rend une liste vide, la sonde de santé répond 503 FEATURE_PENDING, et la page affiche un bandeau qui signale que la console n'est pas câblée à l'infrastructure. Aucun chiffre n'est inventé. En attendant, un administrateur lit l'inventaire en ligne de commande avec podman ps (voir Gestion des conteneurs).

Démo Crypto

La page propose trois onglets : chiffrement homomorphe (FHE), preuve à divulgation nulle (ZKP), cryptographie post-quantique (PQC). Un bandeau « SIMULATION » le dit : la page calcule dans le navigateur, avec des entrées de démonstration. Elle ne protège aucune de vos données.

Marketplace

La page liste 93 modèles de workflow. Le bouton « Déployer » crée le workflow dans votre espace.

Voir aussi

Voix et Canaux

La section Canaux décrit comment votre agent atteint vos visiteurs : apparence du widget, voix, campagnes d'appels, numéros, messageries. Les plans cités ci-dessous sont décrits dans Tarification et offres.

Les pages

/channels ouvre une page unique. Ses cinq sections ont aussi chacune leur adresse.

SectionAdressePlan minimum dans le menu
Marque/channels/brandingPro
Voix/channels/voiceBusiness
Campagnes Voice/channels/voice-campaignsPro
Numéros EU/channels/phone-numbersBusiness
Intégrations/channels/integrationsPro (le plan Essentiel la trouve dans la section Déployer)

L'analytique des appels est une page de la section Analytique : /call-analytics. Les adresses /channels/whatsapp, /channels/telegram et /channels/sms mènent à la page Intégrations.

Marque (widget)

La page est un ensemble de huit sections repliables, suivies d'un aperçu :

  1. Titre et description de l'assistant
  2. Apparence et images
  3. Police, thème et couleurs
  4. Variantes d'interface
  5. Configuration des onglets
  6. Confidentialité et mentions
  7. Paramètres avancés
  8. Code widget et déploiement (voir aussi l'étape 7, « intégrer le chat à votre site », de la prise en main guidée)

Voix

La page a quatre onglets : reconnaissance vocale (STT), synthèse vocale (TTS), WebRTC, paramètres. Au-dessus, quatre cartes reprennent les statistiques d'appels.

BriqueMoteurHébergé
Reconnaissance vocaleFaster-Whisper (Large v3, Medium, Small)Dans la pile de l'application
Synthèse vocaleKokoro (v1, voix française, voix allemande)Dans la pile de l'application
Temps réelLiveKitDans la pile de l'application

Les boutons « Tester » de cette page sont désactivés. Le micro de la page Chat et de l'Orchestrateur utilise la même reconnaissance vocale.

Le code contient un pont téléphonique (LiveKit vers une ligne SIP européenne, avec une règle anti-fraude sur les destinations). Aucune page ne le pilote encore. Les variables de la chaîne vocale sont dans Variables d'environnement.

Campagnes Voice et Numéros EU

Ces deux pages sont annoncées mais non disponibles. Le bouton « Nouvelle campagne » et le bouton « Acheter un numéro » sont désactivés (« Bientôt disponible »). La page Numéros liste trois fournisseurs candidats ; elle ne gère aucun numéro.

Intégrations

La page a trois onglets : Canaux actifs, Ajouter un canal, Webhook URL. Les canaux « Via n8n » passent par le connecteur n8n.

CanalMode de connexionPlan minimum
TelegramDirectEssentiel
WhatsApp BusinessVia n8nPro
DiscordVia n8nPro
Messenger (Meta)Via n8nPro
WebRTCDirectBusiness

Deux écarts à connaître :

  • le formulaire de la page propose Telegram, Courriel (SMTP/IMAP), WhatsApp Business, Discord et Slack. L'API n'accepte que cinq genres : WhatsApp, Telegram, Discord, Messenger et WebRTC. Le courriel et Slack sont donc refusés à l'enregistrement, et Messenger et WebRTC n'ont pas encore de carte dans le formulaire ;
  • l'état de connexion affiche « Déconnecté » pour tous les canaux : aucune sonde de connexion n'existe, et la page ne montre pas un « Connecté » qu'elle ne peut pas mesurer.

Analytique des appels

La page /call-analytics liste les appels (30 derniers jours) et ouvre le détail d'un appel (transcription, coût, latence). Le service de statistiques d'appels rend le nombre d'appels, les appels terminés ou abandonnés et la durée moyenne. Les champs avancés (temps de réponse, sentiment, heures de pointe, intentions) sont renvoyés vides, faute de données stockées : la page n'invente pas de taux de résolution ni de satisfaction.

Voir aussi

Analytique

Les pages d'analytique et d'évaluation mesurent l'usage de votre agent et la qualité de ses réponses. Certaines mesures sont encore partielles : ce chapitre dit lesquelles.

Les pages

PageAdresseSection du menuPlan minimum
Analytique/analyticsAnalytiqueEssentiel (vue simple)
Historique Chat/chat-historyAnalytiqueEssentiel (vue simple)
Analytique Appels/call-analyticsAnalytiquePro
Leads / CRM/leadsAnalytiquePro
Lead Funnel/lead-funnelAnalytiquePro
Messages Proactifs/proactive-messagesAnalytiquePro
Logs App/logsAnalytiquePro
Logs Serveur/server-logsAnalytiquePro
Conformité EU/compliance-dashboardSécuritéBusiness
Datasets, Évaluateurs, Évaluations, A/B Testing/datasets, /evaluators, /evaluations, /ab-testingÉvaluationsEnterprise

Les plans Essentiel et Starter ont l'analytique simple : deux pages (Analytique et Historique Chat). Les plans sont décrits dans Tarification et offres.

Analytique 360

La page offre une période (24 heures, 7, 30 ou 90 jours), un filtre de canal (Tous, Web, WhatsApp, Telegram, Voix ; voir Voix et Canaux) et quinze onglets. Le filtre de canal n'est pas transmis à l'API : il ne change aucun chiffre aujourd'hui.

Un seul onglet est branché : Vue d'ensemble. Les quatorze autres affichent « Section en cours de portage V1 » (Interactions, Performance, Outils MCP, Gateways, Ollama / LLM, Voix, Base de connaissances, Workflows, Infrastructure, Sécurité / Crypto, Protocole MCP, Leads / CRM, Conformité EU, Anti-Hallucination).

Dans la Vue d'ensemble :

CarteSource
Conversations totales, Messages envoyésMesures de l'API
Taux de résolution (cible > 85 %)Mesure de l'API quand elle existe, sinon un tiret
Temps de réponse moyen (cible < 2000 ms)Mesure de l'API quand elle existe, sinon un tiret
Satisfaction, Taux d'abandon (cible < 8 %)Pas de source : un tiret
Appels outils MCP, Minutes vocales, Ops cryptoPas de source : zéro fixe
Score Gaia-X, Anti-hallucination (cible < 3 %)Pas de source : un tiret

Les graphiques (conversations par jour, messages par heure, répartition par canal) n'ont pas encore de données et s'affichent vides. Le bouton d'export est désactivé. Un zéro ou un tiret sur cette page ne signifie donc pas « rien ne s'est passé » : cela peut signifier « non mesuré ».

Les cibles affichées (résolution, temps de réponse, abandon, hallucination) sont des objectifs de la page, pas des résultats mesurés.

Leads / CRM

La page suit les prospects de votre espace :

  • liste avec recherche et filtre de statut, ou tableau en colonnes (nouveau, contacté, qualifié, proposition, négociation) ;
  • création, modification, suppression d'un prospect ;
  • quatre compteurs de synthèse ;
  • une liste des prospects venus des formulaires publics du site (contact, lettre d'information).

La page ne crée pas de prospect à partir de l'Orchestrateur.

Lead Funnel

La page affiche cinq paliers de score (Cold, Engaged, Qualified, Hot, Highly Qualified). Les compteurs y sont à zéro : la page est une base d'éditeur, pas encore une mesure.

Journaux

  • Logs App (/logs) : les 50 derniers événements du serveur, lus en mémoire. L'historique long via VictoriaLogs est annoncé pour plus tard (voir Journaux pour les journaux côté serveur).
  • Logs Serveur (/server-logs) : filtre par niveau et par recherche sur les dernières 24 heures, pause, effacement, export, rafraîchissement.

Conformité EU

La page affiche une matrice par référentiel : RGPD, NIS2, EUCS, Gaia-X, eIDAS, avec un score, des vérifications réussies, en alerte ou en échec, et un filtre. Le rapport vient de l'API (/compliance/report). Ce rapport est une auto-évaluation déclarative, pas un audit indépendant ; chaque vérification porte sa base (« self-declared » ou « measured »). Si l'API ne répond pas, la page affiche un rapport local fixe à la place.

Voir le chapitre Conformité RGPD.

Évaluations

Réservées aux plans Enterprise et Souverain.

  1. Datasets : importez un fichier CSV de questions et de réponses attendues.
  2. Évaluateurs : créez un évaluateur de l'un de ces types : personnalisé, juge LLM, similarité, expression régulière.
  3. Évaluations : lancez une évaluation en choisissant un workflow, un dataset et un ou plusieurs évaluateurs. Le détail d'une évaluation a sa page (/evaluations/<id>).
  4. A/B Testing : comparez des variantes de prompt.

Les mesures de précision, de rappel ou de F1 ne figurent pas parmi les types d'évaluateur.

Voir aussi

  • Voix et Canaux : apparence du widget, voix, campagnes d'appels, numéros, messageries
  • Workflows : l'éditeur, la palette de nœuds, les exécutions
  • Chat : l'historique et les messages proactifs vus depuis la page Chat
  • Supervision : les métriques et points de santé côté exploitation
  • Journaux : où le backend écrit, et l'export vers VictoriaLogs
  • Conformité RGPD : le fond du référentiel que la matrice auto-évalue

Paramètres

Ce chapitre couvre la section Paramètres (réglages, facturation, compte) et la section Gestion (utilisateurs, rôles, SSO, connexions). Les espaces de travail vivent dans la section Agence. Les plans minimums du tableau sont ceux de Tarification et offres.

Les pages

PageAdresseSection du menuPlan minimum
Paramètres/settingsParamètresTous
Facturation/billingParamètresTous
Compte/accountParamètresTous
Utilisateurs/usersGestionBusiness
Rôles/rolesGestionBusiness
Config SSO/sso-configGestionBusiness
Activité Connexion/login-activityGestionBusiness
Observabilité/observabilityGestionBusiness
Espaces de Travail/workspacesAgenceEnterprise

La page des tarifs (/pricing) est une page publique du site, pas une page de l'application. Pour gérer votre abonnement, utilisez Facturation.

Paramètres

La page a trois onglets : Général, Fonctionnalités, Accès rapides.

  • Général : six champs (nom du site, adresse du site, courriel de support, taille maximale de fichier, délai de session, langue par défaut).
  • Fonctionnalités : neuf interrupteurs (réponses en flux continu, envoi de fichiers, entrée vocale, tableau de bord analytique, interface générative, multi-locataire, SSO, journaux d'audit, limitation de débit).
  • Accès rapides : huit raccourcis vers d'autres pages (apparence, sécurité, clés API, entre autres).

Limite actuelle : le bouton Enregistrer envoie les six champs et les neuf interrupteurs sous les clés generalSettings et featureFlags. L'API de cette page ne lit que timezone et language, que la page n'envoie pas : rien n'est enregistré depuis cette page. Le fuseau horaire et la langue de l'utilisateur se règlent dans Compte, qui les enregistre.

Compte

La page porte le profil, le mot de passe, la double authentification, les notifications, l'export de vos données et la suppression du compte (voir Conformité RGPD pour l'exercice des droits). Les langues proposées sont le français, l'anglais, le néerlandais et l'allemand. Seuls le français et l'anglais ont une interface complète (1 610 clés au 2026-10-03) : le néerlandais et l'allemand n'ont que 26 clés traduites, le reste s'affiche en français.

Double authentification

Après le mot de passe, la connexion demande un second facteur : un code envoyé par courriel, ou le code d'une application d'authentification (TOTP) si vous l'avez activée dans Compte. L'administrateur du déploiement peut exiger le TOTP pour tous les comptes, ou pour des rôles choisis. Cette exigence est une option de configuration du serveur, pas une règle fixe par rôle (voir Variables d'environnement).

Utilisateurs et rôles

La page Utilisateurs liste les comptes de votre organisation, avec leur état, et permet de les modifier. Le bouton « Ajouter un utilisateur » crée un compte à partir d'un courriel, d'un nom, d'un rôle et d'un statut. La page Rôles liste les rôles de votre organisation, en crée et en supprime.

Les rôles ne sont pas une liste fixe : chaque organisation définit les siens. Le moteur de politiques est décrit dans Architecture de confiance zéro. Une permission s'écrit ressource:action (par exemple credentials:view). Le catalogue compte 88 permissions en 18 catégories, parmi lesquelles mcpgateways, mcpgatewayflows, tools, credentials, variables, apikeys, documentStores, datasets, executions, evaluators, evaluations, workspace, logs. Le joker * donne tous les droits. Il n'existe pas de permission workflows:view : les workflows relèvent de mcpgateways et mcpgatewayflows.

Les pages d'administration /admin* sont réservées aux rôles admin, superadmin, super_admin et owner. Tout autre rôle, ou un rôle inconnu, voit un écran « accès réservé ».

Espaces de travail

Un espace de travail regroupe des workflows, identifiants et historiques. La page /workspaces liste, crée et modifie les espaces de votre organisation. Les données sont cloisonnées par organisation (voir Architecture Chatbotaurus). OpenBao n'intervient que si votre organisation a choisi cette option (voir Sécurité et identifiants).

SSO

La page Config SSO a trois onglets : configuration, fournisseurs, sessions. La configuration Authentik demande un identifiant court (slug), un identifiant client et l'adresse du serveur d'authentification. Deux interrupteurs activent le SSO et la création automatique des utilisateurs. L'onglet sessions permet de terminer une session. Le bouton « Ajouter un provider » (SAML, LDAP) est désactivé : l'ajout de fournisseurs supplémentaires est en cours d'intégration côté serveur.

Voir le guide SSO Authentik.

Activité de connexion

Le tableau liste, pour chaque connexion : l'utilisateur, le statut, l'adresse IP, la localisation, l'appareil et l'heure. Il offre des filtres de recherche, de statut et de dates, une alerte quand des connexions suspectes sont détectées, et un export CSV. Les limiteurs de connexion sont décrits dans Sécurité.

Voir aussi

Conseils

Une page de conseils courts, tous vérifiables dans le produit ou dans le code.

Parlez en langage naturel

Il n'y a pas de syntaxe spéciale. Décrivez la tâche comme à un collègue : Chatbotaurus choisit l'outil du connecteur qui y répond. Plus la demande nomme l'objet (un client, une facture, un rendez-vous), plus le choix de l'outil est sûr.

Étendez avec des connecteurs

Chatbotaurus parle le protocole MCP. Chaque service métier est un connecteur décrit par un fichier connectors/<id>.yaml. Le dépôt en contient 195 (mesure du 2026-10-03 : ls connectors/*.yaml | wc -l). Le chapitre Vue d'ensemble des connecteurs présente le catalogue. Pour en écrire un, voir Fichiers de configuration.

Les modèles tournent chez vous

L'inférence passe par Ollama, sur votre infrastructure. La liste des modèles retenus est fixée dans crates/forge-core/src/model_governance.rs :

RôleModèle
Traduction (rôle Main du code, jamais d'appel d'outil)cas/eurollm-1.7b-instruct-q8
Génération : repli et défaut de OLLAMA_MODELministral-3:3b
Embeddings (calculés en local par fastembed)paraphrase-multilingual-MiniLM-L12-v2 (vecteurs de 384 dimensions)

Changer cette liste est une décision de souveraineté, pas un réglage : elle se modifie avec une justification de licence. Le modèle de génération se choisit avec OLLAMA_MODEL et le modèle d'embeddings du pipeline RAG avec EMBEDDING_MODEL (voir Variables d'environnement).

Gardez les sessions courtes

Une conversation longue remplit la fenêtre de contexte du modèle, et les réponses perdent en précision. Si elles deviennent moins pertinentes, ouvrez une nouvelle conversation. C'est un conseil d'usage, pas une mesure de ce dépôt.

Itérez sur vos demandes

Vous n'avez pas à trouver la bonne formulation du premier coup. Reformulez, précisez l'objet, relancez.

Profils du catalogue

Le catalogue regroupe ses serveurs en quatre profils :

ProfilContenu
solo1 serveur : Odoo
starter5 serveurs
business12 serveurs
enterprisetous les serveurs du catalogue

GET /api/v1/mcp/catalog-business/profiles les liste. La route POST /api/v1/mcp/catalog-business/profiles/{name}/deploy existe, mais elle répond aujourd'hui 503 FEATURE_PENDING : le pilotage de Podman par le backend n'est pas branché, elle ne déploie rien. Le tutoriel Parcourir le catalogue de services et préparer un déploiement explique ce qui marche et ce qui est en sommeil.

Protégez vos données

  • Les points d'accès de la voix doivent être dans l'UE : le code refuse les autres (validate_eu_endpoint, crates/forge-voice/src/stt.rs).
  • Le registre des connecteurs rejette un connecteur dont les données ne restent pas dans l'UE ou chez vous.
  • Aucun secret n'est stocké dans les manifestes de connecteurs : ils lisent l'environnement.
  • Les journaux masquent clés, jetons et adresses e-mail avant écriture.

Détails et limites : Sécurité.

Surveillez

Sondez GET /api/v1/readyz depuis votre supervision. Le chapitre Supervision dit ce qui est mesuré aujourd'hui et ce qui ne l'est pas encore.

Mettez à jour avec méthode

Si vous disposez des sources sous licence : récupérez les changements, puis reconstruisez le workspace.

git pull
cargo build --workspace --release

En développement, dx serve (lancé depuis crates/forge-ui) recharge le frontend à chaque modification. Le backend se redémarre.

Voir aussi

Connecteurs MCP

Un connecteur est un fichier YAML du dossier connectors/ du dépôt. Il déclare un service, sa méthode d'authentification, sa licence et la liste des outils que l'agent peut appeler. Ce chapitre donne les chiffres mesurés le 2026-10-03 et renvoie vers les douze connecteurs décrits dans ce livre.

Ce qui est mesuré

QuoiValeurComment c'est mesuré
Fichiers de connecteurs195ls connectors/*.yaml (dont TEMPLATE.yaml, le gabarit, que le chargeur saute)
Entrées du catalogue métier108catalog-business.json, nombre d'entrées
Entrées au statut available15même fichier, champ status
Entrées au statut coming-soon93même fichier, champ status
Services mcp-* du plan client43container_name: mcp- dans podman-compose.vps2.yml

Les trois premiers chiffres sont aussi ceux du site public. Ils viennent de crates/forge-ui/src/config/chiffres_mesures.rs, fichier généré, daté du 2026-10-03.

Le nombre de fichiers (195) et le nombre d'entrées du catalogue (108) ne se recouvrent pas. Douze entrées du catalogue n'ont pas de fiche YAML : collabora, faster-whisper, gnuhealth, logseq, mywms, openmom, pgadmin, postgresql, property-base, timescaledb, valkey et une entrée de détection d'intrusion. À l'inverse, 99 fichiers YAML n'ont pas d'entrée au catalogue (gabarit compris).

Un connecteur du catalogue au statut coming-soon est annoncé, pas ouvert. Le statut est une donnée du catalogue, il ne dit rien de l'état du fichier YAML.

Comment un connecteur est chargé

Au démarrage, forge-api lit le dossier connectors/, remplace les variables ${VAR:-défaut} par l'environnement, puis enregistre un connecteur par fichier. Le moteur HTTP sert les fichiers à authentification HTTP. Le connecteur odoo a son propre client XML-RPC. Le connecteur calrs passe par une commande dans un conteneur (voir CalRS). Source : connectors/README.md et crates/forge-mcp/src/connector/catalogue.rs.

Dans tools/list, le nom d'un outil des connecteurs HTTP est préfixé par l'identifiant du connecteur : l'outil get_visits du fichier matomo.yaml s'appelle matomo.get_visits (moteur HTTP des connecteurs). Les chapitres suivants donnent les noms tels qu'ils sont écrits dans les fichiers, sans ce préfixe.

Chaque connecteur déclare sa conformité. Le registre le refuse si gdpr_compliant vaut false ou si data_residency n'appartient pas à la liste eu, eu-west, eu-central, france, germany, finland, netherlands, ireland, self-hosted (connectors/README.md, section « Gate EU / Gaia-X »). Cette règle porte sur ce que le fichier déclare. Elle ne prouve pas où tourne l'instance du client.

Une seconde règle décide du dispatch : seuls les identifiants de la liste ALLOWED_MCP_SERVERS (liste des serveurs autorisés du code) sont exécutés, et tools/list n'affiche que leurs outils. Mesuré le 2026-10-03 : sur les 194 fichiers hors gabarit, 98 sont dans cette liste et 96 n'y sont pas. dolibarr et freescout font partie des 96 (un test du dépôt le verrouille) : leur fiche se charge, leurs outils ne sont pas appelables tant que l'identifiant n'est pas ajouté à la liste.

Authentification

Types d'authentification présents dans les 195 fichiers, mesurés le 2026-10-03 : aucune (73), bearer (52), clé d'API en en-tête (33), basic (20), jeton de connexion (5), jeton en paramètre d'URL (4), oauth2 (3), et quelques cas particuliers. Deux fichiers (odoo, calrs) n'ont pas de bloc auth parce que leur transport n'est pas HTTP.

Les chapitres suivants nomment les variables que chaque fichier lit. Côté locataire, les valeurs sont saisies comme identifiants de la plateforme et stockées chiffrées en base. OpenBao est un mode optionnel : une organisation qui y a enregistré son AppRole voit ses secrets lus depuis OpenBao en priorité. Sans cet AppRole, OpenBao n'est jamais contacté (résolution des identifiants du code).

Les douze connecteurs décrits ici

Compte d'outils mesuré dans chaque YAML le 2026-10-03. Pour odoo, le YAML ne déclare que 6 outils ; les 711 outils nommés vivent dans le registre Rust.

ConnecteurOutilsLecture seuleAuthentificationStatut au catalogueService dans le plan clientAutorisé au dispatch
Authentik442ouibeareravailablenonoui
CalRS7sans objetaucune (commande dans le conteneur)availableouioui
Dolibarr263ouiclé en en-têtecoming-soonnonnon
Forgejo482nonbearercoming-soonoui, pour le poste de développementoui
FreeScout15ouiclé en en-têtecoming-soonnonnon
Listmonk76nonbasiccoming-soonouioui
Matomo113ouijeton en paramètreavailableouioui
n8n49nonclé en en-têteavailableouioui
Nextcloud167nonbasicavailablenonoui
Odoo711 (registre)nonXML-RPCavailableoui, 17 servicesoui
Rocket.Chat338nonclé en en-tête et identifiantcoming-soonnonoui
Typesense79nonclé en en-têtecoming-soonouioui

« Lecture seule » veut dire que tous les outils du YAML utilisent la méthode GET. « Service dans le plan client » veut dire qu'un container_name: mcp-… existe dans podman-compose.vps2.yml. Une réponse « non » ne dit pas que le service est inutilisable : le client peut apporter sa propre instance. « Autorisé au dispatch » veut dire que l'identifiant figure dans ALLOWED_MCP_SERVERS.

Les outils d'écriture sont classés par leur nom (classification de sécurité des outils, dans le code). Un nom qui porte drop, truncate, erase, purge, wipe, ou qui se termine par unlink ou destroy, n'est jamais exécuté par l'agent. Un nom qui porte delete, cancel, refund, pay, charge, transfer, remove ou revoke n'est exécuté qu'après une autorisation humaine explicite. Les outils create, update et send passent sans cette étape. Les chapitres qui suivent écrivent « supprime » pour ce que le fichier déclare ; ce que l'agent exécute seul est plus étroit.

Le catalogue métier

Le catalogue est servi par l'API sous /api/v1/mcp/catalog-business, pour un utilisateur authentifié. GET /api/v1/mcp/catalog-business renvoie les 108 entrées embarquées dans le binaire, avec un filtre optionnel par catégorie. GET /api/v1/mcp/catalog-business/{id}/registry-tools liste les outils que le registre connaît pour un connecteur. Les routes de cycle de vie (déployer, démarrer, arrêter, secrets) répondent encore 503 avec le marqueur feature_pending : l'adaptateur Podman n'est pas branché (crates/forge-api/src/routes/mcp_catalog_business.rs, commentaire de tête).

Les entrées sont rangées en 34 catégories. Par taille décroissante, au 2026-10-03 : Communication (7 entrées), puis CRM & ERP, DevOps, Monitoring et Database (5 entrées chacune).

Les connecteurs de données publiques de l'UE

Dix-huit fichiers portent un nom de secteur : agriculture, culture, cybersecurity, education, employment, energy, environment, fintech, foodsafety, governance, innovation, industry, legaltech, maritime, sme, health, spatial, quantum. Chacun interroge le portail de données ouvertes de l'UE, sans authentification, avec 28 à 30 outils. Un dix-neuvième, broadcast, est un connecteur à jeton avec 2 outils.

Utiliser un connecteur

  1. Vérifiez dans le tableau ci-dessus que la colonne « Autorisé au dispatch » vaut « oui » : sinon les outils ne sont pas appelables.
  2. Ayez une instance du service : la vôtre, ou celle du plan client si la colonne « Service dans le plan client » vaut « oui ».
  3. Enregistrez les identifiants : page Identifiants (/credentials) de l'application, fiche du connecteur. Le chapitre du connecteur donne le nom de la fiche et ses champs (CalRS n'a rien à saisir). Connecter Odoo à la passerelle MCP déroule ce parcours de bout en bout.
  4. Posez la question dans le chat, ou appelez l'outil par tools/call (Routes MCP).

Ajouter un connecteur

Le tutoriel Créer votre premier connecteur MCP décrit la forme d'un fichier YAML.

Voir aussi

Connecteur Authentik

Connecteur Authentik

Authentik est un fournisseur d'identité (SSO, OIDC, SAML, LDAP). Le connecteur lit l'API REST v3 d'une instance Authentik. Il est en lecture seule : aucun de ses outils ne crée, ne modifie ni ne supprime quoi que ce soit.

Mesuré le 2026-10-03 dans connectors/authentik.yaml : 442 outils, tous en méthode GET.

Ce que déclare le fichier

PropriétéValeur
Fichierconnectors/authentik.yaml
ProtocoleAPI REST, chemins sous /api/v3/
Authentificationjeton Authorization: Bearer, lu dans AUTHENTIK_API_KEY
Adresse de l'instancevariable AUTHENTIK_URL
Licence déclaréeMIT
Résidence déclaréeauto-hébergé

Outils

Les noms d'outils sont de la forme authentik_<ressource>_<action>. Exemples réels : authentik_users_list, authentik_users_get, authentik_groups_list, authentik_applications_list, authentik_applications_check_access.

Répartition par préfixe de nom, mesurée sur les 442 outils :

PréfixeOutilsPréfixeOutils
stages80events17
sources61flows12
providers56rbac11
propertymappings45admin9
policies33oauth29
authenticators32enterprise, rac6 chacun
core23crypto5
outposts21applications, managed4 chacun

Les 8 autres outils se répartissent entre users et groups (2 chacun) et quatre ressources isolées (brands, root, schema, property, 1 chacune).

Les ressources users et groups n'ont chacune que deux outils : lister et lire. Il n'existe pas d'outil authentik_create_user ou authentik_delete_user.

Configuration

VariableRôle
AUTHENTIK_URLAdresse de l'instance Authentik à interroger
AUTHENTIK_API_KEYJeton d'API (porté en en-tête Bearer)

Les valeurs se saisissent comme identifiants de la plateforme : page Identifiants (/credentials), fiche Authentik IAM, champs « URL du serveur » et « API Token » (ce dernier alimente AUTHENTIK_API_KEY). Le délai d'attente déclaré par le fichier est de 30 000 ms.

Déploiement

Le fichier compose du plan backend (podman-compose.yml) déploie un service Authentik pour l'authentification de la plateforme. Le fichier du plan client (podman-compose.vps2.yml) ne contient aucun service Authentik. Le connecteur ne dépend pas de ce service : il vise l'instance désignée par AUTHENTIK_URL.

Cas d'usage

  • Lister les utilisateurs, groupes et applications d'une instance.
  • Vérifier l'accès d'un utilisateur à une application (authentik_applications_check_access).
  • Consulter les flux, fournisseurs, politiques et événements pour un audit.

Limites

  • Lecture seule. Le provisionnement d'utilisateurs n'est pas fait par ce connecteur.
  • Le statut du connecteur au catalogue est available. Cela décrit l'entrée du catalogue, pas une preuve de service sur votre instance.

Fichier source

Le connecteur est déclaré dans connectors/authentik.yaml.

Voir aussi

Connecteur CalRS

CalRS est un outil de prise de rendez-vous écrit en Rust, sous licence AGPL-3.0, avec une base SQLite et le protocole CalDAV. Il est le seul connecteur d'agenda de ce type dans connectors/ : connectors/calrs.yaml (décision notée dans l'en-tête de ce fichier, ADR-0009).

Ce chapitre garde le nom de fichier calcom.md pour que les liens existants continuent de fonctionner.

Transport

CalRS n'expose pas d'API HTTP, selon l'en-tête de connectors/calrs.yaml. Le connecteur ne parle donc pas à une adresse web. Il lance une commande podman exec … calrs <sous-commande> dans le conteneur CalRS. Conséquences :

  • il n'y a ni adresse d'instance, ni clé d'API, ni en-tête d'authentification à configurer ;
  • l'autorisation est celle du socket Podman, en amont du connecteur ;
  • aucune variable d'environnement n'est lue par ce connecteur.

Le nom d'identifiant historique calcomApi existe encore côté plateforme. Il est rattaché au connecteur calrs et ne publie aucune variable d'environnement (table de correspondance des identifiants du code, entrée calcomApi).

Outils

Mesuré le 2026-10-03 : 7 outils déclarés dans connectors/calrs.yaml. Le client Rust qui les exécute est crates/forge-mcp/src/connector/calrs_cli_client.rs.

OutilRôle
list_bookingsLister les rendez-vous réservés
show_calendarAfficher le calendrier
list_event_typesLister les types de rendez-vous
list_slotsLister les créneaux disponibles d'un type de rendez-vous (paramètre slug obligatoire, days optionnel)
create_bookingCréer un rendez-vous
cancel_bookingAnnuler un rendez-vous
create_event_typeCréer un type de rendez-vous

Trois de ces outils écrivent : create_booking, cancel_booking, create_event_type.

Déploiement

Un service CalRS figure dans podman-compose.vps2.yml, avec une image construite localement et un volume de données. Un commentaire de ce fichier le classe « catalogue » et précise qu'il est hors des plans thérapeute depuis le 2026-07-08.

Le connecteur n'a de sens que si le conteneur CalRS tourne sur la même machine que le processus qui lance la commande.

Limites

  • Aucun outil de disponibilité par utilisateur : list_slots travaille sur un type de rendez-vous identifié par son slug.
  • Le conteneur déployé ne contient aucun type de rendez-vous par défaut. Il faut en créer un (create_event_type) avant de lister des créneaux. Cette remarque vient d'une mesure du 2026-08-30 consignée dans le YAML.
  • L'entrée du catalogue métier (calrs, catégorie Scheduling) a le statut available.

Fichiers sources

Le connecteur est déclaré dans connectors/calrs.yaml et exécuté par crates/forge-mcp/src/connector/calrs_cli_client.rs.

Voir aussi

Connecteur Dolibarr

Connecteur Dolibarr

Dolibarr est un ERP/CRM open source pour petites structures. Le connecteur lit l'API REST de Dolibarr. Il est en lecture seule : il n'existe aucun outil de création, de modification ni de suppression.

Mesuré le 2026-10-03 dans connectors/dolibarr.yaml : 263 outils, tous en méthode GET (156 de type liste, 107 de type lecture d'un enregistrement).

Ce connecteur n'est pas appelable aujourd'hui : son identifiant ne figure pas dans la liste des serveurs autorisés (section Déploiement plus bas). Vous pouvez enregistrer ses identifiants, mais tools/list n'affiche pas ses outils et un appel est refusé.

Ce que déclare le fichier

PropriétéValeur
Fichierconnectors/dolibarr.yaml
ProtocoleAPI REST, chemins sous /api/index.php/
Authentificationclé d'API en en-tête DOLAPIKEY, lue dans DOLIBARR_API_KEY
Adresse de l'instancevariable DOLIBARR_URL
Licence déclaréeGPL-3.0
Résidence déclaréeauto-hébergé

Le fichier indique que les outils ont été vérifiés contre la documentation officielle de l'API REST de Dolibarr (consultée le 2026-06-24) et que les écritures (POST, PUT) sont exclues par choix.

Outils

Les noms suivent deux formes : list_<ressource> et get_<ressource>…. Exemples réels : list_thirdparties, get_thirdparty, list_invoices, get_invoice, list_proposals, list_orders, list_products, list_bankaccounts.

Ressources les mieux couvertes, par nombre d'outils dont un segment du nom (séparé par _) est la ressource, mesuré sur les 263 outils :

RessourceOutils
setup (paramétrage)45
products25
thirdparties (tiers)17
members (adhérents)13
invoices, projects9 chacune
users, orders, bankaccounts, tasks8, 7, 6 et 6
proposals, recruitments5 chacune

Le reste couvre des ressources plus petites : contrats, interventions, tickets, notes de frais, salaires, entrepôts, mouvements de stock, factures fournisseurs.

Configuration

VariableRôle
DOLIBARR_URLAdresse de l'instance Dolibarr
DOLIBARR_API_KEYClé d'API, envoyée dans l'en-tête DOLAPIKEY

Dans l'application : page Identifiants (/credentials), fiche Dolibarr, champs « URL du serveur » et « API Key ».

Déploiement

Ni podman-compose.vps2.yml ni podman-compose.yml ne déploient Dolibarr. Le connecteur vise une instance que vous fournissez. L'entrée du catalogue métier a le statut coming-soon.

L'identifiant dolibarr ne figure pas dans ALLOWED_MCP_SERVERS (liste des serveurs autorisés du code). Le fichier se charge, mais ses outils n'apparaissent pas dans tools/list et le dispatch les refuse (un test du dépôt le verrouille).

Limites

  • Lecture seule. Créer un devis ou une facture n'est pas possible avec ce connecteur.
  • Quatre outils portent le préfixe dolibarr_ (par exemple dolibarr_get_mos, dolibarr_list_users_groups), les 259 autres non : le nommage n'est pas uniforme.

Fichier source

Le connecteur est déclaré dans connectors/dolibarr.yaml.

Voir aussi

  • Vue d'ensemble : chiffres mesurés, chargement et règles communes aux douze connecteurs
  • Créer votre premier connecteur MCP : forme d'un fichier YAML et ajout d'un connecteur à la passerelle
  • Routes MCP : ouvrir une session et appeler un outil par JSON-RPC
  • Tarification : nombre de connecteurs métier inclus dans chaque offre
  • Odoo : l'autre ERP/CRM du livre, avec des outils d'écriture

Connecteur Forgejo

Connecteur Forgejo

Forgejo est une forge logicielle auto-hébergeable (dépôts Git, tickets, demandes de fusion, versions). Le connecteur appelle son API REST v1, compatible Gitea.

Mesuré le 2026-10-03 dans connectors/forgejo.yaml : 482 outils.

Méthode HTTPOutils
GET248
POST93
DELETE80
PATCH32
PUT29

Le connecteur lit donc 248 ressources et en modifie 234. Il peut supprimer des dépôts, des branches, des versions et des webhooks.

Ce que déclare le fichier

PropriétéValeur
Fichierconnectors/forgejo.yaml
ProtocoleAPI REST, chemins sous /api/v1/
Authentificationjeton Authorization: Bearer, lu dans FORGEJO_API_KEY
Adresse de l'instancevariable FORGEJO_URL
Licence déclaréeMIT
Résidence déclaréeauto-hébergé

Outils

Les noms n'ont pas de préfixe de connecteur : repos_list, repos_create, issues_create, pulls_merge, branches_protect, releases_create, webhooks_create.

Répartition par préfixe de nom, mesurée sur les 482 outils (les préfixes repos et repo sont deux familles distinctes dans le fichier) :

PréfixeOutilsPréfixeOutils
repos117issue19
repo63issues11
user60pulls10
admin41users10
orgs28branches8
org28teams7

Les préfixes restants (get, list, releases, activitypub, webhooks, labels, milestones, tags, packages, notify, settings, commits, notifications, markdown, et quelques autres) totalisent 80 outils.

Opérations couvertes par des outils nommés : création, lecture, modification et suppression de dépôts ; tickets avec commentaires, étiquettes et assignations ; demandes de fusion avec diff, revues et fusion ; branches avec protection ; versions ; webhooks ; étiquettes et jalons ; organisations et équipes ; paquets ; administration.

Configuration

VariableRôle
FORGEJO_URLAdresse de l'instance Forgejo
FORGEJO_API_KEYJeton d'API (la variable FORGEJO_API_TOKEN n'est lue nulle part)

Dans l'application : page Identifiants (/credentials), fiche Forgejo Git, champs « URL du serveur » et « Access Token » (ce dernier alimente FORGEJO_API_KEY).

Le délai d'attente déclaré est de 30 000 ms.

Déploiement

podman-compose.vps2.yml contient un service Forgejo (image officielle épinglée, base SQLite, ports liés à la boucle locale). Un commentaire de ce fichier précise qu'il est conservé pour la pile de développement du poste, et qu'il ne fait plus partie du plan client déployé depuis le 2026-09-10. Pour un usage client, le connecteur vise l'instance désignée par FORGEJO_URL.

L'entrée du catalogue métier a le statut coming-soon.

Limites

  • La licence MIT est celle que déclare le fichier YAML. Vérifiez la licence de la version de Forgejo que vous installez.
  • Les outils de lecture et d'écriture sont dans le même connecteur : les droits réels dépendent du jeton fourni.

Fichier source

Le connecteur est déclaré dans connectors/forgejo.yaml.

Voir aussi

Connecteur FreeScout

Connecteur FreeScout

FreeScout est un outil de support client auto-hébergeable, sous licence AGPL-3.0. Le connecteur lit les conversations, clients et boîtes de réception via l'API REST de FreeScout. Il est en lecture seule.

Mesuré le 2026-10-03 dans connectors/freescout.yaml : 15 outils, tous en méthode GET.

Ce connecteur n'est pas appelable aujourd'hui : son identifiant ne figure pas dans la liste des serveurs autorisés (section Déploiement plus bas). Vous pouvez enregistrer ses identifiants, mais tools/list n'affiche pas ses outils et un appel est refusé.

Ce que déclare le fichier

PropriétéValeur
Fichierconnectors/freescout.yaml
ProtocoleAPI REST, chemins sous /api/
Authentificationclé d'API en en-tête X-FreeScout-API-Key, lue dans FREESCOUT_API_KEY
Adresse de l'instancevariable FREESCOUT_URL
Licence déclaréeAGPL-3.0
Statut amonta_verifier

Le statut a_verifier est celui que porte le fichier. Dans le dépôt, il signifie qu'aucune sonde n'a encore établi qu'un amont répond (référentiel de statut amont du dépôt). Les outils sont donc vérifiés contre le contrat déclaré de l'API, pas contre une réponse réelle.

Outils

OutilRôle
list_conversationsLister les conversations (filtres : boîte, statut, page)
get_conversationLire une conversation avec ses échanges
list_mailboxesLister les boîtes de réception
list_mailbox_foldersLister les dossiers d'une boîte
list_mailbox_custom_fieldsLister les champs personnalisés d'une boîte
list_customersLister les clients
get_customerLire un client
list_tagsLister les étiquettes
list_timelogsLister les temps passés
list_conversation_timelogsLister les temps passés sur une conversation
list_usersLister les agents
get_userLire un agent
get_current_userLire l'utilisateur de la clé
list_webhooksLister les webhooks
get_reportLire un rapport

Le fichier précise que les 14 opérations d'écriture de l'API FreeScout ont été laissées de côté sur décision du titulaire, le 2026-09-04. Répondre à un ticket, changer un statut ou assigner une conversation n'est donc pas possible avec ce connecteur.

Configuration

VariableRôle
FREESCOUT_URLAdresse de l'instance FreeScout
FREESCOUT_API_KEYClé d'API

Dans l'application : page Identifiants (/credentials), fiche FreeScout Helpdesk, champs « URL du serveur » et « API Key ».

Déploiement

Ni podman-compose.vps2.yml ni podman-compose.yml ne déploient FreeScout. Le connecteur vise une instance que vous fournissez. L'entrée du catalogue métier a le statut coming-soon.

L'identifiant freescout ne figure pas dans ALLOWED_MCP_SERVERS (liste des serveurs autorisés du code). Le fichier se charge, mais ses outils n'apparaissent pas dans tools/list et le dispatch les refuse (un test du dépôt le verrouille).

Cas d'usage

  • Retrouver une conversation ou un client par l'agent.
  • Consulter les temps passés et les rapports.

Fichier source

Le connecteur est déclaré dans connectors/freescout.yaml.

Voir aussi

Connecteur Listmonk

Connecteur Listmonk

Listmonk est un gestionnaire de lettres d'information et de listes de diffusion, sous licence AGPL-3.0. Le connecteur appelle son API REST.

Mesuré le 2026-10-03 dans connectors/listmonk.yaml : 76 outils.

Méthode HTTPOutils
GET31
POST17
PUT15
DELETE13

Ce que déclare le fichier

PropriétéValeur
Fichierconnectors/listmonk.yaml
ProtocoleAPI REST, chemins sous /api/
AuthentificationHTTP Basic : identifiant dans LISTMONK_API_USER, secret dans LISTMONK_API_KEY
Adresse de l'instancevariable LISTMONK_URL
Licence déclaréeAGPL-3.0
Résidence déclaréeauto-hébergé

Outils

La plupart des outils portent le préfixe listmonk_. 17 outils n'en ont pas, par exemple get_bounces ou get_campaign_analytics.

DomaineExemples réels
Abonnéslistmonk_list_subscribers, listmonk_create_subscriber, listmonk_blocklist_subscriber, listmonk_search_subscribers, export_subscriber_data_by_id
Listeslistmonk_list_lists, listmonk_create_list, listmonk_get_list_subscribers
Campagneslistmonk_list_campaigns, listmonk_create_campaign, listmonk_start_campaign, listmonk_pause_campaign, listmonk_get_campaign_stats, get_campaign_analytics
Modèleslistmonk_list_templates, listmonk_create_template, listmonk_preview_template
Transactionnellistmonk_send_transactional
Rebondsget_bounces, get_bounce_by_id, listmonk_bounces_delete
Médias et importsget_media, listmonk_media_create, listmonk_import_subscribers_create
Réglages et maintenancelistmonk_settings_update, listmonk_maintenance_subscribers_delete

Il n'existe pas d'outil d'annulation de campagne nommé comme tel : les outils de pilotage d'une campagne sont listmonk_start_campaign et listmonk_pause_campaign.

Des outils de suppression en masse existent (listmonk_subscribers_query_delete_create, listmonk_maintenance_subscribers_delete). Ils agissent sur des abonnés réels.

Configuration

VariableRôle
LISTMONK_URLAdresse de l'instance Listmonk
LISTMONK_API_USERIdentifiant de l'utilisateur d'API
LISTMONK_API_KEYSecret de l'utilisateur d'API

Dans l'application : page Identifiants (/credentials), fiche Listmonk Newsletter, champs « URL du serveur », « Username » (qui alimente LISTMONK_API_USER) et « API Token » (qui alimente LISTMONK_API_KEY).

Les variables LISTMONK_USERNAME et LISTMONK_PASSWORD ne sont lues par aucun connecteur.

Déploiement

podman-compose.vps2.yml déploie un service Listmonk (image officielle, base Postgres partagée, volume pour les médias téléversés). L'entrée du catalogue métier a le statut coming-soon.

Fichier source

Le connecteur est déclaré dans connectors/listmonk.yaml.

Voir aussi

Connecteur Matomo

Connecteur Matomo

Matomo est un outil d'analyse d'audience web, sous licence GPL-3.0, que l'on peut héberger soi-même. Le connecteur interroge son API de rapports. Il est en lecture seule.

Mesuré le 2026-10-03 dans connectors/matomo.yaml : 113 outils, tous en méthode GET.

Pourquoi seulement de la lecture

L'API de Matomo modifie des données par des requêtes GET. Une passe de correction du 2026-06-25, consignée dans le fichier, a donc retiré 29 outils de mutation (création et modification d'objectifs, de sites, d'utilisateurs, de segments, d'alertes, anonymisation, suppression de données de personnes). Il reste 113 méthodes de rapport. generate_report et export_data_subjects sont conservés : ils renvoient des données.

Ce que déclare le fichier

PropriétéValeur
Fichierconnectors/matomo.yaml
ProtocoleAPI de rapports, chemin unique /index.php
Authentificationjeton token_auth passé en paramètre de requête, lu dans MATOMO_API_KEY
Adresse de l'instancevariable MATOMO_URL
Licence déclaréeGPL-3.0
Résidence déclaréeauto-hébergé

Le jeton voyage dans l'URL de la requête, parce que Matomo n'accepte pas d'en-tête d'authentification pour cette API (explication consignée dans le fichier). Gardez-le hors de tout journal d'accès que vous ne maîtrisez pas.

Outils

Les noms n'ont pas de préfixe de connecteur. Chaque outil prend en paramètres idSite (entier), period et date. Il n'existe pas de variable MATOMO_SITE_ID : le site se choisit à chaque appel.

Exemples réels :

BesoinOutils
Visitesget_visits_summary, get_visits, get_unique_visitors, get_actions, get_bounce_count
Pagesget_page_urls, get_page_titles, get_entry_page_urls, get_exit_page_urls
Sources de traficget_referrer_type, get_all_referrers, get_keywords, get_search_engines, get_socials
Objectifs et conversionsget_goals, get_goal, get_conversions
Audienceget_country, get_city, get_device_type, get_browsers, get_os_families
Détail des visitesget_last_visits_details, get_visitor_profile, get_counters
Données personnellesexport_data_subjects

Il n'existe pas d'outil nommé get_live_visitors. Les visites récentes se lisent avec get_last_visits_details.

Configuration

VariableRôle
MATOMO_URLAdresse de l'instance Matomo
MATOMO_API_KEYJeton d'authentification de l'API

Dans l'application : page Identifiants (/credentials), fiche Matomo Analytics, champs « URL du serveur », « Site ID » et « API Token » (ce dernier alimente MATOMO_API_KEY). Le champ « Site ID » est demandé par le formulaire, mais le connecteur ne le lit pas : indiquez le site (idSite) à chaque appel.

Les variables MATOMO_TOKEN et MATOMO_SITE_ID ne sont lues par aucun connecteur.

Déploiement

podman-compose.vps2.yml déploie Matomo (image officielle épinglée) avec une base MariaDB dédiée. L'entrée du catalogue métier a le statut available.

Exemple

Combien de visiteurs uniques sur le site 1 la semaine dernière ?

L'agent choisit get_unique_visitors avec idSite, period et date.

Fichier source

Le connecteur est déclaré dans connectors/matomo.yaml.

Voir aussi

  • Vue d'ensemble : chiffres mesurés, chargement et règles communes aux douze connecteurs
  • Créer votre premier connecteur MCP : forme d'un fichier YAML et ajout d'un connecteur à la passerelle
  • Routes MCP : ouvrir une session et appeler un outil par JSON-RPC
  • Tarification : nombre de connecteurs métier inclus dans chaque offre
  • RGPD : droits des personnes, en regard de l'outil d'export des données

Connecteur n8n

Connecteur n8n

n8n est un outil d'automatisation de workflows. Le connecteur appelle l'API publique REST de n8n pour lister, créer, activer et supprimer des workflows, et pour lire les exécutions.

Mesuré le 2026-10-03 dans connectors/n8n.yaml : 49 outils.

Méthode HTTPOutils
GET20
POST12
DELETE8
PUT7
PATCH2

Ce que déclare le fichier

PropriétéValeur
Fichierconnectors/n8n.yaml
ProtocoleAPI REST, chemins sous /api/v1/
Authentificationclé d'API en en-tête X-N8N-API-KEY, lue dans N8N_API_KEY
Adresse de l'instancevariable N8N_URL
Licence déclaréeSustainable-Use (fair-code, source disponible)

Le catalogue métier la libelle « Sustainable-Use (fair-code, source-available) ».

Outils

Les noms n'ont pas de préfixe de connecteur. Répartition par ressource, mesurée sur les 49 outils :

RessourceOutilsExemples réels
workflows12workflows_list, workflows_get, workflows_create, workflows_activate, workflows_deactivate, workflows_delete
projects8projects_list, projects_create, projects_users_create
executions7executions_list, executions_get, executions_retry, executions_list_failed
tags6tags_list, tags_create
users5users_list, users_change_role
variables5variables_list, variables_create
credentials4credentials_create, credentials_get_schema
sourcecontrol, audit1 chacunesourcecontrol_pull, audit_create

Il n'existe pas d'outil qui lance un workflow à la demande : ni n8n_execute_workflow, ni équivalent. Le connecteur sait activer ou désactiver un workflow, relancer une exécution (executions_retry) et lire l'historique.

Le connecteur crée et supprime aussi des utilisateurs, des identifiants et des variables d'une instance n8n. Donnez à la clé d'API les seuls droits nécessaires.

Huit chemins de confort qui n'existent pas

Un avertissement du 2026-09-05, en tête du fichier, rapporte une mesure sur une instance vivante. Huit outils de commodité (comptage des exécutions, statistiques, workflows actifs, utilisateur courant) visaient des chemins absents de la spécification que sert n8n lui-même. Vérifié le 2026-10-03 : aucun de ces huit noms ne figure parmi les 49 outils actuels. La capacité existe en passant par les chemins réels (par exemple la liste des exécutions avec un filtre de statut) ; elle est à reprendre, pas à supposer.

Configuration

VariableRôle
N8N_URLAdresse de l'instance n8n
N8N_API_KEYClé d'API n8n

Dans l'application : page Identifiants (/credentials), fiche n8n Automation, champs « URL du serveur » et « API Key ».

Le connecteur envoie le User-Agent mgaas-connector/1.0. Un User-Agent contenant « bot » fait répondre n8n par un corps vide (mesure du 2026-07-03 consignée dans le fichier).

Déploiement

podman-compose.vps2.yml déploie un service n8n (image officielle, base Postgres partagée, volume qui conserve la clé de chiffrement de n8n). L'entrée du catalogue métier a le statut available.

Exemple

Active le workflow « Synchronisation clients ».

L'agent retrouve le workflow avec workflows_list, puis appelle workflows_activate.

Fichier source

connectors/n8n.yaml

Voir aussi

Connecteur Nextcloud

Connecteur Nextcloud

Nextcloud est une plateforme de fichiers et de collaboration sous licence AGPL-3.0. Le connecteur appelle ses interfaces WebDAV et OCS (REST).

Mesuré le 2026-10-03 dans connectors/nextcloud.yaml : 167 outils.

Méthode HTTPOutils
GET89
POST40
DELETE21
PUT16
PATCH1

Ce que déclare le fichier

PropriétéValeur
Fichierconnectors/nextcloud.yaml
ProtocoleWebDAV (/remote.php/dav/…) et OCS (/ocs/v2.php/…)
AuthentificationHTTP Basic : identifiant dans NEXTCLOUD_API_USER, secret dans NEXTCLOUD_API_KEY
Adresse de l'instancevariable NEXTCLOUD_URL
En-têtes fixesOCS-APIRequest: true, Accept: application/json
Licence déclaréeAGPL-3.0
Résidence déclaréeauto-hébergé

L'en-tête Accept est nécessaire : sans lui, OCS répond en XML étiqueté JSON (remarque consignée dans le fichier).

Outils

Tous les noms commencent par nc_. Répartition par famille, pour les principales :

FamilleOutilsExemples réels
nc_share15nc_share_create, nc_share_list, nc_share_get_shared_with_me, nc_share_accept
nc_cloud15nc_cloud_capabilities_list
nc_apps14(interfaces des applications Nextcloud)
nc_core14nc_core_preview_list
nc_user12nc_user_create, nc_user_set_quota, nc_user_add_to_group
nc_deck10nc_deck_list_boards, nc_deck_create_card
nc_taskprocessing9nc_taskprocessing_schedule_create
nc_group, nc_app6 chacunenc_group_create, nc_app_install

Les 66 autres outils se répartissent en petites familles (notifications, activité, références, traduction, texte vers image, étiquettes, avatars, entre autres).

Fichiers : quatre outils seulement, nc_file_get, nc_file_upload, nc_file_download, nc_file_delete, tous sur le chemin WebDAV /remote.php/dav/files/{username}{path}. Aucun outil déclaré ne crée un dossier ni ne liste le contenu d'un dossier, parce que le fichier n'utilise que les méthodes GET, POST, PUT, PATCH et DELETE.

Contacts : trois outils (nc_contact_get, nc_contact_create, nc_contact_update) sur CardDAV. Agenda : un seul outil, nc_calendar_delete. Il n'existe pas d'outil pour lire ou créer des événements de calendrier.

Le connecteur gère aussi les comptes (nc_user_*, nc_group_*) et les applications (nc_app_install, nc_app_remove). Une identité d'administrateur lui donne ces pouvoirs ; préférez un compte restreint.

Configuration

VariableRôle
NEXTCLOUD_URLAdresse de l'instance Nextcloud
NEXTCLOUD_API_USERNom d'utilisateur
NEXTCLOUD_API_KEYSecret associé à l'identifiant (Basic)

Dans l'application : page Identifiants (/credentials), fiche Nextcloud, champs « URL du serveur », « Username » (qui alimente NEXTCLOUD_API_USER) et « App Password (revocable) » (qui alimente NEXTCLOUD_API_KEY). Générez ce mot de passe d'application dans les réglages de sécurité de Nextcloud : ce n'est pas votre mot de passe principal.

Les variables NEXTCLOUD_USERNAME et NEXTCLOUD_PASSWORD ne sont lues par aucun connecteur.

Déploiement

Ni podman-compose.vps2.yml ni podman-compose.yml ne déploient Nextcloud. Le connecteur vise une instance que vous fournissez. L'entrée du catalogue métier a le statut available.

Fichier source

connectors/nextcloud.yaml

Voir aussi

  • Vue d'ensemble — chiffres mesurés, chargement et règles communes aux douze connecteurs
  • Créer votre premier connecteur MCP — forme d'un fichier YAML et ajout d'un connecteur à la passerelle
  • Routes MCP — ouvrir une session et appeler un outil par JSON-RPC
  • Tarification — nombre de connecteurs métier inclus dans chaque offre
  • Limites — la plateforme ne stocke pas de fichiers, ils restent dans l'outil connecté

Connecteur Odoo

Connecteur Odoo

Le connecteur Odoo pilote une instance Odoo par le protocole XML-RPC. Parmi les douze connecteurs décrits dans ce livre, c'est celui qui expose le plus d'outils : 711 outils nommés au registre, mesurés le 2026-10-03.

Deux endroits où se compter

Le fichier connectors/odoo.yaml ne déclare que 6 outils (crm.search_leads, crm.create_lead, sale.list_orders, account.list_invoices, hr.list_employees, project.list_tasks). Les 711 outils nommés vivent dans le registre Rust crates/forge-mcp/src/connector/odoo_tools_registry.rs. Un test du dépôt affirme ce nombre. Le site public affiche le même chiffre (OUTILS_ODOO dans crates/forge-ui/src/config/chiffres_mesures.rs).

Ce que déclare le fichier

PropriétéValeur
Fichierconnectors/odoo.yaml
ProtocoleXML-RPC (type odoo)
Licence déclaréeLGPL-3.0
Résidence déclaréeauto-hébergé

Il n'y a pas de bloc auth : le connecteur lit quatre valeurs de connexion.

Configuration

VariableRôle
ODOO_URLAdresse de l'instance Odoo
ODOO_DATABASENom de la base de données
ODOO_USERNAMEIdentifiant de connexion
ODOO_API_KEYClé d'API Odoo (obligatoire : le fichier la déclare avec :?, sans valeur par défaut)

Les variables ODOO_DB et ODOO_PASSWORD ne sont lues par aucun connecteur.

Parcours complet, avec la fiche Odoo ERP/CRM et un premier appel : Connecter Odoo à la passerelle MCP.

Pour un locataire, les valeurs sont saisies comme identifiants de la plateforme et stockées chiffrées. Une organisation peut en plus stocker un AppRole OpenBao : l'URL, la base et la clé sont alors lues depuis OpenBao en priorité, au moment de la requête (résolution des identifiants du code, entrée odooApi).

Outils nommés

Mesure du 2026-10-03 sur les 711 entrées du registre, par opération :

OpérationOutils
search148
read120
group (agrégat en lecture)5
create113
update105
delete103
action (confirmer, valider, archiver, entre autres)117

Les lectures (search, read, group) sont donc 273. Les 438 autres modifient des données. Les 711 outils visent 140 modèles Odoo. Les noms sont de la forme <module>_<objet>_<action>.

Exemples réels, tous présents au registre :

DomaineOutils
Contactscontacts_search, contacts_create, contacts_merge, contacts_export_gdpr
CRMcrm_lead_create, crm_lead_convert, crm_lead_won
Ventessales_order_search, sales_order_create, sales_order_confirm
Achatspurchase_order_confirm
Facturationinvoice_search, invoice_create, invoice_post
Stockinventory_product_search
Ressources humaineshr_employee_search (87 outils portent le préfixe hr)
Projetsproject_task_create
Site et contenuwebsite_page_search, blog_post_create

Les préfixes les mieux fournis sont hr (87 outils), inventory (51), sales (43), website (39), mrp (35) et crm (34).

Les anciens noms odoo_search_read, odoo_sale_order_list et odoo_invoice_validate n'existent pas au registre. Les noms informels sont rapprochés des noms canoniques à l'appel par odoo_tool_resolver.

Quatre outils génériques

Quatre outils prennent le modèle en argument : record_create, record_read, record_update, record_delete (crates/forge-mcp/src/connector/odoo_generic_crud.rs). Ils ne fonctionnent que sur une liste blanche de 402 modèles métier (odoo_metier_models.rs). Le framework, les rapports, la messagerie et la sécurité en sont exclus.

Écritures gardées

Parmi ces 402 modèles, 24 sont gardés en écriture : plan de comptes, journaux, taxes, lignes d'écriture comptable, relevés bancaires, entre autres. Une création, une modification ou une suppression sur l'un d'eux exige une approbation humaine via /actions/approvals. Elle n'est jamais exécutée seule par l'agent. La lecture de ces modèles reste libre.

Déploiement

podman-compose.vps2.yml déploie 17 services Odoo, un par secteur (thérapie, médical, juridique, immobilier, finance, entre autres). L'entrée du catalogue métier (odoo, catégorie CRM & ERP) a le statut available.

Limites techniques

  • Le client HTTP du connecteur a un délai d'attente de 30 secondes.
  • L'identifiant utilisateur obtenu à la connexion est gardé en mémoire 600 secondes, puis redemandé.

Exemple

Quels sont les contacts créés cette semaine dans Odoo ?

L'agent choisit un outil de recherche sur les contacts (contacts_search), construit le filtre et exécute l'appel XML-RPC.

Fichiers sources

connectors/odoo.yaml, crates/forge-mcp/src/connector/odoo_tools_registry.rs, crates/forge-mcp/src/connector/odoo_generic_crud.rs, crates/forge-mcp/src/connector/odoo_metier_models.rs

Voir aussi

Connecteur Rocket.Chat

Connecteur Rocket.Chat

Rocket.Chat est une messagerie d'équipe auto-hébergeable. Le connecteur appelle son API REST v1.

Mesuré le 2026-10-03 dans connectors/rocketchat.yaml : 338 outils.

Méthode HTTPOutils
GET279
POST58
PUT1

L'API de Rocket.Chat écrit par POST, y compris pour supprimer : rc_channel_delete et rc_message_delete sont des POST.

Ce que déclare le fichier

PropriétéValeur
Fichierconnectors/rocketchat.yaml
ProtocoleAPI REST, chemins sous /api/v1/
Authentificationjeton en en-tête X-Auth-Token, lu dans ROCKETCHAT_API_KEY
Identifiant d'utilisateuren-tête X-User-Id, lu dans ROCKETCHAT_USER_ID
Adresse de l'instancevariable ROCKETCHAT_URL
Licence déclaréeMIT
Résidence déclaréeauto-hébergé

Outils

Tous les noms commencent par rc_. Répartition par famille, pour les principales :

FamilleOutilsExemples réels
rc_livechat83rc_livechat_agent_info_get
rc_chat, rc_rooms14 chacunerc_chat_getmentionedmessages_list
rc_users13rc_users_autocomplete_list
rc_channel12rc_channel_create, rc_channel_invite, rc_channel_archive, rc_channel_set_topic
rc_user, rc_dm12 chacunerc_user_create, rc_dm_create, rc_dm_history
rc_message10rc_message_send, rc_message_search, rc_message_history, rc_message_pin, rc_message_react
rc_group, rc_team, rc_channels10 chacunerc_group_create, rc_team_create

Les autres familles couvrent les intégrations et webhooks (rc_integration_*, 8 outils), les rôles (rc_role_*, 6), les abonnements, les réglages (rc_setting_*), la modération, l'omnicanal, les statistiques et l'administration. Sur les 62 familles de noms, 33 ne comptent qu'un ou deux outils.

La famille rc_livechat est la première par le nombre : elle concerne le chat en direct pour visiteurs et représente 83 outils sur 338.

Configuration

VariableRôle
ROCKETCHAT_URLAdresse de l'instance Rocket.Chat
ROCKETCHAT_API_KEYJeton d'authentification personnel
ROCKETCHAT_USER_IDIdentifiant de l'utilisateur propriétaire du jeton

La variable ROCKETCHAT_AUTH_TOKEN n'est lue par aucun connecteur. Le délai d'attente déclaré est de 30 000 ms.

Dans l'application : page Identifiants (/credentials), fiche Rocket.Chat, champs « URL du serveur », « User ID » et « Auth Token ». Le champ « Auth Token » alimente ROCKETCHAT_API_KEY.

Déploiement

Ni podman-compose.vps2.yml ni podman-compose.yml ne déploient Rocket.Chat. Le connecteur vise une instance que vous fournissez. L'entrée du catalogue métier a le statut coming-soon.

Cas d'usage

  • Envoyer un message dans un canal (rc_message_send).
  • Rechercher dans l'historique (rc_message_search).
  • Créer un canal ou une conversation directe.

Fichier source

connectors/rocketchat.yaml

Voir aussi

Connecteur Typesense

Connecteur Typesense

Typesense est un moteur de recherche en texte intégral, tolérant aux fautes de frappe, sous licence GPL-3.0. Le connecteur appelle son API REST pour chercher, gérer les collections et les documents, et administrer le cluster.

Mesuré le 2026-10-03 dans connectors/typesense.yaml : 79 outils.

Méthode HTTPOutils
GET36
POST16
DELETE14
PUT10
PATCH3

Ce que déclare le fichier

PropriétéValeur
Fichierconnectors/typesense.yaml
ProtocoleAPI REST
Authentificationclé d'API en en-tête X-TYPESENSE-API-KEY, lue dans TYPESENSE_API_KEY
Adresse de l'instancevariable TYPESENSE_URL
Licence déclaréeGPL-3.0
Résidence déclaréeauto-hébergé

Outils

Les noms n'ont pas de préfixe de connecteur. Répartition par préfixe, mesurée sur les 79 outils :

PréfixeOutilsExemples réels
collections10collections_create, collections_delete, collections_documents_import_create
analytics9analytics_rules_create, analytics_events_list
curation8curation_sets_list, curation_sets_items_update
synonym8synonym_sets_list, synonym_sets_items_update
list, get5 chacunlist_collections, list_keys, list_aliases, get_health, get_stats, get_metrics, get_debug
conversations, nl, operations5 chacunnl_search_models_create, operations_snapshot_create
aliases, keys, presets, stemming, stopwords3 chacunaliases_update, keys_create
search, documents, config, multi1 chacunsearch, documents_export, multi_search_create

search interroge /collections/{collection}/documents/search. Les opérations d'administration du cluster (operations_snapshot_create, operations_db_compact_create, operations_cache_clear_create) sont des outils d'écriture.

L'import en masse existe (collections_documents_import_create). Il n'existe pas d'outil de clonage de collection.

Configuration

VariableRôle
TYPESENSE_URLAdresse de l'instance Typesense
TYPESENSE_API_KEYClé d'API (en-tête X-TYPESENSE-API-KEY)

Dans l'application : page Identifiants (/credentials), fiche Typesense Search, champs « URL du serveur » et « API Key ».

Le connecteur expose des outils d'écriture et de suppression (14 DELETE) : les droits effectifs sont ceux de la clé fournie.

Déploiement

podman-compose.vps2.yml déploie Typesense (image officielle épinglée, volume de données, port lié à la boucle locale). L'entrée du catalogue métier a le statut coming-soon.

Fichier source

connectors/typesense.yaml

Voir aussi

  • Vue d'ensemble — chiffres mesurés, chargement et règles communes aux douze connecteurs
  • Créer votre premier connecteur MCP — forme d'un fichier YAML et ajout d'un connecteur à la passerelle
  • Routes MCP — ouvrir une session et appeler un outil par JSON-RPC
  • Tarification — nombre de connecteurs métier inclus dans chaque offre
  • Connaissances — collections et recherche vectorielle gérées par la plateforme elle-même

Architecture Chatbotaurus

Chatbotaurus est une plateforme MGaaS (MCP Gateway as a Service) européenne et souveraine, écrite en Rust. Elle combine un agent conversationnel, une passerelle MCP alimentée par des connecteurs déclarés en YAML, et une infrastructure auto-hébergeable sous Podman.

À la fin de ce chapitre, vous saurez situer chaque composant, dire dans quel plan il tourne et quelle page détaille son exploitation.

Vue d'ensemble

Quatre couches superposées, de haut en bas : l'interface forge-ui, le backend forge-api, la passerelle MCP forge-mcp, montée dans forge-api et empaquetée dans forge-gateway, et l'infrastructure Podman en deux plans.

La plateforme tient en quatre couches :

  • Interface : forge-ui, une seule base de code Dioxus 0.7 (binaire chatbotaurus). Elle se compile en wasm pour le navigateur (fonctionnalité web), ou en application bureau et mobile (fonctionnalités desktop et mobile de crates/forge-ui/Cargo.toml).
  • Backend : forge-api, un serveur Axum qui expose /api/v1/** (REST, SSE, multipart, WebSocket), adossé à SeaORM sur PostgreSQL. Authentification, jeton CSRF, limitation de débit et contrôles de conformité UE sont des middlewares de ce crate.
  • Passerelle MCP : le moteur forge-mcp (connecteurs, routage, sessions, transport Streamable HTTP). Il est monté dans forge-api (route /api/v1/mcp) et empaqueté seul dans forge-gateway, le binaire du service mcp-gateway du plan client.
  • Infrastructure : conteneurs Podman répartis en deux plans (voir la section « Deux plans, une règle de nommage »), avec PostgreSQL, Valkey, Qdrant, OpenBao, Authentik, Ollama, la chaîne vocale et l'observabilité.

Deux plans, une règle de nommage

Le déploiement est découpé en deux projets Podman, chacun avec son réseau :

PlanRéseau PodmanFichier composeServices
Backend (notre plan)chatbotaurus-vps1podman-compose.ymlforge-*
Clientmgaas-vps2podman-compose.vps2.ymlmcp-*

La règle tient au nom du service : un conteneur nommé mcp-* appartient au plan client, tout autre nom au plan backend. PostgreSQL et Valkey sont rattachés aux deux réseaux (alias DNS postgres et valkey sur mgaas-vps2) pour que les outils du plan client les joignent par leur nom.

Deux blocs superposés : le plan backend, avec l'API, son ingress, PostgreSQL et Valkey, et le plan client, avec la passerelle MCP, les outils du client et son ingress ; PostgreSQL et Valkey sont aussi joints depuis le réseau du plan client.

Figure 1 : les deux plans de déploiement, leur règle de nommage et les deux services rattachés aux deux réseaux.

En production, ces plans sont décrits par des unités Quadlet (containers/*/*.container), l'ingress du plan backend est forge-traefik et celui du plan client mcp-caddy. Le détail est dans Déploiement avec Podman.

Crates du workspace

Le fichier Cargo.toml à la racine déclare ces membres :

CrateRôle (description de son Cargo.toml)
forge-apiServeur HTTP Axum : API REST, transport MCP, WebSocket
forge-coreCœur métier : agents, RAG, workflows, anti-hallucination
forge-mcpMoteur de la passerelle MCP : connecteurs, routage, sessions
forge-gatewayBinaire « serveur gateway » du plan client (service mcp-gateway)
forge-authAuthentification, autorisation, OIDC, TOTP, politiques Cedar
forge-dbCouche base de données : entités SeaORM, migrations
forge-auditJournal d'audit à altération détectable, conformité AI Act, chaîne de Merkle
forge-commonPrimitives transverses : erreurs, cache, traces
forge-wireContrats de transmission partagés entre forge-api et forge-ui
forge-uiInterface Dioxus multiplateforme
forge-voiceService vocal (STT, TTS, WebRTC) avec fournisseurs européens
extraction documentairecrate prévu (spec 115, T-115-50), non encore suivi dans le dépôt ; son nom est déjà déclaré dans le Cargo.toml de l'arbre de travail (mesure du 2026-10-03)
forge-opsDéploiement, amorçage, diagnostics, reprise (CLI)
forge-cliCLI de gestion du serveur, des outils MCP et des modèles
forge-tuiInterface terminal
forge-docsPipeline de documentation mdBook (ce livre)
forge-replayBanc de rejeu de contrats V1/V2
forge-oracleOracle différentiel exécutable V1/V2
forge-test-utilsBanc de test de bout en bout
forge-pgtestPoint de vérité unique de l'image PostgreSQL des tests

Pile technique

CoucheTechnologie
InterfaceRust + Dioxus 0.7
BackendRust + Axum + SeaORM + PostgreSQL + Valkey
Client HTTPreqwest avec rustls (pas d'OpenSSL)
AuthentificationJWT HS256, TOTP (RFC 6238), OIDC avec Authentik
ChiffrementAES-256-GCM (aes-gcm), TLS par rustls
AutorisationCedar, politiques dans le dossier policies/
VecteursQdrant (RAG)
SecretsOpenBao
Observabilité et détectionVictoriaMetrics et VictoriaLogs (plan de développement), Beszel et CrowdSec (déployés). Falco : unité écrite, retirée du déploiement le 2026-09-19
Stockage objetSeaweedFS (S3, Apache-2.0)

Moteur MGaaS : quatre couches

Le moteur d'orchestration vit dans crates/forge-core/src/mgaas/ :

COUCHE 1 : raisonnement
  ToTLite, SelfConsistency, ChainOfVerification, MCTSLite

COUCHE 2 : orchestration d'agents
  routeur MoELite, TaskDecomposer, AgentMCPRegistry

COUCHE 3 : intelligence des outils
  RAREngine, DynamicToolPruner, ToolPatternMemory

COUCHE 4 : exécution et validation
  SpeculativeDecoder, ParallelStreamingExecutor, GroundingEngine

Sous pression de ressources, ce moteur est conçu pour désactiver ses techniques coûteuses par paliers : voir Gestion des erreurs.

État mesuré : la route GET /api/v1/mgaas/engines (crates/forge-api/src/routes/mgaas.rs) déclare « dormants », sans appelant de production, neuf des douze moteurs qu'elle liste. Seuls MoELiteRouter, TaskDecomposer et StructuredOutputValidator sont appelés en production.

Transport MCP : JSON-RPC 2.0 en Streamable HTTP

Dans forge-api, la route est montée dans crates/forge-api/src/router.rs :

POST   /api/v1/mcp   → JSON-RPC (initialize, tools/list, tools/call)
GET    /api/v1/mcp   → flux SSE de notifications
DELETE /api/v1/mcp   → terminer la session
  • La session est portée par l'en-tête Mcp-Session-Id. Sa durée de vie par défaut est de 30 minutes d'inactivité (crates/forge-mcp/src/session.rs).
  • La version de protocole annoncée à initialize est 2025-03-26 (crates/forge-mcp/src/protocol.rs).
  • Ces routes exigent un utilisateur authentifié, et la surface MCP peut être coupée par l'interrupteur MCP_ENABLED.
  • Le binaire forge-gateway expose, lui, POST /mcp et GET /health sur le port 8811 du plan client.

Pour explorer la flotte de connecteurs depuis l'API : GET /api/v1/mcp/catalogue (alias GET /api/v1/mcp/catalog) et GET /api/v1/mcp-gateway/servers.

Connecteurs MCP

Chaque fichier connectors/*.yaml déclare un connecteur. Au démarrage de forge-api, le CatalogueLoader (crates/forge-mcp/src/connector/catalogue.rs) lit ce dossier, résout les variables d'environnement et enregistre le connecteur dans le registre. Le nombre de connecteurs évolue avec le dépôt : il se compte avec ls connectors/*.yaml, jamais avec un chiffre recopié dans une page.

Un connecteur n'est accepté que s'il passe le contrôle de conformité UE du registre : voir Conception des connecteurs MCP.

Les connecteurs couvrent notamment les ERP et CRM (Odoo, ERPNext), les outils de collaboration, le support, l'analytique, les workflows (n8n), la sécurité, l'IA et un grand nombre de sources de données publiques européennes.

Modèles et chaîne vocale

  • LLM : exécutés par Ollama (service forge-ollama). Le modèle par défaut se règle par la variable OLLAMA_MODEL, et forge-cli model pull télécharge un modèle.
  • Embeddings : calculés localement (crate fastembed, crates/forge-core/src/rag/embedder.rs). La dimension des vecteurs est lue à l'exécution depuis le modèle chargé, pas fixée dans la documentation.
  • Voix : synthèse par forge-kokoro-tts, transcription par forge-faster-whisper, temps réel par forge-livekit.

Les fournisseurs LLM tiers sont optionnels et désactivés par défaut.

Authentification

Les méthodes sont cumulables selon la configuration de l'organisation : mot de passe, second facteur TOTP (application d'authentification) et SSO OIDC via Authentik.

  • Le jeton d'accès est un JWT signé en HS256 (l'algorithme est épinglé côté serveur). Sa durée se règle par JWT_EXPIRY ; le défaut du code est de 7 jours (crates/forge-api/src/state.rs).
  • Protection CSRF par double soumission : cookie csrf-token et en-tête x-csrf-token sur les requêtes POST, PUT et DELETE.
  • Les secrets de connecteurs sont chiffrés en AES-256-GCM avant stockage ; les locataires soumis à une exigence réglementaire peuvent les loger dans OpenBao.

Cloisonnement des locataires

Le filtre de locataire canonique repose sur l'organisation (organization_id), appliqué par accessible_workspace_filter (crates/forge-api/src/extractors/mod.rs). Un contrôle de pré-commit sur le cloisonnement des locataires protège les handlers du backend.

Gestion des erreurs

Chaque niveau capture et traduit ses erreurs :

  • Transport MCP : JSON-RPC invalide, session expirée ;
  • Connecteurs : délai dépassé, authentification, limite amont atteinte ;
  • Moteur IA : dégradation par paliers sous pression de ressources.

Détails : Gestion des erreurs.

Compilation et contrôles

# Workspace complet
cargo build --workspace --release

# Interface web (wasm)
cargo build -p forge-ui --target wasm32-unknown-unknown --bin chatbotaurus

# Tests
cargo test --workspace

# Lint strict
cargo clippy --workspace --all-targets -- -D warnings

Les contrôles de pré-commit refusent notamment un fichier Rust de plus de 300 lignes sans exemption motivée et l'usage des termes « parity » ou « parité » sans preuve associée.

Voir aussi

Gestion des erreurs

Chatbotaurus gère les erreurs à plusieurs niveaux : une énumération d'erreurs commune à tout le backend, une enveloppe JSON stable côté API, des codes JSON-RPC pour le transport MCP, un disjoncteur pour les services en aval et une dégradation par paliers du moteur d'IA.

À la fin, vous saurez lire un code d'erreur renvoyé par l'API ou par le transport MCP et savoir où chercher la cause.

Erreurs de l'API REST

Les handlers de forge-api renvoient des ForgeError (crates/forge-core/src/error.rs). Chaque variante porte un statut HTTP et un code lisible par machine :

VarianteStatutCode
InvalidInput400INVALID_INPUT
Validation400VALIDATION_FAILED
Unauthorized401UNAUTHORIZED
Forbidden403FORBIDDEN
NotFound404NOT_FOUND
Conflict409CONFLICT
Unprocessable422UNPROCESSABLE
RateLimited429RATE_LIMITED
Internal, Config, Serialization500INTERNAL_ERROR, CONFIG_ERROR, SERIALIZATION_ERROR
Database500DATABASE_ERROR
Vault500VAULT_ERROR
Upstream502UPSTREAM_ERROR
CircuitOpen, Unavailable503CIRCUIT_OPEN, SERVICE_UNAVAILABLE
Timeout504TIMEOUT

Vault et VAULT_ERROR sont des noms historiques du code : le coffre de secrets du produit est OpenBao.

Les erreurs de domaine (Agent, Workflow, Rag, Embedding, HallucinationDetected, Ollama) répondent 500 avec les codes AGENT_ERROR, WORKFLOW_ERROR, RAG_ERROR, EMBEDDING_ERROR, HALLUCINATION_DETECTED et OLLAMA_ERROR.

Le corps de réponse a toujours la même forme :

{
  "error": {
    "code": "NOT_FOUND",
    "message": "resource not found: user id=42",
    "status": 404
  }
}

Une réponse 429 ajoute le champ retryAfterSecs dans le corps et l'en-tête HTTP Retry-After. La conversion en réponse HTTP est faite par crates/forge-common/src/error.rs : niveau de trace warn pour un 404, info pour les autres 4xx, error pour les 5xx.

Pour agir sur un code précis (TIMEOUT, SERVICE_UNAVAILABLE, RATE_LIMITED, CIRCUIT_OPEN, session MCP expirée), voir Problèmes connus.

Messages sans fuite d'information

Un message d'erreur de base de données, de client HTTP ou de fichier peut embarquer une requête SQL, une URL interne ou un chemin local. Les handlers passent donc par safe_message (crates/forge-api/src/safe_error.rs) : le client reçoit un texte fixe et neutre. En développement local seulement, l'opérateur peut démarrer le serveur avec FORGE_VERBOSE_ERRORS=1 pour obtenir le détail.

Le même module fournit error_body et error_body_with_request_id (ajoute un champ request_id pour relier une réponse à ses traces).

Transport MCP

Le transport Streamable HTTP répond en JSON-RPC 2.0. Codes émis par crates/forge-mcp/src/transport/ et crates/forge-api/src/routes/mcp.rs :

CodeCasExemple de message
-32700JSON invalideinvalid JSON-RPC request
-32600Requête invalidemissing Mcp-Session-Id, session expired or unknown
-32601Méthode inconnuemethod '<nom>' not found
-32602Paramètres invalidesmissing 'name'
-32603Erreur internetool call failed, session creation failed

Les messages du code -32603 sont génériques (passés par safe_message). Une session expire après 30 minutes d'inactivité : le client doit alors renvoyer initialize.

Connecteurs

  • Limite amont atteinte : si le service tiers répond 429, le connecteur renvoie RATE_LIMITED avec le Retry-After de l'amont (60 secondes à défaut). Un connecteur peut aussi déclarer rate_limit_per_min : la limite est alors vérifiée avant l'appel réseau.
  • Délai dépassé : chaque connecteur a un timeout_ms (30 000 par défaut). Un dépassement est renvoyé en TIMEOUT (504).
  • Service injoignable : une erreur de connexion devient SERVICE_UNAVAILABLE (503).
  • URL interdite : une URL de base fournie par un locataire qui vise le réseau interne est refusée avant tout appel (Forbidden, message SSRF_BLOCKED).

Agents : disjoncteur

Chaque agent exécuté par un AgentWorker (crates/forge-core/src/agent/worker.rs) est protégé par un disjoncteur à trois états (fermé, ouvert, semi-ouvert). Par défaut il s'ouvre après quelques échecs consécutifs, reste ouvert un court délai avant de passer en semi-ouvert, et considère un appel comme échoué au-delà d'un délai borné. Tant qu'il est ouvert, l'appel échoue immédiatement avec CIRCUIT_OPEN (503). Une primitive générique équivalente existe dans crates/forge-core/src/security/circuit_breaker.rs.

Moteur d'IA : dégradation par paliers

Cette cascade est livrée mais non branchée : les moteurs de raisonnement qu'elle coupe n'ont pas d'appelant de production (voir Supervision). Le moniteur de ressources du moteur MGaaS (crates/forge-core/src/mgaas/resource_monitor.rs) choisit un niveau de dégradation à partir de la RAM utilisée, du CPU et de la latence moyenne. Il existe cinq niveaux, par ordre décroissant de capacités :

  1. FULL : toutes les techniques de raisonnement actives ;
  2. NO_MCTS : MCTSLite désactivé ;
  3. NO_TOT : ToTLite désactivé en plus ;
  4. NO_SELF_CONSISTENCY : l'auto-cohérence est désactivée en plus ;
  5. TEMPLATE_ONLY : réponses issues de gabarits, dernier recours.

Les seuils (mémoire, processeur, latence) sont fixés dans le code du moniteur de ressources et ne sont pas publiés ici.

Règle appliquée : si un seul seuil critique est franchi, le niveau est TEMPLATE_ONLY. Sinon, si un seuil d'avertissement est franchi, le niveau est NO_SELF_CONSISTENCY quand la mémoire dépasse nettement son seuil d'avertissement, NO_TOT quand le processeur est très chargé, et NO_MCTS dans les autres cas, latence comprise (marges fixées dans le code).

Escalier descendant de cinq niveaux, de FULL à TEMPLATE_ONLY, choisi par le moniteur de ressources à partir de la RAM, du CPU et de la latence ; la cascade est marquée livrée mais non branchée.

Figure 2 : les cinq niveaux de dégradation du moteur d'IA, par ordre décroissant de capacités.

Le moteur anti-hallucination (crates/forge-core/src/anti_hallucination/) a son propre indicateur de niveau opérationnel, distinct du précédent : Full, NoCache, NoRag, NoSemantic, TemplateOnly, Maintenance. Il décide quelles fonctions sont annoncées au client, et ne se confond pas avec le moniteur de ressources ci-dessus.

Observabilité

  • Les journaux du backend sont écrits en JSON par défaut ; LOG_FORMAT=pretty ou compact donne une sortie lisible (init_tracing, crates/forge-api/src/main.rs). TRACING_JSON, fixée dans podman-compose.yml, n'est pas lue par forge-api.
  • Chaque requête reçoit un identifiant par la couche RequestIdLayer.
  • Le plan backend embarque VictoriaMetrics (métriques) et VictoriaLogs (logs) ; la détection d'intrusion repose sur CrowdSec. L'unité Falco existe mais est retirée du déploiement depuis le 2026-09-19.

Voir aussi

Conception des connecteurs MCP

Ce chapitre décrit comment un service externe devient un ensemble d'outils MCP dans Chatbotaurus. Le moteur est le crate forge-mcp. À la fin, vous saurez écrire le manifeste d'un connecteur et ce que le contrôle de conformité UE en refuse.

Deux types de connecteurs

1. Connecteur déclaratif YAML (cas général)

Un fichier connectors/<nom>.yaml décrit le service et ses outils. Au démarrage, forge-api lit le dossier désigné par la variable CONNECTOR_CATALOGUE_DIR (par défaut ./connectors). Il enregistre chaque connecteur dans le registre. Le fichier connectors/TEMPLATE.yaml est un modèle à copier. Pas à pas : Créer votre premier connecteur MCP. Le dossier n'est lu qu'au démarrage : redémarrez forge-api après chaque modification (voir Fichiers de configuration).

Exemple tiré de connectors/matomo.yaml, abrégé (l'URL par défaut y est remplacée par une adresse d'exemple) :

id: matomo
display_name: "Matomo Analytics"
base_url: "${MATOMO_URL:-https://matomo.exemple.eu}"
base_url_env: MATOMO_URL
auth:
  type: query_token
  param: token_auth
  token_env: MATOMO_API_KEY
compliance:
  data_residency: self-hosted
  self_hosted: true
  gdpr_compliant: true
  license: "GPL-3.0"
  gaia_x: true
timeout_ms: 30000
tools:
  - name: get_visits_summary
    description: "Matomo Reporting API VisitsSummary.get"
    method: GET
    path: "/index.php"
    param_location: query
    input_schema:
      type: object
      properties:
        module: { type: string, default: "API" }
        method: { type: string, default: "VisitsSummary.get" }
        format: { type: string, default: "JSON" }

Champs principaux (structure HttpConnectorConfig, crates/forge-mcp/src/connector/http.rs) :

ChampRôle
id, display_nameIdentifiant unique et nom lisible
base_urlURL de base ; ${VAR:-défaut} est résolu depuis l'environnement au démarrage
base_url_envVariable portant l'URL propre à un locataire (instance auto-hébergée par client)
authMéthode d'authentification, discriminée par type
complianceMétadonnées de conformité UE, contrôlées à l'enregistrement
timeout_msDélai de la requête (30 000 par défaut)
cache_ttl_sCache de lecture des GET, désactivé à 0 (défaut) ; jamais actif dans un contexte locataire
rate_limit_per_minPlafond publié par l'amont, vérifié avant l'appel
tools[]name, description, method (GET, POST, PUT, PATCH, DELETE), path ({param} est remplacé par un argument), param_location (query, body ou path), input_schema (JSON Schema)

Types d'authentification : none, bearer, api_key, basic, query_token, jwt_exchange, oauth2, login_token, checksum, json_rpc_session. Les fichiers YAML ne portent jamais de secret : ils nomment la variable d'environnement qui le contient (token_env, key_env, entre autres).

Les outils sont exposés avec le préfixe de leur connecteur : l'outil get_visits_summary du connecteur matomo s'appelle matomo.get_visits_summary.

2. Connecteur natif Rust

Pour un protocole qui n'est pas du REST (par exemple l'XML-RPC d'Odoo, crates/forge-mcp/src/connector/odoo_xmlrpc_client.rs) ou une transformation lourde, on implémente le trait McpConnector (crates/forge-mcp/src/connector/mod.rs) :

#[async_trait::async_trait]
pub trait McpConnector: Send + Sync + 'static {
    fn id(&self) -> &str;
    fn display_name(&self) -> &str;
    fn compliance(&self) -> &EuCompliance;
    async fn list_tools(&self) -> ForgeResult<Vec<ToolDefinition>>;
    async fn execute(
        &self,
        tool_name: &str,
        arguments: serde_json::Value,
    ) -> ForgeResult<Vec<ContentBlock>>;
    async fn health_check(&self) -> ForgeResult<ConnectorHealth>;
    // ... plus des méthodes avec valeur par défaut (voir le fichier)
}

Un connecteur natif est enregistré dans le ConnectorRegistry au même titre qu'un connecteur YAML.

Contrôle de conformité UE

ConnectorRegistry::register appelle EuCompliance::validate. Un connecteur dont gdpr_compliant vaut false, ou dont la résidence des données n'est pas européenne (ou self-hosted), est rejeté au démarrage et journalisé. La classification de la résidence est centralisée dans crates/forge-mcp/src/connector/residence.rs. Côté exécution, chaque appel de serveur repasse par la fonction unique forge_core::compliance::is_server_allowed.

Cycle de vie

  1. Enregistrement : au démarrage, le CatalogueLoader charge les YAML et le registre reçoit aussi les connecteurs natifs.
  2. Découverte : le client MCP appelle tools/list sur POST /api/v1/mcp. Le catalogue se consulte aussi par GET /api/v1/mcp/catalogue.
  3. Exécution : le client appelle tools/call sur la même route.
  4. Résultat : le connecteur renvoie des blocs de contenu MCP (ContentBlock).

Chaîne verticale : un manifeste YAML ou un connecteur natif Rust sont enregistrés dans le registre avec contrôle de conformité UE, puis découverts par tools/list, exécutés par tools/call et rendus en blocs de contenu.

Figure 3 : du connecteur à l'outil MCP, avec le contrôle de conformité UE à l'enregistrement et à chaque appel.

Identifiants et secrets

  • Les identifiants tiers d'un locataire sont chiffrés en AES-256-GCM avant stockage. Au démarrage, crates/forge-api/src/connector_credential_env.rs les déchiffre et les publie dans les variables d'environnement que lisent les connecteurs. Les locataires réglementés peuvent utiliser une couche OpenBao.
  • À chaque requête, les secrets du seul locataire appelant sont installés pour la durée de l'appel. Avec FORGE_MULTI_TENANT_STRICT=1, le chargement global au démarrage est sauté et aucun connecteur ne retombe sur les identifiants globaux du déploiement.

Sécurité

  • SSRF : une URL de base fournie par un locataire (base_url_env) est contrôlée en deux temps avant tout appel réseau. Premier temps : analyse de l'URL (schéma, adresse, hôtes internes). Second temps : résolution DNS avec refus des adresses privées. Une violation renvoie Forbidden avec le motif SSRF_BLOCKED. Ce contrôle ne s'applique qu'aux URL fournies par un locataire : l'URL du YAML ou de l'environnement de l'opérateur n'y est pas soumise. Aucune option d'exploitation ne le désactive ; seule la compilation des tests le lève.
  • Actions irréversibles : un outil irréversible ne s'exécute qu'après une approbation humaine explicite, limitée au nom exact de l'outil (crates/forge-mcp/src/connector/human_authorization.rs). Un outil destructif n'est jamais autorisable par cette voie.
  • Un connecteur peut être limité à la lecture : le connecteur Matomo, par exemple, ne publie que des outils de rapport.

Bonnes pratiques

  • Connexions : un seul client reqwest réutilisé par connecteur.
  • Limites amont : déclarez rate_limit_per_min quand l'API publie un plafond ; une réponse 429 est renvoyée en RATE_LIMITED avec son Retry-After.
  • Cache : cache_ttl_s convient aux données publiques en lecture seule ; laissez-le à 0 pour tout le reste.
  • Données publiques : le champ grounded fait accompagner chaque réponse de sa source (source_url, retrieved_at).

Voir aussi

Documentation Swagger : contrat OpenAPI et authentification

forge-api sert son contrat OpenAPI lui-même, généré depuis le code avec la bibliothèque utoipa. Il n'existe pas d'interface Swagger UI servie par le backend : vous récupérez le document et l'ouvrez dans l'outil de votre choix (Swagger Editor, Postman, Insomnia, générateur de client).

Dans les exemples de ce livre, <hote-api> désigne le nom d'hôte de l'API, sans schéma : app.<domaine> derrière le nom public (voir Diagnostics et signalement). Sur un poste de développement, écrivez http://localhost:3000 à la place de https://<hote-api>.

Où récupérer le contrat

RouteContenu
GET /api/v1/openapi.jsonDocument OpenAPI en JSON
GET /api/v1/openapi.yamlLe même document en YAML
GET /openapi.jsonMême source, à la racine du serveur
GET /openapi.yamlMême source, à la racine du serveur

Ces routes sont publiques. La variable OPENAPI_ENABLED=false les coupe : elles répondent alors 404. Le champ servers du document vaut / parce que les chemins documentés portent déjà le préfixe /api/v1.

curl "https://<hote-api>/api/v1/openapi.json" -o forge-openapi.json

Ce que couvre le contrat, et ce qu'il ne couvre pas

Le contrat est partiel. Il se limite aux opérations annotées avec #[utoipa::path] dans crates/forge-api/src/openapi/. Mesures reproductibles :

FaitCommandeRésultat
Opérations annotéesgit grep -hoE '#\[utoipa::path\(' -- crates/forge-api/src/openapi | wc -l125
Chemins distinctsgit grep -hoE 'path = "/api/v1[^"]*"' -- crates/forge-api/src/openapi | sort -u | wc -l109
Appels .route( actifs dans router.rsgit grep -c '^\s*\.route(' -- crates/forge-api/src/router.rs793

Familles documentées (étiquettes du contrat) : santé, facturation, authentification, OAuth/OIDC, SSO, sessions, chat, passerelle de chat, messages de gateway, prédictions, documents (RAG, document store, scraping, chunks), clés d'API, compte, rôles.

Familles absentes du contrat : le transport MCP (/api/v1/mcp), le catalogue métier (/api/v1/mcp/catalog-business/*), la gestion des gateways (/api/v1/gateways/*), les retours (/api/v1/feedback), les outils, variables et identifiants. Pour ces routes, la référence est ce livre, qui les décrit une par une d'après le routeur.

Le document déclare trois schémas de sécurité : BearerAuth (JWT dans Authorization: Bearer), CookieAuth (cookie jwt) et ApiKeyAuth (en-tête X-API-Key). Seuls les deux premiers sont consommés par des routes aujourd'hui : ApiKeyAuth est déclaré sans route qui l'accepte.

Authentification

La majorité des routes exigent un jeton, donc un compte (Prise en main guidée, étape 1). Il s'obtient par la connexion, avec un second facteur (OTP e-mail ou application TOTP) lorsqu'il est exigé :

# 1. connexion
curl -X POST "https://<hote-api>/api/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"email":"<email>","password":"<mot-de-passe>"}'

La réponse porte requires_2fa. Quand il vaut false et que la connexion réussit, elle contient directement token : passez à l'envoi du jeton plus bas. Un e-mail inconnu ou un mot de passe erroné répond 401 (UNAUTHORIZED), et si requires_mfa_enrollment vaut true, aucun jeton n'est rendu : enrôlez d'abord un second facteur. Quand requires_2fa vaut true, la réponse contient aussi two_factor_token et method (email ou totp) :

# 2. validation du second facteur
curl -X POST "https://<hote-api>/api/v1/auth/2fa/verify" \
  -H "Content-Type: application/json" \
  -d '{"two_factor_token":"<two_factor_token>","code":"<code>"}'

La réponse est {"authenticated": true, "token": "<token>"}. Le renvoi du code par e-mail se fait par POST /api/v1/auth/2fa/resend. La connexion par fournisseur d'identité (OIDC) passe par GET /api/v1/auth/oidc/login.

Ensuite, joignez le jeton à chaque appel (les tutoriels le rangent dans la variable JWT) :

Authorization: Bearer <token>

Les navigateurs utilisent le cookie jwt posé par la connexion. Le jeton vit 7 jours par défaut (variable JWT_EXPIRY). POST /api/v1/auth/refresh (alias POST /api/v1/auth/refreshToken) renouvelle une session encore valide et rend {"token": ...} ; il n'existe pas de jeton de rafraîchissement séparé : un jeton expiré ne peut pas être renouvelé, il faut se reconnecter.

Quelques routes sont publiques (santé, contrat OpenAPI, conformité publique, prediction/{id} d'une gateway publiée, SBOM).

Provisionnement SCIM

Le provisionnement d'utilisateurs et de groupes suit SCIM 2.0 sous /api/v1/scim/v2/ : Users, Groups, ServiceProviderConfig, Schemas et ResourceTypes. Il s'authentifie par un jeton porteur SCIM dédié.

Format des erreurs

Une erreur est un objet {"error": {"code": "...", "message": "..."}} ; les erreurs de l'extracteur d'authentification ajoutent status. Codes fréquents : UNAUTHORIZED (401), FORBIDDEN (403), NOT_FOUND (404), VALIDATION_FAILED (422), FEATURE_PENDING (503, capacité prévue non livrée). Le dépassement de débit est différent : le limiteur répond 429 avec un corps vide et l'en-tête retry-after (en secondes). Le transport MCP répond, lui, en erreurs JSON-RPC (error.code, error.message) : voir Routes MCP.

Limites de débit

Le limiteur est par adresse IP et par préfixe de route (le préfixe de longueur maximale l'emporte) :

PréfixeDéfautRéglage
/api/v1/100 requêtes par secondeFORGE_RATE_LIMIT_PER_SEC
/api/v1/prediction (début de chemin : couvre aussi /api/v1/predictions)20 requêtes par minuteFORGE_RATE_LIMIT_PREDICTION_PER_MIN
/api/v1/stats/route-events30 requêtes par minutefixe

Les routes d'authentification ont en plus leurs propres limiteurs (auth_rate_limiter, account_rate_limiter).

Voir aussi

API-as-a-Service EU souverain

Ce chapitre décrit ce que la plateforme fait aujourd'hui pour exposer des sources de données européennes sous forme d'appels JSON structurés, et ce qui reste prévu. À la fin, vous savez ouvrir une session MCP, appeler un outil de connecteur (par session ou par appel direct) et lister le registre. Chaque route citée existe dans crates/forge-api/src/router.rs et chaque chiffre vient d'une commande que vous pouvez relancer.

Le principe

Une source de données (API publique d'une institution, service auto-hébergé) est décrite par un fichier YAML de connecteur dans connectors/. Au démarrage, forge-api charge ces fichiers dans un registre ; chaque outil déclaré devient un outil MCP nommé {id-du-connecteur}.{outil} (exemple : data-europa.search_datasets). Le client n'a pas à connaître l'API amont : il appelle l'outil, la plateforme exécute la requête et rend le résultat en JSON.

Mesures reproductibles :

FaitCommandeRésultat au moment de l'écriture
Fichiers de connecteursls connectors/*.yaml | wc -l195
Entrées du catalogue business embarquévoir catalog_embeds_full_business_catalogue dans crates/forge-api/src/routes/mcp_catalog_business.rs108

Les deux nombres sont distincts : le registre exécutable (les YAML) et le catalogue business (une liste de fiches de serveurs, voir le chapitre « Routes du catalogue métier »). Ne les confondez pas.

Appeler un connecteur

Deux chemins authentifiés mènent au même registre. Il faut un jeton (Swagger, section Authentification) et l'adresse de votre API : <hote-api> désigne le nom d'hôte de l'API, sans schéma (app.<domaine> derrière le nom public, voir Diagnostics et signalement). Sur un poste de développement, écrivez http://localhost:3000 à la place de https://<hote-api>.

1. Transport MCP (JSON-RPC, session). Ouvrez une session avec initialize, puis appelez tools/call en passant l'en-tête Mcp-Session-Id reçu :

# 1. ouvrir la session (l'identifiant de session revient dans l'en-tête de réponse)
curl -i -X POST "https://<hote-api>/api/v1/mcp" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"mon-client","version":"1.0.0"}}}'

# 2. appeler un outil de connecteur
curl -X POST "https://<hote-api>/api/v1/mcp" \
  -H "Authorization: Bearer <token>" \
  -H "Mcp-Session-Id: <session-id>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"data-europa.search_datasets","arguments":{"q":"energie","limit":5}}}'

La forme des réponses (result.type, result.content, error.code) est décrite dans Routes MCP.

2. Appel direct, sans session. POST /api/v1/mcp/catalog-business/tools/call prend {server, tool, args} et exécute l'outil dans le registre :

curl -X POST "https://<hote-api>/api/v1/mcp/catalog-business/tools/call" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"server":"data-europa","tool":"search_datasets","args":{"q":"energie","limit":5}}'

La réponse est {"success": true, "server": ..., "tool": ..., "result": ...} en cas de succès, ou {"success": false, "error": ...} (statut HTTP 200) si le connecteur est absent ou si l'exécution échoue. Un serveur absent de la liste des serveurs autorisés est refusé avant même la recherche dans le registre, par un 403 de corps {"error": {"code": "FORBIDDEN", ...}} dont le message dit « hors du plan ou non conforme EU ». Cette liste ne dépend pas du locataire (voir Connecteurs MCP).

Pour lister ce que le registre contient :

curl "https://<hote-api>/api/v1/mcp/catalogue" -H "Authorization: Bearer <token>"

La réponse est {"catalogue": [...], "total": N} ; chaque entrée porte l'id, le display_name et le bloc compliance (résidence des données, auto-hébergé, RGPD, licence, Gaia-X).

Sources européennes disponibles

Des connecteurs de sources publiques européennes existent dans connectors/ : eurlex, eurostat, cordis, openaire, europeana, ecb-data, europe-pmc, data-europa. Un méta-moteur de recherche auto-hébergé, searxng, déclare les outils query, config et health.

Ce qui n'existe pas : il n'y a pas de connecteur dédié aux sites de l'EDPB, de la CURIA, de l'EBA ou de l'ESMA. Les sources ci-dessus sont celles que le dépôt livre ; toute autre source passe par l'ajout d'un fichier YAML de connecteur.

Garde-fous réellement en place

  • Authentification : les deux chemins exigent un jeton (Authorization: Bearer ou cookie jwt). Une session MCP est liée à l'utilisateur qui l'a ouverte.
  • Conformité UE : chaque appel d'outil passe par un point d'étranglement de conformité avant l'exécution (is_server_allowed dans forge-core).
  • Plafond amont : le champ rate_limit_per_min du YAML d'un connecteur plafonne les appels sortants vers la source.
  • Secrets : les identifiants d'un locataire sont chiffrés au repos (AES-256-GCM) et résolus à la requête ; ils ne sont jamais renvoyés en clair.
  • Inventaire logiciel : le SBOM CycloneDX du binaire servi est public sur GET /.well-known/sbom (hors préfixe /api/v1).
  • Analyse d'images : l'analyse Trivy des images est exécutée en CI (workflow de CI du dépôt), pas au moment d'un appel d'API.

Ce qui est prévu, et ce qui est retiré

SujetStatutRéférence
Déploiement de conteneurs par l'API (deploy, start, stop, restart)Prévu : ces routes répondent aujourd'hui 503 FEATURE_PENDINGspec 16, tâche P5.5 (route d'opérations de déploiement)
Extraction de contenu de pages web par un service d'exploration dédiéRetiré de ce chapitre : aucune tâche de spec ne le porteaucune
Offres tarifaires « Standard / Premium / Enterprise » par connecteurRetiré : aucune tâche de spec ni aucune route de facturation par connecteuraucune
Recherche par connecteur sous un préfixe mcp/gatewaysN'existe pas : ce préfixe n'est monté nulle part ; utilisez tools/callaucune

Voir aussi

Routes MCP (Streamable HTTP)

Le transport MCP de la plateforme suit le protocole Streamable HTTP, révision 2025-03-26 (constante MCP_PROTOCOL_VERSION dans forge-mcp). Les échanges sont du JSON-RPC 2.0. La route est déclarée dans crates/forge-api/src/router.rs et ses gardes d'authentification dans crates/forge-api/src/routes/mcp.rs.

Désactivation. Le groupe /api/v1 se coupe avec API_ENABLED=false, et le transport MCP avec MCP_ENABLED=false (ou API_ENABLED=false). Une surface coupée répond un 404 JSON, jamais un 403.

Transport principal

MéthodeRouteRôle
POST/api/v1/mcpRequête JSON-RPC (un objet par requête)
GET/api/v1/mcpFlux SSE d'une session
DELETE/api/v1/mcpFermer une session (204)

Les trois exigent un jeton (Authorization: Bearer <token> ou cookie jwt). <hote-api> est défini dans Swagger. Une session est liée à l'utilisateur qui l'a ouverte : l'identité passée dans les paramètres d'initialize est écrasée par celle du jeton, et une session qui n'appartient pas à l'appelant répond 404 avec le code JSON-RPC -32600 (« session inconnue »).

Diagramme de séquence entre le client, la passerelle MCP et Valkey : initialize crée la session, puis tools/list, tools/call, le flux SSE et DELETE qui la ferme.

Figure 4 : une session MCP, de initialize à DELETE.

POST /api/v1/mcp

En-têtes : Content-Type: application/json, et Mcp-Session-Id: <session-id> pour toutes les méthodes sauf initialize et ping.

Un seul objet JSON-RPC par requête. Le corps est désérialisé en une requête unique : un tableau (batch JSON-RPC) n'est pas accepté. Pour enchaîner plusieurs appels, envoyez plusieurs requêtes.

Méthodes JSON-RPC traitées (liste du match de mcp_post_handler) :

MéthodeRôle
initializeOuvre une session, renvoie les capacités et l'en-tête Mcp-Session-Id
pingTest de vie
tools/listOutils disponibles (connecteurs autorisés pour la plateforme)
tools/callExécute un outil
resources/list, resources/readRessources MCP
prompts/list, prompts/getModèles de prompts
completion/completeComplétion d'arguments
logging/setLevelNiveau de journalisation

Toute autre méthode répond -32601 (« method not found »). Un corps qui n'est pas une requête JSON-RPC valide répond 400 avec -32700.

initialize

curl -i -X POST "https://<hote-api>/api/v1/mcp" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"mon-client","version":"1.0.0"}}}'

La réponse contient protocolVersion, les capabilities (tools, resources, prompts, completion, logging) et serverInfo (name: "chatbotaurus-forge"). L'identifiant de session est dans l'en-tête de réponse mcp-session-id. Copiez-le dans une variable (export SESSION=<session-id>) : les appels suivants le renvoient dans l'en-tête Mcp-Session-Id.

tools/list

curl -X POST "https://<hote-api>/api/v1/mcp" \
  -H "Authorization: Bearer <token>" \
  -H "Mcp-Session-Id: <session-id>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'

La réponse porte result.tools, une liste d'objets name, description, inputSchema et connector_id. Les noms d'outils ont la forme {id-du-connecteur}.{outil}. Prenez les noms exacts dans la réponse de tools/list, jamais dans un exemple de document.

tools/call

curl -X POST "https://<hote-api>/api/v1/mcp" \
  -H "Authorization: Bearer <token>" \
  -H "Mcp-Session-Id: <session-id>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"data-europa.search_datasets","arguments":{"q":"energie","limit":5}}}'

Réponse : statut HTTP 200 et un objet JSON-RPC. En cas de succès, result.type vaut success et result.content est une liste de blocs (type, text). Avant l'exécution, un échec est un objet error à la place de result, et error.code reprend le code HTTP de l'échec tout en gardant le statut HTTP 200 : 401 session expirée, 403 serveur absent de la liste autorisée, 404 outil inconnu. Si le connecteur lui-même échoue, result.type vaut error et result porte code et message, toujours avec le statut HTTP 200.

Sans Mcp-Session-Id, la réponse est 400 (-32600, « missing Mcp-Session-Id »). Une session expirée ou inconnue répond 401 : en statut HTTP pour tools/list, dans error.code pour tools/call.

GET /api/v1/mcp

Ouvre un flux text/event-stream pour la session désignée par Mcp-Session-Id. Le flux envoie un événement open ({"sessionId": ...}) puis un commentaire de maintien de connexion toutes les 30 secondes.

Capacité en sommeil. Les capacités annoncent tools.listChanged, mais aucune notification n'est poussée aujourd'hui sur ce flux : seuls l'événement open et les signaux de maintien sont émis (commentaire du code dans mcp_get_handler). Ne bâtissez pas de logique client sur des notifications serveur.

DELETE /api/v1/mcp

Ferme la session de Mcp-Session-Id, libère ses ressources et inscrit la fermeture au journal d'audit. Réponse 204 No Content.

Sessions

  • Chaque session est un UUID, stocké dans Valkey.
  • Durée de vie par défaut : 30 minutes (DEFAULT_SESSION_TTL dans forge-mcp/src/session.rs). Chaque tools/call rafraîchit ce délai.
  • La session est vérifiée à chaque requête ; si le magasin de sessions est indisponible, la réponse est 503 (-32603).

Catalogue des connecteurs

MéthodeRouteRôle
GET/api/v1/mcp/catalogueConnecteurs du registre
GET/api/v1/mcp/catalogue/{id}Un connecteur
GET/api/v1/mcp/catalogAlias de /mcp/catalogue
GET/api/v1/mcp/connectorsAlias de /mcp/catalogue

Ces routes exigent un jeton. GET /api/v1/mcp/catalogue renvoie {"catalogue": [{"id", "display_name", "compliance": {...}}], "total": N}.

curl "https://<hote-api>/api/v1/mcp/catalogue" -H "Authorization: Bearer <token>"

La fiche descriptive des serveurs business (catégorie, fournisseur, pays, certifications) est servie par /api/v1/mcp/catalog-business, décrit dans le chapitre « Routes du catalogue métier ».

Documentation de l'API

Il n'existe pas de serveur de documentation séparé. Le contrat OpenAPI est servi par forge-api lui-même (voir le chapitre « Swagger »).

Voir aussi

Routes du catalogue métier

Le catalogue business est la liste des serveurs MCP que la plateforme sait décrire et proposer. Toutes les routes vivent sous /api/v1/mcp/catalog-business (il n'existe aucun préfixe mcp/gateways : d'anciennes versions de ce livre le citaient à tort). Elles sont déclarées dans crates/forge-api/src/router.rs et implémentées dans crates/forge-api/src/routes/mcp_catalog_business.rs.

Authentification. Toutes ces routes exigent un jeton (Authorization: Bearer <token> ou cookie jwt). Les opérations de cycle de vie sont de plus réservées aux rôles admin et owner : un autre rôle reçoit 403 FORBIDDEN.

<hote-api> est défini dans Swagger.

État réel. La lecture du catalogue est opérationnelle. Les opérations qui piloteraient des conteneurs (deploy, start, stop, restart, secrets, security, déploiement de profil) répondent aujourd'hui 503 avec le code FEATURE_PENDING : l'adaptateur Podman n'est pas branché sur forge-api. C'est une capacité prévue (spec 16, tâche P5.5 ; voir la section « Cycle de vie : prévu, répond 503 » plus bas), pas une capacité livrée.

Lecture du catalogue

MéthodeRouteRôle
GET/api/v1/mcp/catalog-businessListe des fiches de serveurs
GET/api/v1/mcp/catalog-business/{id}Fiche d'un serveur
GET/api/v1/mcp/catalog-business/{id}/statusDisponibilité au registre
GET/api/v1/mcp/catalog-business/profilesProfils de déploiement
GET/api/v1/mcp/catalog-business/deployedServeurs prouvés opérationnels
GET/api/v1/mcp/catalog-business/toolsOutils MCP exposés par la passerelle
GET/api/v1/mcp/catalog-business/{id}/registry-toolsOutils d'un connecteur du registre
POST/api/v1/mcp/catalog-business/tools/callExécuter un outil de connecteur
GET/api/v1/stats/catalog-businessCompteurs des modèles personnalisés, pas du catalogue (voir la note plus bas)

GET /api/v1/mcp/catalog-business

Paramètre de requête : category (valeur exacte d'une catégorie, par exemple Communication ou CRM%20%26%20ERP une fois encodé ; all ou vide = pas de filtre). Le paramètre tier est accepté mais n'est pas appliqué : le catalogue renvoie tous les serveurs et le client filtre.

curl "https://<hote-api>/api/v1/mcp/catalog-business?category=Communication" \
  -H "Authorization: Bearer <token>"

Réponse : {"servers": [...], "total": N}. Il n'y a pas de pagination. Une fiche porte ces champs, lus dans routes/data/catalog-business.json :

{
  "id": "odoo",
  "name": "Odoo",
  "description": "ERP/CRM open source complet: ventes, achats, stock, comptabilite, RH et plus.",
  "category": "CRM & ERP",
  "iconName": "Briefcase",
  "provider": "Odoo SA",
  "country": "Belgique",
  "endpoints": 331,
  "status": "available",
  "certifications": ["RGPD", "ISO27001", "SOC2", "Gaia-X"],
  "license": "LGPL-3.0",
  "documentation": "https://www.odoo.com/documentation",
  "verified": true,
  "pullCount": 1247,
  "tags": ["erp", "crm", "comptabilite", "rh", "stock", "ventes"],
  "version": "17.0",
  "tier": "official"
}

Le catalogue embarqué contient 108 fiches (test catalog_embeds_full_business_catalogue). GET .../{id} renvoie la fiche seule, ou 404 NOT_FOUND si l'identifiant est inconnu.

Les champs certifications, verified et pullCount sont des valeurs écrites dans le fichier embarqué. Aucun code de la plateforme ne les calcule ni ne les vérifie : ne les lisez ni comme une certification obtenue, ni comme un compteur de téléchargements mesuré.

GET /api/v1/mcp/catalog-business/{id}/status

Rend l'état honnête d'un serveur : sa disponibilité au registre, pas celle d'un conteneur.

{
  "serverId": "odoo",
  "containerId": null,
  "port": null,
  "uptime": null,
  "startedAt": null,
  "status": "available",
  "proven_operational": true,
  "runtime": { "known": false, "reason": "podman_adapter_not_wired" }
}

status vaut available si le connecteur est dans le registre, sinon not_registered. Un identifiant absent du catalogue rend 404.

GET /api/v1/mcp/catalog-business/profiles

Les profils sont lus dans le fichier de profils du dépôt. La réponse est {"profiles": [...]}. Il y en a quatre :

ProfilServeurs
Solo1
Starter5
Business12
Enterprisetous les serveurs du fichier (37)

Ces 37 serveurs sont ceux du fichier de profils, pas les 108 fiches du catalogue embarqué : ce sont deux inventaires différents.

GET /api/v1/mcp/catalog-business/deployed

Rend la liste des identifiants de serveurs prouvés opérationnels par un audit en direct (OPERATIONAL_PROVEN_LIVE, dans forge-core), sous la forme d'un tableau JSON d'identifiants. Ce n'est pas un inventaire de conteneurs Podman.

Exécuter un outil

POST /api/v1/mcp/catalog-business/tools/call prend server, tool et args (forme de la réponse : voir API-as-a-Service EU souverain) :

curl -X POST "https://<hote-api>/api/v1/mcp/catalog-business/tools/call" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"server":"searxng","tool":"query","args":{"q":"reglement ia"}}'

GET .../{id}/registry-tools liste les outils d'un connecteur et répond {"id": ..., "registry_tools": [...]} ; pour un identifiant absent du registre, la réponse reste 200 avec "registry_tools": [] et un champ error. GET .../tools répond {"tools": [...], "total": N} : les outils des connecteurs autorisés. La route voisine GET .../{id}/tools répond toujours {"id": ..., "tools": []} : elle est un emplacement de compatibilité, utilisez registry-tools.

Note sur GET /api/v1/stats/catalog-business. Cette route compte les lignes de la table des modèles personnalisés et renvoie {"total": N, "last_24h": M}. Elle ne décrit pas le catalogue de serveurs.

Cycle de vie : prévu, répond 503

MéthodeRouteRôle requisRéponse aujourd'hui
POST/api/v1/mcp/catalog-business/{id}/deployadmin, owner503 FEATURE_PENDING
POST/api/v1/mcp/catalog-business/{id}/startadmin, owner503 FEATURE_PENDING
POST/api/v1/mcp/catalog-business/{id}/stopadmin, owner503 FEATURE_PENDING
POST/api/v1/mcp/catalog-business/{id}/restartadmin, owner503 FEATURE_PENDING
POST/api/v1/mcp/catalog-business/profiles/{name}/deployadmin, owner503 FEATURE_PENDING
POST/api/v1/mcp/catalog-business/{id}/secretsadmin, owner503 FEATURE_PENDING
GET/api/v1/mcp/catalog-business/{id}/securitytout utilisateur connecté503 FEATURE_PENDING

Un appelant sans rôle admin ou owner reçoit d'abord 403 (et la tentative est auditée) ; un administrateur reçoit le 503. La réponse porte l'en-tête Retry-After: 86400 et ce corps :

{
  "error": {
    "code": "FEATURE_PENDING",
    "message": "MCP catalog-business lifecycle deferred to spec 16 REQ-5 (POST <route de deploiement prevue>) + Podman socket mount for forge-api"
  },
  "feature_pending": "catalog_business",
  "tracking": "V1: routes/mcp-streamable-http/index.ts L370-377"
}

Conséquences pour votre intégration : ne programmez pas de déploiement par cette API aujourd'hui. Le rapport de scan Trivy et le SBOM par serveur ne sont pas servis par .../{id}/security (503). Le SBOM CycloneDX de la plateforme elle-même est public sur GET /.well-known/sbom. Les secrets d'un locataire se gèrent par /api/v1/credentials (voir le chapitre « Routes des ressources »).

Voir aussi

Routes des gateways et de la prédiction

Une gateway est un assistant conversationnel : un graphe de workflow (flow_data) rattaché à un espace de travail, qui peut être publié pour un usage public. Ce chapitre décrit les routes réelles sous /api/v1/gateways, les messages, la prédiction (envoi d'une question), les retours utilisateur, le « warm start » et les sondes de santé.

Convention : les corps de requête et de réponse des routes de ce chapitre sont du JSON en snake_case (sauf mention contraire). Une erreur a la forme {"error": {"code": "...", "message": "..."}}, sauf le dépassement de débit (429, corps vide : voir Swagger). Les listes sont des objets à clé nommée (par exemple {"gateways": [...], "total": N} pour GET /api/v1/gateways) ; le serveur n'ajoute pas d'enveloppe générique {data, meta}.

Gestion des gateways

Toutes ces routes exigent un jeton (Authorization: Bearer <token>) et sont cloisonnées par organisation : un espace de travail hors de votre périmètre est refusé. L'identifiant d'espace de travail (workspace_id) se lit par GET /api/v1/workspaces (réponse {"workspaces": [...], "total": N}, avec l'id de chaque espace). Parcours minimal pour exposer un assistant : POST /api/v1/gateways, puis POST /api/v1/gateways/{id}/publish, puis POST /api/v1/prediction/{id}. <hote-api> est défini dans Swagger.

MéthodeRouteRôle
GET/api/v1/gatewaysListe (filtre ?workspace_id=)
POST/api/v1/gatewaysCréer
GET/api/v1/gateways/{id}Détail, avec flow_data
PUT/api/v1/gateways/{id}Mettre à jour
DELETE/api/v1/gateways/{id}Supprimer (204)
POST/api/v1/gateways/{id}/publishPublier (génère le jeton public)
POST/api/v1/gateways/{id}/unpublishDépublier
POST/api/v1/gateways/{id}/regenerate-tokenRégénérer le jeton public
POST/api/v1/gateways/{id}/transferTransférer vers un autre espace de travail
POST/api/v1/gateways/transfer-batchTransfert en masse
GET/api/v1/gateways/{id}/budgetLire le budget mensuel de jetons
PATCH/api/v1/gateways/{id}/budgetFixer le budget mensuel de jetons

POST /api/v1/gateways

Corps (structure CreateGatewayRequest) : name et workspace_id sont obligatoires ; flow_data est une chaîne JSON ; gateway_type, chatbot_config et deployed sont facultatifs.

curl -X POST "https://<hote-api>/api/v1/gateways" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Assistant comptabilite","workspace_id":"<uuid-espace>","flow_data":"{\"nodes\":[],\"edges\":[]}","deployed":false}'

Réponse 201 avec la gateway : id, name, type, deployed, is_public, category, workspace_id, created_at, updated_at, approval_required, et public_token / public_expires_at / flow_data / last_transfer quand ils existent (flow_data n'est pas renvoyé dans la liste). Le plafond du plan est appliqué à la création : au-delà du quota de gateways ou de workflows, la réponse est un refus de quota (402, ou 503 si le quota ne peut pas être évalué).

PUT /api/v1/gateways/{id} accepte, tous facultatifs : name, flow_data, deployed, is_public, chatbot_config, api_config, category et approval_required (supervision humaine par gateway).

Publication

curl -X POST "https://<hote-api>/api/v1/gateways/<gateway-id>/publish" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"expires_at":"2027-01-31T23:59:59Z"}'

Le corps JSON est attendu même sans expiration : envoyez {}. expires_at (RFC 3339) est facultatif ; une valeur mal formée est refusée plutôt qu'ignorée (400, code VALIDATION_ERROR). Pour une gateway dont le graphe désigne un patient (lien patient), l'expiration est obligatoire en pratique : sans expires_at elle vaut 30 jours, au-delà de 90 jours ou dans le passé la publication est refusée (constantes fixées dans le code). La réponse est la gateway à jour, avec son public_token.

Transfert, budget

POST .../transfer prend to_workspace_id (obligatoire), reason et transmission_note. POST /api/v1/gateways/transfer-batch prend from_workspace_id, to_workspace_id et, facultativement, gateway_ids, reason, transmission_note. PATCH .../budget prend {"monthly_limit": <entier>} ; 0 signifie illimité.

Historique des conversations

MéthodeRouteRôle
GET/api/v1/gateways/{id}/chat-sessionsConversations d'une gateway, par date décroissante
GET/api/v1/gateways/{id}/chat-messagesMessages d'une conversation
GET/api/v1/gateway-messagesListe paginée des messages de votre organisation
POST/api/v1/gateway-messagesEnregistrer un message
GET/api/v1/gateway-messages/{id}Un message
DELETE/api/v1/gateway-messages/{id}Supprimer un message (204)

GET .../chat-messages prend chatId (la conversation) et order (ASC par défaut, ou DESC). GET .../chat-sessions accepte chatType mais ne filtre pas dessus : la plateforme n'enregistre pas le canal d'une conversation.

curl "https://<hote-api>/api/v1/gateways/<gateway-id>/chat-messages?chatId=conv-123&order=ASC" \
  -H "Authorization: Bearer <token>"

GET /api/v1/gateway-messages prend limit et offset et renvoie {"gateway_messages": [...], "total": N, "offset": ..., "limit": ...}. POST /api/v1/gateway-messages prend role, mcp_gateway_id, content, chat_type et chat_id (et session_id facultatif). Un message d'une gateway d'une autre organisation répond 403.

Prédiction : poser une question

MéthodeRouteAccès
POST/api/v1/prediction/{id}Public : gateway publiée et non expirée, sinon 404
POST/api/v1/predictionsAuthentifié, complétion LLM directe
POST/api/v1/predictions/streamAuthentifié, flux SSE

POST /api/v1/prediction/{id}

{id} est l'identifiant de la gateway. Cette route sert le widget intégrable ; elle ne demande pas de jeton, mais la gateway doit être publiée. Corps : question (ou message), sessionId facultatif, streaming facultatif (accepté, mais la réponse est toujours consolidée en un seul bloc).

curl -X POST "https://<hote-api>/api/v1/prediction/<gateway-id>" \
  -H "Content-Type: application/json" \
  -d '{"question":"Quels sont les clients avec un chiffre d affaires superieur a 100k ?","sessionId":"conv-123"}'

Réponse (forme de la branche d'exécution d'outil) :

{
  "gateway_id": "<uuid>",
  "chat_id": "conv-123",
  "text": "Voici les clients...",
  "response": "Voici les clients...",
  "generated_by": { "...": "marquage IA" },
  "agent": {
    "tool": "<outil utilisé>",
    "module": "<module>",
    "resolution_path": "<chemin de résolution>",
    "confidence": 0.9
  }
}

Cas particuliers : 400 MISSING_QUESTION si ni question ni message ; 403 SECURITY_BLOCKED si le garde d'injection de prompt bloque l'entrée ; une demande de conseil clinique reçoit un refus rédigé avec refusal_reason. POST /api/v1/prediction (sans identifiant) répond 412 ID_REQUIRED. Le quota par défaut est de 20 requêtes par minute et par adresse IP sur le préfixe /api/v1/prediction (variable FORGE_RATE_LIMIT_PREDICTION_PER_MIN). Le limiteur compare le début du chemin : /api/v1/predictions et /api/v1/predictions/stream tombent dans le même seau.

POST /api/v1/predictions

Complétion directe, jeton obligatoire. Corps : prompt (obligatoire), system, model, max_tokens, temperature, session_id. Réponse : {"text", "model", "tokens", "latency_ms", "generated_by"}.

Retours utilisateur

MéthodeRouteRôle
POST/api/v1/feedbackCréer un retour (201)
GET/api/v1/feedbackLister (filtres gateway_id, chat_id, rating)
GET/api/v1/feedback/{id}Un retour
PUT/api/v1/feedback/{id}Mettre à jour

Corps de création : message_id (uuid), gateway_id (uuid), chat_id, rating (thumbs_up, thumbs_down ou null) et content. Un autre rating répond 422 VALIDATION_FAILED.

Warm start

MéthodeRouteRôle
GET/api/v1/mcp/warm-start?userId=<uuid>Test de reconnexion

Capacité en sommeil. Cette route répond aujourd'hui toujours {"warmStart": false, "predictiveQuestion": null, ...} avec le drapeau "shim_pending_v2_1": true. La détection d'inactivité et la question prédictive ne sont pas livrées ; elles sont portées par la tâche T-V1M2-ENGINES-04 de la spec 23. Le userId doit être le vôtre (un rôle admin ou owner peut interroger un autre utilisateur) ; sinon 403, et 400 si userId est absent.

Santé

MéthodeRouteContenu
GET/api/v1/healthProcessus vivant : status, service, version (+ sha)
GET/api/v1/healthzAlias de /health
GET/api/v1/readyzPostgreSQL, Valkey, nombre de connecteurs ; 503 si dégradé
GET/api/v1/health/statusPage de statut : PostgreSQL, Ollama, Qdrant, Authentik, SMTP ; 503 si overall vaut down

Ces quatre routes sont publiques (voir Supervision). readyz ne sonde que PostgreSQL et Valkey ; l'état d'Ollama et de Qdrant se lit dans /api/v1/health/status.

curl "https://<hote-api>/api/v1/readyz"

Voir aussi

  • Chat : la page qui consomme ces routes, onglets, historique et messages proactifs
  • Routes des ressources : document stores, identifiants et variables rattachés aux espaces de travail
  • Documentation Swagger : obtention du jeton, format des erreurs et limites de débit
  • Routes MCP : transport MCP par session, pour appeler directement les outils
  • Analytique : mesures de conversations et de messages dans l'application

Routes des ressources

Ce chapitre décrit les ressources que votre organisation gère par l'API : les document stores (base de connaissances vectorielle), les outils, les variables, les identifiants, les statistiques et la conformité. Toutes les routes sont sous /api/v1, exigent un jeton (Authorization: Bearer <token>) sauf mention contraire, et sont cloisonnées par organisation. <hote-api> est défini dans Swagger.

Document Store (Qdrant)

Un document store est une collection vectorielle (Qdrant) cloisonnée par organisation, utilisée pour la recherche sémantique. L'identifiant du store sert de nom de collection.

MéthodeRouteRôle
GET/api/v1/document-store/storeListe des stores
POST/api/v1/document-store/storeCréer un store
GET/api/v1/document-store/store/{id}Détail d'un store
PUT/api/v1/document-store/store/{id}Mettre à jour (name, description, loaders, whereUsed)
DELETE/api/v1/document-store/store/{id}Supprimer
POST/api/v1/document-store/upsert/{id}Découper, vectoriser et indexer un texte
POST/api/v1/document-store/vectorstore/queryRecherche sémantique
POST/api/v1/document-store/scrape/pageRécupérer une page, indexation facultative
POST/api/v1/document-store/crawlLancer un crawl en arrière-plan (202)
GET/api/v1/document-store/crawl-progress/{crawl_id}Avancement d'un crawl

Créer un store

Corps : name et workspace_id obligatoires, description facultatif.

curl -X POST "https://<hote-api>/api/v1/document-store/store" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Base juridique","workspace_id":"<uuid-espace>"}'

Réponse 201 : le nouveau store, avec id (c'est le <store-id> des commandes suivantes), name, description, status, workspace_id et created_date.

Indexer un texte

POST /api/v1/document-store/upsert/{id} : {id} est l'identifiant du store. Corps : content (le texte), source_id et metadata facultatifs. La réponse est {"store_id", "source_id", "chunks_ingested"}. L'ingestion est soumise au quota de vecteurs du plan (refus 402, ou 503 si le décompte n'est pas possible).

curl -X POST "https://<hote-api>/api/v1/document-store/upsert/<store-id>" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"content":"Le droit a l oubli est prevu par l article 17 du RGPD.","source_id":"rgpd-art-17"}'

Interroger

curl -X POST "https://<hote-api>/api/v1/document-store/vectorstore/query" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"query":"droit a l oubli","store_id":"<store-id>"}'

Réponse : {"query", "store_id", "results": [...], "total": N}.

Récupérer et crawler une page

POST .../scrape/page prend url et, pour indexer le résultat, store_id. POST .../crawl prend url et store_id et répond 202 avec un crawl_id à suivre sur GET .../crawl-progress/{crawl_id}.

Ce qui n'existe pas, ou ne fonctionne pas encore

  • Il n'y a pas de route .../store/{id}/upload (téléversement multipart), ni .../store/{id}/crawl, ni .../store/{id}/chunks. L'indexation de texte passe par upsert/{id}. Un chunk se modifie (PUT) et se supprime (DELETE) sur /api/v1/document-store/chunks/{store_id}/{loader_id}/{chunk_id}. Ses métadonnées se modifient (PATCH) sur le même chemin suivi de /metadata. Il n'y a pas de lecture (GET) sur ce chemin : les chunks se lisent par GET /api/v1/documents/{doc_id}/chunks et GET /api/v1/doc-chunks/{id}.
  • Trois routes de loader répondent 503 FEATURE_PENDING (capacité en sommeil, la réponse l'annonce au lieu de simuler un succès) : POST /api/v1/document-store/loader/process/{loader_id}, POST /api/v1/document-store/loader/upload-url et POST /api/v1/document-store/loader/upload-table.
  • POST /api/v1/document-store/refresh et .../refresh/{store_id} accusent réception ("status": "queued") sans lancer de traitement.
  • Pour les documents bruts (fichiers), voir aussi /api/v1/documents et /api/v1/attachments.

Outils personnalisés

MéthodeRouteRôle
GET/api/v1/toolsListe
POST/api/v1/toolsCréer
GET/api/v1/tools/{id}Détail
PUT/api/v1/tools/{id}Mettre à jour
DELETE/api/v1/tools/{id}Supprimer

Corps de création, en camelCase : name, description, color, iconSrc, schema (chaîne), func (chaîne), workspaceId.

Variables

MéthodeRouteRôle
GET/api/v1/variablesListe
POST/api/v1/variablesCréer
GET/api/v1/variables/{id}Détail
PUT/api/v1/variables/{id}Mettre à jour
DELETE/api/v1/variables/{id}Supprimer

Corps de création : name, workspace_id obligatoires ; value et type facultatifs.

Identifiants

MéthodeRouteRôle
GET/api/v1/credentialsListe (valeurs masquées)
POST/api/v1/credentialsCréer
GET/api/v1/credentials/{id}Détail (valeur masquée)
PUT/api/v1/credentials/{id}Mettre à jour
DELETE/api/v1/credentials/{id}Supprimer
curl -X POST "https://<hote-api>/api/v1/credentials" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"name":"Ma cle de service","value":"<secret>"}'

Pour brancher un connecteur, envoyez credentialName et plainDataObj (un objet de champs) à la place de value, comme à l'étape 1 de Connecter Odoo à la passerelle MCP. workspaceId est facultatif (par défaut, le premier espace accessible). La réponse est 201, avec la fiche : id, name, credential_name, masked_value, workspace_id, created_at et updated_at.

La valeur est chiffrée au repos (AES-256-GCM, clé dérivée par identifiant) et n'est jamais renvoyée en clair : les réponses portent une valeur masquée. PUT et DELETE sur /api/v1/credentials sans identifiant sont refusés par conception (412).

Statistiques

MéthodeRouteRôle
GET/api/v1/statsTableau de bord global (rôle admin ou owner)
GET/api/v1/stats/gateways{"total", "last_24h"} des gateways
GET/api/v1/stats/tools{"total", "last_24h"} des outils (last_24h répète total : un outil n'a pas de date de création)

/api/v1/stats/dashboard est un autre chemin vers le même tableau de bord. La famille /api/v1/stats/* compte plus de vingt autres routes de lecture (leads, workflows, security, latency, ollama, entre autres). La liste complète est dans le contrat de routes de router.rs.

Conformité et audit

MéthodeRouteAccès
GET/api/v1/compliance/statusPublic : statut gradué RGPD / AI Act
GET/api/v1/compliance/reportPublic
GET/api/v1/compliance/privacyPublic
GET/api/v1/compliance/model-cardsPublic
GET/api/v1/compliance/manifestPublic : manifeste de confiance signé
GET/api/v1/compliance/system-cardPublic
GET/api/v1/admin/auditJournal d'audit chaîné (rôles admin et owner)
GET/api/v1/admin/audit/headTête de la chaîne
GET/api/v1/admin/audit/statsStatistiques du journal
GET/api/v1/admin/audit/exportExport de la chaîne

/api/v1/compliance/status rend des statuts gradués (par exemple "gdpr": {"status": "partial", ...} et "ai_act": {"status": "in_progress", ...}), dérivés de signaux réels, jamais une affirmation figée de conformité totale.

Il n'existe pas de sous-route rgpd ni audit-log sous compliance (d'anciennes versions de ce livre les citaient). Le journal d'audit se lit sur /api/v1/admin/audit. La route GET /api/v1/audit/events existe mais répond 501 : elle n'est pas branchée sur le registre, et sa réponse nomme la route canonique.

Voir aussi

Créer votre premier connecteur MCP

Ce tutoriel décrit le chemin réel pour ajouter un service HTTP à la passerelle MCP de Chatbotaurus : un fichier YAML déclaratif, une ligne dans la liste des serveurs autorisés, des identifiants chiffrés, puis un appel de test. Il s'adresse à un contributeur qui travaille sur le dépôt. À la fin, l'outil de votre service figure dans tools/list et un appel tools/call en rend les données.

Prérequis

  • Chatbotaurus installé et fonctionnel (voir Installation).
  • Le dépôt cloné : le connecteur est un fichier du dépôt, pas un réglage de l'interface.
  • Python 3 pour le validateur de connecteurs.
  • Un jeton de session d'un compte du locataire, obtenu comme décrit dans Swagger (section Authentification), puis rangé dans la variable JWT : export JWT=<token>.
  • De quoi reconstruire le backend : l'étape 3 modifie du code Rust, compilé dans le binaire.
  • Un accès au service que vous branchez (adresse et clé), avec les seuls droits utiles.

Les commandes de ce tutoriel visent le backend local http://localhost:3000. Sur un déploiement, remplacez cette adresse par celle de votre API (https://<hote-api> dans les chapitres API).

Ce qu'est un connecteur

Un connecteur déclaratif est un fichier connectors/<id>.yaml. Au démarrage, forge-api lit tous les fichiers de ce dossier, remplace les ${VAR:-défaut} par l'environnement, et enregistre un connecteur HTTP dans le registre. Un fichier invalide est ignoré avec un message de journal : il ne fait pas échouer le démarrage, il disparaît. C'est la première chose à vérifier quand un connecteur « n'apparaît pas ».

Un connecteur n'est pas un module Rust à écrire. Pour un service HTTP, le YAML suffit. Le code Rust n'intervient que pour des protocoles qui ne sont pas du HTTP (c'est le cas d'Odoo, dispatché en XML-RPC).

Étape 1 : partir du gabarit

Copiez le gabarit, qui est la forme de référence maintenue avec le parseur :

cp connectors/TEMPLATE.yaml connectors/mon-service.yaml

Remplissez les champs obligatoires :

id: mon-service                         # kebab-case, identique au nom de fichier
display_name: "Mon Service"
upstream_status: a_verifier             # hebergeable | a_verifier | non_http

base_url: "${MON_SERVICE_URL:-https://api.mon-service.eu}"
base_url_env: MON_SERVICE_URL

auth: { type: bearer, token_env: MON_SERVICE_API_KEY }

compliance:
  data_residency: self-hosted
  self_hosted: true
  gdpr_compliant: true
  license: "MIT"
  gaia_x: true

timeout_ms: 30000

tools:
  - name: mon_service_list_items
    description: "Lister les éléments, avec filtres optionnels."
    method: GET
    path: "/items"
    param_location: query
    input_schema:
      type: object
      properties:
        limit: { type: integer }

  - name: mon_service_get_item
    description: "Récupérer un élément par identifiant."
    method: GET
    path: "/items/{id}"
    param_location: path
    input_schema:
      type: object
      properties:
        id: { type: string }
      required: [id]

  - name: mon_service_create_item
    description: "Créer un élément."
    method: POST
    path: "/items"
    param_location: body
    input_schema:
      type: object
      properties:
        title: { type: string }
      required: [title]

Cinq règles qui évitent les pannes silencieuses :

  • Chaque outil porte method et path. Sans eux, le chargement du connecteur échoue et le catalogue avale l'erreur.
  • Avec param_location: path, seuls les arguments qui correspondent à un {placeholder} du chemin sont transmis. Les autres sont abandonnés sans message : un filtre déclaré ainsi ne filtre rien. Utilisez query ou body.
  • Un outil qui écrit commence par un verbe d'écriture (create, update, delete, entre autres). Le nom sert aux contrôles de sécurité à classer l'outil en lecture ou en écriture.
  • Le data_residency doit appartenir à eu, eu-west, eu-central, france, germany, finland, netherlands, ireland ou self-hosted, et gdpr_compliant doit être vrai : sinon le registre rejette le connecteur.
  • Les secrets ne sont jamais dans le YAML : seulement le nom de la variable (token_env). Les types d'authentification du gabarit sont none, bearer, api_key, basic et query_token. Le parseur en connaît d'autres (login_token, oauth2, jwt_exchange, entre autres) : voir l'énumération AuthConfig dans crates/forge-mcp/src/connector/http.rs.

Choisissez un base_url par défaut qui répond réellement : un défaut qui ne résout jamais fabrique un connecteur qu'aucune mesure ne pourra rendre vert.

Étape 2 : valider le fichier

python scripts/audit/validate-connectors.py

Le validateur lit le même schéma que le parseur. Résultat attendu : la ligne [OK] HARD checks all passed. et le code de sortie 0. Une ligne [FAIL] suivie de la liste des fautes dit ce qu'il faut corriger : corrigez tout message de niveau HARD avant de continuer. La licence déclarée sous compliance.license est aussi contrôlée par une garde du dépôt, qui refuse les licences à source disponible (SSPL, BSL, BUSL, Elastic-2.0 et assimilées).

Étape 3 : autoriser le connecteur

La passerelle refuse de dispatcher un connecteur dont l'identifiant ne figure pas dans la liste des serveurs autorisés. C'est le point d'étranglement de conformité européenne : sans cette ligne, le connecteur se charge, mais ses outils n'apparaissent pas dans tools/list (outils_autorises, crates/forge-mcp/src/gateway.rs) et l'appel est refusé. Les fiches dolibarr et freescout sont dans ce cas.

Ajoutez "mon-service" à ALLOWED_MCP_SERVERS dans crates/forge-core/src/compliance/allowed_servers.rs. Un test du même fichier compte les entrées de la liste : mettez à jour ce compte avec une justification dans le commit, c'est voulu.

Étape 4 : enregistrer les identifiants du locataire

Les identifiants d'un locataire sont chiffrés en AES-256-GCM en base. Au moment d'un appel, la passerelle déchiffre les identifiants du locataire et les publie comme variables d'environnement, pour cette seule requête. Tout champ de la fiche dont le nom ressemble à une variable de connecteur (majuscules et suffixe _KEY, _TOKEN, _SECRET, _PASSWORD, _USER, _URL, _ID, _DATABASE, entre autres) est publié tel quel : nommez donc les champs comme les variables du YAML.

curl -X POST http://localhost:3000/api/v1/credentials \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "mon-service-prod",
    "credentialName": "monServiceApi",
    "plainDataObj": {
      "MON_SERVICE_URL": "https://api.mon-service.eu",
      "MON_SERVICE_API_KEY": "votre-clé-secrète"
    }
  }'

Résultat attendu : 201, avec la fiche créée (id, name, credential_name, masked_value, workspace_id, created_at, updated_at). La valeur secrète n'est jamais renvoyée. Sans workspaceId, la fiche va dans le premier espace de travail accessible ; sans espace accessible, la réponse est 400 (NO_WORKSPACE).

La page /credentials de l'application propose la même action par un formulaire pour les fiches du catalogue de l'interface.

Étape 5 : recharger les connecteurs

Les fichiers de connectors/ ne sont lus qu'au démarrage du backend.

  • En développement, le surveillant du backend reconstruit et remplace le processus ; sinon relancez le lanceur du backend.
  • Sur un déploiement Podman, le dossier connectors/ et la liste de l'étape 3 sont copiés dans l'image du backend à la construction : reconstruisez l'image avec votre modification (voir Déploiement avec Podman), puis redémarrez le conteneur :
podman restart forge-api

Contrôlez ensuite le journal de démarrage : une ligne failed to load connector config ou connector rejected by registry nomme le fichier fautif. L'absence de ces deux lignes, puis la présence de vos outils dans tools/list (étape 6), confirment le chargement.

Étape 6 : tester par le protocole MCP

Le transport est Streamable HTTP sur un seul point d'entrée, /api/v1/mcp. Il faut d'abord ouvrir une session ; l'identifiant revient dans l'en-tête Mcp-Session-Id.

# 1. Ouvrir la session et lire l'en-tête de réponse Mcp-Session-Id
curl -i -X POST http://localhost:3000/api/v1/mcp \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{},"id":1}'

# 2. Lister les outils
curl -X POST http://localhost:3000/api/v1/mcp \
  -H "Authorization: Bearer $JWT" \
  -H "Mcp-Session-Id: $SESSION" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":2}'

# 3. Appeler un outil : le nom est <id du connecteur>.<nom de l'outil>
curl -X POST http://localhost:3000/api/v1/mcp \
  -H "Authorization: Bearer $JWT" \
  -H "Mcp-Session-Id: $SESSION" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
      "name": "mon-service.mon_service_list_items",
      "arguments": { "limit": 5 }
    },
    "id": 3
  }'

Résultats attendus :

  • Appel 1 : 200, un en-tête mcp-session-id et un corps result (protocolVersion, capabilities, serverInfo). Copiez l'identifiant dans la variable SESSION : export SESSION=<session-id>.
  • Appel 2 : 200 et result.tools, une liste d'objets name, description, inputSchema et connector_id. Ajoutez | jq -r '.result.tools[].name | select(startswith("mon-service."))' à la commande pour ne garder que vos outils. Si votre connecteur n'y figure pas, vérifiez l'étape 3 (liste), l'étape 5 (rechargement) et le journal de démarrage.
  • Appel 3 : 200 aussi. result.type vaut success et result.content porte les blocs de texte. Avant l'exécution, un échec est un objet error à la place de result, et error.code reprend le code HTTP de l'échec (401 session expirée, 403 serveur hors de la liste autorisée, 404 outil inconnu). Si votre service amont échoue, result.type vaut error et result porte code et message.

Sans Mcp-Session-Id, tools/call répond 400. Une session expire après 30 minutes d'inactivité.

Quand le YAML ne suffit pas

Pour un protocole qui n'est pas du HTTP, un connecteur natif implémente le trait McpConnector du crate forge-mcp (crates/forge-mcp/src/connector/mod.rs) : id, display_name, compliance, list_tools, execute, health_check, et required_auth_env_vars si le connecteur consomme un secret. Le connecteur Odoo (odoo_xmlrpc_client.rs) est l'exemple à lire. Ce cas est rare.

Bonnes pratiques

  • Les lectures peuvent être mises en cache (cache_ttl_s, désactivé par défaut). Le cache n'est jamais actif sous un contexte de locataire, pour qu'aucune réponse ne passe d'un locataire à l'autre.
  • Déclarez timeout_ms en fonction du service cible.
  • Testez le connecteur contre le service réel avant de le proposer : un connecteur qui répond 200 sur une réponse non filtrée est un faux vert.

Voir aussi

Connecter Odoo à la passerelle MCP

Ce tutoriel montre comment relier votre instance Odoo à Chatbotaurus, puis appeler un premier outil. Le connecteur Odoo parle XML-RPC avec une clé d'API Odoo. Il n'y a ni module à installer côté Odoo pour les modèles standard, ni mot de passe d'utilisateur à confier à la plateforme.

Prérequis

  • Une instance Odoo accessible depuis le backend Chatbotaurus : la vôtre, ou l'une des instances de démonstration du plan client (une par secteur, conteneurs nommés mcp-odoo-<secteur>).
  • Quatre informations Odoo : l'URL du serveur, le nom de la base, le nom d'utilisateur et une clé d'API.
  • Un compte Chatbotaurus et un jeton de session (section Authentification), rangé dans la variable JWT : export JWT=<token>.
  • Un espace de travail accessible à ce compte : la fiche d'identifiants y est rangée.

Les exemples visent http://localhost:3000. Avec un compte hébergé, remplacez cette adresse par celle de votre API (https://<hote-api>, voir API-as-a-Service EU souverain).

La clé d'API se crée dans Odoo, depuis les préférences de l'utilisateur (onglet Sécurité du compte). Utilisez un utilisateur dédié, dont les droits Odoo sont limités à ce que l'assistant doit faire. Les droits du compte API sont la dernière barrière d'autorisation.

Ce qui est exposé

Le registre de dispatch Odoo contient 711 outils nommés, regroupés par module (contacts, CRM, ventes, achats, stock, comptabilité, RH, projet, entre autres). S'y ajoute un quatuor générique record_create / record_read / record_update / record_delete, qui prend le modèle en argument pour les modèles métier sans outil nommé. Les noms sont de la forme <module>_<objet>_<action>, par exemple contacts_search, contacts_create, crm_lead_create, sales_order_confirm.

Trois règles de sécurité s'appliquent, quelle que soit la configuration :

  • Les outils destructifs (nom portant drop, truncate, erase, purge, wipe, ou se terminant par unlink ou destroy) ne sont jamais exécutés par l'agent, même approuvés. Les outils irréversibles (suppression, annulation, remboursement, paiement) ne s'exécutent qu'après une autorisation humaine explicite (crates/forge-mcp/src/connector/human_authorization.rs).
  • Une écriture ciblée (update, delete, action) exige un id entier explicite ; sans cible, elle est refusée au lieu de réussir dans le vide.
  • Les modèles du noyau comptable sont en lecture seule pour l'agent ; une écriture y passe par l'approbation d'un humain.

Les noms odoo_search_read, odoo_create ou odoo_execute_kw n'existent pas dans le registre : prenez les noms réels dans la réponse de tools/list.

Étape 1 : enregistrer les identifiants du locataire

Depuis l'application, ouvrez la page Identifiants (/credentials), choisissez la fiche Odoo ERP/CRM et renseignez les quatre champs :

Champ du formulaireContenu
URL du serveurl'adresse de votre Odoo
Databasele nom de la base Odoo
Usernamel'identifiant de l'utilisateur API
API Keyla clé d'API créée dans Odoo

Par l'API, la même fiche s'enregistre ainsi (credentialName doit valoir odooApi, c'est lui qui relie la fiche au connecteur) :

curl -X POST http://localhost:3000/api/v1/credentials \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "odoo-ma-societe",
    "credentialName": "odooApi",
    "plainDataObj": {
      "odooUrl": "https://odoo.exemple.eu",
      "odooDatabase": "ma_base",
      "odooUsername": "api_user@exemple.eu",
      "odooApiKey": "votre-clé-api"
    }
  }'

Résultat attendu de la commande : 201 et la fiche créée (id, name, credential_name, masked_value, workspace_id, created_at, updated_at), sans la clé d'API.

Les quatre champs sont tous nécessaires : un jeu incomplet est refusé par le connecteur au lieu d'être complété au hasard. Les données sont chiffrées au repos, et les champs secrets (la clé d'API) sont masqués quand la fiche est relue.

Étape 2 : ouvrir une session MCP

curl -i -X POST http://localhost:3000/api/v1/mcp \
  -H "Authorization: Bearer $JWT" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{},"id":1}'

Résultat attendu : 200, un corps result (protocolVersion, capabilities, serverInfo) et l'en-tête mcp-session-id. Copiez sa valeur dans la variable SESSION (export SESSION=<session-id>) : elle est obligatoire sur les appels suivants (voir Routes MCP) et expire après 30 minutes d'inactivité.

Étape 3 : appeler un premier outil

Un outil Odoo s'appelle par son nom préfixé par odoo.. Les paramètres sont à plat : query (terme libre cherché dans les champs textuels du modèle), limit, offset, order, fields. S'y ajoutent des filtres sur les champs du modèle (un suffixe tel que __gte ou __lte choisit l'opérateur).

curl -X POST http://localhost:3000/api/v1/mcp \
  -H "Authorization: Bearer $JWT" \
  -H "Mcp-Session-Id: $SESSION" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
      "name": "odoo.contacts_search",
      "arguments": { "query": "dupont", "limit": 5 }
    },
    "id": 2
  }'

Résultat attendu : 200, result.type égal à success et les lignes trouvées dans result.content. Un échec avant l'exécution (session expirée, outil inconnu) arrive sous la forme d'un objet error dont error.code reprend le code HTTP de l'échec ; un échec d'Odoo lui-même arrive dans result, avec result.type égal à error : voir Dépannage plus bas.

Sans limit, une recherche rend jusqu'à 500 lignes. Précisez toujours une borne.

Étape 4 : utiliser le chat

Une fois la fiche enregistrée, vous n'avez plus besoin d'appeler les outils à la main. Posez la question dans le chat (« quels sont mes derniers contacts ? ») et le routeur choisit l'outil Odoo adapté. Les lectures sont exécutées directement ; une suppression, un paiement ou une écriture sur les modèles comptables gardés attend une approbation (voir Odoo, section Écritures gardées).

Champs personnalisés

Un champ Odoo personnalisé (préfixe x_) s'installe par un module d'addon Odoo, au moment de l'installation de l'instance. Il ne se crée jamais par XML-RPC en cours d'exploitation : une telle écriture fige le conteneur Odoo. Une fois le champ présent, il est lisible et écrivible comme n'importe quel champ du modèle.

Dépannage

SymptômeCause probable
Refus pour jeu d'identifiants incompletun des quatre champs de la fiche est vide
Erreur d'authentification Odooclé d'API révoquée, ou utilisateur sans accès à la base indiquée
400 « missing Mcp-Session-Id »l'étape 2 n'a pas été faite, ou l'en-tête manque
Outil refusé « destructive tool » ou « irreversible tool »comportement voulu : un outil destructif n'est jamais exécuté par l'agent, un outil irréversible (par exemple une suppression) exige une validation humaine
Outil inconnu (error.code 404, statut HTTP 200)un nom absent du registre, par exemple un ancien nom ; consultez les noms réels par tools/list
error.code 401la session de l'étape 2 a expiré (30 minutes d'inactivité) : ouvrez-en une nouvelle
Réponse 400 NO_WORKSPACE à l'étape 1aucun espace de travail n'est accessible à ce compte

Voir aussi

Parcourir le catalogue de services et préparer un déploiement

Le catalogue métier est la liste des serveurs MCP que la plateforme sait décrire, regrouper en profils et suivre. Ce tutoriel parcourt ce qui fonctionne aujourd'hui (consulter, filtrer, lire les profils, connaître l'état) et dit sans détour où s'arrête l'automatisation : le déploiement d'un service par l'API est en sommeil et répond 503.

Ce qui marche, ce qui est en sommeil

OpérationRoute (préfixe /api/v1/mcp/catalog-business)État
Lister le catalogueGET /actif
Détail d'un serveurGET /{id}actif
Lister les profilsGET /profilesactif
Serveurs prouvés opérationnelsGET /deployedactif
État d'un serveurGET /{id}/statusactif (disponibilité au registre)
Déployer un serveurPOST /{id}/deploy503, en sommeil
Déployer un profilPOST /profiles/{name}/deploy503, en sommeil
Démarrer / arrêter / redémarrerPOST /{id}/start, /stop, /restart503, en sommeil
Profil de sécuritéGET /{id}/security503, en sommeil
Enregistrer des secretsPOST /{id}/secrets503, en sommeil

Les opérations en sommeil dépendent du pilotage de Podman par le backend, pas encore branché. Tant qu'il ne l'est pas, elles répondent 503 avec l'en-tête Retry-After et un corps FEATURE_PENDING, jamais un faux succès. Les opérations de cycle de vie sont de plus réservées aux rôles admin et owner : tout autre rôle reçoit 403. Seule exception, GET /{id}/security : ouverte à tout utilisateur connecté, elle répond 503.

Toutes les routes exigent un jeton de session ($JWT).

Prérequis

  • Chatbotaurus installé et fonctionnel (voir Installation).
  • Un jeton de session (Swagger, section Authentification), rangé dans la variable JWT. Pour tenter un déploiement, un compte de rôle admin ou owner.
  • curl et jq pour les commandes ci-dessous, lancées contre le backend local http://localhost:3000 (sur un déploiement, remplacez cette adresse par celle de votre API).

Étape 1 : consulter le catalogue

# Tous les serveurs
curl -s -H "Authorization: Bearer $JWT" \
  http://localhost:3000/api/v1/mcp/catalog-business \
  | jq '.servers[] | {id, name, category, status}'

# Filtrer par catégorie
curl -s -H "Authorization: Bearer $JWT" \
  "http://localhost:3000/api/v1/mcp/catalog-business?category=CRM%20%26%20ERP" | jq .total

# Le détail d'un serveur
curl -s -H "Authorization: Bearer $JWT" \
  http://localhost:3000/api/v1/mcp/catalog-business/odoo | jq .

La réponse est de la forme { "servers": [...], "total": N }. Chaque entrée porte id, name, description, category, provider, country, license, status, tags et version. Le champ status vaut available ou coming-soon : le catalogue décrit plus de serveurs qu'il n'en livre, et ce champ dit lesquels sont prêts. Un identifiant inconnu rend 404.

Étape 2 : lire les profils

Un profil est un regroupement de serveurs pour un usage. La réponse est de la forme { "profiles": [...] }.

curl -s -H "Authorization: Bearer $JWT" \
  http://localhost:3000/api/v1/mcp/catalog-business/profiles | jq .

Il existe quatre profils : Solo (l'ERP seul), Starter (cinq serveurs : ERP, automatisation, analytique, fichiers, modèle local), Business (douze serveurs, avec agenda, documents, visioconférence, GED, supervision et voix) et Enterprise (tous les serveurs du fichier de profils). Les identifiants de serveurs d'un profil sont ceux du fichier de profils, tenu côté serveur : ils portent le préfixe mcp- et le suffixe -eu, et diffèrent des id de la liste du catalogue (par exemple odoo).

Étape 3 : savoir ce qui est réellement opérationnel

curl -s -H "Authorization: Bearer $JWT" \
  http://localhost:3000/api/v1/mcp/catalog-business/deployed | jq .

Cette route ne rend pas un inventaire de conteneurs. Elle rend la liste des serveurs prouvés opérationnels, sous la forme d'un tableau JSON d'identifiants : un identifiant n'y figure que si un outil de lecture a rendu des données réelles lors d'une vérification en direct. Elle sert de source unique à l'application, qui affiche donc le même état « déployé » sur toutes ses pages.

curl -s -H "Authorization: Bearer $JWT" \
  http://localhost:3000/api/v1/mcp/catalog-business/odoo/status | jq .

L'état d'un serveur dit s'il est enregistré dans le registre (available ou not_registered), s'il est prouvé opérationnel, et que l'état d'exécution du conteneur est inconnu tant que le pilotage Podman n'est pas branché (runtime.known: false).

Étape 4 : tenter un déploiement

curl -i -X POST -H "Authorization: Bearer $JWT" \
  http://localhost:3000/api/v1/mcp/catalog-business/odoo/deploy

Avec un compte admin ou owner, la réponse attendue aujourd'hui est :

HTTP/1.1 503 Service Unavailable
Retry-After: 86400

{ "error": { "code": "FEATURE_PENDING", ... }, "feature_pending": "catalog_business" }

Avec un autre rôle, c'est 403. Ce 503 n'est pas une panne : c'est l'état documenté de la fonction. Arrêtez-vous là côté API.

Comment déployer un service en attendant

Les services du catalogue destinés au plan client sont décrits dans le fichier Compose du plan client, où chaque serveur MCP est un service nommé mcp-*. Le déploiement passe par ce plan, avec podman-compose (avec un tiret), décrit dans Déploiement avec Podman. Les secrets ne passent pas par l'API du catalogue : ils sont enregistrés en identifiants du locataire (page /credentials), comme dans le tutoriel Connecter Odoo.

Dans l'application

La page MCP > Serveurs Business (/mcp/servers/business) présente le même catalogue, avec l'état « déployé » tiré de la route /deployed. La page de passerelle par secteur (/mcp/gateways/business) regroupe les serveurs par métier. Ce sont des pages de l'application, pas des routes d'API.

Voir aussi

Variables d'environnement

Le backend forge-api se configure par variables d'environnement. Il lit le fichier .env au démarrage avec dotenvy, puis lit les variables du processus. Ce chapitre liste les variables que le code lit réellement, avec leur défaut quand il existe. Il ne liste pas les 2 992 lignes du fichier modèle .env.example (mesure du 2026-10-03 : wc -l .env.example) : la plupart concernent des outils tiers et des connecteurs, pas le backend.

Règle de lecture. Une variable citée ici est lue par le code ; le fichier est indiqué quand il importe. Ce chapitre n'est pas exhaustif : il omet des options réservées à un module précis. Pour savoir si une variable est lue : grep -rn "NOM_DE_LA_VARIABLE" crates/*/src.

Priorité

  1. Les variables du processus (celles que pose le lanceur, podman ou la session) priment. dotenvy ne remplace jamais une variable déjà définie.
  2. Le fichier .env du répertoire courant complète ce qui manque.
  3. Les valeurs par défaut compilées dans le code s'appliquent en dernier.

Le code ne charge aucun fichier .env.staging ni .env.production. Pour un autre environnement, posez les variables dans le processus.

Les secrets de production ne sont pas dans le dépôt. Sur chaque hôte, un script d'initialisation génère les fichiers d'environnement sur la machine cible, avec des permissions restreintes, et n'imprime jamais les valeurs (script d'initialisation des secrets de l'hôte). OpenBao peut en plus surcharger des secrets au démarrage (voir la section « Secrets externes (OpenBao) » plus bas).

Pour générer un secret : openssl rand -hex 32.

Variables exigées au démarrage

Si l'une d'elles manque, forge-api s'arrête avec le code 1 (contrôle de démarrage du code).

VariableRôleRègle
DATABASE_URLURL PostgreSQLObligatoire
REDIS_URLURL Valkey (compatible Redis)Obligatoire. VALKEY_URL, si elle existe, est lue en premier pour la connexion
JWT_SECRETSecret de signature des jetons (HS256)32 caractères au moins, ni valeur par défaut connue, ni gabarit (change_me, replace_me, entre autres)

Serveur HTTP

VariableRôleDéfaut
PORTPort d'écoute3000
HOSTAdresse d'écoute (BIND_ADDRESS en repli)toutes les interfaces
APP_URLURL publique de l'applicationhttp://localhost:8008 (défaut de forge-core, port historique : l'API écoute sur 3000)
CORS_ORIGINSOrigines autorisées, séparées par des virguleshttp://localhost:8080, :8081, :8082
COOKIE_DOMAINDomaine des cookies de session en productionvide
FORGE_MAX_BODY_BYTESTaille maximale d'un corps de requête2 Mio
FORGE_MAX_UPLOAD_BYTESTaille maximale d'un envoi multipart25 Mio
CSP_HEADER, HSTS_HEADERRemplacent les en-têtes Content-Security-Policy et Strict-Transport-Securityvaleurs du code

Journalisation

VariableRôleDéfaut
RUST_LOGFiltre tracing-subscriberinfo,forge_api=debug,forge_mcp=debug quand la variable est absente ou invalide
LOG_FORMATpretty ou compact : sortie lisible. Toute autre valeur : JSONJSON

TRACING_JSON, posée dans podman-compose.yml, n'est lue que par forge_core::observability::init_tracing, que forge-api n'appelle pas : il appelle sa propre fonction init_tracing (crates/forge-api/src/main.rs). Elle ne change donc rien au format des journaux de forge-api.

Voir Journaux.

Authentification

VariableRôleDéfaut
JWT_EXPIRYDurée du jeton d'accès : 7d, 24h, 30m, 3600s ou un nombre de secondes7 jours
JWT_EXPIRY_SECSAlias en secondes, lu si JWT_EXPIRY est absente ou illisible7 jours
FORCE_2FAImpose un second facteur à la connexion par mot de passe (true ou 1) : code TOTP si le compte l'a enrôlé, sinon code envoyé par e-mailtrue
FORGE_MFA_TOTP_REQUIRED1 ou true : refuse la connexion d'un compte sans TOTP enrôlé, pour tous les comptesdésactivé
FORGE_MFA_REQUIRED_ROLESRôles séparés par des virgules (par exemple admin,owner) : même refus, pour ces rôles seulementvide
FORGE_PQC_ENABLED1 ajoute une signature ML-DSA-65 au jeton de session, en plus de HS256désactivé
NODE_ENV, ENVIRONMENT, RUST_ENV, APP_ENVDéclarent l'environnement. development, dev, local ou test déclarent un développementabsent = posture production
FORGE_DEV1, true ou yes déclare un développementabsent

Le silence ne relâche aucune garde : sans déclaration explicite de développement, forge-api applique la posture production.

Les deux réglages FORGE_MFA_* sont lus par la connexion par mot de passe. Un compte créé par le SSO n'a pas de second facteur applicatif : Authentik le porte en amont.

Le code de vérification envoyé par e-mail et le jeton intermédiaire du second facteur vivent quelques minutes dans Valkey (valeur fixe dans le code).

Clés de durcissement

VariableRôleRègle
AT_REST_ENCRYPTION_KEYRacine du chiffrement des secrets stockés (TOTP, identifiants de connecteurs, SSO)Distincte de JWT_SECRET. Sans elle, le code retombe sur JWT_SECRET
AUDIT_SIGNING_KEYSignature de la chaîne d'auditSans elle, la chaîne n'est pas signée
FORGE_STRICT_SECRETS1 rend les deux clés ci-dessus obligatoiresSans cette variable, leur absence est un avertissement
FORGE_TENANT_STRICT1 active le cloisonnement strict par organisationObligatoire hors développement déclaré, sinon arrêt au démarrage
FORGE_MULTI_TENANT_STRICTDésactive l'hydratation globale des identifiants de connecteursPosée sur les hôtes de production
PHI_AT_REST_KEYClé de 64 caractères hexadécimaux pour le chiffrement des données de santéObligatoire en production, tolérée absente en développement déclaré
PHI_AT_REST_KEY_PREVIOUSAncienne clé, lue en repli pendant une rotationOptionnelle
EXPORT_SEAL_KEYScellement des exportsOptionnelle. Absente : l'export scellé est indisponible

Détails : Sécurité.

Limiteurs de débit (connexion)

VariableRôleDéfaut
ACCOUNT_HASH_SALTSel du hachage d'identité par comptevide. Vide = limiteur par compte désactivé
ACCOUNT_RATE_LIMIT_FAILURES_BLOCKÉchecs avant blocage du comptedéfaut du code, non publié
ACCOUNT_RATE_LIMIT_WINDOW_SECSFenêtre de comptagedéfaut du code, non publié
ACCOUNT_RATE_LIMIT_BLOCK_SECSDurée du blocagedéfaut du code, non publié
AUTH_RATE_LIMIT_FAILURES_BACKOFFÉchecs par IP avant ralentissementdéfaut du code, non publié
AUTH_RATE_LIMIT_FAILURES_BLOCKÉchecs par IP avant blocagedéfaut du code, non publié
AUTH_RATE_LIMIT_BLOCK_DURATION_SECSDurée du blocage par IPdéfaut du code, non publié
AUTH_RATE_LIMIT_WHITELISTIP exemptées du seau par IP, séparées par des virgulesvide

Sources : les deux limiteurs de connexion du code.

Purges planifiées

Ces purges sont actives par défaut. Une variable à 0 (ou false) suspend la purge concernée.

VariableRôleDéfaut
RETENTION_SWEEP_ENABLEDPurge des journaux vocaux expirésactive
RETENTION_SWEEP_HOURSCadence de cette purge24
RETENTION_VOICE_DAYSDurée de conservation des journaux vocaux90
BACKUP_RETENTION_SWEEP_ENABLEDPurge des travaux de sauvegarde terminésactive
BACKUP_RETENTION_DAYSDurée de conservation des sauvegardes, en repli du réglage par cible de sauvegarde30
ACCOUNT_PURGE_ENABLEDEffacement définitif des comptes en attente de suppressionactive

Sources : crates/forge-api/src/routes/retention_worker.rs, routes/backup_retention/mod.rs, routes/account_purge_worker.rs et crates/forge-api/src/main.rs (lancement des trois planificateurs).

Messagerie (SMTP)

VariableRôleDéfaut
SMTP_HOSTServeur SMTPlocalhost
SMTP_PORTPort587
SMTP_USERCompte authentifié. C'est aussi l'adresse expéditriceaucun
SMTP_PASSWORDMot de passe du compteaucun
SMTP_SECUREtrue pour une connexion TLS directefalse
EMAIL_FROM, EMAIL_FROM_NAMEExpéditeur de repli et nom affichénom : Chatbotaurus

L'expéditeur est toujours le compte authentifié SMTP_USER : un From différent casse l'alignement SPF et DKIM (crates/forge-core/src/email/mod.rs). Il n'existe pas de variable SMTP_SKIP.

Authentification unique (Authentik, OIDC avec PKCE)

La route GET /api/v1/auth/oidc/login lit ces variables :

VariableRôleDéfaut
AUTHENTIK_SERVER_URLAdresse du serveur Authentikaucun : absente, la route répond 503 SSO_UNAVAILABLE
AUTHENTIK_CLIENT_IDIdentifiant du client OIDCaucun : même réponse 503
AUTHENTIK_CLIENT_SECRETSecret du client OIDCaucun : même réponse 503
AUTHENTIK_REDIRECT_URIURL de retour enregistrée chez Authentikhttp://localhost:8008/api/v1/auth/oidc/callback, défaut de développement : posez-la toujours
OIDC_ALLOW_UNVERIFIED_EMAIL1 ou true accepte un fournisseur qui n'émet pas email_verifiedrefus

La route de retour du backend est GET /api/v1/auth/oidc/callback (crates/forge-api/src/router.rs).

ForgeConfig lit aussi SSO_AUTHENTIK_ENABLED, AUTHENTIK_SLUG, AUTHENTIK_CALLBACK_URL, AUTHENTIK_LOGOUT_URL et AUTHENTIK_ROLE_MAPPING (crates/forge-core/src/config.rs, bloc authentik). Mesure du 2026-10-03 : aucun code hors de config.rs ne consomme ces champs (grep -rn "\.sso\." crates/*/src ne rend rien en dehors de ce fichier). Ils n'ont donc aucun effet sur la connexion SSO aujourd'hui.

Modèles de langage (Ollama)

VariableRôleDéfaut
OLLAMA_BASE_URLAdresse d'Ollamahttp://localhost:11434
OLLAMA_MODELModèle de générationministral-3:3b dans la configuration ; ministral-3:3b-instruct dans l'orchestrateur (OLLAMA_DEFAULT_MODEL en repli)
OLLAMA_EMBEDDING_MODELModèle d'embeddings du client Ollama. Le pipeline RAG n'en dépend pas : il vectorise en local avec fastembed (voir EMBEDDING_MODEL)paraphrase-multilingual-MiniLM-L12-v2
OLLAMA_TIMEOUT_SECSDélai d'une requête (configuration)120
OLLAMA_MAX_RETRIESNouvelles tentatives2
OLLAMA_TEMPERATURETempérature (orchestrateur)0,5
OLLAMA_MAX_TOKENSLongueur maximale de réponse (orchestrateur)800

La liste des modèles souverains (crates/forge-core/src/model_governance.rs) nomme cas/eurollm-1.7b-instruct-q8 (rôle Main, réservé à la traduction : le code précise qu'il ne sert jamais à l'appel d'outil), ministral-3:3b (repli de génération, et défaut de OLLAMA_MODEL) et l'embedder ci-dessus. Aucun défaut du code ne désigne un fournisseur hors UE.

Recherche vectorielle et RAG

VariableRôleDéfaut
QDRANT_URLAdresse gRPC de Qdranthttp://localhost:6334
QDRANT_HOSTAdresse REST utilisée par la sonde de santédérivée de QDRANT_URL
QDRANT_API_KEYClé d'APIaucune
QDRANT_COLLECTION_PREFIXPréfixe des collectionsforge
EMBEDDING_MODELModèle fastembed du pipeline RAG : multilingual (ou variable absente) donne paraphrase-multilingual-MiniLM-L12-v2, 384 dimensions (crates/forge-core/src/rag/embedder.rs)multilingual
QDRANT_VECTOR_SIZEDimension des vecteurs768 dans la configuration, 384 à la création des collections au démarrage
RAG_CHUNK_SIZE, RAG_CHUNK_OVERLAPDécoupage des documents512 et 64
RAG_TOP_K, RAG_SCORE_THRESHOLDPassages retenus et seuil5 et 0,7
ANTI_HALLUCINATION_THRESHOLDSeuil de la garde anti-hallucination0,75

L'embedder du pipeline produit des vecteurs de 384 dimensions. Si vous posez QDRANT_VECTOR_SIZE, posez 384 : une collection créée avec une autre dimension refuse chaque insertion (crates/forge-api/src/main.rs).

Secrets externes (OpenBao)

OpenBao est facultatif. Si BAO_ADDR est posée, il surcharge les secrets d'exécution au démarrage ; sinon les secrets viennent de l'environnement.

VariableRôleDéfaut
BAO_ADDRAdresse du serveurabsente : OpenBao désactivé
BAO_TOKENJeton d'accèsaucun
BAO_KV_MOUNTPoint de montage KV v2secret
BAO_KV_PREFIXPréfixe sous le montagechatbotaurus
BAO_NAMESPACEEspace de nomsaucun
BAO_TIMEOUT_SECSDélai HTTP10
BAO_AUDIT_REQUIREDVrai : le démarrage est refusé si aucun périphérique d'audit n'est actif côté coffrefaux
BAO_CACERT, BAO_CLIENT_CERT, BAO_CLIENT_KEYTLS mutuelaucun

Voix

VariableRôleDéfaut
STT_PROVIDERMoteur de transcription : speaches, kyutai ou mistralspeaches
STT_ENDPOINTAdresse du moteur de transcriptionà définir (voir le paragraphe sous le tableau)
STT_MODELModèle de transcriptionSystran/faster-whisper-large-v3
STT_LANGUAGELanguefr
STT_API_KEYClé d'API du moteur de transcriptionaucune
TTS_PROVIDERMoteur de synthèsekokoro
TTS_ENDPOINTAdresse du moteur de synthèseà définir
TTS_ENDPOINT_SPEACHESAdresse du service qui sert l'allemandabsente : service non déployé

Les défauts de STT_ENDPOINT et TTS_ENDPOINT dans le code sont des adresses publiques qui ne servent rien. Définissez toujours ces deux variables. Le code refuse un point d'accès hors UE.

Supervision

VariableRôleDéfaut
PROMETHEUS_BEARER_TOKENJeton d'accès au point /metricsabsent : session plateforme élevée exigée
FORGE_SIEM_ENABLED1 exporte la chaîne d'audit vers VictoriaLogsdésactivé
FORGE_SIEM_URLAdresse de VictoriaLogshttp://localhost:9428

Voir Supervision.

Connecteurs

CONNECTOR_CATALOGUE_DIR désigne le dossier des manifestes ; le défaut est ./connectors (crates/forge-api/src/main.rs).

Les fichiers connectors/*.yaml interpolent l'environnement avec ${VARIABLE:-défaut} (valeur de repli) ou ${VARIABLE:?message} (la valeur vaut une chaîne vide si la variable est absente ; le message n'est qu'une indication et n'arrête pas le chargement). Chaque connecteur déclare ses propres variables ; pour Odoo : ODOO_URL, ODOO_DATABASE, ODOO_USERNAME, ODOO_API_KEY. Voir Fichiers de configuration.

Frontend (forge-ui)

Le frontend est une application wasm : elle ne lit aucune variable d'environnement dans le navigateur. En web, elle appelle le chemin relatif /api/v1 du même domaine. Sur les cibles natives, l'adresse de l'API se fixe à la compilation avec API_URL ; le défaut est http://localhost:3000/api/v1 (crates/forge-ui/src/config/api.rs).

Voir aussi

Fichiers de configuration

Ce chapitre dit quels fichiers le code lit, où ils vivent et dans quel ordre ils s'appliquent. La liste des variables est dans Variables d'environnement.

Les fichiers que le code lit

FichierEmplacementLu parRôle
.envRépertoire de lancement (racine du dépôt en développement)dotenvy, au démarrage de forge-apiVariables de développement. Ignoré par git
.env.exampleRacine du dépôtPersonne : c'est un modèle à copierListe commentée des variables, avec des valeurs à remplacer
connectors/*.yamlRacine du dépôt, ou le dossier CONNECTOR_CATALOGUE_DIRCatalogueLoader (crates/forge-mcp/src/connector/catalogue.rs)Un manifeste par connecteur
policies/chatbotaurus.cedarschema et policies/policies.cedarDossier policies/, chemin relatif au répertoire de lancementload_cedar_policy_engine (crates/forge-api/src/main.rs)Règles d'autorisation Cedar
crates/forge-ui/Dioxus.tomlCrate forge-uidxRéglages du serveur de développement du frontend
crates/forge-docs/book.tomlCrate forge-docsmdbookRéglages de ce livre

Le code ne lit pas de fichier .env.staging ni .env.production. Pour un autre environnement, posez les variables dans le processus.

Si policies/ est absent ou illisible depuis le répertoire de lancement, le comportement dépend de la posture. En développement déclaré, le moteur Cedar n'est pas chargé, forge-api démarre sans lui et les gardes Cedar laissent passer. En posture de production, forge-api refuse de démarrer (décision de démarrage du moteur Cedar, dans le code). Lancez le binaire depuis la racine du dépôt.

Fichiers de déploiement

Deux plans Podman existent, chacun avec son fichier Compose :

FichierPlanContenu
podman-compose.ymlBackend (services forge-*)PostgreSQL, Valkey, Qdrant, Ollama, Authentik, OpenBao, VictoriaMetrics, VictoriaLogs, CrowdSec, voix, sauvegarde
podman-compose.vps2.ymlClient (services mcp-*)Passerelle MCP et serveurs d'outils métier

Ces fichiers servent au développement local. En production, le déploiement installe des unités Quadlet : un fichier containers/<service>/<service>.container par service, appliqué par containers/scripts/deploy-all.sh. Voir Déploiement avec Podman.

Tapez podman-compose avec un tiret. podman compose (avec une espace) ne fournit pas de moteur Compose propre : il délègue à un outil externe qui peut manquer.

Les deux réseaux et les volumes de données sont déclarés external dans les fichiers Compose : compose ne les crée pas. Créez-les avant le premier lancement (procédure dans Déploiement avec Podman).

Configuration du backend

forge-api construit sa configuration avec ForgeConfig::from_env (crates/forge-core/src/config.rs). Créez .env à la racine du dépôt (cp .env.example .env, ou le fichier minimal ci-dessous) ; seules DATABASE_URL, REDIS_URL et JWT_SECRET sont exigées, et openssl rand -hex 32 produit un JWT_SECRET valable (voir Variables d'environnement). Exemple minimal de .env de développement, avec des gabarits à remplacer :

DATABASE_URL=postgres://<utilisateur>:<mot-de-passe>@localhost:5432/<base>
REDIS_URL=redis://localhost:6380
JWT_SECRET=<32-caracteres-aleatoires-au-minimum>
OLLAMA_BASE_URL=http://localhost:11434
QDRANT_URL=http://localhost:6334
SMTP_HOST=<serveur-smtp>
SMTP_PORT=587
SMTP_USER=<compte-smtp>
SMTP_PASSWORD=<mot-de-passe-smtp>
RUST_LOG=info,forge_api=debug

Le Valkey de podman-compose.yml est publié sur le port 6380 de l'hôte par défaut (variable REDIS_PORT) ; 6379 est le port interne du conteneur. Si vous utilisez un Redis local sur 6379, adaptez l'URL. Avec le compose de développement, l'utilisateur, le mot de passe et la base de DATABASE_URL sont ceux des variables DATABASE_USER, DATABASE_PASSWORD et DATABASE_NAME (valeurs par défaut de développement dans podman-compose.yml).

Au démarrage, forge-api imprime sur l'erreur standard dotenvy: loaded <chemin> si .env a été chargé, ou dotenvy: .env NOT loaded sinon. Si le message dit que le fichier n'a pas été chargé, le répertoire de lancement n'est pas la racine du dépôt.

Les valeurs de production ne sont pas dans le dépôt. Un script génère sur chaque hôte les fichiers d'environnement avec des permissions restreintes (script d'initialisation des secrets de l'hôte). Si BAO_ADDR est posée, OpenBao surcharge ensuite les secrets d'exécution.

Configuration du frontend

forge-ui ne lit aucun fichier à l'exécution.

  • Le serveur de développement est dx serve, lancé depuis crates/forge-ui. Dioxus.toml le règle pour surveiller le dossier src : une modification de code recharge la page sans redémarrer.
  • En web, le frontend appelle le chemin relatif /api/v1 du même domaine. Sur les cibles natives, API_URL fixe l'adresse à la compilation ; le défaut est http://localhost:3000/api/v1 (crates/forge-ui/src/config/api.rs).
  • Les textes de marque, les liens et les offres affichés sur le site vivent dans crates/forge-ui/src/config/site.rs. Ce fichier ne contient pas l'adresse de l'API.

Manifestes de connecteurs (connectors/*.yaml)

Au démarrage, forge-api charge chaque .yaml du dossier. Il remplace les ${VARIABLE:-défaut} par l'environnement, puis enregistre le connecteur. Un manifeste invalide est journalisé et ignoré, il n'arrête pas le démarrage.

Le dossier contient 195 manifestes (mesure du 2026-10-03 : ls connectors/*.yaml | wc -l). Forme d'un connecteur HTTP (modèle commenté : connectors/README.md) :

id: <identifiant>
display_name: "<nom affiché>"
base_url: "${<VARIABLE>:-<url-par-defaut>}"
auth:
  type: bearer            # none | bearer | api_key | basic | query_token | jwt_exchange | oauth2 | login_token | checksum | json_rpc_session
  token_env: <VARIABLE>
compliance:
  data_residency: eu
  self_hosted: true
  gdpr_compliant: true
  license: "<licence>"
timeout_ms: 30000
tools:
  - name: <outil>
    description: "<description>"
    method: GET
    path: "/chemin/{parametre}"
    param_location: path
    input_schema:
      type: object
      properties: {}

Le manifeste d'Odoo suit une autre forme : type: odoo et les champs url, database, username, api_key, lus dans ODOO_URL, ODOO_DATABASE, ODOO_USERNAME et ODOO_API_KEY (connectors/odoo.yaml). La clé d'API y est marquée obligatoire (${ODOO_API_KEY:?...}), mais le chargeur la remplace par une chaîne vide si elle est absente : le manifeste se charge, et les appels d'Odoo échouent faute d'identifiants.

Le registre refuse un connecteur dont gdpr_compliant vaut false ou dont la résidence des données n'est pas dans l'UE ou auto-hébergée. Le journal le dit : connector rejected by registry.

Les secrets ne sont jamais écrits dans les manifestes : ils viennent de l'environnement.

Appliquer un changement

  • Backend : redémarrez forge-api. Il ne relit pas la configuration à chaud. En développement sous Windows, scripts/dev/watch-forge-api.ps1 reconstruit et relance le binaire après une modification de code.
  • Frontend : rien à faire en développement, dx serve recharge.
  • Services Podman : en développement, podman-compose -f podman-compose.yml up -d applique la nouvelle définition ; --force-recreate recrée les conteneurs. En production, l'hôte tire lui-même la branche principale (minuteur systemd) : voir « Déploiement tiré par l'hôte » dans Déploiement avec Podman.

Voir aussi

Déploiement avec Podman

Chatbotaurus utilise Podman, pas Docker, pour ses conteneurs. Ce guide décrit les deux plans de déploiement, l'environnement de développement (podman-compose) et la production (unités Quadlet).

À la fin de ce chapitre, vous aurez créé les réseaux et les volumes, démarré les deux plans en développement, et vous saurez comment la production est déployée, suivie et ramenée à l'image précédente.

Prérequis

  • Podman et podman-compose. Tapez bien podman-compose avec un tiret : podman compose (avec un espace) n'est qu'un adaptateur qui cherche un fournisseur externe.
  • Pour la production : un hôte Linux avec systemd, un compte non privilégié dédié (noté <compte-deploiement> ci-dessous) et les unités Quadlet de containers/.
  • Les fichiers podman-compose.yml et podman-compose.vps2.yml, le dossier containers/ et les scripts cités dans ce chapitre font partie des sources sous licence (voie d'accès : Contribuer). Lancez les commandes podman-compose depuis la racine de ces sources.
  • Aucun fichier .env n'est nécessaire pour un premier essai en développement : les fichiers compose portent des valeurs par défaut de développement. Le stockage objet fait exception : il reste fermé tant que ses variables SEAWEEDFS_S3_* ne sont pas renseignées (voir Problèmes connus, section « Le stockage objet S3 refuse toutes les requêtes »).

Deux plans, deux réseaux

PlanProjet et réseauFichierNom des services
Backend (notre plan)chatbotaurus-vps1podman-compose.ymlforge-*
Clientmgaas-vps2podman-compose.vps2.ymlmcp-*

Règle : un service nommé mcp-* est dans le plan client, tout autre nom dans le plan backend. Tout nouveau serveur MCP est un service du fichier podman-compose.vps2.yml, jamais un podman run isolé.

Les deux réseaux sont créés avant le premier lancement (les fichiers compose les déclarent external) :

podman network create chatbotaurus-vps1
podman network create mgaas-vps2

Les volumes de données sont external eux aussi (bloc volumes: en fin de chaque fichier compose) : compose ne les crée pas. Créez-les avant le premier lancement. Leurs noms portent un préfixe hérité (par exemple <prefixe-du-projet>_forge-pgdata), choisi pour ne jamais recréer un volume vide. Pour le plan backend :

for v in $(awk '/^volumes:/{f=1} f && /^    name:/{print $2}' podman-compose.yml); do
  podman volume exists "$v" || podman volume create "$v"
done

Faites de même avec podman-compose.vps2.yml. La liste des noms se lit avec grep -n "name:" podman-compose.yml.

La boucle ne crée que les volumes absents : vous pouvez la relancer sans risque. Résultat attendu : podman volume ls affiche ces noms et podman network ls les deux réseaux. Si l'un d'eux manque, le premier lancement échoue : voir Problèmes connus, section « Un conteneur ne démarre pas ».

PostgreSQL et Valkey du plan backend sont rattachés aux deux réseaux, avec les alias DNS postgres et valkey sur mgaas-vps2 : les outils du plan client (Odoo, Listmonk, n8n, Grafana, Mattermost, entre autres) les joignent par ces noms.

Développement : démarrer les plans

# Plan backend
podman-compose -p chatbotaurus-vps1 up -d

# Plan client (passerelle MCP et serveurs des offres)
podman-compose -p mgaas-vps2 -f podman-compose.vps2.yml up -d

# Vérifier
podman ps --format "table {{.Names}}\t{{.Status}}"

Résultat attendu : chaque conteneur du plan affiche l'état Up, et ceux qui déclarent une sonde de santé passent à healthy après leur délai de démarrage. Les services des profils container-api et backup ne démarrent pas sans leur profil : c'est normal. Un conteneur à l'état Exited, ou absent hors profil : lisez podman logs <conteneur> et suivez Problèmes connus, section « Un conteneur ne démarre pas ».

En développement, le binaire forge-api tourne sur l'hôte (scripts/dev/run-forge-api.ps1) ; le service forge-api du compose est derrière le profil container-api et ne démarre que sur demande :

podman-compose -p chatbotaurus-vps1 --profile container-api up -d forge-api

Services du plan backend (podman-compose.yml)

ServiceConteneurRôlePort publié (hôte → conteneur)
postgresforge-postgresBase principale (image postgres:16-alpine)5432
valkeyforge-valkeyCache et sessions6380 → 6379 (par défaut)
qdrantforge-qdrantBase vectorielle6333 et 6334
ollamaforge-ollamaLLM locaux (limite mémoire fixée dans le plan compose)11434
authentikforge-authentikSSO / IAM9000 et 9443
forge-apiforge-apiBackend Rust (profil container-api)3000
openbaoforge-openbaoSecrets8200
pgadminforge-pgadminAdministration PostgreSQL5050
victoriametricsforge-victoriametricsMétriques8428
victorialogsforge-victorialogsJournaux9428
faster-whisperforge-faster-whisperTranscription (STT)10300 → 8000
tts-modelsforge-tts-modelsTéléchargement des modèles vocaux—
kokoro-ttsforge-kokoro-ttsSynthèse vocale8880
livekitforge-livekitTemps réel (WebRTC)7880, 7881, 7882/udp
crowdsecforge-crowdsecDétection d'intrusion—
seaweedfsforge-seaweedfsStockage objet S3 (Apache-2.0)8333, lié à la boucle locale
backup-agentforge-backup-agentAgent de sauvegarde (profil backup)—
tusdforge-tusdRéception TUS des archives (profil backup)—

Les sauvegardes sont décrites dans Sauvegarde et restauration.

Plan client (podman-compose.vps2.yml)

Le service mcp-gateway (binaire forge-gateway, port 8811) est le point d'entrée du protocole MCP du plan. Autour de lui : les instances Odoo par offre (mcp-odoo-therapie, mcp-odoo-medical, mcp-odoo-finance et les autres), mcp-element, mcp-cryptpad, mcp-listmonk, mcp-n8n, mcp-grafana, mcp-plausible, mcp-moodle, mcp-calrs, mcp-forgejo, mcp-mattermost, mcp-paperless, mcp-frappe, mcp-searxng, mcp-typesense, mcp-umami, mcp-matomo et leurs bases. La liste exacte se lit avec :

grep container_name podman-compose.vps2.yml

Production : unités Quadlet

En production, chaque conteneur est une unité Quadlet containers/<service>/<service>.container, gérée par systemd sous le compte <compte-deploiement>. Côté plan backend, on y trouve par exemple forge-traefik (ingress), forge-api, forge-ui (fichiers statiques du front servis par nginx), forge-openbao, forge-qdrant, forge-ollama, forge-livekit, forge-authentik-server, forge-authentik-worker, forge-crowdsec et forge-tusd. Sur ce plan, seuls l'ingress et le service temps réel publient des ports sur toutes les interfaces ; les autres unités n'écoutent que sur la boucle locale de l'hôte. Dans l'unité forge-api, le port 3000 n'est publié que sur la boucle locale de l'hôte. Le détail des ports et des règles n'est pas publié. L'ingress du plan client est mcp-caddy. Les unités forge-falco et forge-zeek existent dans containers/, mais deploy-all.sh les a retirées de ses niveaux le 2026-09-19 : elles ne sont pas déployées.

Orchestration depuis un poste d'opérateur

containers/scripts/deploy-all.sh pilote les deux plans par niveaux cumulatifs de 1 (démarrage) à 5 (plateforme).

Prérequis : sur le poste, bash, ssh, tar et curl ; sur chaque hôte cible, le compte de déploiement non privilégié avec sudo, podman, Quadlet, python3, le mode « linger » (voir Problèmes connus, section « Les services Quadlet ne redémarrent pas après un redémarrage de l'hôte ») et le dossier cible. L'étape preflight vérifie ces points. Les hôtes se désignent par --hote-backend et --hote-client (alias SSH ou utilisateur@hôte), le dossier déployé par --app. Les niveaux 4 et 5 sont refusés tant qu'une unité qu'ils exigent n'existe pas dans containers/. Code de sortie : 0 si chaque étape demandée est prouvée, 1 sinon, 2 pour une erreur d'usage.

# Lister ce que le niveau 1 déploie, avec ce que le code prouve
bash containers/scripts/deploy-all.sh --liste 1

# Voir les commandes sans se connecter
bash containers/scripts/deploy-all.sh 1 --plan backend --dry-run

# Étapes, dans cet ordre : preflight, expedier, images, cible, prouver (ou tout)
bash containers/scripts/deploy-all.sh 1 --plan backend --etape prouver

Le script ne contient aucun secret : ils naissent sur la cible (scripts d'initialisation des secrets, exécutés sur l'hôte pendant l'étape cible, de façon idempotente : relancer l'étape est sans danger). Résultat attendu de l'étape prouver : un accès HTTPS, certificat vérifié, à chaque nom public du niveau ; un nom qui ne résout pas imprime l'enregistrement DNS à créer chez votre hébergeur.

Déploiement tiré par l'hôte

Le chemin courant n'est pas une poussée depuis un poste : l'hôte tire. Un minuteur systemd utilisateur lance un script 2 minutes après la fin du passage précédent (OnUnitInactiveSec=120). Le script regarde si la branche principale a avancé :

ScriptRôle
scripts/deploy/vps-autodeploy-front.shConstruit le front (dx build --release) et bascule le dossier servi par forge-ui, puis prouve par HTTPS
scripts/deploy/vps-autodeploy-backend.shConstruit l'image backend sur l'hôte, met à jour l'unité forge-api, redémarre et prouve par HTTPS
scripts/deploy/vps-autodeploy-vps2.shDéploie le plan client : seules les unités dont un fichier source a changé sont redémarrées

Installation et suivi, depuis le poste de l'opérateur :

bash scripts/deploy/installer-autodeploy-hote.sh --vps1   # ou --vps2, --tout
bash scripts/deploy/suivre-autodeploy.sh

Les deux commandes ci-dessus se connectent en SSH : elles lisent l'hôte cible dans la variable HOTE (l'installateur lit aussi HOTE_VPS2 pour le plan client) et la clé SSH dans CLE. Posez ces variables explicitement avant de les lancer. Résultat attendu de suivre-autodeploy.sh : l'état du minuteur (active), le SHA déployé, puis la fin du journal et de la construction du front. Il ne lit pas l'état du backend : comparez le champ sha de /api/v1/healthz au commit attendu (voir Supervision).

Points à connaître :

  • l'image backend est étiquetée par le SHA du commit (localhost/forge-stack:<sha-court>) et construite par podman build -f Containerfile . sur l'hôte ; aucune image n'est supprimée, l'étiquette précédente reste disponible ;
  • si la santé locale n'est pas prouvée après le redémarrage, le script revient à l'image précédente ;
  • un commit qui ne touche que la documentation ne reconstruit pas l'image ;
  • aucune clé ni port n'est exposé par ce mécanisme : l'hôte tire, il ne reçoit rien.

La description complète du processus est dans docs/deploiement/PROCESSUS-PAR-PUSH.md.

Construction des images

Le Containerfile à la racine construit en plusieurs étapes les binaires Rust (forge-api, forge-cli, forge-ops) vers une image finale minimale ; Containerfile.production en est la variante de production.

podman build -t localhost/forge-stack:dev -f Containerfile .

Le front se construit à part :

dx build --release --platform web --package forge-ui

Modèles Ollama

Une fois forge-ollama démarré, téléchargez les modèles dont vous avez besoin :

podman exec forge-ollama ollama pull <nom-du-modèle>
podman exec forge-ollama ollama list

Le modèle utilisé par défaut se règle par la variable OLLAMA_MODEL du backend. Le CLI forge-cli propose aussi une sous-commande model pull. Le service forge-api du compose (profil container-api) fixe lui-même une valeur par défaut de OLLAMA_MODEL (lisible dans podman-compose.yml) ; le binaire lancé sur l'hôte suit, lui, les défauts de Variables d'environnement. Téléchargez le modèle que votre backend demande. Résultat attendu : ollama list affiche le modèle téléchargé.

Contrôle de la chaîne d'approvisionnement

  • Le dépôt tient un SBOM CycloneDX par composant dans docs/sbom/ (python scripts/audit/sbom_cyclonedx.py --check vérifie qu'il correspond au Cargo.lock).
  • Le workflow de CI du dépôt analyse l'image backend avec Trivy (gravité HIGH et CRITICAL). Il est dormant : aucun exécuteur n'y est rattaché, il ne tourne pas aujourd'hui. Les exceptions acceptées sont listées dans un fichier d'exceptions motivées du dépôt. Un script d'analyse des images se lance à la main.

Notes importantes

  • Les unités Quadlet de production sont préférées en mode rootless ; binder les ports 80 et 443 en rootless exige de baisser net.ipv4.ip_unprivileged_port_start (valeur à fixer au plus à 80, avec les droits administrateur ; l'en-tête de l'unité de l'ingress, dans les sources, donne le détail).
  • OpenBao se re-scelle au redémarrage : voir le guide d'exploitation du coffre (hors de ce livre) pour la topologie de descellement.
  • Les fichiers compose portent des valeurs par défaut de développement pour certains mots de passe : surchargez-les par l'environnement (fichier .env), ne les réutilisez jamais en production. En production, les secrets sont créés sur l'hôte par les scripts d'initialisation des secrets et ne figurent pas dans le dépôt.

Voir aussi

Gestion des conteneurs

Ce chapitre rassemble les gestes du quotidien pour exploiter les conteneurs de Chatbotaurus. Deux contextes cohabitent :

  • le développement et les essais, avec podman-compose (podman-compose.yml et podman-compose.vps2.yml) ;
  • la production, avec des unités Quadlet pilotées par systemd sous le compte non privilégié dédié, <compte-deploiement> (mode rootless : aucune commande sudo podman n'est nécessaire).

Le choix de déploiement est décrit dans Déploiement avec Podman.

Réseaux

RéseauPlanContenu
chatbotaurus-vps1BackendServices forge-*
mgaas-vps2ClientPasserelle MCP et services mcp-*

Les adresses de ces réseaux ne sont pas fixées par la documentation : les conteneurs se joignent par leur nom (DNS interne Podman), et PostgreSQL et Valkey portent les alias postgres et valkey sur les deux réseaux.

podman network ls
podman network inspect chatbotaurus-vps1 --format '{{.Name}}'

Commandes courantes

Les commandes ci-dessous valent pour le développement comme pour la production, sauf mention contraire.

Lister les conteneurs

podman ps -a --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

Journaux d'un conteneur

podman logs -f forge-api
podman logs --tail 100 forge-postgres

Pour une unité Quadlet, le journal systemd donne aussi l'historique des démarrages :

journalctl --user -u forge-api.service -n 100

Redémarrer un service

# Développement
podman-compose -p chatbotaurus-vps1 restart postgres

# Production (unité Quadlet)
systemctl --user restart forge-api.service
systemctl --user status forge-api.service

Résultat attendu : systemctl --user status affiche active (running). Sinon, lisez journalctl --user -u forge-api.service -n 100 et suivez Problèmes connus.

Inspecter un conteneur

podman inspect forge-valkey --format '{{.State.Status}}'

Statistiques de ressources

podman stats --no-stream

Services principaux

Noms de conteneurs du plan backend, avec leur port d'écoute interne :

ConteneurPortRôle
forge-postgres5432Base de données principale
forge-valkey6379Cache et sessions
forge-qdrant6333 (REST), 6334 (gRPC)Base vectorielle
forge-ollama11434Inférence IA locale (limite mémoire fixée dans le plan compose)
forge-authentik9000SSO / IAM (en production : forge-authentik-server et forge-authentik-worker)
forge-openbao8200Gestion des secrets
forge-api3000Backend Rust
forge-victoriametrics8428Métriques
forge-victorialogs9428Journaux
forge-crowdsec—Détection d'intrusion
forge-seaweedfs8333Stockage objet S3

En production, forge-traefik est l'ingress du plan backend et mcp-caddy celui du plan client.

Les limites mémoire déclarées se lisent dans les fichiers :

grep -n "memory:" podman-compose.yml

Mise à jour d'un service

La marche diffère selon le contexte.

En production

La mise à jour est tirée par l'hôte. Un minuteur, 2 minutes après la fin du passage précédent, reconstruit l'image backend ou le front quand la branche principale avance. Voir la section « Déploiement tiré par l'hôte » du chapitre Déploiement avec Podman. Pour suivre l'état du front (ce script ne lit pas celui du backend : comparez le champ sha de /api/v1/healthz au commit attendu) :

bash scripts/deploy/suivre-autodeploy.sh

Si une image doit être rétablie à la main : l'étiquette précédente reste sur l'hôte (podman images | grep forge-stack). Remettez-la dans l'unité forge-api.container, puis :

systemctl --user daemon-reload
systemctl --user restart forge-api.service

En développement

Si le service porte des données (PostgreSQL, Valkey, Qdrant), sauvegardez-les d'abord : Sauvegarde et restauration.

podman-compose -p chatbotaurus-vps1 pull postgres
podman-compose -p chatbotaurus-vps1 up -d postgres

Sauvegardes

Les sauvegardes sont décrites dans Sauvegarde et restauration. Les commandes manuelles sont les mêmes que celles utilisées par scripts/backup/nightly.sh.

Dépannage

Quelques pannes fréquentes et le premier geste à faire.

Conteneur qui ne démarre pas

# Logs du conteneur
podman logs forge-postgres

# Ports occupés (Linux)
ss -tlnp | grep 5432

# Espace disque
df -h

Vérifiez aussi que les deux réseaux existent : podman network ls. Les fichiers compose les déclarent externes et ne les créent pas. Les volumes de données sont dans le même cas : podman volume ls, et la boucle de création de Déploiement avec Podman.

Conflit de port

# Linux
ss -tlnp | grep <port>
# Windows (développement local)
netstat -ano | Select-String "5432"

Le port de Valkey publié sur l'hôte est 6380 par défaut, pour éviter une collision avec un Redis local sur le port 6379.

Ollama ne charge pas le modèle

# Mémoire disponible
free -h

# Modèles installés
podman exec forge-ollama ollama list

# Télécharger un modèle manquant
podman exec forge-ollama ollama pull <nom-du-modèle>

Un service attend un autre

Les services du compose déclarent des sondes de santé (healthcheck) : PostgreSQL, Valkey et Qdrant doivent être sains avant le démarrage du service forge-api. Vérifiez l'état avec :

podman ps --format "table {{.Names}}\t{{.Status}}"

Voir aussi

Sauvegarde et restauration

Chatbotaurus dispose de deux chaînes de sauvegarde qui coexistent :

  1. la chaîne par scripts (scripts/backup/), qui exporte PostgreSQL, Valkey, Qdrant et, selon l'hôte, MariaDB vers un stockage S3 européen ;
  2. la chaîne par agents sur l'hôte (spec 114), où un agent installé sur chaque hôte envoie ses archives à l'orchestrateur intégré à forge-api.

Le script de retour arrière scripts/backup/rollback.sh permet de revenir de la seconde à la première sans migration destructive. bash scripts/backup/rollback.sh --dry-run (mode par défaut) vérifie les préconditions et imprime les commandes ; --appliquer arrête ensuite l'agent et tusd, et --appliquer --conteneurs le fait par podman stop sur un hôte sans unités Quadlet. Le script s'arrête avant tout arrêt d'unité si la chaîne par scripts n'est pas présente et valide.

À la fin de ce chapitre, vous saurez sauvegarder chaque composant, restaurer depuis chacune des deux chaînes et prouver qu'une restauration fonctionne.

Deux chaînes de sauvegarde superposées : la chaîne par scripts, du script nocturne au stockage S3 européen, et la chaîne par agents sur l'hôte, de l'agent au récepteur TUS puis à l'orchestrateur ; une flèche de retour arrière relie la seconde à la première.

Figure 5 : les deux chaînes de sauvegarde et le retour arrière de la seconde vers la première.

Ce qui est sauvegardé

ComposantMéthodeFichier produit
PostgreSQLpg_dump au format custom, compression 9archive horodatée
ValkeyBGSAVE puis copie du dump.rdbarchive horodatée
Qdrantun instantané par collection (API REST, port 6333)archive horodatée
MariaDBmariadb-dump --all-databases, uniquement si MARIADB_CONTAINER est définiarchive horodatée
Manifesteliste des fichiers et de l'hôtemanifeste horodaté

Le script échoue franchement (code de sortie 1) si l'export PostgreSQL échoue ou si Qdrant ne renvoie aucune collection : une sauvegarde vide ne sort jamais « verte ».

L'étape Valkey est plus tolérante. Si BGSAVE échoue, ou si le fichier dump.rdb de Valkey est introuvable sur l'hôte, le script écrit un avertissement, saute l'étape et sort quand même avec le code 0 (scripts/backup/nightly.sh, étape Valkey). Lisez le journal, ne vous fiez pas au seul code de sortie.

Sauvegarde automatisée

scripts/backup/nightly.sh est conçu pour tourner chaque nuit, à une heure creuse sous cron, côté opérateur :

0 <heure> * * * <chemin-d-installation>/scripts/backup/nightly.sh >> <journal-de-sauvegarde> 2>&1

Il lit sa configuration dans l'environnement (variables du stockage S3 européen, PG_*, VALKEY_*, QDRANT_*). Le fichier qui les porte (fichier d'environnement de la sauvegarde, hors du dépôt, mode 0600) ne se commite jamais. Le détail des variables et l'installation sont dans scripts/backup/README.md, livré avec les sources.

Prérequis de nightly.sh et de restore.sh : les outils aws (client S3), curl, jq, pg_dump, pg_restore et redis-cli, et l'accès réseau à PostgreSQL, Valkey et Qdrant (le port REST de Qdrant, 6333, pas le gRPC 6334). Variables à exporter : le point d'accès, la clé d'accès, la clé secrète et le compartiment du stockage S3 ; l'hôte, le port, l'utilisateur et la base de PostgreSQL, avec le mot de passe fourni par un fichier désigné par PGPASSFILE ; l'hôte, le port et le mot de passe de Valkey ; l'hôte, le port et la clé d'API de Qdrant.

  • Chiffrement : TLS pendant le transfert, chiffrement SSE-S3 au repos.
  • Rétention : 30 jours par défaut (BACKUP_RETENTION_DAYS) ; le script supprime lui-même les sauvegardes plus anciennes.
  • Point de reprise : une sauvegarde nocturne réussie donne un point de reprise de 24 heures au plus. C'est l'objectif de point de reprise (RPO) publié sur la page SLA : moins de 24 h. Il reste une cible, pas un constat : l'exercice de restauration de production n'est pas fait (voir Conformité NIS2).

Sauvegarde par agents sur l'hôte (spec 114)

Un agent de sauvegarde tourne sur l'hôte qui porte les données. Il est décrit par :

  • forge-backup-agent (plan backend) et mcp-backup-agent (plan client), services des fichiers compose derrière le profil backup, et unités Quadlet correspondantes ;
  • forge-tusd, qui reçoit les archives par le protocole TUS et prévient forge-api par un appel de retour ;
  • les routes d'orchestration de forge-api montées sous un préfixe interne, réservé au réseau privé, et l'API d'administration sous /api/v1/admin/backups/.

Démarrage en développement :

podman-compose -p chatbotaurus-vps1 --profile backup up -d backup-agent tusd

L'agent reçoit une clé d'enrôlement générée par l'API d'administration. L'outil forge-ops automatise cette étape :

forge-ops backup status                       # état : agents, cibles, jobs, artefacts
forge-ops backup enroll --name <agent> --origin-host <hôte> --appliquer
forge-ops backup deploy-agent --vps vps1      # unité Quadlet, simulation par défaut
forge-ops backup decrypt <archive.enc>        # déchiffrement hors ligne avec la clé maîtresse

Les archives sont chiffrées avant l'envoi. La rétention est appliquée côté serveur (30 jours par défaut, réglable par cible) par une tâche de fond de forge-api ; une passe manuelle est possible avec POST /api/v1/admin/backups/retention/sweep.

Un stockage objet S3 local, SeaweedFS (forge-seaweedfs, licence Apache-2.0), sert de banc de test avec un compartiment dédié.

Sauvegarde manuelle

Hors du script nocturne, chaque composant se sauvegarde à la main avec son propre outil. Après chaque commande, vérifiez que le fichier produit n'est pas vide (ls -l) : une redirection crée un fichier vide quand l'outil échoue ; les journaux du conteneur disent pourquoi (voir Problèmes connus).

PostgreSQL

podman exec forge-postgres sh -c 'pg_dump -U "$POSTGRES_USER" -Fc "$POSTGRES_DB"' \
  > chatbotaurus_$(date +%Y%m%d).dump

Qdrant

Une collection à la fois (si la clé API est activée, ajoutez -H "api-key: $QDRANT_API_KEY") :

curl -fsS http://localhost:6333/collections
curl -fsS -X POST http://localhost:6333/collections/<collection>/snapshots
# Récupérer le fichier : <nom-du-snapshot> est le champ result.name de la réponse précédente
curl -fsS http://localhost:6333/collections/<collection>/snapshots/<nom-du-snapshot> \
  -o qdrant-<collection>-<horodatage>.snapshot

OpenBao

En production (stockage Raft), la procédure est décrite dans le guide d'exploitation du coffre (hors de ce livre) :

bao operator raft snapshot save <dossier-de-sauvegarde>/snap-$(date +%F).snap

Restauration

La restauration suit la chaîne qui a produit l'archive.

Chaîne par scripts

# Un horodatage précis
bash scripts/backup/restore.sh 20260527-030000

# La plus récente
bash scripts/backup/restore.sh latest

Avant de lancer restore.sh : exportez les mêmes variables que pour nightly.sh (section « Sauvegarde automatisée »), installez aws, pg_restore et redis-cli, et choisissez un horodatage au format AAAAMMJJ-HHMMSS, nom du dossier de la sauvegarde dans le compartiment (latest prend la plus récente). Le script lit aussi VALKEY_CONTAINER (conteneur à redémarrer) et, pour MariaDB, MARIADB_CONTAINER et MARIADB_ROOT_PASSWORD.

restore.sh télécharge l'archive depuis le S3, contrôle le manifeste, puis restaure dans cet ordre : PostgreSQL (pg_restore --clean --if-exists), Valkey (arrêt du conteneur, remplacement du dump.rdb, redémarrage), MariaDB si un export est présent, puis chaque collection Qdrant par envoi de l'instantané. Il écrase les données existantes : il attend 10 secondes avant PostgreSQL et MariaDB pour laisser le temps d'annuler (Ctrl-C).

Résultat attendu : une ligne ... restore OK par composant restauré, des contrôles finaux (nombre de tables PostgreSQL, nombre de clés Valkey), puis Restore completed successfully from backup <horodatage> et le code de sortie 0. Une ligne [WARN] No ... found ; skipping signifie que ce composant n'était pas dans l'archive ; une ligne [FAIL] arrête le script avec le code 1. Ensuite : redémarrez forge-api (voir Gestion des conteneurs), vérifiez GET /api/v1/healthz (voir Diagnostics et signalement), puis qu'un utilisateur connu peut se connecter et retrouver son espace.

Chaîne par agents

Une archive produite par un agent se restaure par une demande à l'API d'administration, jamais par un simple appel : POST /api/v1/admin/backups/restores, avec un compte administrateur et une organisation active. Le corps porte target_id, artifact_id (obligatoire), confirmation: true et confirm_target, le nom exact de la cible réécrit à la main ; reason est facultatif. La réponse est 202 : la demande crée un travail de restauration et une approbation humaine dans la file des approbations. Tant que l'approbation n'est pas donnée, l'agent ne restaure rien. Sans confirmation: true, la réponse est 422 CONFIRMATION_REQUIRED ; sans artifact_id, 422 ARTIFACT_REQUIRED. GET /api/v1/admin/backups/restores liste les demandes.

PostgreSQL à la main

podman exec -i forge-postgres sh -c \
  'pg_restore -U "$POSTGRES_USER" -d "$POSTGRES_DB" --clean --if-exists' \
  < chatbotaurus_20260527.dump

Qdrant à la main

curl -fsS -X POST \
  -F "snapshot=@qdrant-<collection>-<horodatage>.snapshot" \
  http://localhost:6333/collections/<collection>/snapshots/upload

OpenBao

Voir le guide d'exploitation du coffre (restauration d'un instantané Raft puis descellement).

Répétition de restauration

Une sauvegarde qui n'a jamais été restaurée n'est pas une sauvegarde. scripts/backup/drill.sh joue un cycle sauvegarde puis restauration sur une base non critique, compare des compteurs et écrit un rapport daté :

bash scripts/backup/drill.sh --check --hote <alias-ssh>

L'option --check ne vérifie que les préconditions : rien n'est restauré. La répétition réelle ajoute --restore-hote <alias-ssh> et exige un hôte éphémère de restauration et l'option --confirmation ; sans cet hôte, le script le dit au lieu d'inventer un résultat.

Bonnes pratiques

  • Conservez les sauvegardes hors de l'hôte qui porte les données.
  • Ne mettez jamais les clés S3, la clé maîtresse des archives ni les clés de descellement OpenBao dans le dépôt.
  • Répétez une restauration complète à intervalle régulier et consignez le résultat.

Voir aussi

Journaux

Ce chapitre décrit où vont les journaux de Chatbotaurus, dans quel format, et comment les lire. Il distingue ce que le code fait de ce que votre hôte doit configurer.

Confidentialité. Le backend n'a, par défaut, aucune destination externe pour ses journaux : ils restent sur les hôtes que vous exploitez. Un export de la chaîne d'audit vers VictoriaLogs existe, il est désactivé par défaut et ne vise que l'adresse que vous configurez.

Où écrit le backend

forge-api écrit ses journaux sur la sortie standard, avec la bibliothèque tracing. Le backend n'écrit pas ses journaux applicatifs dans un fichier.

RéglageEffet
Format par défautJSON, une ligne par événement
Variable LOG_FORMAT à pretty ou compactSortie compacte lisible, pour le développement
Variable RUST_LOGFiltre par cible et niveau
Variable TRACING_JSONSans effet sur forge-api : posée dans podman-compose.yml, elle n'est pas lue par ce binaire
RUST_LOG absente ou invalideinfo,forge_api=debug,forge_mcp=debug

Chaque ligne JSON porte l'horodatage, le niveau, la cible (le module Rust) et les champs du contexte de requête (request_id, méthode, chemin, statut, durée). Source : init_tracing dans crates/forge-api/src/main.rs.

Filtres RUST_LOG

La syntaxe est celle de tracing-subscriber : des directives cible=niveau séparées par des virgules. Un niveau seul fixe le défaut.

# Développement : forge-api détaillé, le reste en info
RUST_LOG=info,forge_api=debug

# Production : anomalies seules, avec la couche HTTP en info
RUST_LOG=warn,tower_http=info

# Diagnostic ponctuel, très verbeux
RUST_LOG=trace

L'unité de déploiement de forge-api fixe RUST_LOG à info.

Secrets et données personnelles

Toutes les lignes passent par un filtre de rédaction avant d'atteindre la sortie : clés d'API, jetons JWT et bearer, clés privées et adresses e-mail sont masqués (filtre de rédaction du code). C'est un filet : la règle reste de ne pas journaliser de secret.

Lire les journaux d'un conteneur

Les services tournent dans des conteneurs Podman. Lancez les commandes avec le compte qui exécute les conteneurs.

# Suivre un service en direct
podman logs -f forge-api

# Les 100 dernières lignes
podman logs --tail 100 forge-api

# Avec horodatage, sur les dernières 24 heures
podman logs -t --since 24h forge-api

Résultat attendu : des lignes JSON, une par événement. Si Podman répond que le conteneur n'existe pas, vérifiez le nom avec podman ps -a et le compte qui lance la commande (voir Problèmes connus).

Les noms de conteneurs du plan backend (podman-compose.yml) :

ServiceConteneur
API Chatbotaurus (profil container-api)forge-api
PostgreSQLforge-postgres
Valkeyforge-valkey
Qdrantforge-qdrant
Ollamaforge-ollama
Authentikforge-authentik
OpenBaoforge-openbao
VictoriaMetricsforge-victoriametrics
VictoriaLogsforge-victorialogs
Administration PostgreSQL (pgAdmin)forge-pgadmin
Transcription (Speaches)forge-faster-whisper
Téléchargement des modèles vocauxforge-tts-models
Synthèse vocale (Kokoro)forge-kokoro-tts
LiveKitforge-livekit
CrowdSecforge-crowdsec
Agent de sauvegardeforge-backup-agent
Téléversement (tusd)forge-tusd
Stockage objet S3forge-seaweedfs

Les services du plan client portent le préfixe mcp- (podman-compose.vps2.yml). Pour les connaître : podman ps --format "{{.Names}}" sur l'hôte client.

En développement local, forge-api ne tourne pas en conteneur : il est lancé par scripts/dev/run-forge-api.ps1 et écrit dans le terminal qui l'a lancé. Le frontend (dx serve) écrit la compilation et le rechargement dans son propre terminal ; ses erreurs d'exécution apparaissent dans la console du navigateur.

Ce que le dépôt ne règle pas

  • Rotation et taille. Aucune option de taille ou de rotation des journaux de conteneurs n'est fixée dans les fichiers Compose. Dans les unités Quadlet, une seule (searxng) choisit un pilote de journal (journald). Vérifiez la politique de votre hôte avant de laisser un conteneur bavard tourner.
  • Collecte centralisée. forge-victorialogs tourne dans le plan backend de développement. Aucun agent du dépôt n'y envoie les journaux des conteneurs. Ce qui y arrive aujourd'hui, c'est la chaîne d'audit, quand vous activez l'export (voir la section « Chaîne d'audit et export vers VictoriaLogs » plus bas).

Chaîne d'audit et export vers VictoriaLogs

Les événements d'audit (connexions, actions sensibles) forment une chaîne chaînée par empreintes (crates/forge-audit). Un export optionnel les envoie en plus vers VictoriaLogs au format jsonline :

VariableEffetDéfaut
FORGE_SIEM_ENABLEDÀ 1, active l'exportdésactivé
FORGE_SIEM_URLBase de VictoriaLogshttp://localhost:9428

L'export est au mieux : si VictoriaLogs est arrêté, l'écriture dans la chaîne n'est jamais bloquée, et le nombre d'échecs est compté (crates/forge-audit/src/victorialogs_sink.rs).

Pour vérifier que l'export fonctionne, posez les deux variables, redémarrez forge-api (il ne relit pas la configuration à chaud), puis interrogez VictoriaLogs (section « Interroger VictoriaLogs » de Supervision).

Voir aussi

Supervision

Ce chapitre dit ce qui est mesurable aujourd'hui, ce qui est livré mais pas déployé, et ce qui reste à faire. Chaque ligne indique son état.

ÉtatSens
En serviceLe code ou l'unité existe et le déploiement l'installe
Développement seulDéfini dans podman-compose.yml, absent du déploiement Quadlet
Livré, non branchéLe fichier existe, aucun service ne le charge
Retiré du déploiementL'unité existe, le déploiement ne l'installe plus

Points de santé de l'API (en service)

Ces routes sont servies par forge-api (crates/forge-api/src/router.rs).

RouteRôleRéponse
GET /api/v1/healthz (alias /api/v1/health)Le processus répond200 avec status, service, version, et sha du binaire quand il est connu
GET /api/v1/readyzLe backend est prêt200 si PostgreSQL et Valkey répondent, sinon 503 ; indique aussi le nombre de connecteurs chargés
GET /api/v1/health/statusPage d'état publiqueSonde PostgreSQL, Ollama, Qdrant, Authentik et SMTP ; overall vaut operational, degraded ou down ; 503 si down

Le champ sha de healthz permet de vérifier de l'extérieur quelle version tourne après un déploiement.

curl -fsS https://<votre-domaine-api>/api/v1/healthz
curl -fsS https://<votre-domaine-api>/api/v1/readyz

Résultat attendu : healthz répond 200 avec le champ status ; readyz répond 200, ou 503 quand PostgreSQL ou Valkey ne répondent pas (voir Diagnostics et signalement). En production, <votre-domaine-api> est l'adresse publique de l'application, notée app.<domaine> dans les autres chapitres.

Métriques de l'API (en service)

GET /metrics (à la racine, hors /api/v1) rend le format texte Prometheus. L'accès est protégé :

  • avec PROMETHEUS_BEARER_TOKEN posée, le collecteur envoie Authorization: Bearer <jeton> ; un jeton faux reçoit 401 ;
  • sans cette variable, seule une session de plateforme avec élévation est acceptée.

Quatre séries sont émises :

SérieÉtiquettes
forge_http_requests_totalméthode, chemin normalisé, statut
forge_http_request_duration_secondsméthode, chemin normalisé
forge_http_errors_totalméthode, chemin normalisé, statut (4xx et 5xx)
forge_http_active_connectionsaucune

Il n'existe pas de série tool_call_duration_ms, resolve_ms, credentials_ms ni cache_hit_rate dans le code. Les temps par appel d'outil n'ont pas de métrique exportée.

Stockage des métriques et des journaux (développement seul)

podman-compose.yml définit deux services :

ServiceConteneurPortRéglage
VictoriaMetricsforge-victoriametrics8428rétention de 12 mois (--retentionPeriod=12)
VictoriaLogsforge-victorialogs9428rétention par défaut de l'outil

Aucune unité Quadlet ne déploie ces deux services, et ils ne figurent pas dans les niveaux de containers/scripts/deploy-all.sh. Le fichier de collecte prévu pour VictoriaMetrics n'est pas monté dans le conteneur : VictoriaMetrics ne collecte donc rien tant que vous ne l'alimentez pas (collecte configurée par vos soins, ou envoi depuis un autre collecteur).

Les valeurs VICTORIAMETRICS_RETENTION et VICTORIALOGS_RETENTION du fichier .env.example ne sont lues par aucun code.

Règles d'alerte (livré, non branché)

Un fichier de règles d'alerte du dépôt contient 24 règles : disque, mémoire, processeur, charge, conteneur arrêté ou en boucle de redémarrage, sauvegarde ancienne, certificat proche de l'expiration, force brute SSH, pic de décisions CrowdSec, coffre scellé, intégrité du système de fichiers. Elles supposent node_exporter sur l'hôte.

Aucun service vmalert n'existe dans les fichiers Compose ni dans les unités Quadlet. Ces règles ne s'évaluent donc nulle part aujourd'hui. Plusieurs règles ciblent des conteneurs nommés chatbotaurus-*, alors que les conteneurs du plan backend s'appellent forge-* : elles ne correspondraient à rien en l'état. Les brancher est un travail à faire : démarrer vmalert, y monter ce fichier, installer node_exporter et choisir un destinataire des alertes.

Supervision de l'hôte (en service)

Le déploiement du plan backend installe Beszel (hub et agent), un outil de supervision de serveurs : charge, mémoire, disque, conteneurs. Le hub écoute sur la boucle locale de l'hôte et n'est pas publié : la route d'ingress qui le placerait derrière Authentik est périmée et n'est câblée par aucun script. Accédez-y par un tunnel SSH.

Détection d'intrusion

OutilÉtatRôle
CrowdSecEn service (forge-crowdsec, niveau 2 du déploiement)Analyse les journaux du proxy inverse et de SSH ; un scénario cible les abus de l'API MCP (seuils et durée de blocage fixés dans un scénario du dépôt, non publiés)
FalcoRetiré du déploiement le 2026-09-19L'unité existe ; le chargement du pilote noyau échoue sur l'hôte cible, une version eBPF reste à concevoir
ZeekRetiré du déploiement le 2026-09-19Fichier de site que la préparation d'hôte n'installe pas

Les outils SIEM et IDS retirés (spec 98), comme les tableaux de bord du plan client, ne font pas partie du plan backend. Grafana existe côté client sous la forme d'un service mcp-grafana de tableaux de bord, accessible par le connecteur du même nom.

Niveaux de dégradation (livré, non branché)

Le code définit une cascade de dégradation selon la charge (DegradationManager, crates/forge-core/src/mgaas/resource_monitor.rs) : Full, puis NoMcts, NoTot, NoSelfConsistency, TemplateOnly. Les seuils de mémoire, de processeur et de latence sont fixés dans le code et ne sont pas publiés ici.

Deux réserves :

  • Les moteurs de raisonnement que cette cascade coupe (arbre de pensées, auto-cohérence, Monte Carlo) n'ont aucun appelant de production : la route GET /api/v1/mgaas/engines les déclare « dormants ».
  • GET /api/v1/mgaas/monitor (réservé aux administrateurs avec élévation) crée un moniteur neuf à chaque appel, et aucun appelant de production n'y écrit de mesure. D'après la lecture du code, le niveau rendu est Full.

Ne bâtissez pas d'alerte sur ce point.

Interroger VictoriaLogs

Quand l'export d'audit est activé (voir Journaux), VictoriaLogs répond sur son API LogsQL, par exemple /select/logsql/query (chemins utilisés par le connecteur connectors/victorialogs.yaml). Le connecteur du catalogue permet de poser ces requêtes depuis le chat.

Bonnes pratiques

  • Sondez readyz depuis votre supervision externe, pas healthz : healthz répond même quand la base est arrêtée.
  • Posez PROMETHEUS_BEARER_TOKEN sur un jeton aléatoire et donnez-le au seul collecteur.
  • Branchez vos propres alertes avant de compter sur le fichier de règles.

Voir aussi

Diagnostics et signalement

Ce chapitre rassemble les outils intégrés pour diagnostiquer un problème, signaler une anomalie et demander une fonctionnalité.

BesoinOutilRésultat
L'API répond-elle ?Routes de santé de forge-apiJSON d'état
Quel conteneur est tombé ?podman ps, podman logsÉtat et journaux
Quelle version tourne ?Champ sha de /api/v1/healthzSHA du commit déployé
Où en est le déploiement ?scripts/deploy/suivre-autodeploy.shDernier SHA, journal
Signaler une anomalieCourriel au supportÉchange tracé

Santé de la plateforme

forge-api expose trois routes de santé, sans authentification :

# Vivacité : répond 200 tant que le processus tourne (et indique la version)
curl -s http://localhost:3000/api/v1/healthz | jq .

# Disponibilité : vérifie PostgreSQL et Valkey
curl -s http://localhost:3000/api/v1/readyz | jq .

# Page d'état : une entrée par service (up, down ou degraded) avec sa latence
curl -s http://localhost:3000/api/v1/health/status | jq .

La réponse de healthz porte status, service, version et, quand l'environnement du processus la fournit (FORGE_GIT_SHA), le champ sha. Comparer ce sha au dernier commit est une façon simple de savoir si un déploiement est arrivé.

Résultat attendu : readyz répond 200 quand PostgreSQL et Valkey répondent, 503 sinon ; health/status répond 503 quand l'état global (overall) vaut down. En cas de 503, passez à la vérification manuelle des services ci-dessous.

Derrière le nom public, remplacez localhost:3000 par https://app.<domaine>.

Vérification manuelle des services

# État de tous les conteneurs
podman ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

# PostgreSQL
podman exec forge-postgres sh -c 'pg_isready -U "$POSTGRES_USER"'

# Valkey
podman exec forge-valkey valkey-cli ping

# Qdrant (liste des collections)
curl -s http://localhost:6333/collections | jq .

# Ollama : modèles disponibles
podman exec forge-ollama ollama list

# OpenBao : état de scellement (code de sortie 2 = scellé)
podman exec forge-openbao bao status

# Passerelle MCP du plan client (port 8811)
curl -s http://localhost:8811/health

Résultat attendu : pg_isready répond « accepting connections » ; valkey-cli ping répond PONG ; la requête Qdrant liste les collections ; ollama list liste les modèles ; bao status rend le code de sortie 2 quand le coffre est scellé ; la passerelle répond à /health. Un échec renvoie à la section correspondante de Problèmes connus.

Les noms des conteneurs sont ceux des fichiers compose. En production, les services d'une unité Quadlet se pilotent avec systemd :

systemctl --user status forge-api.service

Ressources

# Mémoire et CPU par conteneur
podman stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.CPUPerc}}"

# Espace utilisé par Podman (images, conteneurs, volumes)
podman system df

# Espace disque de l'hôte
df -h

Journaux du backend

# Temps réel
podman logs -f forge-api

# 100 dernières lignes
podman logs --tail 100 forge-api

# Pour une unité Quadlet : journal systemd
journalctl --user -u forge-api.service -n 100

Les journaux de forge-api sont écrits en JSON par défaut, une ligne par événement, avec les champs du contexte de requête courant (LOG_FORMAT=pretty donne une sortie lisible ; TRACING_JSON n'est pas lue par ce binaire). Chaque requête porte un en-tête X-Request-ID (généré s'il manque) que la réponse renvoie : quand un utilisateur signale une erreur, demandez-lui cet identifiant pour retrouver la ligne.

Voir aussi Journaux.

Diagnostic de la passerelle MCP

Les routes MCP de forge-api exigent un utilisateur authentifié (en-tête Authorization: Bearer <jeton>, ou cookie de session) ; $TOKEN est le jeton rendu par la connexion, décrite dans Documentation Swagger :

# Ouvrir une session (la réponse porte l'en-tête Mcp-Session-Id)
curl -i -X POST http://localhost:3000/api/v1/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{}},"id":1}'

# Consulter le catalogue des connecteurs
curl -s http://localhost:3000/api/v1/mcp/catalogue \
  -H "Authorization: Bearer $TOKEN" | jq .

Pour les erreurs renvoyées, voir Gestion des erreurs.

Suivre un déploiement

Le déploiement est tiré par l'hôte (minuteur toutes les 2 minutes). Depuis le poste d'un opérateur :

bash scripts/deploy/suivre-autodeploy.sh

Il affiche l'état du minuteur, le dernier SHA déployé et la fin du journal et de la construction, tous relatifs au front. Il ne lit pas l'état du backend : comparez le champ sha de /api/v1/healthz au commit attendu.

Signaler une anomalie

Écrivez à support@chatbotaurus.com en indiquant :

  • la description du problème ;
  • les étapes pour le reproduire ;
  • le comportement attendu et le comportement observé ;
  • les journaux pertinents, anonymisés ;
  • la version (sha de /api/v1/healthz) et l'environnement (production, plan client ou développement local) ;
  • l'identifiant X-Request-ID de la requête en cause, s'il est connu.

Attention : confidentialité

Avant de partager des journaux, retirez toute information sensible : clés d'API, jetons, mots de passe, adresses IP, données personnelles. Ne partagez jamais les clés de descellement OpenBao.

Une faille de sécurité se signale à security@chatbotaurus.com, pas par le canal ordinaire.

Demander une fonctionnalité

Écrivez à support@chatbotaurus.com avec le préfixe [Feature] dans l'objet et décrivez :

  • le cas d'usage ;
  • la solution proposée ;
  • les alternatives envisagées ;
  • l'impact sur la conformité UE, si applicable.

Voir aussi

Problèmes connus

Chatbotaurus, comme tout système complexe, peut rencontrer des problèmes occasionnels. Ce guide fournit des solutions pour les cas courants. Les noms de conteneurs sont ceux des fichiers podman-compose.yml (plan backend, services forge-*) et podman-compose.vps2.yml (plan client, services mcp-*).

Astuce : un problème qui n'est pas listé ici ?

Écrivez à support@chatbotaurus.com en suivant la marche décrite dans Diagnostics et signalement.

Par symptôme

Vous constatezSection
Un conteneur ne démarre pas, un réseau ou un volume est introuvableUn conteneur ne démarre pas
Les services ne repartent pas après un redémarrage de l'hôteLes services Quadlet ne redémarrent pas après un redémarrage de l'hôte
Un port est déjà utiliséConflit de port
Les conteneurs ne se joignent pas par leur nomRésolution DNS entre conteneurs
Des données disparaissent après un redémarrageVolumes et persistance des données
Une modification n'apparaît pas en productionMa modification n'apparaît pas en production
Ollama est tué ou ne répond plusOllama à court de mémoire (OOM)
Ollama répond « model not found »Modèle introuvable
Les réponses du modèle sont lentesLatence élevée des réponses
Erreur 503 sur la lecture d'un secretOpenBao scellé
Un service ne reçoit pas ses secretsUn service ne reçoit pas ses secrets
« session expired or unknown » ou « missing Mcp-Session-Id »Erreur de session Streamable HTTP
Un connecteur ne répond pas (TIMEOUT, SERVICE_UNAVAILABLE, RATE_LIMITED, SSRF_BLOCKED)Un connecteur échoue
connector rejected by registry au démarrageUn connecteur est rejeté au démarrage
Erreur CIRCUIT_OPEN (503)Erreur CIRCUIT_OPEN (503)
PostgreSQL refuse la connexionPostgreSQL : connexion refusée
Qdrant renvoie des erreurs de lectureQdrant : index corrompu
Le stockage objet répond 403 à toutLe stockage objet S3 refuse toutes les requêtes
Le wasm ne compile pasErreur de compilation du wasm
dx serve ne recharge plusdx serve ne recharge plus
Un réglage du frontend est sans effetLa configuration du frontend est ignorée
403 sur les POST, PUT ou DELETELe CSRF rejette les requêtes
Tous les utilisateurs sont déconnectés après un redémarrage du backendLe JWT est invalide après un redémarrage du backend
La connexion SSO échoueConnexion impossible

Infrastructure Podman

Un conteneur ne démarre pas

  1. Lisez les journaux du conteneur :
    podman logs forge-postgres
    
  2. Vérifiez que les deux réseaux existent (les fichiers compose les déclarent externes et ne les créent pas) :
    podman network ls | grep -E "chatbotaurus-vps1|mgaas-vps2"
    
  3. S'ils manquent, créez-les :
    podman network create chatbotaurus-vps1
    podman network create mgaas-vps2
    
  4. Pour un service sous Quadlet, regardez l'unité systemd :
    systemctl --user status forge-api.service
    journalctl --user -u forge-api.service -n 100
    

Les services Quadlet ne redémarrent pas après un redémarrage de l'hôte

Les unités Quadlet tournent sous un compte de déploiement non privilégié (rootless). Sans le mode « linger » de systemd, elles s'arrêtent à la déconnexion et ne repartent pas au démarrage. Le script containers/scripts/enable-linger.sh l'active, une fois, par hôte. Il se lance en root, après la création du compte de déploiement, en lui passant le nom de ce compte : bash containers/scripts/enable-linger.sh <compte-deploiement> (le compte doit exister, sinon le script s'arrête et dit de le créer). Résultat attendu : des lignes [OK], dont lingering enabled, puis la vérification du répertoire d'exécution et du socket Podman de ce compte.


Conflit de port

Si un port est déjà utilisé :

ss -tlnp | grep <port>

Sous Windows (développement local) :

netstat -ano | Select-String "5432"

Ports publiés par défaut en développement : 5432 (PostgreSQL), 6380 (Valkey, pour ne pas entrer en collision avec un Redis local sur 6379), 6333 (Qdrant), 11434 (Ollama), 9000 (Authentik), 8200 (OpenBao).


Résolution DNS entre conteneurs

Si les conteneurs ne se résolvent pas entre eux par leur nom :

  1. Vérifiez qu'ils sont sur le même réseau :
    podman inspect forge-api --format '{{json .NetworkSettings.Networks}}'
    
  2. Vérifiez le moteur réseau de Podman (netavark attendu) :
    podman info | grep -i networkBackend
    
  3. Rechargez les réseaux :
    podman network reload --all
    
  4. En dernier recours, recréez les conteneurs (les volumes sont conservés).

Rappel : PostgreSQL et Valkey portent les alias postgres et valkey sur mgaas-vps2. Un service du plan client doit utiliser ces alias, pas forge-postgres.


Volumes et persistance des données

Si des données disparaissent après un redémarrage :

  1. Vérifiez les volumes montés :
    podman inspect forge-postgres --format '{{json .Mounts}}'
    podman volume ls
    
  2. Utilisez les volumes nommés des fichiers compose (noms logiques forge-pgdata, forge-valkey-data, forge-qdrant-data, entre autres) plutôt que des montages temporaires. Ces volumes sont external : leur nom réel est la clé name: du bloc volumes: (grep -n "name:" podman-compose.yml) et compose ne crée pas un volume externe absent. La création est décrite dans Déploiement avec Podman.

Déploiement

Ma modification n'apparaît pas en production

Le déploiement est tiré par l'hôte, toutes les 2 minutes, et seulement si la branche principale a avancé. Vérifiez dans l'ordre :

  1. le champ sha de /api/v1/healthz correspond-il à votre commit ?
    curl -s https://app.<domaine>/api/v1/healthz | jq .
    
  2. où en est le déploiement du front (ce script ne lit pas l'état du backend : l'étape 1 le prouve) ?
    bash scripts/deploy/suivre-autodeploy.sh
    
  3. un commit qui ne touche que la documentation ne reconstruit pas l'image backend : c'est normal ;
  4. si le service ne répond pas après un redémarrage, le script du backend revient à l'image précédente et l'indique dans son état.

Après un déploiement du front, rechargez la page en vidant le cache du navigateur : l'ancien wasm peut rester en cache.


Ollama et modèles IA

Ollama à court de mémoire (OOM)

Si Ollama est tué par le noyau :

  1. Vérifiez la mémoire disponible :
    free -h
    
  2. Vérifiez les limites du conteneur (fixées dans le plan compose) :
    podman inspect forge-ollama | grep -i memory
    
  3. Solutions :
    • augmentez la limite mémoire si l'hôte le permet ;
    • réduisez le nombre de modèles chargés simultanément ;
    • choisissez un modèle plus petit (variable OLLAMA_MODEL).

Modèle introuvable

Si Ollama répond « model not found » :

# Modèles disponibles
podman exec forge-ollama ollama list

# Télécharger le modèle manquant
podman exec forge-ollama ollama pull <nom-du-modèle>

Le nom doit correspondre à celui que le backend demande (OLLAMA_MODEL).


Latence élevée des réponses

Si les réponses du LLM sont lentes :

  1. Vérifiez l'utilisation CPU (podman stats --no-stream).
  2. Vérifiez qu'un seul modèle est chargé : passer d'un modèle à l'autre est coûteux.
  3. Le code prévoit une dégradation par paliers au-delà de 10 s de latence moyenne (voir Gestion des erreurs), mais les moteurs qu'elle coupe n'ont pas d'appelant de production : ne comptez pas dessus pour réduire la latence (voir Supervision).

OpenBao (gestion des secrets)

OpenBao scellé

OpenBao se scelle au redémarrage. Symptôme : erreur 503 sur les appels qui lisent un secret.

  1. Vérifiez l'état (code de sortie 2 = scellé) :
    podman exec forge-openbao bao status
    
  2. Descellez avec le seuil de clés défini à l'initialisation. La commande demande la clé à la saisie :
    podman exec -it forge-openbao bao operator unseal
    
    Répétez avec des clés distinctes jusqu'à Sealed: false.

Attention

Les clés de descellement se conservent séparément et en lieu sûr. Ne les commitez jamais dans le dépôt. La topologie de descellement est décrite dans le guide d'exploitation du coffre, hors de ce livre.


Un service ne reçoit pas ses secrets

  1. Vérifiez qu'OpenBao est descellé (voir la section « OpenBao scellé » ci-dessus).
  2. Vérifiez les permissions du jeton utilisé par le backend.
  3. Consultez les journaux du backend :
    podman logs --tail 100 forge-api
    

Passerelle MCP

Erreur de session Streamable HTTP

Si vous recevez une erreur « session expired or unknown » (code JSON-RPC -32600) ou « missing Mcp-Session-Id » :

  1. Vérifiez que l'en-tête Mcp-Session-Id est présent dans la requête ;
  2. les sessions expirent après 30 minutes d'inactivité ;
  3. ouvrez une nouvelle session par une requête initialize sur POST /api/v1/mcp.

Un connecteur échoue

Si un connecteur (Odoo, n8n, Matomo, entre autres) ne répond pas :

  1. Identifiez le code d'erreur renvoyé :
    • TIMEOUT (504) : le service tiers est trop lent (voir timeout_ms du connecteur) ;
    • SERVICE_UNAVAILABLE (503) : connexion impossible ;
    • RATE_LIMITED (429) : limite de l'amont atteinte, respectez Retry-After ;
    • Forbidden avec SSRF_BLOCKED : l'URL de base fournie par le locataire vise le réseau interne, elle est refusée.
  2. Vérifiez que le conteneur du service tourne :
    podman ps --filter name=mcp-
    
  3. Vérifiez les identifiants du connecteur (variable token_env ou key_env du YAML, ou identifiants du locataire).
  4. Lisez les logs du service concerné (podman logs mcp-n8n, par exemple).

Un connecteur est rejeté au démarrage

Au démarrage, forge-api journalise connector rejected by registry (EU compliance?) pour un connecteur dont gdpr_compliant vaut false ou dont la résidence des données n'est pas européenne. Corrigez le bloc compliance du YAML : voir Conception des connecteurs MCP.


Erreur CIRCUIT_OPEN (503)

Le disjoncteur d'un agent s'est ouvert après plusieurs échecs consécutifs. Il laisse repasser un essai après un court délai. Cherchez la cause des échecs dans les journaux de forge-api (modèle indisponible, connecteur en erreur), puis attendez le délai ou corrigez la cause.


Base de données et stockage

PostgreSQL : connexion refusée

  1. Vérifiez que le conteneur tourne :
    podman ps | grep forge-postgres
    
  2. Vérifiez les journaux :
    podman logs forge-postgres
    
  3. Vérifiez que le port 5432 n'est pas pris par une autre instance PostgreSQL locale.

Qdrant : index corrompu

Si Qdrant renvoie des erreurs de lecture :

  1. Lisez les journaux :
    podman logs forge-qdrant
    
  2. Restaurez d'abord l'instantané de la collection (voir Sauvegarde et restauration).
  3. En dernier recours, supprimez la collection (les embeddings devront être régénérés) :
    curl -X DELETE http://localhost:6333/collections/<collection>
    

Le stockage objet S3 refuse toutes les requêtes

Le service forge-seaweedfs est fermé par défaut : si les variables SEAWEEDFS_S3_* référencées par son fichier d'identités sont absentes ou vides, toute requête est refusée (403). Renseignez ces variables dans l'environnement du compose puis recréez le service : podman-compose -p chatbotaurus-vps1 up -d --force-recreate seaweedfs. Résultat attendu : une requête signée avec ces clés aboutit, une requête anonyme reçoit toujours 403.


Interface (Dioxus wasm)

Erreur de compilation du wasm

La commande de référence est :

cargo build -p forge-ui --target wasm32-unknown-unknown --bin chatbotaurus

Quatre causes reviennent souvent :

La cible wasm peut ne pas être installée. Installez-la :

rustup target add wasm32-unknown-unknown

Un cache cargo corrompu après une interruption brutale peut laisser des artefacts incohérents :

cargo clean -p forge-ui
cargo build -p forge-ui --target wasm32-unknown-unknown --bin chatbotaurus

Les erreurs de compilation Rust se diagnostiquent plus vite avec cargo check, qui s'arrête avant l'édition de liens :

cargo check -p forge-ui --target wasm32-unknown-unknown

Enfin, une Dioxus CLI obsolète se manifeste par des erreurs opaques à l'édition de liens ou à l'empaquetage. Réinstallez la dernière version 0.7 :

cargo install dioxus-cli --force

Le paquet de production se construit avec :

dx build --release --platform web --package forge-ui

Sous Windows, l'optimiseur wasm-opt peut planter et dx rend pourtant un code de sortie 0 : une ligne ERROR dans sa sortie suffit à refuser le paquet. La construction de production se fait sous Linux.

dx serve ne recharge plus

Il arrive que l'observateur de fichiers se désynchronise (montage croisé Windows/WSL). Arrêtez dx serve, puis relancez-le :

dx serve --package forge-ui --bin chatbotaurus --port 8080

La configuration du frontend est ignorée

Le frontend wasm ne lit pas les variables d'environnement système à l'exécution (il s'exécute dans le navigateur). Sa configuration est compilée :

  • la marque, les liens et les offres affichés viennent de crates/forge-ui/src/config/site.rs ;
  • l'adresse de l'API vient de crates/forge-ui/src/config/api.rs : en web, le chemin relatif /api/v1 du même domaine ; sur les cibles natives, la valeur de API_URL fixée à la compilation (défaut http://localhost:3000/api/v1).

Pour appliquer un changement : éditez le fichier, reconstruisez le wasm ; dx serve recharge automatiquement.

Le CSRF rejette les requêtes

Symptôme : 403 sur les POST, PUT ou DELETE.

Vérifiez :

  1. que le cookie csrf-token est présent (outils du navigateur, onglet Application, Cookies) ;
  2. que l'en-tête x-csrf-token est envoyé avec la même valeur que le cookie ;
  3. que l'origine du frontend figure dans CORS_ORIGINS côté backend.

Le JWT est invalide après un redémarrage du backend

La valeur de JWT_SECRET doit rester stable d'un démarrage à l'autre. Si elle change (par exemple générée au hasard à chaque lancement), tous les jetons émis avant deviennent invalides. Fixez JWT_SECRET dans votre fichier d'environnement et chargez-le à chaque démarrage.


Authentik (authentification)

Connexion impossible

  1. Vérifiez qu'Authentik répond (port 9000 en développement) :
    podman ps --filter name=authentik
    
  2. Lisez les journaux (en développement forge-authentik, en production forge-authentik-server et forge-authentik-worker) :
    podman logs forge-authentik
    
  3. Vérifiez l'application et le fournisseur OIDC dans la console d'administration.

Performance et surveillance

Seuils de dégradation

Le code prévoit de réduire les techniques d'IA quand l'un de ces seuils est franchi (crates/forge-core/src/mgaas/types.rs). Cette cascade est livrée mais non branchée (voir Supervision).

Les seuils (mémoire, processeur, latence) sont fixés dans le code et ne sont pas publiés ici.

VictoriaMetrics (forge-victoriametrics, port 8428) et VictoriaLogs (forge-victorialogs, port 9428) existent dans le compose de développement. Rien ne les alimente par défaut et aucune unité Quadlet ne les déploie : voir Supervision.


Besoin d'aide supplémentaire ?

  1. Consultez les diagnostics intégrés pour rassembler les informations utiles.
  2. Écrivez à support@chatbotaurus.com.

Voir aussi

Conformité RGPD

Chatbotaurus est conçu pour appliquer le règlement (UE) 2016/679 (RGPD) dans le code. Le statut précis est « prêt par conception » : les contrôles sont câblés et une preuve exécutable existe pour chacun. Ce n'est pas une certification. Aucun organisme tiers n'a délivré de certificat RGPD.

Ce chapitre cite chaque obligation avec son article, le mécanisme qui l'applique, et ce qui reste ouvert. Les numéros d'article sont ceux du texte officiel du règlement ; vérifiez-les sur ce texte avant de les opposer à un tiers.

Obligations et mécanismes

ObligationMécanisme dans le produit
Minimisation (art. 5, par. 1, point c)Les secrets d'un client ne sont pas chargés au démarrage : ils sont résolus à la requête, par organisation, et n'existent en mémoire que le temps de l'appel.
Consentement (art. 7)Formulaire de consentement avant conversation, configurable et persisté. Les consentements du domaine de santé se donnent en deux étapes, par finalité, avec un jeton dédié par flux, portés par organisation.
Accès et portabilité (art. 15 et 20)Export du compte livré dans le produit.
Effacement (art. 17)Suppression et purge des données personnelles côté serveur (balayages : Variables d'environnement, section « Purges planifiées ») ; effacement d'un dossier patient sur les surfaces de santé.
Protection dès la conception (art. 25)Le cloisonnement par organisation est appliqué dans chaque requête, pas par un réglage. Les traces d'exécution ne traversent pas les organisations, même pour un administrateur.
Registre des traitements (art. 30)Un registre est tenu dans le dépôt, versionné avec le code. Il est à l'état de brouillon : la confirmation par le délégué à la protection des données et le conseil est en attente.
Sécurité du traitement (art. 32)Second facteur (TOTP, WebAuthn) et cookies durcis avec protection CSRF. Mots de passe hachés en Argon2id. Identifiants de services externes chiffrés en AES-256-GCM. Journal des connexions.
Responsabilité (art. 5, par. 2)Journal d'audit chaîné ; sa vérification à la demande par un administrateur est disponible.
Transferts (chapitre V)Mesure d'audience auto-hébergée, aucun script ni cookie tiers. Les domaines de cloud hors UE sont refusés par une couche du serveur.

Données de santé

Les données de santé relèvent de l'article 9. Le produit les traite en qualité de sous-traitant pour le compte de professionnels, avec une autorisation dédiée du module santé. La condition de l'article 9, par. 2, applicable est à confirmer par le conseil juridique : le registre le dit explicitement.

L'analyse d'impact (AIPD) existe dans le dépôt, aux formats auto-évaluation et complet.

Hébergement et sous-traitants

  • L'inférence de l'IA est locale : modèles auto-hébergés et recherche documentaire sur le même plan.
  • Les sous-traitants de l'attestation de résidence sont européens ou suisses (décision d'adéquation de la Commission pour la Suisse, à vérifier sur le texte officiel).
  • L'attestation de résidence des données est un projet, en attente de validation par le conseil.
  • Les prestataires de paiement et de courriel transactionnel sont nommés dans Comparatifs, critère par critère ; le prestataire de paiement l'est aussi dans Tarification, section Paiement et facturation.
  • Un prestataire de paiement américain existe comme voie de secours seulement. Son activation pour des personnes concernées européennes exige une évaluation de transfert et des clauses contractuelles types. Les prestataires européens sont le choix par défaut.

Conservation

La conservation est définie par type de donnée et détaillée dans la politique de confidentialité. Elle est appliquée par des balayages qui échouent en sécurité :

  • les sauvegardes : 30 jours par défaut, purge limitée aux travaux terminés ;
  • la voix : balayage de rétention dédié ;
  • l'observabilité : durée à confirmer. L'accord de sous-traitance (DPA) annonce 90 jours (docs/legal/dpa.md, section des journaux) ; le compose de développement fixe 12 mois pour VictoriaMetrics ;
  • le dossier clinique garde sa rétention légale, par exception.

Exercer ses droits

  • Contact du délégué à la protection des données : dpo@chatbotaurus.com.
  • Délai de réponse : 30 jours calendaires (art. 12, par. 3).
  • Réclamation possible auprès de l'autorité de contrôle de votre pays : la CNIL en France ; la CNPD au Luxembourg (à vérifier sur le texte officiel).
  • Au 27 mai 2026, la fonction de délégué est portée par l'opérateur. Son externalisation vers un cabinet certifié est prévue.

Ce qui reste ouvert

  • Registre des traitements : à formaliser et à signer.
  • Base de l'article 9, par. 2 : à confirmer.
  • Attestation de résidence des données : en attente.
  • Le chiffrement applicatif des données de santé au repos est actif en production (PHI_AT_REST_KEY est obligatoire au démarrage). Son étendue sur toutes les données de santé reste à établir. Le chiffrement du disque est documenté.
  • Le droit d'effacement est câblé sur les surfaces de santé et d'apprentissage. Son étendue sur le reste est à vérifier surface par surface.

Voir aussi

  • Réponse aux incidents — notification des violations (articles 33 et 34) et calendrier de réponse
  • Modèle de menaces — où vit le risque sur les données de santé et les secrets
  • Architecture de confiance zéro — classification des données et chiffrement au repos, contrôle par contrôle
  • Conformité NIS2 — mesures de sécurité et de continuité exigées par les clients régulés
  • SLA, support et niveaux de service — engagements de disponibilité, de support et de reprise après incident
  • Routes des ressources — routes publiques de conformité (statut gradué, manifeste signé) et journal d'audit chaîné
  • API-as-a-Service EU souverain — le registre des connecteurs et le bloc de conformité (résidence des données) de chaque entrée
  • Dans le dépôt : docs/legal/ (registre, AIPD, accord de sous-traitance, politique de confidentialité)

Conformité NIS2

La directive (UE) 2022/2555 (NIS2) fixe des mesures de gestion des risques de cybersécurité, et des délais de notification des incidents, pour les entités essentielles et importantes. Les articles cités ci-dessous (21 et 23) sont ceux de ce texte officiel ; vérifiez-les sur lui avant de les opposer à un tiers.

Notre position, exactement

  • Statut : partiellement prêt. Une partie des contrôles est câblée ; le reste est identifié et non livré.
  • Par sa taille, Chatbotaurus n'est pas parmi les entités essentielles ou importantes. Il applique l'article 21 parce que ses clients régulés doivent sécuriser leur chaîne d'approvisionnement (article 21, par. 2, point d). Leur exigence devient la sienne.
  • Aucune certification ni audit de conformité NIS2 n'est délivré à ce jour. La page publique de sécurité place l'auto-évaluation et l'audit à l'horizon 2026-2027.

Mesures en place

Les mesures sont groupées par famille ; chaque ligne dit ce qui est câblé et ce qui manque.

Gestion des risques

  • Un modèle de menaces STRIDE est tenu dans le dépôt, avec ses lacunes : voir le chapitre Modèle de menaces.
  • Des gardes exécutables mesurent le câblage des contrôles de sécurité avant chaque livraison.

Chaîne d'approvisionnement (article 21, par. 2, point d)

  • Analyse Trivy (gravité haute et critique) de l'image du backend et signature de l'image par un workflow dormant : aucun exécuteur n'y est rattaché, il ne tourne pas aujourd'hui.
  • Inventaire logiciel (SBOM) au format CycloneDX pour les artefacts publiés, dans le dépôt.
  • Avis de vulnérabilités au format CSAF, avec justifications VEX.
  • Images épinglées, et image de l'agent de sauvegarde servie par un miroir européen. Les registres hors UE sont interdits par une garde.
  • Une couche du serveur refuse les domaines de cloud hors UE.

Gestion des incidents (article 23, à vérifier sur le texte officiel)

  • Procédure interne documentée : sévérité, confinement, éradication, notification. Voir le chapitre Réponse aux incidents.
  • Calendrier suivi : alerte précoce sous 24 heures, notification sous 72 heures, rapport final sous un mois.
  • Limite : la notification aux autorités dans les délais est un processus encore à formaliser. Il n'y a ni supervision 24/7 ni SIEM temps réel.

Contrôle d'accès

  • Authentification fédérée via Authentik, ou mot de passe avec second facteur.
  • Second facteur : TOTP, WebAuthn et codes de secours. Par défaut, FORCE_2FA impose un second facteur à la connexion par mot de passe (TOTP, sinon code par courriel). L'obligation d'enrôler le TOTP par rôle est un réglage de déploiement (FORGE_MFA_REQUIRED_ROLES, FORGE_MFA_TOTP_REQUIRED). Un compte créé par le SSO s'appuie sur le second facteur d'Authentik.
  • Rôles et politiques Cedar ; journal d'audit chaîné.
  • Gouvernance des canaux de messagerie : tout canal passant par un fournisseur soumis au Cloud Act (WhatsApp, Telegram, Messenger) est inactif par défaut. Son activation par client exige une décision d'architecture documentée et un audit du flux.

Cryptographie

  • TLS en bordure : Traefik sur le plan de la plateforme, Caddy sur le plan du client, avec renouvellement automatique des certificats. Traefik impose TLS 1.3 au minimum par défaut ; une option distincte, hors défaut, autorise TLS 1.2 pour des clients anciens. Les clients HTTP du backend utilisent rustls, sans OpenSSL.
  • Mots de passe en Argon2id, identifiants en AES-256-GCM, journal d'audit en XChaCha20-Poly1305.
  • Secrets : sops + age, puis OpenBao pour le profil régulé. Voir le chapitre OpenBao et secrets.
  • Post-quantique : ML-DSA-65 (FIPS 204) sur le jeton et ML-KEM-768 (FIPS 203) sur le canal de la passerelle MCP, sur activation. Une anticipation, pas une exigence de la directive.

Continuité et sauvegarde

  • Sauvegarde par agent installé sur l'hôte qui porte les données : un agent par hôte, en tirage seul, chiffré, avec rétention de 30 jours.
  • Restauration protégée : URL signée à durée courte et approbation humaine.
  • Des procédures de restauration sont exercées par moteur de base, avec rapports datés dans le dépôt.
  • Limite : l'exercice de restauration de production n'est pas fait. Il est bloqué sur une ressource du titulaire. Aucun objectif de temps de reprise n'est promis par ce chapitre.

Le règlement d'exécution

Le règlement d'exécution (UE) 2024/2690 fixe au niveau européen les exigences techniques de l'article 21, par. 2 pour certains fournisseurs de services numériques. Le guide technique de l'ENISA qui l'accompagne décline des familles de mesures avec des exemples de preuves. Selon l'analyse interne, les gardes couvrent déjà la majorité des familles ; les familles encore nues sont la continuité et les sauvegardes exercées, la formation et la remédiation automatisée.

Ce qui reste ouvert

  • Formaliser la notification aux autorités.
  • Exercice de restauration de production.
  • Test d'intrusion indépendant.
  • Formation à la cybersécurité.

Voir aussi

Gaia-X

Gaia-X est un cadre européen de confiance et de souveraineté pour les services cloud. Ce chapitre dit ce que Chatbotaurus a fait, et ce qu'il n'a pas fait.

Statut

  • Prêt par conception. La souveraineté des dépendances est câblée, et une preuve exécutable existe.
  • Aucun label Gaia-X n'a été obtenu. Aucune auto-évaluation formelle n'a été déposée.
  • La page publique de sécurité place le label Gaia-X à l'horizon 2026-2027. C'est une cible, pas un acquis.

Une ancienne version de ce chapitre portait un badge « score 9/10 » et parlait d'une Self-Description publiée. Aucun auteur ni méthode ne soutenait ce score. Il est retiré.

Ce qui est câblé

PrincipeMécanisme
Souveraineté des dépendancesListe blanche de serveurs : un serveur MCP n'est utilisable que s'il est autorisé. Les serveurs de fournisseurs américains sont refusés.
Refus des points de terminaison non souverainsUne couche du serveur refuse les domaines de cloud hors UE.
RésidenceExécution locale de l'inférence et de la recherche documentaire ; mesure d'audience auto-hébergée ; aucun script tiers.
TransparenceLe code, les gardes et les registres de conformité sont dans le dépôt. Les statuts affichés sur le site ne peuvent pas dépasser ceux du registre interne, ce qu'une garde vérifie.
Chaîne d'approvisionnementInventaire logiciel CycloneDX, analyse Trivy, avis CSAF et VEX, images épinglées.
PortabilitéExport du compte via l'API, au format JSON. Voir la limite ci-dessous.
InteropérabilitéProtocole MCP standard pour les connecteurs.

Ce qui n'est pas fait

  • Pas de label. Pas d'auto-évaluation déposée.
  • Self-Description. Un brouillon existe dans le dépôt au format JSON-LD. Son numéro d'enregistrement est marqué en attente. Il n'est pas publié. Plusieurs de ses déclarations techniques doivent être réalignées sur le code avant toute publication, notamment la section chiffrement homomorphe : le produit n'en fournit pas aujourd'hui.
  • Réversibilité. Un script rejouable qui restitue la base d'un client sur une instance vierge n'existe pas encore. Le règlement (UE) 2023/2854 (Data Act), articles 23 à 31 (à vérifier sur le texte officiel), en fait une obligation directe : c'est le premier chantier ouvert sur ce point.
  • Fédération. Participer à une fédération Gaia-X (catalogue fédéré, identité décentralisée) n'est pas livré. Ce chapitre ne la présente pas comme un acquis.

Souveraineté et licence

La souveraineté se lit aussi sur les licences. La plateforme n'embarque que des composants à licence permissive. Les outils du client, chez lui, peuvent être sous une licence plus restrictive, parce que la frontière est une API et non une œuvre dérivée.

Voir aussi

  • Conformité RGPD — obligations de protection des données, hébergement et sous-traitants européens
  • Conformité NIS2 — chaîne d'approvisionnement, cryptographie et continuité exigées par les clients régulés
  • Conception des connecteurs MCP — contrôle de conformité UE appliqué à chaque connecteur au démarrage
  • Sauvegarde et restauration — ce que la plateforme sauvegarde et restaure aujourd'hui, et ses limites
  • SLA, support et niveaux de service — engagements de disponibilité et de reprise, et ce qu'ils ne couvrent pas
  • Dans le dépôt : le registre des référentiels (docs/compliance/referentiels-360.yaml)

Sécurité

Ce chapitre décrit les protections que le code applique, avec le fichier qui les porte. Il sépare ce qui est en place de ce qui reste à faire. Il ne revendique aucune certification. À la fin, vous saurez quelles clés poser avant de passer en production et quelles protections reposent sur votre exploitation.

Principes

  • Démarrage fermé. Sans déclaration explicite de développement (FORGE_DEV, ou NODE_ENV, ENVIRONMENT, RUST_ENV, APP_ENV valant development, dev, local ou test), forge-api applique la posture production. Le silence n'est jamais une autorisation.
  • Cloisonnement par organisation. Les listes sont filtrées par organisation. Hors développement déclaré, forge-api refuse de démarrer sans FORGE_TENANT_STRICT à 1.
  • Données hébergées dans l'UE. Le registre des connecteurs refuse un connecteur dont la résidence des données n'est pas dans l'UE ou auto-hébergée (connectors/README.md).

Secrets

  • Dans le dépôt : aucun. Les fichiers .env sont ignorés par git. Le modèle .env.example ne porte que des gabarits.
  • En production, un script génère les fichiers d'environnement sur la machine cible, avec des permissions restreintes, et n'imprime jamais les valeurs (script d'initialisation des secrets de l'hôte).
  • OpenBao est facultatif. Si BAO_ADDR est posée, il surcharge les secrets d'exécution. Le service du fichier Compose tourne en mode développement ; la configuration de production est portée par l'unité de production du coffre.
  • Journaux. Un filtre masque les clés d'API, jetons, clés privées et adresses e-mail avant l'écriture (filtre de rédaction du code).

Au démarrage de production, forge-api vérifie :

ContrôleRègle
JWT_SECRET32 caractères au moins, ni valeur connue ni gabarit
FORGE_STRICT_SECRETS à 1AT_REST_ENCRYPTION_KEY et AUDIT_SIGNING_KEY deviennent obligatoires ; sinon leur absence est un avertissement
PHI_AT_REST_KEYObligatoire en production, 64 caractères hexadécimaux : sinon forge-api refuse de démarrer
CloisonnementFORGE_TENANT_STRICT à 1, obligatoire

Le dépôt ne planifie pas de rotation automatique de l'ensemble des secrets : elle reste à organiser côté exploitation. Deux rotations manuelles existent : celle de la clé des données de santé (l'ancienne clé se pose dans PHI_AT_REST_KEY_PREVIOUS, lue en repli) et celle de la clé de l'agent de sauvegarde (route d'administration de la sauvegarde).

Authentification

MécanismeDétailComposant
Mots de passeArgon2id, paramètres de coût fixés dans le codehachage des mots de passe
Jeton d'accèsJWT signé HS256, algorithme verrouillé à la vérification ; durée 7 jours par défautextracteur d'authentification
Cookie de sessionjwt, attribut HttpOnly ; en production SameSite=Strict, Secure et domaine fixé par COOKIE_DOMAINcouche cookie
Second facteurApplication TOTP, ou code envoyé par e-mail à durée de vie courte ; imposé par défaut (FORCE_2FA)connexion par mot de passe
Codes de secoursCodes à usage unique pour qui perd son authentificateurcodes de secours
SSOAuthentik, OIDC avec PKCE (code_challenge_method=S256)client OIDC
Autorisation fineMoteur Cedar, chargé depuis policies/. Absent ou invalide en posture de production : forge-api refuse de démarrer. En développement déclaré : Cedar désactivé, les gardes Cedar laissent passerdémarrage du serveur
Post-quantiqueOption FORGE_PQC_ENABLED : le jeton porte une signature ML-DSA-65 en plus de HS256, pour les clients qui la vérifientcouche cookie, signature des jetons

Le second facteur n'est pas réservé aux administrateurs : il s'applique à tous les comptes tant que FORCE_2FA n'est pas désactivée.

Protection des requêtes

ProtectionDétailComposant
CSRFDouble soumission : cookie csrf-token lisible par le frontend, copié dans l'en-tête x-csrf-token sur les écritures. Le jeton est aussi conservé 2 heures dans Valkey. Les routes d'avant connexion, /mcp et /webhooks en sont exemptéescouche CSRF
Débit généralPar IP : 100 requêtes par seconde sur /api/v1, 30 par minute pour les événements de route, 20 par minute pour le chat public, 1 000 par minute ailleurs. Réponse 429 avec Retry-Afterlimiteur de débit
Connexion, par compteAu-delà d'un nombre d'échecs dans une fenêtre glissante, le compte est bloqué pour une durée fixée dans le code. L'identité est un hachage salé : l'e-mail en clair n'atteint pas Valkey. Sans ACCOUNT_HASH_SALT, ce limiteur est désactivélimiteur par compte
Connexion, par IPSeau large, secondaire. Une liste d'exemption existe pour lui seullimiteur par adresse
Taille des corps2 Mio par défaut, 25 Mio pour l'envoi de fichiers ; 413 au-delàlimite de taille
En-têtes HTTPX-Content-Type-Options, X-Frame-Options: DENY, Referrer-Policy, Permissions-Policy, Cross-Origin-Opener-Policy, Content-Security-Policy, et Strict-Transport-Security quand la requête est en HTTPSen-têtes de sécurité
Métriques/metrics refuse l'accès anonymemétriques

Chaque ligne nomme le composant du serveur qui porte la protection.

Chiffrement

En transit. Le proxy inverse du plan backend (Traefik) impose TLS 1.3 au minimum dans son option par défaut ; une option distincte, hors défaut, autorise TLS 1.2 pour les clients anciens. En posture production, la connexion de forge-api à PostgreSQL applique les paramètres TLS de la configuration.

Au repos. Ce que le code chiffre :

  • les secrets TOTP, les identifiants de connecteurs et les secrets SSO, en AES-256-GCM, avec une clé dérivée par enregistrement depuis AT_REST_ENCRYPTION_KEY ;
  • les colonnes de données de santé, avec PHI_AT_REST_KEY (crates/forge-db) ;
  • la chaîne d'audit, chaînée par empreintes et signée avec AUDIT_SIGNING_KEY (crates/forge-audit).

Le dépôt n'établit pas de chiffrement transparent de PostgreSQL, de Qdrant ou de Valkey. Protégez le disque de l'hôte.

Intrusion et conteneurs

  • Les services tournent sous Podman, sans Docker, avec des unités Quadlet utilisables sans droits administrateur.
  • CrowdSec détecte les adresses abusives et prend des décisions de blocage. Le déploiement du plan backend l'installe.
  • Falco (comportement à l'exécution) a une unité, retirée du déploiement depuis le 2026-09-19 en attendant une version compatible avec le noyau de l'hôte.
  • Le contrôle mutuel par certificat (ZERO_TRUST_ENABLED) est décrit comme une ébauche dans le code, prête pour une intégration mTLS complète. Ne le comptez pas comme une protection.

Chaîne d'approvisionnement

  • Un workflow construit l'image backend, l'analyse avec Trivy (gravité HIGH et CRITICAL, correctifs disponibles seulement) et la signe avec Cosign par clé (workflow de CI du dépôt). Il est dormant : aucun exécuteur n'y est encore rattaché, il ne tourne pas aujourd'hui.
  • Un script analyse les images référencées par les fichiers Compose, et un autre génère un SBOM (scripts/ops/generate-sbom.sh). Ils se lancent à la main.

Bonnes pratiques d'exploitation

  • N'exposez jamais PostgreSQL, Qdrant, Valkey ni OpenBao sur Internet.
  • Posez ACCOUNT_HASH_SALT, AT_REST_ENCRYPTION_KEY, AUDIT_SIGNING_KEY, PHI_AT_REST_KEY et FORGE_STRICT_SECRETS (à 1) en production.
  • Protégez /metrics par PROMETHEUS_BEARER_TOKEN.
  • Gardez des permissions restreintes sur les fichiers d'environnement.
  • Relisez les gabarits avant de coller une valeur réelle dans un ticket, un journal ou un message : ne publiez jamais de secret.

Signaler une vulnérabilité

Le serveur publie /.well-known/security.txt (crates/forge-api/src/router.rs). Écrivez à security@chatbotaurus.com ; la divulgation coordonnée est décrite dans Réponse aux incidents.

Documents juridiques

Le dossier docs/legal/ du dépôt contient les textes de référence : politique de confidentialité, conditions d'utilisation, accord de traitement des données, analyses d'impact, registre des traitements et attestation de résidence des données.

Voir aussi

Architecture de confiance zéro

Le zero trust tient en une phrase : aucune requête n'est crue sur sa seule provenance réseau. Ce chapitre décrit les principes retenus et les composants qui les portent. Il ne décrit pas la topologie réelle de l'hébergement : elle ne se publie pas. À la fin, vous saurez lire le statut de chaque contrôle (câblé, optionnel, prévu) et ce qui reste à votre charge.

Ce que ce chapitre affirme, et ce qu'il n'affirme pas

La grille de lecture est celle de la norme NIST SP 800-207, qui pose sept principes pour une architecture zero trust. C'est une grille, pas une certification : aucun organisme tiers n'a évalué Chatbotaurus contre ce référentiel.

Chaque ligne ci-dessous porte un statut :

  • Câblé : le code existe et s'exécute par défaut.
  • Optionnel : le code existe, un réglage de l'opérateur l'active.
  • Prévu : une décision ou un chantier est tracé, rien n'est livré.

Identité : qui parle

ContrôleStatutDétail
Jeton de session signé, algorithme épingléCâbléLe serveur refuse un jeton dont l'algorithme n'est pas celui attendu.
Signature post-quantique du jeton (ML-DSA-65, FIPS 204)OptionnelUne seconde signature est ajoutée au jeton classique quand FORGE_PQC_ENABLED=1. Sans ce réglage, le jeton reste classique.
Canal hybride X25519 + ML-KEM-768 (FIPS 203) vers la passerelle MCPOptionnelActivé par FORGE_PQC_CHANNEL_ENABLED côté passerelle.
Second facteur (TOTP, WebAuthn, codes de secours)CâbléPar défaut (FORCE_2FA vaut true), la connexion par mot de passe exige un second facteur : TOTP si enrôlé, sinon code par courriel. L'obligation d'enrôler le TOTP par rôle est un réglage de déploiement : FORGE_MFA_REQUIRED_ROLES ou FORGE_MFA_TOTP_REQUIRED. Un compte créé par le SSO n'a pas de second facteur applicatif : Authentik le porte en amont.
Authentification fédérée (OIDC)Câblé, avec repliVoir le chapitre SSO Authentik.

L'état réel des primitives cryptographiques se lit sur le point d'entrée GET /api/v1/crypto/status. Il répond selon l'environnement, jamais selon une affirmation figée.

Réseau : segmentation en deux plans

Le déploiement sépare deux plans, chacun dans son propre réseau de conteneurs :

  • le plan de la plateforme (backend, base, coffre de secrets, observabilité) ;
  • le plan des outils du client (passerelle et serveurs MCP).

Le principe : un compromis d'un plan ne donne pas un accès direct à l'autre. Le pont entre les deux peut être coupé pendant un incident. Les ports internes sont liés à la boucle locale de l'hôte ; sur le plan de la plateforme, seuls l'ingress et le service temps réel publient sur toutes les interfaces. Le détail des adresses, des ports et des règles n'est pas publié.

Un fichier de règles nftables existe pour le plan client. Son application effective sur chaque hôte relève de l'opérateur.

Application : ce que chaque requête traverse

La pile de couches du serveur API est documentée dans le code et verrouillée par un test. Dans l'ordre d'entrée :

  1. identifiant de requête ;
  2. en-têtes de sécurité ;
  3. détection d'énumération (blocage automatique de l'adresse) ;
  4. limiteur par compte, puis limiteur par adresse sur les chemins d'authentification ;
  5. vérification mTLS / SPIFFE, optionnelle ;
  6. refus des domaines de cloud hors UE (huit domaines) ;
  7. cloisonnement par organisation au niveau de la base (RLS PostgreSQL) ;
  8. limiteur de débit, jeton anti-CSRF, délai maximal par requête.

Pile de huit couches traversées dans l'ordre par chaque requête, dont la vérification mTLS optionnelle, jusqu'au handler où s'appliquent les rôles et les politiques Cedar.

Figure 6 : les huit couches que traverse chaque requête avant le handler.

La couche mTLS est désactivée par défaut (ZERO_TRUST_ENABLED). Quand elle est active, elle n'accepte l'identité du client que si un proxy de confiance l'a posée (ZERO_TRUST_TRUST_PROXY) : sans cette précaution, un en-tête forgé suffirait. Elle est donc à ranger en Optionnel, pas en défense par défaut.

L'autorisation combine des rôles (RBAC) et des politiques Cedar. Les politiques sont lues dans policies/. En posture de production, l'absence ou l'invalidité de ces fichiers refuse le démarrage. Seule une posture de développement explicite tolère un moteur absent, et dans ce cas les gardes Cedar laissent passer. Les gardes Cedar sont appelées par handler : toutes les routes ne passent pas par elles.

Appareil : le conteneur

Un « appareil » est ici un conteneur Podman sans privilège.

  • Le conteneur du backend s'exécute sans nouveaux privilèges, avec toutes les capacités retirées sauf celle de lier un port, une limite de processus et de mémoire, et un /tmp en mémoire sans exécution.
  • Les images sont épinglées (tag, parfois empreinte).
  • Un workflow analyse l'image du backend avec Trivy (gravité haute et critique) et la signe avec Cosign. Il est dormant : aucun exécuteur n'y est rattaché, il ne tourne pas aujourd'hui.
  • Des profils seccomp et AppArmor sont maintenus dans le dépôt. Leur application sur chaque service n'est pas établie par le dépôt : ne pas la tenir pour acquise.

Données : classer et chiffrer

Le classificateur de données distingue cinq niveaux : public, interne, personnel, sensible (article 9 du RGPD) et restreint.

DonnéeProtection
Identifiants de services externesAES-256-GCM au repos, valeur jamais renvoyée (masquée en lecture)
Mots de passeArgon2id
Secret TOTPchiffré au repos
Journal d'auditXChaCha20-Poly1305 sur le puits chiffré
Secrets de déploiementsops + age, puis OpenBao à l'exécution (chapitre OpenBao et secrets)

Le mode « compute » de la surface FHE est une enveloppe AES-256-GCM. Ce n'est pas du chiffrement homomorphe. Le chiffrement homomorphe est sur la feuille de route, pas dans le produit.

Visibilité : voir ce qui se passe

  • Journal d'audit chaîné (SHA-256), vérifiable à la demande par un administrateur (/audit/verify : 200 vérifiée, 409 rompue, 503 indéterminée).
  • Métriques de l'API au format Prometheus (/metrics, accès protégé). VictoriaMetrics et VictoriaLogs existent dans le plan de développement ; aucune unité de production ne les déploie et rien ne les alimente par défaut. L'export de la chaîne d'audit vers VictoriaLogs est optionnel (FORGE_SIEM_ENABLED=1).
  • Beszel (supervision de l'hôte) et CrowdSec (blocage des adresses malveillantes en bordure) sont déployés par le plan de la plateforme.
  • Falco (sécurité d'exécution) a une unité Quadlet, retirée du déploiement le 2026-09-19 : il n'est pas déployé. Les outils SIEM et IDS retirés (spec 98) ne font plus partie du plan.
  • Il n'y a ni SIEM temps réel ni centre de supervision 24/7. L'émetteur SIEM du code est dormant.

Automatisation

  • La rotation des secrets se fait par OpenBao, sur procédure opérateur. Il n'y a pas de rotation automatique des certificats mTLS livrée.
  • Le révoquement d'un jeton compromis passe par une liste de refus des jetons.
  • Les gardes du dépôt (gates) s'exécutent avant chaque commit : elles font échouer la livraison quand une exigence n'est plus tenue.

Lacunes assumées

  • Pas de test d'intrusion indépendant à ce jour. Le modèle de menaces est un modèle de bureau, écrit par l'équipe qui a écrit le code.
  • mTLS entre services : optionnel, désactivé par défaut.
  • Application des profils seccomp / AppArmor : non démontrée par le dépôt.
  • Pas de supervision humaine 24/7.

Voir aussi

  • Modèle de menaces — actifs, frontières de confiance et menaces que ces contrôles doivent couvrir
  • Réponse aux incidents — comment ces contrôles servent à détecter, confiner et notifier un incident
  • OpenBao et secrets — les deux paliers de gestion des secrets et leur rotation
  • SSO Authentik — authentification fédérée OIDC, repli par mot de passe et second facteur
  • Conformité NIS2 — exigences de gestion des risques que cette architecture doit satisfaire

Modèle de menaces

Le modèle de menaces de Chatbotaurus part des menaces, pas des contrôles. La première version du programme de sécurité était partie d'un inventaire de ce qui existait. Le modèle STRIDE actuel part des actifs et des flux, puis note ce qui manque. À la fin, vous saurez quelles menaces sont couvertes, lesquelles ne le sont pas, et dans quel ordre se classent les risques résiduels.

Une honnêteté d'abord

Ce modèle a été écrit par l'équipe qui a écrit le code. Il ne peut pas se valider lui-même. C'est une hypothèse structurée sur l'emplacement du risque, à confirmer ou réfuter par un test d'intrusion indépendant. Ce test n'a pas eu lieu à ce jour.

Actifs, par ordre de criticité décroissante

ActifPourquoi il compte
Données de santé et dossierscatégorie particulière (article 9 du RGPD)
Secrets (connecteurs, base, clés de signature, clés d'API de modèles)une fuite ouvre tout le reste
Données des clients et frontière entre organisationsl'isolation est le cœur du produit
Matériel d'authentification (jetons, TOTP, WebAuthn, clés d'API)prise de compte
Intégrité du journal d'auditpreuve en cas d'incident
Entrées et sorties du modèle de langageinjection, fuite
Facturation et créditsfraude
Sauvegardes et restaurationune fuite donne un dossier complet

Frontières de confiance

Les flux traversent neuf frontières : Internet, bordure TLS, pile du serveur API, cerveau de l'agent, modèle de langage, connecteurs, recherche documentaire (RAG), stockage, et enfin les agents de sauvegarde. STRIDE est appliqué à chaque passage de frontière.

STRIDE sur les passages critiques

PassageMenaceContrôleÉtat
Bordure vers APIForce brute sur les compteslimiteur par compte et par adressecâblé
Bordure vers APIUsurpation d'adresse par en-têtel'en-tête du proxy n'est lu que si l'opérateur l'autorisecâblé
Bordure vers APIClickjacking, XSSen-têtes de sécuritécâblé
Bordure vers APICSRF sur cookiejeton anti-CSRF à double soumissioncâblé
Bordure vers APIRequête lentedélai maximal par requêtecâblé
Bordure vers APIInondation distribuée, épuisement de connexionstraitement en bordurelacune (opérateur)
AuthentificationJeton forgéalgorithme épinglécâblé
AuthentificationAttaque sur mot de passeArgon2idcâblé
AutorisationEscalade de privilègesrôles et politiques Cedarcâblé
AutorisationIDOR / BOLA (accès à la ressource d'une autre organisation)gardes de handler et RLS PostgreSQLpartiel : non prouvé de façon adverse
AgentInjection directe (anglais, français, unicode, base64)filtre d'injection, heuristiquecâblé
AgentAction destructive lancée par le modèleporte d'agence excessive : suppression et paiement exigent une approbation humainecâblé
AgentInjection indirecte (texte malveillant dans un document ou une sortie d'outil)neutralisation du contenu non fiable avant retour dans l'invitepartiel (heuristique)
AgentParaphrase, multi-tours, homoglyphesle filtre est une heuristique, pas un classificateurlacune
ConnecteursSSRF, y compris rebond DNSvérification de l'adresse résolue, adresse épingléecâblé
ConnecteursFuite de secret entre organisationssecrets résolus à la requête, par organisationcâblé
Retour du modèleFuite de l'invite système ou de données personnellesanalyse de sortiecâblé sur /prediction, lacune sur le flux du chat
StockageInjection SQLrequêtes paramétréescâblé
StockageAltération du journalchaîne de hachage, vérification à la demandecâblé
StockageChiffrement des données de santé au reposchiffrement applicatif des colonnes de santé (actif en production : PHI_AT_REST_KEY est obligatoire au démarrage), chiffrement de disque documentépartiel : l'étendue sur toutes les données de santé n'est pas établie
SauvegardesRestauration forgéeURL signée à durée courte et approbation humainecâblé
SauvegardesImage d'agent hors UEimage servie par un miroir UE, registres hors UE interdits par une gardecâblé

Plusieurs connecteurs parlent en http:// à l'intérieur d'un même plan : c'est une décision documentée et acceptée. Elle est à rouvrir si un connecteur traverse un jour une frontière d'hôte.

Risques résiduels, par ordre

  1. Journal de lecture des données de santé incomplet : les lectures de l'agent sur l'ERP ne sont pas toutes tracées.
  2. Sortie du chat non analysée pour les données personnelles.
  3. IDOR non prouvé de façon adverse.
  4. Contrôles RGPD de santé à étendre : l'effacement et la rétention sont actifs par défaut pour les journaux vocaux et les comptes en attente de suppression, mais leur étendue sur le reste des données de santé reste à vérifier surface par surface.
  5. Déni de service au niveau applicatif, hors bordure.
  6. Aucune validation indépendante : test d'intrusion, certification d'hébergement de données de santé, supervision des incidents.

Menaces propres à l'IA

MenaceMitigation présenteLimite
Injection d'invitefiltre d'entrée, neutralisation du contenu récupéréheuristique
Exfiltration par le modèleanalyse de sortiepartielle (voir ci-dessus)
Empoisonnement de modèlesomme SHA-256 des modèles comparée à une base épingléela signature du manifeste est réservée, jamais vérifiée
Usage non autorisé du modèleauthentification, limitation de débit
Hallucinationmise en règle sur sources (grounding)une réponse sans source est signalée, pas supprimée

Acteurs

Opportunistes, concurrents, acteurs étatiques, personnel interne, militants : le modèle les considère tous, avec des capacités croissantes. Aucune de ces catégories n'est exclue de l'analyse.

Exercices

Des scénarios d'exercice sont prévus (fuite de données, menace interne, rançongiciel, chaîne d'approvisionnement). Le dépôt n'établit pas qu'ils ont été joués. La page publique du plan d'incident annonce un exercice sur table trimestriel : c'est un engagement, pas un historique.

Revue du modèle

Le modèle est repris après chaque incident (étape de retour d'expérience du plan d'incident). Une revue adverse du modèle lui-même a été faite en interne et a relevé des frontières omises, notamment les webhooks entrants.

Voir aussi

Réponse aux incidents

Ce chapitre résume la procédure interne de réponse aux incidents de sécurité. Elle orchestre des mécanismes qui existent dans le code. Elle ne décrit pas une équipe de sécurité dédiée : il n'y en a pas. À la fin, vous saurez classer un incident, dans quel ordre agir et qui prévenir dans quels délais.

Portée et limites, dites d'abord

  • Le projet est mené par une seule personne, appuyée par un délégué à la protection des données et un conseil juridique externes.
  • Il n'y a pas de centre de supervision 24/7.
  • Il n'y a pas de SIEM temps réel : l'émetteur SIEM du code est dormant.
  • Falco (sécurité d'exécution) a une unité Quadlet, retirée du déploiement le 2026-09-19 : il n'est pas déployé. Les outils SIEM et IDS retirés (spec 98) ne font plus partie du plan.
  • La détection repose donc sur la revue du journal d'audit, sur CrowdSec en bordure, sur les métriques de l'API (/metrics), sur l'export optionnel de la chaîne d'audit vers VictoriaLogs, et sur la disponibilité humaine. Aucun agent du dépôt n'envoie les journaux des conteneurs vers un stockage central.

Le délai de détection est borné par cette disponibilité. C'est une limite assumée, pas une promesse.

Niveaux de sévérité

NiveauDéfinitionExemple
SEV-1 critiquedonnées de santé exposées ou exfiltrées, ou compromission d'un secret racinefuite d'un dossier entre organisations, vol de clé
SEV-2 élevéaccès non autorisé sans exfiltration prouvée, ou indisponibilité d'un service de données de santéaccès à un contenu d'une autre organisation, déni de service
SEV-3 modérétentative bloquée par un contrôle, anomalie à instruireinjection refusée, limiteur déclenché
SEV-4 faiblebruit ou faux positifbalayage opportuniste bloqué

Une violation touchant des données de santé (article 9 du RGPD) est classée SEV-1 jusqu'à preuve du contraire.

Les délais de réponse que l'entreprise s'engage à tenir envers ses clients sont publiés sur la page publique du plan de réponse aux incidents. Ce chapitre ne les reprend pas : une seule source évite qu'ils divergent.

Phases

La procédure suit cinq phases, de la préparation au retour d'expérience.

Cinq étapes superposées et numérotées : préparation, détection et analyse, confinement, éradication et reprise, notification et retour d'expérience.

Figure 7 : les cinq phases de la réponse à incident.

1. Préparation

Ce qui est en place et à maintenir :

  • journal d'audit chaîné par empreintes : toute altération est détectable, et l'intégrité se vérifie à la demande ;
  • journal des lectures de dossiers patients ;
  • gel des opérations irréversibles : suppression et paiement exigent une approbation humaine ;
  • contrôle des rôles dans le chat ;
  • gardes d'injection d'invite et de sortie ;
  • secrets : sops + age au socle, OpenBao à l'exécution quand BAO_ADDR est défini, avec une procédure de rotation ;
  • deux plans réseau séparés et isolables ;
  • modèle de menaces tenu à jour.

Garder aussi sous la main : les contacts du délégué à la protection des données et de l'autorité nationale, et un canal de communication hors de l'infrastructure potentiellement compromise.

2. Détection et analyse

Sources : le journal d'audit (échecs de validation de jeton, jetons révoqués rejetés, refus de rôles, opérations destructives bloquées), la réputation d'adresses, les compteurs du limiteur d'authentification dans Valkey, les alertes de CrowdSec, les signalements de réponses non sourcées.

Triage, dans l'ordre :

  1. confirmer que ce n'est pas un faux positif ;
  2. classer la sévérité ;
  3. horodater le début : cette heure déclenche les délais légaux ;
  4. préserver les preuves ;
  5. délimiter le périmètre : quelle organisation, quelles données sensibles, quel secret.

Pendant un incident, ne pas purger le journal d'audit. Suspendre les balayages de rétention tant que l'enquête est ouverte : RETENTION_SWEEP_ENABLED=0 (journaux vocaux) et BACKUP_RETENTION_SWEEP_ENABLED=0 (travaux de sauvegarde terminés). ACCOUNT_PURGE_ENABLED=0 suspend l'effacement définitif des comptes en attente ; il suspend une obligation d'effacement, donc la décision se prend avec le délégué à la protection des données.

3. Confinement

L'objectif est d'arrêter la propagation sans détruire les preuves.

  • Jeton compromis : l'inscrire sur la liste de refus, forcer une nouvelle authentification, désactiver le compte si besoin.
  • Secret compromis : le révoquer et le renouveler dans OpenBao. Pour la clé de chiffrement des données de santé au repos, une procédure de rotation sans interruption existe.
  • Service compromis ou déni de service : isoler le plan concerné en coupant le pont entre les deux plans ; s'appuyer sur les limiteurs et les délais déjà en place.
  • Abus de l'agent : les opérations irréversibles sont déjà bloquées. En incident, passer la passerelle concernée en lecture seule ou suspendre l'organisation.
  • Adresse hostile : la bloquer en bordure.

À ne pas faire : effacer les journaux, « nettoyer » la base, redéployer par-dessus les preuves.

4. Éradication et reprise

  • Retirer l'accès de l'attaquant : clés renouvelées, sessions fermées, comptes compromis désactivés.
  • Corriger la cause racine, avec un test de non-régression.
  • Vérifier l'intégrité de l'image des conteneurs et des modèles (sommes de contrôle épinglées).
  • Restaurer depuis des sauvegardes saines. Vérifier que la chaîne d'audit n'est pas rompue.
  • Si des données personnelles sont touchées, déclencher l'effacement ou la rectification requis.
  • Surveillance renforcée temporaire, puis réactivation des balayages de rétention suspendus.

La restauration depuis les sauvegardes a des procédures exercées par moteur de base. Un exercice de restauration de production n'a pas encore été fait : il est bloqué sur une ressource (voir le chapitre NIS2).

5. Notification et retour d'expérience

DestinataireDélaiBase
Autorité de protection des données72 heures après la prise de connaissanceRGPD, article 33 (à vérifier sur le texte officiel)
Personnes concernéessans retard injustifié, si risque élevéRGPD, article 34 (à vérifier sur le texte officiel)
Autorité nationale de cybersécuritéalerte précoce 24 heures, notification 72 heures, rapport final un moisNIS2, article 23 (à vérifier sur le texte officiel)

Les textes officiels sont liés dans Conformité RGPD et Conformité NIS2. Le calendrier NIS2 s'applique aux entités essentielles et importantes. Selon son propre dossier de conformité, Chatbotaurus n'est pas, par sa taille, dans ce champ. Il suit ce calendrier parce que ses clients régulés l'exigent de leur chaîne d'approvisionnement.

La décision de notifier revient au délégué à la protection des données et au conseil. La procédure fournit les faits, pas la qualification juridique. Le référentiel interne classe d'ailleurs la notification aux autorités dans les délais comme un processus encore à formaliser.

Après chaque incident : compte rendu écrit (cause racine, chronologie, ce qui a marché et manqué), mise à jour du modèle de menaces, test adverse ajouté pour verrouiller la régression.

Signaler une vulnérabilité

Une politique de divulgation coordonnée est publiée :

  • adresse de signalement : security@chatbotaurus.com ;
  • fichier /.well-known/security.txt (RFC 9116), valable jusqu'au 17 août 2027 ;
  • avis de sécurité au format CSAF, et inventaire logiciel (SBOM, CycloneDX).

Exercices

Des scénarios sont prévus : fuite de données, menace interne, rançongiciel, chaîne d'approvisionnement. La page publique annonce des exercices réguliers. Le dépôt ne contient pas de compte rendu d'exercice joué : c'est un engagement, pas un historique.

Voir aussi

SSO Authentik

Authentik (licence permissive, auto-hébergé) est le fournisseur d'identité de l'opérateur. L'application s'y connecte en OpenID Connect avec le flux à code d'autorisation et PKCE. Un mot de passe avec second facteur reste le repli quand le SSO n'est pas configuré.

Ce qui est en place

ÉlémentDétail
FournisseurAuthentik, service du plan de la plateforme
ProtocoleOIDC, flux à code d'autorisation, PKCE, state et nonce
État de session de connexionstocké dans Valkey, 10 minutes
Jeton de session applicatifémis par l'application après la connexion, en cookie
Replisi la configuration SSO est absente, la route répond 503 SSO_UNAVAILABLE et l'interface retombe sur mot de passe plus second facteur
IdP national luxembourgeoisun second fournisseur est prévu sur le même callback, comme point d'entrée pour l'espace européen de données de santé. C'est un échafaudage, qui exige une configuration et un client enregistré

Parcours de connexion

  1. GET /api/v1/auth/oidc/login : l'application génère state, vérifieur PKCE et nonce, les place dans Valkey, puis redirige vers Authentik.
  2. L'utilisateur s'authentifie chez Authentik.
  3. GET /api/v1/auth/oidc/callback : l'application relit l'état, échange le code, et refuse la connexion dans les cas suivants :
    • état expiré ou inconnu ;
    • nonce du jeton d'identité absent ou différent (protection contre le rejeu) ;
    • adresse courriel non vérifiée par le fournisseur (email_verified), sauf option explicite de l'opérateur (OIDC_ALLOW_UNVERIFIED_EMAIL=1) ;
    • adresse déjà utilisée par un compte local créé avec un mot de passe. Un compte fédéré ne s'attache jamais en silence à un compte local : c'est la parade contre la prise de compte par SSO.
  4. Sinon, l'application trouve ou crée l'utilisateur local, émet son jeton et redirige vers le tableau de bord.

Chaque échec est écrit au journal d'audit, avec un code d'erreur.

Diagramme de séquence entre le navigateur, Authentik, l'application et Valkey : demande de connexion, redirection, authentification, retour avec le code, quatre cas de refus, puis jeton de session et tableau de bord.

Figure 8 : le parcours de connexion SSO par OpenID Connect, avec ses quatre cas de refus.

Configuration de l'application

Le SSO est actif quand ces variables d'environnement sont définies :

  • AUTHENTIK_SERVER_URL
  • AUTHENTIK_CLIENT_ID
  • AUTHENTIK_CLIENT_SECRET
  • AUTHENTIK_REDIRECT_URI (le défaut est une adresse de développement : posez-la en production)

Avant de poser ces variables, créez dans Authentik un fournisseur OAuth2/OIDC et l'application qui l'utilise : l'identifiant et le secret du client alimentent AUTHENTIK_CLIENT_ID et AUTHENTIK_CLIENT_SECRET, AUTHENTIK_SERVER_URL est l'adresse du serveur Authentik, et l'URL de retour enregistrée chez Authentik doit être exactement la valeur de AUTHENTIK_REDIRECT_URI, qui se termine par la route de retour /api/v1/auth/oidc/callback. Le serveur demande les portées openid, profile et email : le fournisseur doit les accorder. Les écrans d'Authentik dépendent de sa version et ne sont pas décrits ici.

Résultat attendu : GET /api/v1/auth/oidc/login répond par une redirection vers Authentik. Une réponse 503 SSO_UNAVAILABLE signifie que AUTHENTIK_SERVER_URL, AUTHENTIK_CLIENT_ID ou AUTHENTIK_CLIENT_SECRET manque ; l'interface retombe alors sur le mot de passe et le second facteur.

Les valeurs de secrets ne se placent pas dans le dépôt. Elles suivent la chaîne décrite dans le chapitre OpenBao et secrets.

Second facteur

Par défaut, FORCE_2FA vaut true : la connexion par mot de passe exige un second facteur, code TOTP si le compte l'a enrôlé, sinon code envoyé par courriel. L'obligation d'enrôler le TOTP est, elle, un réglage de déploiement :

  • FORGE_MFA_REQUIRED_ROLES exige l'enrôlement TOTP pour les rôles listés (par exemple admin,owner) ;
  • FORGE_MFA_TOTP_REQUIRED l'exige pour tous les comptes.

Un compte soumis à l'obligation et sans TOTP actif se voit refuser la connexion jusqu'à son enrôlement. Les mécanismes disponibles sont TOTP, WebAuthn et des codes de secours. Si l'opérateur n'a posé aucun des deux réglages, rien n'oblige un rôle particulier au TOTP, et le code par courriel reste exigé tant que FORCE_2FA n'est pas désactivée. Un compte créé par le parcours SSO ci-dessus n'a pas de second facteur applicatif (commentaire du code : « Authentik handles MFA upstream ») : l'authentification multifacteur de ces comptes relève de la configuration d'Authentik.

Autres services du plan client

Plusieurs outils du plan client (par exemple Grafana, Forgejo, Mattermost) peuvent être reliés à Authentik. Chaque outil se configure selon ses propres capacités :

  • OIDC natif quand l'outil le supporte : application et fournisseur OAuth2/OIDC dans Authentik, URI de redirection côté outil.
  • Proxy d'authentification quand il ne le supporte pas : Authentik fournit un point d'entrée de type outpost. Une unité Quadlet authentik-proxy existe dans le dépôt.

Le dépôt ne recense pas, service par service, lequel est relié à Authentik en production. Cette liste relève de l'opérateur du plan.

Points d'attention

  • Le SSO de l'application ne dépend pas du proxy frontal : la redirection OIDC est gérée par le serveur API lui-même. La configuration du proxy d'entrée (Caddy et Traefik ont chacun des fichiers dans le dépôt) ne change pas ce parcours.
  • Si l'IdP n'émet pas email_verified, ne pas contourner la vérification sans en mesurer le risque.
  • Le jeton de session est classique par défaut. Une signature post-quantique ML-DSA-65 s'y ajoute quand FORGE_PQC_ENABLED=1.

Voir aussi

OpenBao et secrets

Aucun secret n'est enregistré en clair dans le dépôt, ne se loge dans une réponse d'API ni dans un journal. La gestion des secrets suit deux paliers. Le premier est le socle, le second est le coffre du profil régulé. À la fin, vous saurez où vit chaque secret, quand OpenBao s'applique et ce qui reste à votre charge (initialisation du coffre, rotation).

Pourquoi OpenBao

Le coffre de secrets précédent était sous licence BSL, incompatible avec le plan de la plateforme, qui exige des licences permissives. Il a été retiré (décision DEC-34-008). Son remplaçant est OpenBao (MPL-2.0, Linux Foundation). Les variables de configuration portent le préfixe natif BAO_*. OpenBao est le coffre actuel du palier régulé.

Deux paliers

PalierMécanismeQuand
1. Soclesops + age : secrets chiffrés, versionnés, déchiffrés vers l'environnement au déploiementtoujours ; fonctionne sans serveur, y compris hors ligne
2. Coffre à l'exécutionOpenBao : lecture des secrets au démarrage et à la demandedès que BAO_ADDR est défini

Quand OpenBao est configuré, chaque secret présent dans le coffre remplace la valeur issue de l'environnement. Un secret absent garde sa valeur d'environnement. Une erreur réelle du coffre (injoignable, authentification refusée) arrête le démarrage : un déploiement régulé ne doit pas démarrer en silence sur des valeurs périmées.

Si BAO_AUDIT_REQUIRED est vrai et qu'aucun journal d'audit n'est actif côté coffre, le démarrage est refusé. L'audit de lecture des secrets est une exigence NIS2 et DORA pour le profil régulé.

Le coffre

OpenBao est défini aux deux niveaux du dépôt : service du plan de la plateforme et unité Quadlet de production (stockage Raft persistant, TLS, journal d'audit déclaratif, conteneur sans privilège, publication sur l'interface locale seulement).

Le coffre ne s'amorce pas lui-même. Son initialisation, la répartition des clés de descellement et l'ensemencement suivent un guide d'exploitation exécuté par le titulaire. Cette cérémonie est une procédure humaine.

Secrets de base gérés par le recouvrement : clé de signature des jetons, mot de passe de la base, URL de connexion à la base, mot de passe SMTP, clé d'API de la base vectorielle, mot de passe de Valkey.

Secrets des clients et des connecteurs

  • Les identifiants de services externes saisis par un client sont chiffrés au repos en AES-256-GCM. La valeur n'est jamais renvoyée : l'API ne retourne qu'une valeur masquée.
  • Les secrets d'un connecteur sont résolus à la requête, par organisation, et n'existent en mémoire que le temps de l'appel. Il n'y a pas de cache de secrets à auditer.
  • Pour le domaine de santé, la résolution passe par OpenBao.

Rotation

  • Les secrets du coffre se renouvellent selon le guide d'exploitation. Pour la clé de chiffrement des données de santé au repos, une procédure sans interruption existe : l'ancienne clé reste disponible en lecture le temps du changement.
  • Après une rotation, le serveur relit ses secrets au redémarrage.
  • Un identifiant client se remplace par l'API des identifiants, par l'utilisateur concerné.

Bonnes pratiques

  • Aucun secret dans le code source, les images, les journaux ni les réponses d'API.
  • Des journaux caviardés pour les valeurs sensibles.
  • Un secret par usage et par organisation.
  • Activer l'audit de lecture du coffre en profil régulé.
  • Ne jamais coller une valeur de secret dans un ticket, un message ou un document.

Lacunes assumées

  • Le recouvrement par OpenBao concerne les six secrets de base listés plus haut. Il n'est pas un coffre pour tout.
  • La clé maître des agents de sauvegarde est protégée par une enveloppe AES-256-GCM adossée à la racine des jetons. Sa migration vers sops + age ou OpenBao est tracée, pas finie.
  • Le chiffrement applicatif des données de santé au repos est actif en production : PHI_AT_REST_KEY doit être fournie, sinon le démarrage est refusé. Il couvre les colonnes qui passent par phi_crypto ; l'étendue sur toutes les données de santé n'est pas établie par le dépôt. Le chiffrement du disque reste documenté comme palier de fond.

Voir aussi

Contribuer

Ce guide s'adresse à l'équipe interne et aux partenaires qui développent sur la base de code avec l'accord du titulaire.

À la fin de ce chapitre, vous aurez construit le workspace, lancé le backend et le frontend en local, et vous saurez quelles règles les hooks appliquent avant un commit.

Cadre

Chatbotaurus est un logiciel propriétaire. Le fichier LICENSE (identifiant SPDX LicenseRef-Chatbotaurus-Proprietary) n'accorde aucun droit d'usage, de copie, de modification ou de distribution sans accord écrit. Les dépendances tierces gardent leur propre licence. Une contribution suppose donc un accord écrit préalable ; la voie de soumission (patch, demande de fusion) est convenue avec le titulaire.

Le code est en Rust : aucune dépendance à Node.js ni à pnpm.

Prérequis

OutilVersionSource
Rust1.91 au minimum (rust-version du workspace), édition 2021Cargo.toml
dioxus-cli (dx)0.7.xcargo install dioxus-cli --locked
Cible wasm32-unknown-unknownpour le frontend webrustup target add wasm32-unknown-unknown
Gitrécent
Python 3exigé par les hooks pre-commit
Un shell POSIXexigé par les hooksGit Bash ou WSL sous Windows
Podmanpour l'infrastructure localepodman-compose, avec un tiret

Le pre-commit lance de nombreux contrôles (.githooks/pre-commit). Sous Windows, vérifiez que python répond dans le shell du hook avant le premier commit.

Obtenir les sources et activer les hooks

git clone <url-du-depot-communiquee-par-le-titulaire>
cd <dossier-du-depot>
git config core.hooksPath .githooks

Les hooks sont versionnés avec le code (.githooks/). Le chemin ci-dessus les active ; sans lui, aucune règle n'est appliquée localement. Ne contournez jamais un hook avec --no-verify : si un hook échoue, corrigez la cause.

Construire et lancer

cargo build --workspace

La première construction est longue ; les suivantes sont incrémentales.

Le backend a besoin au minimum de DATABASE_URL, REDIS_URL et JWT_SECRET (voir Variables d'environnement). PostgreSQL et Valkey doivent tourner d'abord : créez les réseaux et les volumes, puis lancez podman-compose -p chatbotaurus-vps1 up -d postgres valkey (voir Déploiement avec Podman). Lancez ensuite le backend depuis la racine du dépôt, pour qu'il retrouve .env, connectors/ et policies/ :

cargo run -p forge-api

Résultat attendu : forge-api écoute sur le port 3000 par défaut (variable PORT) et curl -s http://localhost:3000/api/v1/healthz répond 200. Sinon, relisez la sortie du processus et suivez Problèmes connus.

Le frontend Dioxus se sert avec rechargement à chaud :

cd crates/forge-ui
dx serve --platform web --port 8080

Résultat attendu : l'application répond sur http://localhost:8080.

Vérifier

cargo check --workspace
cargo clippy --workspace
cargo fmt --all
cargo test -p <crate>

Le dépôt fige le style de rustfmt dans rustfmt.toml. Le workflow de CI (workflow de CI du dépôt) épingle un nightly daté pour cargo check et pour cargo fmt --check. Comme les autres workflows de CI du dépôt, il est dormant : aucun exécuteur n'y est rattaché. Les contrôles qui tournent aujourd'hui sont les hooks locaux.

Branche, commit et push

Le développement se fait sur la seule branche main. Le hook pre-push refuse tout push d'une autre branche, refuse un push dont cargo check --workspace échoue, et laisse passer les étiquettes.

Un message de commit suit le modèle type(portée): résumé, par exemple fix(forge-api): corriger un délai. Les types courants sont feat, fix, docs, refactor, test, chore. Le hook ne l'impose pas : c'est la convention du dépôt. Faites un commit par sujet, avec des chemins explicites (git add <fichier>), jamais git add ..

Les règles que les hooks appliquent

RègleCe qu'elle refuseOù
L1Le mot « parity » (ou « parité ») dans un message sans pied de page Parity-Test: #<identifiant>commit-msg
L2Un fichier .rs de plus de 300 lignes significatives (les lignes vides, les accolades seules et les commentaires seuls ne comptent pas). Une exception demande une entrée justifiée dans scripts/pre-commit/loc-exemptions.txtpre-commit
L3Une valeur métier écrite en dur dans crates/forge-ui/src/pages/*.rspre-commit
L6Une branche qui touche des fichiers hors de son domaine (par exemple docs/* ne touche que la documentation)pre-commit
L8Un fichier neuf de forge-ui absent de docs/parity/PARITY_REGISTRY.yamlpre-commit

Le pre-commit applique aussi, entre autres : aucun emoji dans les fichiers texte, cloisonnement par organisation des handlers de liste (une exception s'annote // TENANT-AUDIT: <raison>), aucun fichier .env ajouté hors le modèle, aucun secret en clair (analyse avant chaque commit), et la règle d'auteur unique du message (commit-msg). La liste complète et les raisons sont dans docs/parity/HOOKS.md du dépôt.

Règles de code

  • Pas de refactorisation dans un commit de portage : un refactor est un commit séparé.
  • Pas de donnée factice inventée dans une page : les pages lisent l'API.
  • Composez avec les crates existantes avant d'en créer une.
  • Les composants forge-ui utilisent #[component] de Dioxus 0.7.
  • Une route de liste filtre par organisation, ou porte une exception annotée et justifiée.

Règles de sécurité

  • Aucun secret dans le dépôt, dans un message de commit ni dans une documentation. Utilisez des gabarits <...>. Aucune adresse IP ni nom d'hôte interne dans ce livre.
  • TLS par rustls : le workspace évite OpenSSL.
  • Chiffrement symétrique : aes-gcm. Mots de passe : Argon2id.
  • Podman, pas Docker, pour toute infrastructure locale.
  • Un connecteur doit déclarer une résidence des données dans l'UE ou auto-hébergée, sinon le registre le rejette.
  • Transport MCP : HTTP « streamable » par rmcp.

Structure du dépôt

Le workspace compte 19 crates suivis par git au 2026-10-03 (git show HEAD:Cargo.toml, bloc members) ; crates/docsite est exclu.

CrateRôle
forge-coreLogique métier : agents, RAG, workflows, garde anti-hallucination
forge-apiServeur HTTP Axum : REST, transport MCP, WebSocket
forge-uiInterface Dioxus 0.7 : web, bureau, mobile
forge-authAuthentification, OIDC, TOTP, politiques Cedar
forge-dbEntités SeaORM, migrations, requêtes
forge-mcpCœur de la passerelle MCP : connecteurs, routage, sessions
forge-gatewayServeur passerelle MCP conteneurisable (JSON-RPC en HTTP « streamable »)
forge-auditJournal d'audit à altération détectable, chaîne de Merkle
forge-voiceVoix : transcription, synthèse, WebRTC, fournisseurs de l'UE
forge-cli, forge-tui, forge-opsOutils en ligne de commande et terminal
forge-docsPipeline mdBook de ce livre
forge-wire, forge-commonContrats et primitives partagés
forge-replay, forge-test-utils, forge-pgtestRejeu de contrats et outils de test
forge-oracleBanc de comparaison différentielle V1/V2
extraction documentairecrate prévu (spec 115, T-115-50), non encore suivi dans le dépôt

Autres dossiers utiles : connectors/ (manifestes des connecteurs), containers/ (unités Quadlet), podman-compose.yml et podman-compose.vps2.yml (plans locaux), policies/ (règles Cedar), scripts/pre-commit/ et scripts/audit/ (les gates), .kiro/specs/ (les spécifications), docs/ (notes du dépôt).

Les chiffres du projet (crates, lignes, connecteurs) changent : mesurez-les avec python scripts/audit/launch_readiness.py plutôt que de les recopier.

Documentation

Les pages de ce livre vivent dans crates/forge-docs/docs/. Pour insérer une image ou une vidéo, voir Rédaction des pages et médias. Reconstruction : cargo run -p forge-docs.

Contact

Pour proposer une contribution, écrivez à admin@chatbotaurus.com avant de commencer.

Voir aussi

Rédaction des pages et médias

Ce guide s'adresse à qui écrit ou relit une page de ce livre. Il décrit comment insérer une image vectorielle, une animation SVG ou une vidéo, avec les classes CSS que le livre fournit. Lisez d'abord le guide de contribution.

Le livre est produit par mdBook. mdBook laisse passer le HTML brut du Markdown sans l'échapper : les balises <figure>, <svg>, <video> et <iframe> ne demandent aucun plugin.

Où vivent les fichiers

DossierContenu
crates/forge-docs/docs/static/img/Images des pages : SVG, PNG. Servi sous /docs/static/img/
crates/forge-docs/docs/assets/Feuilles de style et scripts du livre : media.css, charte.css, theme-icon.js, fr.js (francisation des libellés que mdBook écrit depuis ses scripts), recherche-fr.js (accents repliés et mots vides français dans la recherche)
crates/forge-docs/docs/<rubrique>/Les pages Markdown

book.toml charge media.css et charte.css (clé additional-css) et theme-icon.js, fr.js et recherche-fr.js (clé additional-js). mdBook copie dans le livre tous les fichiers non Markdown du dossier docs/.

Les chemins s'écrivent relativement à la page. Depuis une page de docs/guides/, une image de docs/static/img/ s'écrit ../static/img/<fichier>. Depuis docs/quickstart.md, elle s'écrit ./static/img/<fichier>.

Le livre n'impose pas d'image d'en-tête : aucune page n'en porte aujourd'hui (aucun fichier page-* dans static/img/).

Pour reconstruire et relire le livre :

cargo run -p forge-docs

Résultat attendu : la commande se termine sans erreur mdBook, et le livre construit se lit ensuite sous /docs/ du serveur de développement du frontend (dx serve, port 8080).

Images SVG statiques

Exportez le schéma depuis votre outil vectoriel et retirez les métadonnées inutiles (par exemple avec SVGO). Insérez-le dans un <figure> de classe media-svg : media.css borne la largeur à 720 px, centre la figure et style la légende.

<figure class="media-svg">
  <img
    src="../static/img/<nom-du-schema>.svg"
    alt="<description du contenu du schéma pour un lecteur d'écran>"
    loading="lazy"
  />
  <figcaption>Légende courte.</figcaption>
</figure>

L'attribut alt est obligatoire et décrit le contenu : « schéma » ou « image » ne décrivent rien. loading="lazy" diffère le chargement jusqu'à ce que l'image approche du cadre visible.

Animations SVG inline

Une animation SVG s'écrit dans le Markdown, entre deux lignes vides, à l'intérieur d'un <figure class="media-svg">. Deux techniques existent :

  • CSS (@keyframes) : portable, et la seule que media.css neutralise. Quand le lecteur demande moins de mouvement (prefers-reduced-motion: reduce), la feuille met en pause les animations et les transitions des SVG de la classe media-svg.
  • SMIL (<animate>, <animateTransform>) : autonome, mais media.css ne l'arrête pas. Si vous l'utilisez, ajoutez votre propre règle @media (prefers-reduced-motion: reduce) dans le SVG.

Une animation longue ou coûteuse se range dans un fichier .svg séparé de static/img/, inséré comme image statique.

Vidéos

Le livre vise à ne charger aucune ressource tierce : c'est un objectif en cours. Une vidéo hébergée chez un tiers l'enfreint. Choisissez dans cet ordre.

1. Vidéo courte hébergée avec le livre

Pour une vidéo de moins de 30 secondes, déposez un fichier WebM (VP9) dans static/img/ ou un sous-dossier, et lisez-le avec la balise <video>. Aucun tiers n'est contacté. Le prix : la taille du dépôt augmente. N'y mettez pas de vidéo longue.

<div class="media-video">
  <video controls preload="metadata" poster="../static/img/<affiche>.png">
    <source src="../static/img/<video>.webm" type="video/webm" />
    <track kind="captions" src="../static/img/<video>.fr.vtt"
           srclang="fr" label="Français" default />
    Votre navigateur ne sait pas lire les vidéos HTML5 :
    <a href="../static/img/<video>.webm">téléchargez la vidéo</a>.
  </video>
</div>

Aucune vidéo n'est aujourd'hui stockée dans le dépôt (mesure du 2026-10-03 : git ls-files crates/forge-docs/docs | grep -Ei '\.(webm|mp4)$' ne rend rien).

2. Instance PeerTube européenne

PeerTube, plateforme fédérée, expose un lecteur à l'adresse https://<instance>/videos/embed/<identifiant>. Choisissez une instance dont vous maîtrisez l'hébergement et la juridiction.

3. Plateformes hors UE

YouTube et Vimeo sont des services hors UE. Réservez-les aux cas où aucune alternative n'existe, et dites-le dans la revue. Pour YouTube, utilisez le domaine youtube-nocookie.com, qui limite le dépôt de cookies avant la lecture ; cela réduit le suivi, ce n'est pas une garantie juridique, à valider avec votre délégué à la protection des données.

<div class="media-video">
  <iframe
    src="https://www.youtube-nocookie.com/embed/<identifiant-video>"
    title="<titre descriptif de la vidéo>"
    loading="lazy"
    allowfullscreen
    referrerpolicy="strict-origin-when-cross-origin"
  ></iframe>
</div>

media.css donne au conteneur media-video un ratio 16:9 et une largeur maximale de 860 px. L'attribut title est obligatoire : il donne un nom à l'iframe pour les lecteurs d'écran. N'ajoutez jamais autoplay=1 : la feuille entoure d'un liseré orange les vidéos qui démarrent seules pour que la revue l'attrape.

Liste de contrôle avant revue

  • Chaque image a un alt non vide et descriptif.
  • Chaque <iframe> a un title.
  • Les chemins sont relatifs à la page et le livre se construit sans erreur (cargo run -p forge-docs).
  • Une animation respecte prefers-reduced-motion.
  • Une vidéo avec parole a des sous-titres WebVTT en français. Le référentiel d'accessibilité des services numériques est la norme européenne EN 301 549.
  • Aucune vidéo n'utilise autoplay.
  • Aucun secret, aucune adresse IP, aucun nom d'hôte interne n'apparaît dans une image, une légende ou un sous-titre : le livre est public.

Aucun script de lint Markdown n'est livré avec le dépôt pour le moment : la vérification est la revue humaine.

Voir aussi

  • Contribuer — cadre, hooks et règles de sécurité appliqués à toute contribution
  • Fichiers de configuration — le fichier de réglages lu par mdBook pour ce livre
  • Conformité RGPD — absence de script ou cookie tiers, mesure d'audience auto-hébergée
  • Gaia-X — résidence des contenus et refus des ressources hors UE
  • Sécurité — pourquoi aucun secret ni nom d'hôte interne ne doit paraître

Questions fréquentes

Cette page répond aux questions courantes. Chaque chiffre porte sa date de mesure : le 3 octobre 2026. Ce qui est prévu est dit « prévu ».

Questions générales

Ce que la plateforme est, ce qu'elle coûte et ce qu'elle protège.

Qu'est-ce que Chatbotaurus ?

Chatbotaurus est une plateforme de passerelle MCP hébergée (MGaaS, « MCP Gateway as a Service », voir Glossaire). Elle relie un assistant conversationnel à vos outils métier, par exemple un ERP, un CRM ou un outil d'analyse. Les modèles d'IA tournent sur l'infrastructure de la plateforme, dans l'Union européenne.

Pour un dirigeant, c'est un assistant qui agit dans vos logiciels. Pour un développeur, c'est une passerelle qui parle le protocole MCP (version 2025-03-26), avec une API REST (voir Documentation Swagger).

Au 3 octobre 2026 :

  • 195 fiches de connecteurs YAML ;
  • 175 cartes de serveurs dans l'application, dont 30 prouvées opérationnelles ; le catalogue public compte 108 entrées, dont 15 disponibles ;
  • 711 outils au registre Odoo ;
  • 16 secteurs métier couverts (voir Cas d'usage par secteur).

Est-ce gratuit ?

Un essai gratuit de 14 jours est prévu aux conditions générales de vente. Il est sans engagement et sans carte bancaire. Il donne accès à l'ensemble des fonctionnalités de l'offre Pro. À ce jour le code ne l'applique pas : une inscription reçoit le plan « free », puis le niveau « essentiel » à la fin de l'assistant d'accueil (voir Tarification).

Les offres payantes sont facturées hors taxes, par mois :

OffrePrixPublic visé
Starter9 EURTPE, indépendants
Pro29,90 EURPME
Enterprise99,90 EURETI, institutions
SouverainSur devisBanques, État

Le détail est dans la page Tarification.

Les données sont-elles protégées ?

La plateforme est conçue pour répondre au RGPD, à la directive NIS2, à l'AI Act et au cadre Gaia-X. Elle ne détient aucune certification à ce jour. Le détail et l'état de chaque démarche sont dans la section Conformité UE.

Côté technique :

  • les secrets et mots de passe sont chiffrés (AES-256-GCM au repos, Argon2id pour les mots de passe) ;
  • le transport utilise TLS 1.3 ;
  • les secrets des déploiements régulés sont gérés par OpenBao.

Pour aller plus loin, lisez Zero Trust et OpenBao et secrets.

Quelles langues sont prises en charge ?

ÉlémentLangues
Interfacefrançais et anglais (jeux complets)
Voix (reconnaissance)français, anglais, allemand, espagnol, italien, néerlandais, portugais (7 langues)
TraductionEuroLLM, qui couvre les 24 langues de l'Union européenne

D'autres langues d'interface (allemand, espagnol, italien, luxembourgeois, néerlandais) n'ont qu'un squelette de 26 clés. Elles ne sont pas complètes. Seuls le français, l'anglais, le néerlandais et l'allemand sont proposés dans l'assistant d'accueil et dans la page Compte (voir Paramètres et Limites).

Questions techniques

Connexion, workflows, protocole et données : les questions d'un intégrateur.

Comment me connecter ?

Pas encore de compte ? Créez-le sur /auth/signup (voir Prise en main guidée). Sinon, ouvrez la page de connexion, saisissez votre adresse et votre mot de passe. L'authentification en deux étapes (TOTP et courriel) est disponible (voir Paramètres). Le SSO passe par Authentik en OIDC ; l'ajout de fournisseurs SAML ou LDAP est en cours d'intégration. Voir SSO Authentik.

Comment ajouter un collègue ?

Ouvrez la page Utilisateurs (/users, section Gestion du menu, à partir du plan Business) et utilisez « Ajouter un utilisateur » : courriel, nom, rôle, statut. Les rôles sont décrits dans Paramètres.

Comment appeler l'API ?

Joignez le jeton obtenu par la connexion. Une clé API créée dans la page /api-keys n'est acceptée par aucune route aujourd'hui. Voir Authentification et Sécurité et identifiants.

Mon workflow ne fonctionne pas

Vérifiez dans cet ordre :

  1. Le workflow est-il enregistré et publié ?
  2. Les identifiants du connecteur sont-ils saisis et valides (voir Sécurité et identifiants) ?
  3. Le serveur ou le service connecté répond-il ?
  4. Que disent les journaux d'exécution (page Exécutions) ?

Si une action répond 429, vous avez atteint une limite de débit : attendez et réessayez (voir Limites). Si elle répond 402, le quota de votre offre est atteint. Si elle répond 503, la plateforme n'a pas pu mesurer votre quota ou la fonction n'est pas encore câblée. Le format des erreurs est expliqué dans Gestion des erreurs. Le reste est dans Problèmes connus.

Qu'est-ce que MCP ?

MCP signifie Model Context Protocol. C'est un protocole ouvert qui permet à un modèle d'IA d'appeler des outils externes. Chatbotaurus implémente la spécification 2025-03-26, avec le transport Streamable HTTP et JSON-RPC 2.0. L'ancien transport SSE n'est plus utilisé. Le transport est décrit dans Routes MCP.

Qu'est-ce qu'un workflow ?

Un workflow est un graphe de nœuds que vous assemblez dans l'éditeur visuel : un point de départ, des appels à des serveurs MCP, des conditions, des boucles, une fin. Dans l'API, on l'appelle aussi une « gateway ». Voir Workflows.

Où sont mes données ?

DonnéeStockage
Base relationnellePostgreSQL
Vecteurs (recherche sémantique)Qdrant
CacheValkey
Secrets des déploiements régulésOpenBao
Modèles d'IAexécutés par la plateforme (Ollama), dans l'UE

Aucun appel n'est fait vers un fournisseur extra-européen sans votre consentement explicite. Les services sont décrits dans Déploiement avec Podman. Le cadre juridique est dans Conformité RGPD.

Quels modèles d'IA sont utilisés ?

Le modèle principal est EuroLLM 1,7B. Le repli est ministral-3:3b, de Mistral AI (France). Les vecteurs viennent de paraphrase-multilingual-MiniLM-L12-v2 (384 dimensions). Ces trois modèles (Fournisseurs de modèles) sont la liste fermée de la plateforme (mesure du 3 octobre 2026).

Le choix du connecteur, lui, ne dépend pas du modèle : le routage du chat est déterministe (EntityRouter).

Comment connecter Odoo ?

  1. Ouvrez la page Identifiants (/credentials) de votre espace de travail ; elle est dans le menu à partir du plan Business.
  2. Ajoutez un identifiant Odoo : URL de l'instance et clé API.
  3. Enregistrez-le.
  4. Posez une question métier dans le chat, par exemple « Combien de contacts dans le CRM ? » (même exemple que dans la prise en main guidée).
  5. Utilisez cet identifiant dans vos workflows.

Le connecteur expose 711 outils au registre Odoo. Tutoriel : Connecter Odoo à la passerelle MCP.

Puis-je déployer un serveur du catalogue en un clic ?

Pas encore. Les routes de déploiement, de démarrage, d'arrêt et de configuration des secrets sont montées, mais elles répondent 503 FEATURE_PENDING. Elles attendent le câblage du socket Podman (spec 16, tâche P5.5, non cochée). Voir Parcourir le catalogue de services et préparer un déploiement.

Questions sur le positionnement

Pourquoi cette plateforme plutôt qu'une autre famille d'offres.

Pourquoi pas une offre SaaS d'IA hors UE ?

Une offre SaaS hébergée hors de l'Union relève d'une autre juridiction pour vos données. Chatbotaurus héberge et exécute ses modèles dans l'UE. À l'exécution, la plateforme refuse en outre les identifiants de serveur de 25 services hors UE (liste de refus) et ne route que vers les serveurs de sa liste autorisée (voir Conception des connecteurs MCP).

Ce n'est pas un chatbot généraliste : c'est une passerelle vers vos outils métier. La comparaison point par point est dans Comparatifs.

Puis-je migrer depuis un autre outil d'automatisation ?

Oui, à la main. Il n'existe pas d'import automatique. La page Migration donne les équivalences de concepts.

Questions hors sujet

Le chat de support répond aux questions sur la plateforme. Il ne tient pas de conversation libre sans contexte métier. Pour une question générale, utilisez un assistant généraliste. Le périmètre complet est dans Limites.

Voir aussi

Glossaire

Ce glossaire définit les termes employés par la plateforme et par ce livre. Les définitions sont courtes. Les chiffres portent la date de leur mesure : le 3 octobre 2026.

A

API REST

Interface qui permet à un autre logiciel de parler à la plateforme. Elle vit sous /api/v1. Un accès trop rapide répond 429 (voir Limites). Référence : Routes MCP.

Argon2id

Algorithme de hachage de mots de passe. Il rend le mot de passe stocké irréversible. Voir Sécurité.

Authentik

Fournisseur d'identité libre et auto-hébergé. La plateforme s'y connecte en OpenID Connect pour la connexion unique (SSO) ; un mot de passe avec second facteur reste le repli quand il n'est pas configuré. Voir SSO Authentik.

C

Catalogue (serveurs)

Liste des serveurs MCP proposés par la plateforme : 175 cartes dans l'application, dont 30 prouvées opérationnelles ; le catalogue public compte 108 entrées, dont 15 disponibles. Les autres sont en cours d'intégration. Le déploiement en un clic depuis le catalogue est prévu, pas livré (voir FAQ).

Cedar

Moteur de politiques d'autorisation. Une partie des règles d'accès (par exemple celles de la section Agence) est écrite comme des politiques ; le reste des gardes vit dans le code des routes. Voir Architecture de confiance zéro.

Compute-mode

Traitement de données sensibles avec chiffrement AES-256-GCM côté serveur. Ce n'est pas du chiffrement homomorphe : le chiffrement homomorphe n'est pas implémenté. Voir Comparatifs.

Connecteur

Fiche YAML (connectors/*.yaml) qui décrit comment joindre un outil : identifiant, URL de base, authentification, outils exposés. Il y en a 195. Voir Vue d'ensemble des connecteurs.

CRM

Gestion de la relation client : suivi des prospects et des clients. La page Leads de l'application en donne une vue (voir Analytique) ; le CRM complet vit dans l'outil connecté, par exemple Odoo.

D

Document store

Collection vectorielle (Qdrant) cloisonnée par organisation, utilisée pour la recherche sémantique. L'identifiant du store sert de nom de collection. Voir Routes des ressources.

E

Embedding (plongement vectoriel)

Représentation d'un texte par une liste de nombres. Le modèle est paraphrase-multilingual-MiniLM-L12-v2, qui produit 384 dimensions. Les vecteurs sont stockés dans Qdrant. Voir Connaissances.

EntityRouter

Routeur déterministe du chat. Il décide quel connecteur répond à une demande à partir de règles, pas à partir d'un modèle d'IA. Une même demande suit donc toujours le même chemin. Voir Chat.

Espace de travail (workspace)

Espace qui regroupe vos workflows, vos identifiants et vos données. Les données sont cloisonnées par organisation. Dans l'interface, la page /workspaces liste ces espaces. Voir Paramètres.

EuroLLM

Modèle de langue européen. La plateforme emploie EuroLLM 1,7B (quantifié q8) comme modèle principal, et pour la traduction entre les langues de l'UE. Il n'appelle pas d'outils : le routage reste celui d'EntityRouter. Voir Fournisseurs de modèles.

G

Gaia-X

Initiative européenne pour un espace de données fédéré. La plateforme s'y aligne par auto-évaluation. Elle ne détient pas de certification. Voir Gaia-X.

Gateway

Objet de l'API (ressource gateways) qui porte un workflow : son graphe, ses connecteurs activés, ses règles d'accès. C'est un assistant conversationnel qui peut être publié pour un usage public. Il est limité à l'espace de travail de son propriétaire. Dans l'API, on dit aussi « gateway » pour un workflow. À ne pas confondre avec la passerelle MCP, qui est le service hébergé. Voir Routes des gateways et de la prédiction.

I

Identifiants (credentials)

URL, identifiant et clé API que vous saisissez pour que la plateforme joigne un de vos outils. Ils sont chiffrés au repos. Voir Sécurité et identifiants.

J

Jeton (JWT)

Preuve de connexion que l'API attend dans l'en-tête Authorization: Bearer. Il s'obtient par la connexion. Voir Authentification.

JSON-RPC 2.0

Format de message du protocole MCP : un identifiant, une méthode, des paramètres. Voir Routes MCP.

K

Kit Numérique

Nom commercial de l'offre : « un Kit Numérique adapté à chaque étape de votre croissance ». C'est le même produit que Chatbotaurus. Voir Tarification et offres.

L

Locataire (organisation)

Organisation cliente de la plateforme. Ses données, ses identifiants et ses espaces de travail sont cloisonnés de ceux des autres. Voir Architecture Chatbotaurus.

M

MCP (Model Context Protocol)

Protocole ouvert qui permet à un modèle d'IA d'appeler des outils externes (voir Utiliser les connecteurs MCP). La plateforme implémente la version 2025-03-26.

MGaaS

« MCP Gateway as a Service » : la passerelle MCP hébergée que propose Chatbotaurus. Voir Architecture Chatbotaurus.

ministral-3:3b

Modèle de repli de la plateforme, de Mistral AI (France), voir Fournisseurs de modèles. Il remplace le modèle de repli précédent depuis le 10 août 2026.

N

NIS2

Directive européenne sur la sécurité des réseaux et des systèmes d'information. La plateforme est conçue pour y répondre, sans certification. Voir NIS2.

Nœud

Élément d'un workflow : départ, appel à un serveur MCP, condition, boucle, routage, parallèle, agrégation, fin. Le catalogue des nœuds est dans Workflows.

O

Odoo

ERP open source. Le connecteur Odoo expose 711 outils au registre. Voir Odoo.

Offre

Formule commerciale publiée sur la page Tarifs : un public visé, un prix et ce qu'elle inclut. À ne pas confondre avec le plan, qui est le niveau d'accès. Voir Tarification et offres.

OIDC

OpenID Connect : protocole standard de connexion unique, utilisé par le bouton « Authentik SSO ». Voir SSO Authentik.

OKF (wiki)

Format du wiki de connaissances : une page Markdown avec un en-tête YAML dont le champ type est obligatoire. L'identifiant d'une page est son chemin. Une page sans type est rejetée. Voir Connaissances.

Ollama

Serveur d'inférence qui exécute les modèles de langue de la plateforme. Voir Fournisseurs de modèles.

OpenBao

Coffre de secrets libre, sous licence MPL-2.0. Il sert aux déploiements régulés. Voir OpenBao et secrets.

Orchestrateur

Page de l'interface, dans la section « Écosystème MCP », où un assistant construit vos workflows par le dialogue. Voir MCP et Orchestrateur.

Organisation

Entité cliente de la plateforme et unité de cloisonnement : le filtre de locataire repose sur l'organisation. Le livre dit aussi « locataire » pour la même chose. Voir Architecture Chatbotaurus.

P

Passerelle MCP

Le service hébergé qui relie un assistant conversationnel à vos outils métier par le protocole MCP, avec une API REST. À ne pas confondre avec une « gateway », objet de l'API. Voir Architecture Chatbotaurus.

Plan

Niveau d'accès d'un compte : il décide des pages visibles dans le menu et des capacités disponibles, et chaque plan supérieur garde les capacités des précédents. L'interface dit « plan » (Plan actuel, Changer de plan). Dans les chapitres Podman, « plan » désigne aussi l'un des deux projets de déploiement. Voir Tarification et offres.

Plan (offre)

Niveau d'abonnement. La table des capacités compte six niveaux : Essentiel, Starter, Pro, Business, Enterprise, Souverain ; la grille de prix n'en publie que quatre. Voir Tarification et offres.

Podman

Moteur de conteneurs sans démon. Il fait tourner les services de la plateforme. Voir Déploiement avec Podman.

PQC (cryptographie post-quantique)

Algorithmes résistants à un ordinateur quantique. La plateforme propose ML-KEM-768 pour un canal hybride, en option. Il n'est pas actif par défaut. Voir Comparatifs.

Q

Qdrant

Base de données vectorielle. Elle sert à la recherche sémantique (RAG). Voir Connaissances.

Quadlet

Mode de déploiement de production : un fichier containers/<service>/<service>.container par service. En développement, le déploiement passe par Compose. Voir Déploiement avec Podman.

Quota

Plafond d'une ressource par offre (workflows, serveurs MCP, appels d'API, stockage, utilisateurs, minutes de voix, enregistrements vectoriels). Un quota atteint répond 402. Voir Limites.

R

RAG (Retrieval-Augmented Generation)

Technique où l'assistant cherche d'abord dans vos documents, puis répond en s'appuyant sur ce qu'il a trouvé. Cela réduit les erreurs, sans les supprimer. Voir Limites.

RGPD

Règlement général sur la protection des données. La plateforme est conçue pour y répondre. Voir RGPD.

RLS

Cloisonnement par organisation appliqué au niveau de la base PostgreSQL sur certaines tables seulement (appels, messages de gateway, sessions de l'Orchestrateur, journaux vocaux, entre autres), en plus des gardes des routes. Voir Architecture de confiance zéro.

S

SBOM

Inventaire des composants logiciels d'une image de conteneur, produit lors de l'analyse de sécurité. Voir Déploiement avec Podman.

Serveur MCP

Service qui expose des outils à l'assistant par le protocole MCP. Voir MCP et Orchestrateur.

SLA

Objectif contractuel de service sur les environnements de production sous contrat. Ce n'est pas une garantie sans condition. Voir SLA, support et niveaux de service.

SMTP

Protocole d'envoi de courriel. Le serveur SMTP que vous configurez envoie le code du second facteur. Voir Installation.

SSO

Connexion unique : se connecter avec le compte d'un fournisseur d'identité (ici Authentik) plutôt qu'avec un mot de passe propre à la plateforme. Voir Paramètres.

Streamable HTTP

Transport MCP de la plateforme : requêtes HTTP vers un point d'entrée unique, messages JSON-RPC 2.0. Il remplace l'ancien transport SSE, qui n'est plus utilisé. Voir Routes MCP.

STT et TTS

Reconnaissance vocale (STT, de la voix vers le texte) et synthèse vocale (TTS, du texte vers la voix). Voir Voix et Canaux.

T

TLS

Chiffrement du transport entre le navigateur ou le client d'API et le serveur. Voir Sécurité.

TOTP

Code à usage unique renouvelé par une application d'authentification, utilisé comme second facteur. Voir Paramètres.

Trivy

Scanner de vulnérabilités pour les images de conteneur. Voir Sécurité.

V

Valkey

Fork libre de Redis. Il sert de cache. Voir Gestion des conteneurs.

W

Webhook

Adresse que la plateforme appelle pour signaler un événement. L'envoi de test est réel ; l'émission automatique des événements n'est pas branchée. Voir Sécurité et identifiants.

Workflow

Graphe de nœuds qui automatise un processus. Voir Workflows.

Workspace

Voir « Espace de travail ». Dans les chapitres de développement, le mot désigne aussi le workspace Cargo : l'ensemble des crates déclarés par le Cargo.toml de la racine. Voir Architecture Chatbotaurus.

X

XML-RPC

Protocole d'appel à distance que le connecteur Odoo utilise pour joindre le serveur Odoo. Voir Odoo.

Z

Zero trust

Principe de sécurité : aucune requête n'est crue sur sa seule provenance réseau. Voir Architecture de confiance zéro.

Voir aussi

Migration depuis d'autres outils

Ce guide aide à refaire vos automatisations existantes dans Chatbotaurus. La migration se fait à la main : il n'existe pas d'import automatique de flux venus d'un autre outil. Les noms de nœuds ci-dessous sont ceux du catalogue de l'éditeur de workflows, état au 3 octobre 2026.

Avant de commencer

Une plateforme hébergée dans l'UE refuse certains services (voir Conception des connecteurs MCP). À l'exécution, les identifiants de serveur de 25 services hors UE (messagerie, stockage, automatisation en ligne, hébergeurs cloud, paiement) sont refusés, et seuls les serveurs de la liste autorisée sont appelés. Une automatisation qui dépend d'un de ces services doit donc passer par un équivalent européen.

Équivalences de concepts

Les termes de l'outil d'origine varient. La colonne de gauche donne le concept, quel que soit le nom qu'il porte chez eux.

Concept dans l'outil d'origineDans Chatbotaurus
Automatisation complète (scénario, flux)workflow, appelé aussi gateway
Déclencheurnœud MCP Start ; MCP Webhook Trigger pour un appel HTTP entrant
Action sur un servicenœud connecteur (par exemple Odoo Connector ou n8n Connector), ou tâche {serverId, query} dans MCP Parallel
Filtre, conditionMCP Condition
Chemins multiplesMCP Router
Itération sur une listeMCP Loop
Regroupement de résultatsMCP Aggregator (stratégies merge, first, vote)
Exécution en parallèleMCP Parallel
Reprise sur erreurMCP Retry, MCP Fallback
Validation humaineMCP Approval
Appel à un modèle d'IAMCP LLM
Fin du fluxMCP End

Ce qui n'a pas d'équivalent

  • Code personnalisé. Les nœuds « fonction personnalisée » et « fonction si/sinon » (JavaScript) sont refusés à l'exécution : la plateforme n'exécute pas de JavaScript dans un workflow (voir Limites).
  • Nœud « outil » seul. Le nœud mcpToolNode n'est pas exécutable dans un graphe. Appelez l'outil par une tâche {serverId, query} dans MCP Parallel.
  • Transformation et état. Les nœuds de transformation et d'état de l'ancien moteur ne s'exécutent pas non plus.

Remplacer un service hors UE

La plateforme tient une table de remplacement. Voici des exemples de correspondances (21 services y figurent au total) :

BesoinÉquivalents européens connus
Messagerie d'équipeMattermost, Rocket.Chat, Element
VisioconférenceJitsi
Mesure d'audienceMatomo, Plausible
CRMOdoo
Courriel marketingListmonk, Mautic
Documents partagésCryptPad, OnlyOffice
AgendaCalRS
Hébergement de codeForgejo
Support clientZammad
Moteur de recherche interneTypesense
Stockage de fichiersNextcloud
Formation en ligneMoodle, Chamilo

Chaque équivalent est une fiche de connecteur du dépôt. La liste complète est dans Vue d'ensemble des connecteurs.

Étapes

  1. Inventaire. Listez toutes les automatisations actives.
  2. Priorité. Commencez par les automatisations simples.
  3. Correspondance. Pour chaque automatisation, notez le déclencheur, les actions et les conditions, puis trouvez le nœud équivalent.
  4. Identifiants. Recréez les identifiants dans la section Sécurité (Sécurité et identifiants).
  5. Recréation. Construisez le workflow dans l'éditeur (Workflows).
  6. Essai. Testez chaque workflow depuis le Chat avant de le publier.
  7. Parallèle. Faites tourner l'ancien et le nouveau côte à côte, le temps de comparer les résultats.
  8. Bascule. Désactivez l'ancien outil une fois la comparaison satisfaisante.
  9. Nettoyage. Fermez les comptes devenus inutiles.

Coexister avec n8n

Si vous utilisez déjà n8n, vous pouvez le garder. Le connecteur n8n de la plateforme liste, crée et active des workflows n8n, et lit leurs exécutions, depuis un workflow Chatbotaurus. Vous migrez ensuite les flux un par un, à votre rythme. Voir n8n.

Combien de temps ?

Il n'y a pas d'estimation chiffrée fiable : la durée dépend du nombre de services connectés et de la complexité des conditions. Mesurez-la sur la première automatisation que vous migrez, puis extrapolez.

Besoin d'aide ?

Écrivez à contact@chatbotaurus.com. Les délais de réponse sont dans SLA, support et niveaux de service. Le déploiement assisté de vos outils est une option de l'offre Pro (voir Tarification).

Voir aussi

  • Workflows — la palette de nœuds citée dans les équivalences.
  • Comparatifs — pourquoi migrer vers une passerelle hébergée dans l'UE.
  • Connecteurs MCP — les fiches de connecteurs qui remplacent vos services.
  • Connecteur n8n — garder n8n et migrer les flux un par un.
  • Prise en main guidée — créer le premier workflow après la migration.