Aller au contenu

Administration de la passerelle

Exécution agentique, rôles et permissions, refus de démarrage : ce qu'un exploitant règle et ce qu'un auditeur vérifie.

Interne, peut changer sans préavis. Ce que décrit cette page relève de l’exploitation d’un déploiement, pas du contrat que la passerelle offre à un programme tiers. L’éditeur ne s’y engage pas : ces noms peuvent changer d’une version à l’autre, sans étape de dépréciation. Un changement se manifeste alors au démarrage ou à la mise à jour, par un message qui nomme ce qui manque.

La partie sur laquelle l’éditeur s’engage est le relais.

Ces deux routes sont le protocole par lequel un poste de développement fait exécuter ses commandes d’agent sur la passerelle plutôt que sur la machine du développeur. Le poste et la passerelle voyagent sous le même numéro de version : les publier comme un contrat figerait une couture interne.

Le poste demande à la passerelle d’exécuter une commande de sa session agentique. La réponse est un flux de lignes JSON, une par événement. Protocole entre le poste et la passerelle, versionné avec eux.

POST /_agent-execution/commands/:identifiant/interrupt

Section intitulée « POST /_agent-execution/commands/:identifiant/interrupt »

Le poste interrompt une commande qu’il a lancée, et sa descendance. Une commande inconnue et une commande qui appartient à quelqu’un d’autre reçoivent la même réponse.

Le poste demande ce que son organisation autorise : quels fournisseurs de modèles, quels outils. La réponse porte la politique, sa révision, l’instant où elle a été produite et jusqu’à quand elle vaut ; le poste l’applique et refuse de fonctionner sans elle. Une organisation qui n’impose rien reçoit une réponse normale et vide de politique ; une organisation que la base ne connaît pas est une faute de configuration et reçoit une erreur, jamais une politique vide. Lecture seule, sans authentification : le poste n’a rien à présenter. Protocole entre le poste et la passerelle, versionné avec eux.

