Connecteurs et confinement

Un connecteur déclare une adresse, et c'est le noyau qui effectue l'appel. Aucun connecteur n'effectue son propre appel réseau, y compris celui d'Ollama. Le transport refuse toute adresse non locale, à l'enregistrement et à chaque appel. Cette page documente le registre de connecteurs, la règle de localité et les cas testés.

Pourquoi le connecteur ne fait pas son fetch

Un connecteur est une contribution : un plugin peut en déclarer un. S'il effectuait lui-même son fetch, il appellerait ce qu'il veut, et l'absence de sortie réseau ne serait plus qu'une promesse tenue par du code tiers.

En séparant la déclaration du transport, le connecteur n'a pas la main sur le réseau. Le contrôle est donc porté par le noyau, livré avec l'application et relisible en un seul endroit, et non par du code de plugin installé après coup.

Déclarer un connecteur

K.connectors.register({ id: 'ollama', source: 'core', title: { fr: 'Ollama (local)', en: 'Ollama (local)' }, base: 'http://127.0.0.1:11434', capacites: ['chat', 'outils', 'flux'], modeles: function () { return K.connectors.fetch('http://127.0.0.1:11434/api/tags') .then(function (r) { return r.json(); }); } });
ChampDescription
idIdentifiant namespacé.
baseAdresse de base. Validée à l'enregistrement : une adresse non locale est refusée immédiatement.
capacitesCe que le connecteur sait faire : chat, outils, flux, embeddings.
Le refus est fail-closed à l'enregistrement, pas à l'appel. Un plugin qui déclarerait un connecteur vers un service distant est rejeté au chargement, avec une ligne dans le journal. Il n'y a pas de fenêtre pendant laquelle le connecteur existe et pourrait appeler.

La règle de localité

K.connectors.isLocal(url) normalise l'URL avec new URL(), puis compare le hostname en entier, jamais son début.

AdresseVerdictRaison
http://127.0.0.1:11434/api/chatAcceptéBoucle locale.
http://localhost:11434/api/chatAcceptéBoucle locale.
http://[::1]:11434/api/chatAcceptéBoucle locale IPv6.
http://2130706433/apiAcceptéIP décimale. new URL() la normalise en 127.0.0.1.
http://0x7f.1/apiAcceptéIP hexadécimale, normalisée de même.
http://127.1/apiAcceptéIP abrégée, normalisée de même.
http://127.0.0.1.evil.com/xRefuséNom de domaine. La normalisation le laisse intact ; une comparaison par préfixe l'aurait accepté.
https://api.openai.com/v1/chatRefuséHôte distant.
http://192.168.1.50/apiRefuséRéseau local, mais pas la machine.
file:///etc/passwdRefuséSchéma non autorisé.
//evil.com/xRefuséProtocole implicite.
Les adresses déguisées (décimale, hexadécimale, abrégée) sont vérifiées, pas supposées : new URL() les normalise, et la comparaison sur hostname les reconnait correctement. Le cas délicat est le nom de domaine commençant par une adresse de boucle, comme 127.0.0.1.evil.com : la comparaison du hostname en entier le refuse, là où une comparaison par préfixe l'aurait accepté.

Le transport

K.connectors.fetch(url, opts) est le seul point de sortie. Il applique, dans cet ordre :

#ContrôleEn cas d'échec
1Localité de l'adresse.Rejet, ligne dans le journal.
2Refus de suivre les redirections.Rejet. Une redirection vers un hôte distant contournerait le contrôle 1.
3Filtrage des en-têtes sortants.Les en-têtes internes, dont la campagne, ne sont jamais transmis.
La campagne active est propagée par enveloppement de window.fetch, filtré explicitement aux appels de l'API interne. Un connecteur local, y compris Ollama, ne reçoit donc jamais l'identité de la campagne ni le contexte de l'enquête.

Mode air-gap

Le confinement du transport est indépendant du mode air-gap : il s'applique dans tous les cas. En mode air-gap, aucune connexion sortante n'est tentée par le logiciel, y compris vers la base communautaire ou la veille scientifique, et l'assistant continue de fonctionner puisque son connecteur est local.

Diagnostic

SymptômeCause probable
Le panneau Assistant indique qu'aucun modèle n'est disponible. Ollama n'écoute pas sur 127.0.0.1:11434. Vérifier ollama serve.
Un connecteur de plugin n'apparait pas. Adresse non locale, refusée à l'enregistrement. La raison est dans le journal.
Ollama écoute sur une autre machine du réseau. Configuration non supportée : le transport refuse toute adresse hors boucle locale, y compris 192.168.x.x.
Les réponses arrivent d'un bloc, sans streaming. Comportement attendu quand des outils sont offerts au modèle.