Le poste remet par lots ce que son agent a fait : pour chaque outil appelé, la cible (un chemin, une commande, un hôte, jamais les paramètres, donc jamais le contenu d’un fichier ni la conversation), qui l’a autorisé, comment ça s’est terminé. Un lot qui porte un champ inconnu est refusé en entier ; un lot représenté après une panne réseau est rangé une seule fois. Derrière la même porte que la politique de l’organisation : le poste présente sa licence. Première tranche du registre d’actes (#763) : rien n’est signé, le sujet est déclaré par le poste.

Le poste demande si l’une de ses sessions d’agent peut encore agir. La réponse dit « en vigueur » ou « révoquée », et dans ce cas depuis quand ; elle ne donne ni l’auteur de la révocation ni son motif, qui restent à l’audit. Révoquer une session révoque aussi ses sous-agents. Une session que personne n’a révoquée, ou que la passerelle ne connaît pas, est en vigueur. Derrière la même porte que la politique de l’organisation : le poste présente sa licence. Une panne de lecture répond par une erreur, jamais par « en vigueur ».

Le poste demande l’adresse de l’annuaire d’entreprise et l’identifiant public sous lequel le produit y est enregistré, avant d’avoir la moindre identité, ce qui est toute la raison de cette route. La réponse est lue dans la configuration d’annuaire que la passerelle emploie déjà pour vérifier les jetons, jamais dans une seconde déclaration. Un déploiement sans annuaire configuré répond « rien ici » sans décrire son état. Le secret client, lui, n’est jamais publié.

ChampType
sessionstring
interpreteurstring
argumentsstring[]
variablesSupplementairesRecord<string, string>
sansFluxDeSortieboolean

Le sujet à qui la commande est imputée vient de l’identité vérifiée, jamais du corps.

Un corps qui ne se relit pas est refusé par un 400, jamais complété par des valeurs vides. Voici, mot pour mot, ce que la passerelle répond alors. Ce sont les seules exigences de forme, et les champs qu’aucune de ces phrases ne nomme prennent une valeur par défaut :

  • The request body must be a JSON object.
  • session must be a non-empty string.
  • interpreteur must be a non-empty string.
  • arguments must be an array of strings.
  • variablesSupplementaires must be an object.
  • variablesSupplementaires.<…> must be a string.

La réponse est un flux de lignes JSON : une ligne par événement, terminée par un saut de ligne. La sortie du processus y voyage encodée en base64, parce que son décodage dépend de la plateforme du poste.

  • demarre
  • sortie
  • fin
  • erreur

Il y a quatre rôles, et il n’y en a pas d’autre : aucun rôle « super ». La matrice ci-dessous vit dans le code du produit et ne change que par une version du produit. Ce qui vit en base est l’attribution des rôles à des sujets, qui est de la donnée d’exploitation.

RôlePôlePérimètre de projetPermissions
utilisateur-standardutilisationinterdit3
administrateur-de-projetadministrationobligatoire5
administrateur-d-instanceadministrationinterdit12
auditeurauditinterdit6

Un même sujet ne peut pas porter à la fois un rôle des pôles « administration » et « audit ». C’est cette règle qui rend vraie l’affirmation « l’auditeur n’administre pas, l’administrateur n’audite pas », et c’est elle qui donne sa valeur au journal des décisions.

Un sujet sans rôle attribué obtient un ensemble de permissions vide, donc un refus. C’est l’état de tout le monde sur une instance neuve.

Aucune permission n’appartient à deux rôles. Une politique d’autorisation installée par l’exploitant peut restreindre cette matrice, jamais l’élargir.

PermissionRôle qui la porteCe qu’elle permet
inference:appelerutilisateur-standardAppeler un endpoint d’inférence.
usage:lire-le-sienutilisateur-standardConsulter sa propre consommation, et celle de personne d’autre.
execution:lancerutilisateur-standardFaire exécuter par la passerelle une commande de sa session agentique.
membres:lireadministrateur-de-projetLister les membres du projet et leur état.
membres:affecter-un-planadministrateur-de-projetAffecter ou retirer un plan à un membre.
membres:activeradministrateur-de-projetActiver ou désactiver un membre.
usage:lire-le-projetadministrateur-de-projetConsulter la consommation agrégée du projet.
console:administrer-un-projetadministrateur-de-projetOuvrir la surface d’administration de projet de la console.
plans:administreradministrateur-d-instanceCréer, modifier, supprimer un plan et son plafond.
fournisseurs:administreradministrateur-d-instanceDéclarer un fournisseur : URL de base, en-tête de clé.
modeles:administreradministrateur-d-instanceDéclarer un modèle et ses prix.
endpoints:administreradministrateur-d-instanceCréer, router, activer, supprimer un endpoint.
usage:lire-l-instanceadministrateur-d-instanceConsulter la consommation de toute l’instance.
attributions:administreradministrateur-d-instanceAttribuer et retirer des rôles à des sujets.
membres:lire-l-instanceadministrateur-d-instanceLister les sujets de toute l’instance.
sessions:revoqueradministrateur-d-instanceInvalider immédiatement les sessions d’un sujet.
politique:administreradministrateur-d-instanceInstaller une politique d’autorisation.
organisations:administreradministrateur-d-instanceCréer l’organisation dont ce déploiement sert la politique.
politique-d-organisation:administreradministrateur-d-instanceImposer une politique aux postes d’une organisation, c’est-à-dire la gouvernance de parc.
console:administrer-l-instanceadministrateur-d-instanceOuvrir la surface d’administration d’instance de la console.
journal:lireauditeurLire le journal des décisions d’autorisation.
journal:exporterauditeurExporter le journal pour l’instruire hors du produit.
journal:verifier-l-integriteauditeurVérifier le chaînage et les signatures du journal.
politique:lireauditeurLire la politique en vigueur, sans pouvoir l’installer.
politique-d-organisation:lireauditeurLire la politique imposée aux postes, et tout ce qui a été tenté (installations et refus, avec l’auteur de chacun et ce que son nom vaut), sans pouvoir rien imposer.
console:auditerauditeurOuvrir la surface d’audit de la console.
RouteCodeQuandCorps
exécution agentique401Aucune preuve d’identité utilisable n’accompagne la commande.{ "error": "Missing credentials. Set apiKey in your Lemniscate config." }
exécution agentique401Une preuve est présentée et refusée.{ "error": "Unauthorized." }
exécution agentique403Le sujet figure sur la liste de révocation de l’instance.{ "error": "Your access to this instance has been revoked. Contact the operator of this deployment." }
exécution agentique403Aucun rôle porté par le sujet ne donne le droit de faire exécuter une commande d’agent. La permission attendue est portée par le rôle d’utilisateur standard.{ "error": "Your identity is recognised, but no role you hold carries the right to run agent commands here." }
exécution agentique503La passerelle n’a pas pu lire la liste de révocation, les rôles ou la politique en vigueur.{ "error": "Authorization decision could not be made, so the command was refused." }
exécution agentique503L’accord était acquis et le journal n’a pas pu l’enregistrer. La commande n’est alors pas lancée du tout.{ "error": "Authorization decision could not be recorded, so the command was not run." }
exécution agentique501Cette passerelle n’exécute aucune commande d’agent, ce qui est son état par défaut. Prononcé après l’autorisation, pour qu’un appelant sans aucun droit n’apprenne pas ce que la passerelle offre.{ "error": "This gateway runs no agent commands: no launcher is configured (<nom de la variable>). …" }
exécution agentique400Le corps de la commande n’est pas relisible : ce n’est pas un objet JSON, ou l’un de ses champs n’a pas la forme attendue. Un corps mal formé est refusé, jamais complété par des valeurs vides.{ "error": "<la phrase qui nomme le champ fautif>" }
exécution agentique404L’identifiant ne désigne aucune commande en cours, ou il en désigne une qui appartient à quelqu’un d’autre. Les deux cas reçoivent la même réponse : les distinguer permettrait de recenser les sessions des autres.{ "error": "No such running command." }
src/controlPlane/organizationPolicyRoute.ts500La passerelle est configurée pour servir la politique d’une organisation que sa base ne connaît pas. C’est une faute de configuration, et elle est rendue comme telle : servir « aucune politique » ferait conclure à tout un parc de postes qu’il n’est soumis à aucune restriction, pour une faute de frappe.{ "error": "This gateway is configured to serve the organization \"…\", which does not exist in its database." }
src/controlPlane/agentActsRoute.ts400Le corps de la remise d’actes n’est pas du JSON lisible.{ "error": "the body is JSON" }
src/controlPlane/agentActsRoute.ts400Le lot d’actes remis par le poste ne passe pas la liste blanche : un champ que la projection ne connaît pas (les paramètres bruts d’un appel, en particulier), un champ obligatoire absent, une valeur hors d’une liste fermée, un motif de plus de 300 caractères, ou un lot de plus de 500 actes. Le lot entier est refusé et rien n’est rangé, pour que le poste le représente une fois corrigé plutôt que d’en perdre une partie sans le savoir. Le corps nomme l’acte fautif et la raison.{ "error": "acts refused — act #<n>: <raison>" }
src/controlPlane/identityDiscoveryRoute.ts404Aucun annuaire d’entreprise n’est configuré sur ce déploiement, ou celui qui l’est n’est pas recevable. La réponse ne dit pas laquelle des deux, ni ce qui manque : décrire l’état du déploiement renseignerait un attaquant sur ce qu’il lui reste à contourner.{ "error": "not_found" }
src/controlPlane/requesterLicense.ts401La requête ne présente aucune licence Lemniscate valide : ni en-tête du tout, licence expirée, ou licence signée par quelqu’un d’autre. Les trois reçoivent le même refus, sans dire lequel s’applique : distinguer renseignerait le demandeur sur ce qu’il lui reste à contourner. Le remède est le même dans les trois cas : demander une licence à l’administrateur.{ "error": "This gateway serves an organization's policy only to a workstation that presents a valid Lemniscate license. Present it as Authorization: Bearer . If you have none, ask the administrator who deployed this gateway." }

Un refus de démarrage se lit sur la sortie d’erreur du conteneur : un message, aucune trace de pile, aucun port ouvert, et un code de sortie 1. Aucune configuration incomplète ne retombe sur un comportement dégradé.

Cause
La clé du compte d’administration est absente, vide ou trop faible, dans le profil opéré par l’éditeur.
L’adresse de la base est absente, ou elle porte un paramètre de chiffrement que le code refuse de laisser décider à sa place.
La licence de déploiement est absente, illisible, mal signée, ou expirée depuis plus longtemps que son délai de grâce. La passerelle refuse plutôt que de servir un parc sans licence valide. Ce refus n’existe que dans le profil installé chez le client : le profil opéré par l’éditeur ne porte pas de licence de déploiement.
Le compte avec lequel la passerelle s’est connectée à sa base peut réécrire ou effacer la consommation facturée ou les journaux d’audit, ce qui est le cas du compte propriétaire. Elle refuse de démarrer plutôt que de produire une facturation que son propre producteur peut réécrire. Même refus quand la base ne peut pas répondre à la question, parce que la migration qui crée les rôles de service n’a pas été appliquée : ne pas savoir n’est pas un feu vert.
Le proxy d’entreprise déclaré n’est pas une URL utilisable, ou le magasin d’autorités internes est illisible.
Le certificat de service, la clé qui l’accompagne, l’autorité de la base ou le plafond de durée d’une requête sont incomplets ou hors bornes.
Le répertoire de documentation déclaré est illisible, ne porte pas la fiche d’identité que toute archive emporte, ne déclare pas sa version et son chemin, ou déclare un chemin que cette passerelle ne sert pas. La passerelle refuse plutôt que de servir une documentation dont elle ignore la version ou dont tous les liens seraient cassés.
Le lanceur de commandes d’agent est nommé sans être offert, ou il l’est sans le répertoire de travail qu’il exige.
La passerelle ne sait pas de quelle organisation elle sert la politique aux postes. Elle refuse plutôt que de supposer : une organisation supposée la ferait répondre « rien n’est restreint » à tout un parc de postes, sans que rien n’ait l’air cassé.

Les noms des variables citées par ces messages sont sur la page Variables d’environnement de la passerelle.

L’attribution des rôles, la révocation d’un sujet et l’installation d’une politique se font par des commandes d’administration et par la console. La console a sa page, Console d’administration, et les gestes courants sur les comptes et les clés sont décrits par Suivre et corriger les accès depuis la console. Les commandes d’administration elles-mêmes n’ont aucune page sur ce site. Les tables où tout cela se range sont décrites par Tables de la base de la passerelle.