Comptes de service
Identités machine pour appeler l'API Scrydon sans session utilisateur.
Un compte de service est une identité machine détenue par l'organisation — sans utilisateur, sans navigateur, sans
connexion interactive. Il s'authentifie avec l'un de deux grants OAuth 2.1 : client_credentials,
pour appeler directement l'API de la plateforme avec un jeton d'accès de courte durée (fixée à 5 minutes) ; ou
le grant de jeton machine qu'un pipeline CI utilise via scrydon login --service-account, dont la
durée de vie est configurable et plafonnée par la politique plutôt que fixe. Consultez Durée de vie
du jeton pour comprendre ce qui les distingue.
Pour une application qui ne peut stocker qu'une clé d'API fixe — les paramètres d'IA d'un CRM, une interface de chat, un outil de workflow — un administrateur peut plutôt émettre pour le compte une clé de routeur : une clé de longue durée pour l'AI Gateway qui agit au nom du compte.
Pour vous connecter depuis votre terminal et envoyer un message sous cette identité, suivez Utiliser Claude Code avec un compte de service. Cette page couvre l'URL de l'AI Gateway, l'export du bearer, la sélection du modèle et l'attribution des dépenses. Pour une connexion Scrydon personnelle, utilisez AI Gateway pour les développeurs.
Créer un compte de service
Les administrateurs d'organisation créent des comptes de service sous Paramètres → Membres → Comptes de service. Choisissez un nom et les portées qu'il peut demander, puis copiez le secret client — il n'est affiché qu'une seule fois. Si vous le perdez, effectuez une rotation du secret pour en obtenir un nouveau.
Les portées ont la forme resource:action — choisissez lecture et/ou écriture par ressource. Ressources :
chat, workflows, storage, knowledge, templates, tools, logs, tables,
capabilities — chacune avec :read et :write (par ex. knowledge:read, workflows:write).
:write implique :read sur la même ressource, de sorte qu'un grant knowledge:write satisfait aussi une
exigence knowledge:read.
La ressource capabilities est particulière : capabilities:write permet au jeton d'exécuter les
capacités d'IA de votre organisation (complétion LLM, embeddings, transcription, OCR, synthèse
vocale, génération d'images et de vidéos, modération de contenu) via le point de terminaison unifié ci-dessous.
Les capacités qui fonctionnent réellement sont déterminées par les intégrations activées de votre organisation — la
portée indique seulement que le jeton peut en faire la demande.
Gérer les identifiants
Ouvrez un compte de service sous Paramètres → Membres → Comptes de service. Son ID client est toujours disponible à côté du bouton de copie dans l'en-tête du panneau.
Dans Vue d'ensemble, la section Authentification liste la manière dont le compte prouve son identité :
- Gérer sur une ligne de secret client ouvre ses détails d'expiration et de dernière utilisation. Effectuer une rotation du secret remplace le secret, y compris un secret qui n'expire jamais. Choisissez une durée de vie conforme à la politique de l'organisation, confirmez le remplacement immédiat et copiez le nouveau secret. Confirmez que vous l'avez enregistré avant de fermer ; il n'est affiché qu'une seule fois.
- Ajouter un identifiant fédéré ouvre un sous-panneau permettant de sélectionner un émetteur de confiance enregistré, de saisir
le sujet exact du jeton de charge de travail (
sub) et, éventuellement, de lui donner un nom. Enregistrez d'abord un émetteur sous Paramètres → Gouvernance → Émetteurs de confiance si la liste est vide. - Gérer sur une ligne fédérée affiche son émetteur, son sujet exact et son ID client fédéré. Utilisez cet ID pour l'authentification fédérée. Supprimer demande une confirmation avant de supprimer la liaison. La liste et l'ID client fédéré sont actualisés après les modifications.
- Une ligne de clé de pair affiche l'émetteur pair. Son compte dédié se supprime via le menu du compte.
- Ajouter une clé de routeur émet une clé pour une application qui n'accepte qu'une clé d'API, et Gérer sur une ligne de clé de routeur en effectue la rotation ou la révoque. Consultez Clés de routeur.
Le menu du compte dans l'en-tête contient Désactiver et Supprimer pour l'ensemble du compte de service. Dans l'onglet Identifiants, Identifiants d'extension → Lier un compte gère les comptes d'extension connectés que ce compte de service peut utiliser.
Modifier les permissions d'accès
Dans Accès, sélectionnez Modifier à côté de Permissions. Choisissez l'accès en lecture/écriture par ressource,
puis Enregistrer. L'écriture inclut la lecture. Au moins une permission est requise ; Annuler abandonne le
brouillon. Le même onglet permet aux administrateurs autorisés de configurer ou de modifier l'habilitation du compte dans
la limite de leur propre rang. Un compte de service a besoin d'une habilitation de données pour appeler les opérations de la plateforme, y compris
la liste des modèles du routeur LLM. Si une requête renvoie FORBIDDEN avec le motif clearance_required,
ouvrez Accès → Habilitation de données → Modifier, choisissez le niveau approprié, enregistrez et réessayez.
Qui peut modifier une habilitation, et ce qu'une modification entraîne :
- Vous ne pouvez modifier l'habilitation que d'un compte pour lequel vous êtes déjà habilité : un administrateur habilité en dessous du niveau actuel d'un compte ne peut pas le modifier du tout, pas même pour l'abaisser.
- Vous ne pouvez pas définir une habilitation supérieure à la vôtre. Votre habilitation est vérifiée par Scrydon lui-même ; si elle ne peut pas être déterminée, la modification est refusée et rien n'est changé.
- Relever une habilitation (un niveau supérieur, un nouveau compartiment ou une première habilitation) remplace le secret du compte et révoque ses jetons d'accès existants, car quiconque détenait l'ancien secret n'était habilité que pour l'ancien niveau. Les workflows qui s'exécutent en tant que compte continuent de fonctionner. Tout ce qui, en dehors de Scrydon, utilise le compte, comme un pipeline CI/CD, cesse de fonctionner jusqu'à ce que vous effectuiez une rotation du secret et lui fournissiez le nouveau. Les jetons que les workflows avaient déjà récupérés sont refusés pendant cinq minutes au maximum, jusqu'à ce qu'ils soient récupérés à nouveau. Abaisser une habilitation ne change rien d'autre.
Les permissions retirées cessent d'autoriser les jetons opaques existants dès leur requête suivante. Ajouter une permission n'étend pas le grant d'un jeton existant : demandez un nouveau jeton pour utiliser la permission ajoutée. Les modifications n'annulent pas le travail déjà admis. Les mises à jour de permissions sont enregistrées dans le journal d'audit et s'appliquent aux chemins d'authentification par secret, par fédération et par pair du compte. La gestion des identifiants et des accès requiert des permissions d'administration de l'organisation.
Obtenir un jeton d'accès
Envoyez l'ID client et le secret dans le corps du formulaire (client_secret_post). N'envoyez pas de paramètre resource —
les jetons sont opaques et limités à l'organisation.
curl --fail-with-body -X POST "https://<your-host>/api/auth/oauth2/token" \
-H "content-type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=$CLIENT_ID" \
--data-urlencode "client_secret=$CLIENT_SECRET" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "scope=knowledge:read tools:write"La réponse contient un access_token. Utilisez-le comme jeton bearer auprès de l'API :
curl "https://<your-host>/api/v1/service-account/whoami" \
-H "authorization: Bearer $ACCESS_TOKEN"{ "organizationId": "...", "clientId": "sa_...", "scopes": ["knowledge:read", "tools:write"] }Une requête ne peut demander que des portées accordées au compte de service ; le jeton porte les portées accordées et l'ID de l'organisation, et les points de terminaison en aval appliquent les deux.
Exécuter des capacités d'IA
Avec un grant capabilities:write, un compte de service (ou un jeton de mini-app) peut
appeler les opérations d'IA typées de la Base Platform de votre organisation :
curl -X POST "https://<your-host>/api/platform/v1/ai/llm/complete" \
-H "authorization: Bearer $ACCESS_TOKEN" \
-H "content-type: application/json" \
-d '{
"messages": [{ "role": "user", "content": "Summarize: ..." }]
}'Chaque capacité est une opération distincte sous /api/platform/v1/ai/, et le corps de la requête
transporte les paramètres de cette opération :
| Opération | Entrée | Retourne |
|---|---|---|
ai/llm/complete | messages (+ model, temperature, maxTokens facultatifs) | content, model, usage |
ai/embeddings/generate | texts, model et dimensions facultatifs | vectors |
ai/speech/transcribe | audioBase64, mimeType, language, provider, model facultatifs | transcript |
ai/documents/ocr | documentBase64, mimeType, model facultatif | text, pages |
ai/speech/synthesize | text, voice, speed, model facultatifs | audioBase64, format, mimeType |
ai/images/generate | prompt, size, quality, count, model facultatifs | images (URL et/ou base64) |
ai/video/generate | prompt, duration, resolution, model facultatifs | url ou dataBase64, format |
ai/moderation/evaluate | input (chaîne ou string[]), provider et model facultatifs | results (par texte : flagged, categories, categoryScores, orgVerdict) |
Chaque appel passe par les intégrations configurées de votre organisation, avec les identifiants, la prévention
des fuites de données, la facturation et l'audit appliqués côté serveur — l'appelant ne voit jamais de clé d'API de fournisseur.
Lorsque model est omis, l'appel utilise le modèle par défaut de l'organisation pour cette capacité. Fixez
model explicitement pour les embeddings : les dimensions des vecteurs doivent correspondre partout où vous les stockez.
Lorsqu'une opération accepte provider, en nommer un sans model fixe ce fournisseur et laisse la
plateforme choisir son modèle — pour ai/speech/transcribe, un déploiement qui sert la transcription par lots.
Un fournisseur fixé n'est jamais remplacé par un autre : s'il ne peut pas servir l'appel, la requête échoue avec
CAPABILITY_NOT_CONFIGURED.
Si l'organisation n'a aucune extension activée pour la capacité demandée, l'appel renvoie
409 avec { "error": { "code": "CAPABILITY_NOT_CONFIGURED", ... } } — un administrateur d'organisation peut
en activer une sous Paramètres → Plateforme → Extensions. Les entrées binaires (audioBase64,
documentBase64) sont encodées en base64 et plafonnées à la limite de téléversement de la plateforme.
Accès aux espaces de travail et environnement
Configurez ces réglages indépendamment dans le panneau Accès → Espaces de travail et environnement → Modifier du compte de service :
| Réglage | Signification |
|---|---|
| Tous les espaces de travail | Autorise ce compte dans les espaces de travail actuels et futurs appartenant à son organisation. |
| Espaces de travail sélectionnés | Limite le compte aux espaces de travail que vous sélectionnez. Choisissez-en au moins un. |
| Tous les environnements | Autorise le compte dans chaque environnement des espaces de travail autorisés, y compris les environnements créés ultérieurement. |
| Environnements sélectionnés | Limite le compte aux environnements que vous cochez, comme dev, stg ou prd. |
Un environnement n'accorde pas l'accès à un espace de travail. Un compte configuré avec Espaces de travail sélectionnés :
Azure Hawk et Environnements sélectionnés : Production (prd) ne peut pas accéder à un autre espace de travail ni
s'exécuter sur l'environnement de développement d'Azure Hawk. Ces autorisations donnent un accès de membre ; les rôles
explicites existants dans l'espace de travail continuent de s'appliquer dans la portée sélectionnée.
Lors de la création, Tous les espaces de travail et Tous les environnements sont présélectionnés ; restreignez l'un ou l'autre avant de créer le compte. Le sélecteur d'environnement présélectionnait auparavant l'environnement de rang le plus élevé, ce qui rendait chaque nouveau compte limité à la production et le faisait refuser partout ailleurs. Les environnements sélectionnés enregistrent des slugs précis, pas une règle mouvante du « plus élevé » : réordonner ou ajouter des environnements ne modifie pas les comptes existants.
Un compte autorisé dans tous les environnements ne désigne aucun environnement propre, si bien que chaque requête doit indiquer où elle agit — une exécution de workflow fournit son propre environnement, et un appel d'API direct envoie les en-têtes d'espace de travail et d'environnement. Un identifiant qui n'envoie aucun en-tête, comme une clé de routeur, nécessite exactement un environnement sélectionné ; avec tous les environnements, il ne peut pas résoudre de connexion. Les noms d'environnement doivent utiliser des slugs cohérents d'un espace de travail à l'autre. Un espace de travail dépourvu de l'environnement sélectionné ne peut pas lui substituer un autre environnement.
Le routeur LLM (/api/router) utilise l'environnement enregistré du compte — donnez à un compte de routeur un seul
environnement sélectionné — et ignore délibérément les en-têtes de requête d'espace de travail/d'environnement. Il peut lister les modèles et résoudre les connexions de l'organisation
sans sélectionner d'espace de travail ; les opérations sur les ressources d'un espace de travail nécessitent toujours une cible explicite
dans la portée autorisée du compte. Un appel au routeur au niveau de l'organisation n'a aucun espace de travail auquel attribuer
l'utilisation.
L'enregistrement des réglages d'accès s'applique aux requêtes ultérieures avec jeton opaque, y compris les jetons déjà émis. Aucun nouveau jeton n'est nécessaire. Les comptes existants ne reçoivent pas automatiquement Tous les espaces de travail et ne sont pas déplacés vers Production. Un compte non configuré affiche Non configuré ; configurez-le avant d'utiliser le routeur. Les comptes dotés de l'ancien épinglage d'environnement propre à un espace de travail conservent cet épinglage jusqu'à ce que vous enregistriez explicitement les nouveaux réglages. Les anciennes affectations d'espaces de travail restent en vigueur jusqu'à l'enregistrement d'une politique d'accès explicite.
Si le routeur renvoie 403, examinez le corps de la réponse plutôt que de le jeter avec curl --fail :
curl --fail-with-body --silent --show-error "$ANTHROPIC_BASE_URL/v1/models" \
-H "Authorization: Bearer $ANTHROPIC_AUTH_TOKEN"exact_environment_required signifie que l'identifiant n'a aucun environnement utilisable. Ce motif est distinct de
clearance_required (habilitation de données manquante), de workspace_access_required (espace de travail hors de la
portée du compte) et de environment_mismatch (la requête cible un autre environnement).
L'espace de travail et l'environnement que vous configurez s'appliquent partout où le compte agit, pas seulement dans le
routeur : l'API de Scrydon, son API de tables et les workflows qui s'exécutent en tant que compte le refusent tous
hors de cette portée. Un compte limité à prd ne peut pas être choisi comme identité Run As d'un
workflow dans dev, et le sélecteur en indique la raison.
Sur l'API de tables, ce refus est 404 Not found pour une lecture, de sorte que la réponse ne révèle pas
si la table existe, et 403 sa_not_member_of_workspace pour une écriture. Si le service
d'autorisation de Scrydon ne peut pas répondre à une recherche dont l'API de tables a besoin pour autoriser la requête, comme
la portée du compte, l'API de tables répond 503 AUTHZ_UNAVAILABLE à la place, que le
service ait renvoyé une erreur ou qu'il n'ait pas pu être joint du tout. Ce n'est pas un refus : réessayez la
requête. Créer une table dans un espace de travail ou un environnement qui n'existe pas reste
400 workspace_or_environment_not_found, car dans ce cas le service a répondu.
Une défaillance du service d'autorisation est actuellement signalée comme une erreur serveur 500 plutôt que
503 : l'API de tables n'a pas pu vérifier le jeton du compte. Ce n'est pas non plus un refus.
Durée de vie du jeton
Deux manières d'obtenir un jeton, avec deux règles de durée de vie différentes :
client_credentials(ci-dessus) émet toujours un jeton qui vit 5 minutes, de façon fixe, quelle que soit la politique de l'organisation.- Le grant de jeton machine — celui qu'un pipeline CI utilise via
scrydon login --service-account(voir AI Gateway → Pour les pipelines) — accepte une durée de vie demandée et la plafonne à la plus courte des valeurs suivantes : ce que vous avez demandé, le maximum de votre organisation et un plafond strict fixé par l'opérateur de votre déploiement. Une demande au-delà de l'un ou l'autre maximum est plafonnée, pas refusée — vous obtenez la durée plus courte, pas une erreur.
Tant que votre organisation n'a pas défini sa propre politique, chaque compte fonctionne avec les valeurs par défaut de la plateforme : 1 heure pour une demande qui ne précise aucune durée de vie, 8 heures comme maximum qu'une demande peut atteindre. Un administrateur d'organisation définit le maximum, la valeur par défaut et la durée de vie du secret client propres à l'organisation depuis Paramètres → Gouvernance → Identifiants → Politique (voir Politique des identifiants ci-dessous) ; tant qu'il ne l'a pas fait, chaque organisation fonctionne avec ces valeurs par défaut. Le plafond strict du déploiement est fixé par la personne qui exploite votre installation et n'est pas du tout ajustable côté organisation.
Expiration du secret
Un secret client expire désormais. 180 jours par défaut à compter de sa création ou de sa rotation, jusqu'au maximum propre à votre organisation (également réglable depuis Paramètres → Gouvernance → Identifiants → Politique), qui ne peut lui-même jamais dépasser un plafond strict de 365 jours. La création et la rotation renvoient l'expiration exacte en même temps que le secret en clair — consignez-la à côté de l'endroit où vous stockez le secret, car elle n'est plus affichée ensuite.
Un secret expiré est refusé purement et simplement par les deux grants — aucun n'émettra de jeton avec lui. Effectuez la rotation avant qu'il n'expire.
Si le compte possède aussi un identifiant fédéré, l'authentification fédérée se poursuit indépendamment de l'expiration du secret client. Désactiver ou supprimer le compte empêche l'émission de nouveaux jetons par l'une ou l'autre méthode d'authentification.
Rotation, désactivation et suppression
- Effectuer une rotation du secret émet immédiatement un nouveau secret et invalide l'ancien — il n'y a pas de période de chevauchement. Coordonnez la rotation et mettez à jour chaque consommateur avec le nouveau secret renvoyé par cette opération. La rotation ne révoque pas les jetons d'accès déjà émis.
- Un compte de service créé avec une habilitation se connecte également pour les workflows qui s'exécutent en tant que lui, avec une copie du secret conservée par Scrydon. Sa rotation remplace aussi cette copie par le nouveau secret, de sorte que ces exécutions continuent de fonctionner ; mettez à jour tout autre élément qui utilise le compte, comme un pipeline CI/CD, avec le secret affiché. La création d'un tel compte n'affiche aucun secret ; effectuez donc une rotation une fois pour en obtenir un. Seul un administrateur dont la propre habilitation est égale ou supérieure à celle du compte peut en effectuer la rotation, car un jeton émis avec ce secret porte l'habilitation du compte. Un compte créé de cette manière possède un secret qui n'expire jamais, car personne ne le détient. Une fois la rotation effectuée, le secret a été remis à une personne et expire donc comme n'importe quel autre (voir Expiration du secret). Les workflows qui s'exécutent en tant que compte s'arrêtent à cette date ; effectuez donc une nouvelle rotation avant qu'elle n'arrive. Le créateur, ou les administrateurs de l'organisation, sont prévenus à l'avance. Chaque rotation est enregistrée dans le journal d'audit.
- Désactiver empêche l'émission de nouveaux jetons et rejette les jetons opaques existants dès leur requête authentifiée suivante. Le compte reste dans la liste. Cela n'annule pas le travail déjà admis.
- Supprimer retire définitivement le compte de service et ses identifiants, clés de routeur comprises. Tout consommateur qui utilise encore son ID client cesse de fonctionner ; les jetons d'accès opaques stockés du compte sont également supprimés. La suppression est irréversible — pour remplacer un compte supprimé, créez-en un nouveau. Vous pouvez supprimer un compte, qu'il soit actif ou déjà désactivé.
Clés de routeur
Certaines applications ne savent pas effectuer un échange de jeton. Elles demandent une seule fois une URL de base et une clé d'API, les stockent dans leurs paramètres et envoient la même clé à chaque appel — les paramètres d'IA de Twenty, Open WebUI, n8n, un plugin d'IDE. Une clé de routeur est cette clé. C'est un identifiant de longue durée pour l'AI Gateway qui agit au nom d'un compte de service ; les appels de l'application sont donc gouvernés, facturés et audités au nom de ce compte plutôt qu'à celui de la personne qui l'a configurée.
En émettre une
Ouvrez le compte, sélectionnez Ajouter une clé de routeur sous Authentification, nommez la clé d'après l'application qui la détiendra et choisissez sa durée de vie. Le compte doit d'abord remplir trois conditions :
- Il détient
capabilities:write. Une clé de routeur porte cette seule portée et rien d'autre, même lorsque le compte en détient davantage. Sans elle, la clé n'aurait rien à faire ; l'émission est donc refusée. - Il agit dans un seul environnement. Une clé ne peut pas désigner un environnement à chaque appel ; l'environnement propre du compte est donc celui de la clé. Un compte configuré pour agir dans tous les environnements est refusé avec un lien vers son onglet Accès ; limitez-le d'abord à un seul environnement à cet endroit.
- Votre habilitation est égale ou supérieure à celle du compte. Une clé transmet l'habilitation du compte à quiconque la détient, exactement comme un secret après rotation.
La clé n'est affichée qu'une seule fois. Copiez-la dans l'application avant de fermer le panneau ; celui-ci ne se
fermera pas tant que vous n'aurez pas confirmé l'avoir fait. Le panneau affiche aussi les deux URL de base que demande une application —
/api/router/v1 pour une application qui parle l'API OpenAI, /api/router pour une qui parle
l'API Anthropic — ainsi que les lignes dont un outil de développement a besoin. Consultez
Connecter une application qui n'accepte qu'une clé d'API.
Tester la clé vérifie que Scrydon accepte la clé et dans quel environnement elle agit. Il n'appelle aucun modèle : un test réussi ne montre donc pas qu'un modèle est activé pour cet environnement — envoyez une requête depuis l'application pour le vérifier.
Ce qui détermine si elle fonctionne
La clé est un pointeur vers le compte, pas une copie de ses accès. Chaque appel relit le compte ; une modification du compte atteint donc ses clés dès leur prochain appel — rien n'a à être révoqué à la main :
| Modification du compte | Effet sur ses clés de routeur |
|---|---|
| Désactivé ou supprimé | Refusées |
| Configuré pour agir dans tous les environnements | Refusées jusqu'à ce qu'il soit de nouveau limité à un seul |
capabilities:write retiré | Refusées |
| Déplacé vers un autre environnement | La clé agit dans le nouveau |
Une clé de routeur fonctionne uniquement sur l'AI Gateway (/api/router) et les opérations d'IA de la plateforme
(/api/platform/v1). Les autres API de Scrydon la refusent, tout comme les points de terminaison de clés d'API
personnelles : une clé de routeur se gère uniquement depuis le compte de service.
Durée de vie, rotation et révocation
Une clé de routeur expire toujours : 90 jours par défaut, jusqu'au maximum de votre organisation, qui ne peut jamais dépasser 365 jours. Ces deux valeurs se définissent dans la politique des identifiants.
- Effectuer une rotation de la clé émet une nouvelle clé et maintient la clé actuelle active pendant un chevauchement de votre choix, 1 jour ou 7 jours, pour que vous puissiez basculer l'application sans interruption. La clé actuelle s'arrête à la fin du chevauchement, ou à sa propre expiration si celle-ci survient avant. La nouvelle clé n'est affichée qu'une seule fois, avec l'heure à laquelle l'ancienne s'arrête.
- Révoquer la clé demande une confirmation, puis arrête la clé dès son prochain appel.
Si votre organisation désactive les clés de routeur, aucune nouvelle clé ne peut être émise ni faire l'objet d'une rotation. Les clés déjà émises continuent de fonctionner jusqu'à leur expiration ou leur révocation. L'émission, la rotation et la révocation sont chacune enregistrées dans le journal d'audit, avec leur auteur et le compte concerné. Une émission ou une rotation enregistre aussi l'environnement de la clé, son expiration et l'habilitation qu'elle porte. La clé elle-même n'est jamais enregistrée.
Registre des identifiants
Les administrateurs d'organisation peuvent voir à un seul endroit tous les identifiants d'API machine et personnels de l'organisation — pas seulement les comptes de service — sous Paramètres → Gouvernance → Identifiants, dans l'onglet Registre. Chaque ligne indique son propriétaire, sa portée, son statut (Actif, Expire bientôt ou Expiré) et sa dernière utilisation, couvrant à la fois la clé d'API de routeur propre à une personne et le secret client, les clés de routeur, les identifiants fédérés et les clés de pair d'un compte de service.
Filtrez par Tous, Personnes, Comptes de service ou Nécessite une attention (expire bientôt ou déjà expiré). Depuis cet écran, un administrateur peut révoquer la clé d'API d'une personne ou la clé de routeur d'un compte de service, ou effectuer une rotation du secret client d'un compte de service, y compris lorsqu'il n'en est pas lui-même propriétaire — les mêmes actions que celles décrites dans Rotation, désactivation et suppression ci-dessus, désormais accessibles pour tout identifiant appartenant à un membre actuel. Révoquez les clés personnelles avant de retirer le membre : une fois son adhésion retirée, ses clés personnelles n'apparaissent plus dans le registre de cette organisation. Les révocations par un administrateur sont enregistrées dans le journal d'audit.
Supprimer sur un identifiant fédéré empêche les futurs échanges avec cette liaison émetteur/sujet ; cela ne révoque pas les jetons déjà émis pour le compte. Supprimer un émetteur de confiance supprime tous les identifiants fédérés qui lui sont rattachés. Désactivez le compte de service pour couper également ses jetons opaques existants. Supprimer sur une clé de pair supprime ce compte de pair dédié et ses identifiants.
Politique des identifiants
L'onglet Politique de la même page Paramètres → Gouvernance → Identifiants est l'endroit où un administrateur d'organisation définit :
- la durée de vie la plus longue qu'une demande de jeton machine (
--ttl) peut demander, - ce qu'obtient par défaut une demande qui ne précise aucune durée de vie, et
- la durée pendant laquelle un secret client reste valide avant de devoir faire l'objet d'une rotation, jusqu'au plafond strict de 365 jours (voir Expiration du secret ci-dessus),
- si un administrateur peut émettre une clé de routeur pour un compte de service — activé par défaut, et
- la durée de vie par défaut et maximale d'une clé de routeur, en jours, jusqu'à un plafond strict de 365 jours. Ces valeurs s'appliquent à la clé de routeur propre à une personne comme à celle d'un compte de service.
La page affiche également le plafond strict du déploiement, en lecture seule — seul votre opérateur peut modifier cette valeur, depuis le chart Helm qui déploie votre installation. La durée de vie de jeton affichée est la plus basse entre le maximum de l'organisation et ce plafond du déploiement. Vous pouvez modifier ensemble le maximum et la valeur par défaut de l'organisation, puis les enregistrer en une seule opération.
Une modification ici est plafonnée, pas rétroactive : un jeton ou un secret déjà émis conserve la durée de vie avec laquelle il a été émis. Seul le prochain émis voit la nouvelle limite. Abaisser le maximum ne raccourcit rien de ce qui est déjà en circulation. Pour couper les jetons opaques existants d'un compte de service, désactivez le compte ; pour une clé d'API personnelle, révoquez la clé depuis le registre.
Avertissements d'expiration
Six jours avant l'expiration d'un identifiant, son propriétaire est prévenu — dans l'application et, sauf si vous avez désactivé cette option, par e-mail (le même interrupteur M'envoyer un e-mail pour les nouvelles notifications décrit dans Notifications). Pour la clé d'API propre à une personne, il s'agit de la personne qui l'a créée. Pour le secret client ou la clé de routeur d'un compte de service, l'avertissement va à la personne qui a créé le compte de service — ou, si aucun créateur n'est enregistré, si son utilisateur a été supprimé ou s'il a quitté l'organisation, aux administrateurs de l'organisation.
Vous recevez un seul avertissement par identifiant, et non un avertissement répété tant qu'il reste dans la fenêtre d'avertissement : la rotation d'un secret modifie sa date d'expiration, ce qui fait redémarrer la fenêtre pour la nouvelle date.
Accès aux espaces de travail
Un compte de service est créé au niveau de l'organisation, puis affecté à un espace de travail pour appeler
les API de cet espace de travail — de la même manière qu'un membre ou une équipe est ajouté à un espace de travail. Un administrateur
d'organisation ou d'espace de travail ouvre Paramètres → Espace de travail → Membres → Ajouter des membres ou des groupes et recherche
le compte de service par son nom (il apparaît dans le même sélecteur que les utilisateurs et les équipes), puis lui attribue un rôle
(member ou admin).
L'accès à un point de terminaison d'un espace de travail requiert alors les deux :
- un rôle dans l'espace de travail — le compte doit être affecté à l'espace de travail avec un rôle satisfaisant le point de terminaison
(la lecture/l'écriture nécessitent
member; les actions d'administration nécessitentadmin) ; et - une portée de capacité — le jeton doit porter le
resource:actioncorrespondant (par ex.workflows:write).
La vérification du jeton authentifie le compte de service ; elle n'accorde pas l'opération à elle seule.
Le point de terminaison protégé vérifie les deux exigences dans une seule décision d'autorisation. Si l'autorisation
ne peut pas être évaluée, le point de terminaison renvoie 503 AUTHZ_UNAVAILABLE au lieu de se rabattre sur une
vérification fondée uniquement sur la portée ou uniquement sur le rôle.
Le jeton reste limité à l'organisation. Ciblez un environnement d'espace de travail par requête avec
?environmentId= :
curl "https://<your-host>/api/v1/workflows?environmentId=<environment-id>" \
-H "authorization: Bearer $ACCESS_TOKEN"Un compte qui possède la portée mais aucune affectation à l'espace de travail est rejeté avec 403.
La lecture des journaux d'exécution nécessite la portée logs:read. GET /api/v1/logs renvoie au plus 100 journaux par requête. Passez le nextCursor d'une réponse en tant que ?cursor= pour lire la page suivante. Un limit qui n'est pas un nombre entier compris entre 1 et 100 est rejeté avec 400. Un journal d'appel de webhook n'inclut pas l'adresse ni le client (User-Agent) de l'appelant. Ces informations n'apparaissent que dans Monitor.
Un workflow, un journal ou une exécution qui n'existe pas, et un élément que le jeton n'est pas autorisé à lire, renvoient tous deux 404 avec le même corps, {"error": "Not found", "code": "WORKSPACE_FORBIDDEN"}. La réponse ne révèle pas si l'ID existe.
curl "https://<your-host>/api/v1/logs?environmentId=<environment-id>&limit=100" \
-H "authorization: Bearer $ACCESS_TOKEN"Exécuter une projection de source de données
Une projection de tables stockées ne se rafraîchit que sous le compte de service qu'un administrateur sélectionne pour elle. Sélectionnez-le sous Paramètres → Membres → Comptes de service → Compte d'exécution des projections, par environnement et par source de projection. La liste propose les comptes actifs autorisés à agir dans cet environnement et disposant d'un accès en écriture à Tables. Tant qu'aucun compte n'est sélectionné, les rafraîchissements de la projection échouent et sa table n'est pas publiée. Sélectionner un compte n'accorde aucun accès aux tables : le compte doit toujours être autorisé à écrire la table de sortie et à lire, sans masquage, chaque colonne d'entrée que la projection mappe.
Voir ce qu'un compte a dépensé
Les appels d'un compte de service via l'AI Gateway apparaissent dans Paramètres → Gouvernance → Cost Insights → Utilisation, avec la source définie sur AI Gateway. La dimension de ventilation y est Principal, et non Développeur — un compte de service n'est ni un développeur ni une équipe, et ce tableau doit désormais répondre pour les deux.
Quelques conséquences en découlent directement :
teamIdreste nul. Les dépenses d'un compte de service appartiennent à l'organisation, pas à une équipe — il n'y a aucune personne derrière l'appel à qui imputer le budget d'une équipe.- L'attribution à un espace de travail provient de la cible de la requête. Un appel au routeur au niveau de l'organisation utilise le slug d'environnement enregistré et n'a aucun espace de travail par lequel regrouper ses dépenses. Un appel ciblant un environnement d'espace de travail autorisé est attribué à cet espace de travail.
- Une exécution Run As n'est pas affectée. Les exécutions à identité déléguée d'Agentic sont elles aussi des appels machine en coulisses, mais leurs dépenses continuent d'être facturées à la personne propriétaire de l'exécution — cette fonctionnalité est une colonne supplémentaire, pas un changement de l'attribution déjà faite par un graphique.
- Le compte apparaît sous le nom que vous lui avez donné, de la même manière que la ligne d'une personne affiche son nom. Les appels effectués avec l'une de ses clés de routeur sont comptés pour ce compte.
Les lignes écrites avant la mise en service de cette fonctionnalité ne portent aucun principal — ces données n'ont jamais été capturées et ne peuvent donc pas être reconstituées — et s'affichent comme une ligne explicite Non attribué plutôt que d'être silencieusement retirées du total.
CI sans secret avec la fédération OIDC
Un pipeline peut échanger l'assertion OIDC de son fournisseur CI contre un bearer Scrydon de courte durée. Le pipeline n'a besoin d'aucun secret client Scrydon stocké. Les portées, l'environnement, la politique et l'attribution des dépenses du compte restent les mêmes, quel que soit l'identifiant qui l'authentifie.
Le fournisseur doit émettre une assertion signée en RS256 avec un jti unique et une expiration d'au plus
cinq minutes dans le futur. Cette durée de vie de l'assertion est distincte de la durée de vie du bearer
Scrydon que vous demandez. Configurez votre fournisseur en conséquence avant de rattacher l'identifiant.
Enregistrer la confiance et rattacher le pipeline
- En tant qu'administrateur d'organisation, ouvrez Paramètres → Gouvernance → Émetteurs de confiance. Enregistrez
l'URL exacte de l'émetteur du fournisseur et son URL JWKS en HTTPS. Pour GitHub Actions, il s'agit de
https://token.actions.githubusercontent.comethttps://token.actions.githubusercontent.com/.well-known/jwks. Si le déploiement restreint les émetteurs, les deux origines d'URL doivent être autorisées ; la page affiche le motif de refus du serveur. - Créez un compte de service avec
capabilities:write, choisissez Tous les espaces de travail ou Espaces de travail sélectionnés, et sélectionnez son environnement. Rattachez un identifiant fédéré via le client d'administration authentifié ci-dessous. Il n'existe actuellement aucun formulaire de rattachement dans le panneau du compte.trustedIssuerIdest l'ID d'enregistrement renvoyé parclient.serviceAccount.trustedIssuer.createou.list; list acceptelimit/offsetet renvoietrustedIssuersavectotalCountpour la pagination. - Ouvrez le panneau de détail du compte et copiez l'ID client fédéré. Il diffère de l'ID client utilisé avec le secret ; la demande de jeton doit utiliser cet ID fédéré. Les jetons émis et les dépenses appartiennent toujours au compte d'origine.
En utilisant le client d'authentification configuré de votre application dans une session d'administrateur d'organisation :
const { data, error } = await client.serviceAccount.federatedCredential.create({
organizationId,
clientId: serviceAccountClientId,
trustedIssuerId,
subject: "repo:YOUR-ORG/YOUR-REPO:environment:production",
displayName: "Production CI",
});
if (error) throw new Error(error.message);Utilisez le sub exact émis par votre fournisseur ; l'exemple utilise le format fondé sur le nom de GitHub.
GitHub prend aussi en charge des sujets immuables contenant les ID du propriétaire/dépôt ainsi que des sujets personnalisés.
Faites correspondre la configuration réelle de votre dépôt. Les jokers, les alternatives et les sujets :pull_request
sont refusés. Pour une confiance fondée sur les branches, main et une étiquette de version nécessitent deux lignes :
repo:YOUR-ORG/YOUR-REPO:ref:refs/heads/main et
repo:YOUR-ORG/YOUR-REPO:ref:refs/tags/v1.0.0 ; chaque étiquette supplémentaire nécessite sa propre ligne exacte.
Consultez la référence de GitHub sur le sujet et l'audience OIDC.
Privilégiez un GitHub Environment avec des réviseurs obligatoires et des restrictions de déploiement configurés, lorsque votre offre prend en charge ces protections, ou un environnement GitLab protégé de manière similaire. Un nom d'environnement à lui seul n'impose pas d'approbation humaine ; configurez les protections du fournisseur avant de lui accorder l'accès. Scrydon fait correspondre le sujet signé et ne vérifie pas indépendamment qui a approuvé le job. Consultez les paramètres de protection des environnements GitHub.
Échange dans GitHub Actions
Définissez les variables de dépôt SCRYDON_PLATFORM_URL (par exemple https://auth.your-company.com,
sans barre oblique finale) et SCRYDON_FEDERATED_CLIENT_ID. Ce sont des identifiants, pas des secrets.
L'environnement du job doit correspondre au sujet enregistré. Demandez l'URL complète du point de terminaison de jeton
comme audience OIDC : https://auth.your-company.com/api/auth/oauth2/token. L'audience par défaut de GitHub
ne fonctionnera pas.
Ce job demande un bearer pour une heure, sous réserve des plafonds de votre organisation et de votre déploiement,
puis effectue une requête authentifiée de liste des modèles auprès de l'AI Gateway. Il nécessite curl et jq.
name: AI Gateway CI
on: workflow_dispatch
permissions:
id-token: write
jobs:
gateway:
runs-on: ubuntu-latest
environment: production
env:
SCRYDON_PLATFORM_URL: ${{ vars.SCRYDON_PLATFORM_URL }}
SCRYDON_FEDERATED_CLIENT_ID: ${{ vars.SCRYDON_FEDERATED_CLIENT_ID }}
steps:
- name: Exchange workload identity and use AI Gateway
shell: bash
run: |
set -euo pipefail
TOKEN_ENDPOINT="$SCRYDON_PLATFORM_URL/api/auth/oauth2/token"
ASSERTION="$(curl --fail --silent --show-error --get \
-H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" \
--data-urlencode "audience=$TOKEN_ENDPOINT" \
"$ACTIONS_ID_TOKEN_REQUEST_URL" | jq -er '.value')"
echo "::add-mask::$ASSERTION"
TOKEN="$(curl --fail --silent --show-error "$TOKEN_ENDPOINT" \
--data-urlencode "client_id=$SCRYDON_FEDERATED_CLIENT_ID" \
--data-urlencode "grant_type=urn:scrydon:params:oauth:grant-type:machine-token" \
--data-urlencode "client_assertion_type=urn:scrydon:params:oauth:client-assertion-type:federated-workload-jwt" \
--data-urlencode "client_assertion=$ASSERTION" \
--data-urlencode "scope=capabilities:write" \
--data-urlencode "ttl_seconds=3600" | jq -er '.access_token')"
echo "::add-mask::$TOKEN"
unset ASSERTION
export ANTHROPIC_BASE_URL="$SCRYDON_PLATFORM_URL/api/router"
export OPENAI_BASE_URL="$SCRYDON_PLATFORM_URL/api/router/v1"
export ANTHROPIC_API_KEY="$TOKEN" OPENAI_API_KEY="$TOKEN"
curl --fail --silent --show-error "$OPENAI_BASE_URL/models" \
-H "Authorization: Bearer $OPENAI_API_KEY"
# Run your coding tool here, in this same step.Utilisez le grant de jeton machine, et non client_credentials : le client fédéré n'est enregistré
que pour ce grant. Chaque assertion est à usage unique ; obtenez une nouvelle assertion pour un autre échange.
La connexion --service-account-secret de la CLI est destinée à l'authentification par secret et n'accepte pas
d'assertion OIDC. L'échange direct ci-dessus ne nécessite aucun fichier d'identifiants de la CLI.
Le bearer de courte durée existe toujours dans l'environnement du processus de l'outil. Tenez-le à l'écart des journaux,
des artefacts et des caches ; demandez une durée de vie qui couvre le job et effectuez un nouvel échange pour chaque nouveau job.
Les variables ci-dessus n'existent que dans cette étape. Si votre outil s'exécute dans une étape ultérieure, transmettez explicitement le
bearer masqué via le mécanisme de votre fournisseur CI, comme $GITHUB_ENV.
Faire confiance à un autre pair Scrydon
Une relation entre pairs utilise un compte de service dédié authentifié avec private_key_jwt
natif. Le pair émetteur génère et conserve une nouvelle paire de clés RSA pour chaque relation
de réception, à l'aide d'une bibliothèque standard ou d'un service de gestion de clés. Utilisez RS256 avec une clé RSA d'au moins
2048 bits. Conservez la clé privée dans le magasin de clés protégé de l'émetteur ; n'envoyez que le JWK public
au destinataire. Ne réutilisez jamais la clé de signature /api/auth/jwks de l'une ou l'autre installation.
L'administrateur de l'organisation destinataire enregistre la clé publique via son client authentifié :
const { data, error } = await client.serviceAccount.peer.create({
organizationId,
name: "Build tenant",
scopes: ["capabilities:write"],
environmentId,
peerIssuer: "https://sender.example.com",
jwks: { keys: [publicJwk] },
});
if (error) throw new Error(error.message);
const peerClientId = data.peer.clientId;publicJwk doit contenir exactement kty: "RSA", kid, alg: "RS256", use: "sig", n et
e. Enregistrez une seule clé ; les champs de clé privée et les URL de clé distantes sont refusés. La liste
d'émetteurs autorisés du déploiement destinataire s'applique également à peerIssuer.
Renvoyez peerClientId à l'émetteur. Pour chaque échange, l'émetteur signe une assertion à l'aide de sa
clé privée stockée. Par exemple, avec SignJWT de jose :
import { SignJWT } from "jose";
const assertion = await new SignJWT({})
.setProtectedHeader({ alg: "RS256", kid: publicJwk.kid })
.setIssuer(peerClientId)
.setSubject(peerClientId)
.setAudience("https://receiver.example.com/api/auth/oauth2/token")
.setIssuedAt()
.setExpirationTime("2m")
.setJti(crypto.randomUUID())
.sign(privateKey);Envoyez l'assertion par POST au point de terminaison de jeton de ce destinataire avec les champs de formulaire client_id=peerClientId,
grant_type=urn:scrydon:params:oauth:grant-type:machine-token,
client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer,
client_assertion=assertion, scope=capabilities:write et la valeur ttl_seconds que vous demandez.
iss et sub sont tous deux l'ID client émis par le destinataire, et non l'URL de l'émetteur.
Le fournisseur natif vérifie la clé publique intégrée enregistrée sans récupérer le JWKS de l'émetteur.
Supprimez la clé de pair depuis le registre des identifiants, ou appelez
client.serviceAccount.peer.delete({ organizationId, clientId: peerClientId }), pour supprimer la
relation. Les autres pairs et la clé de signature de la plateforme ne sont pas affectés. Pour remplacer une clé, enregistrez
une nouvelle relation, basculez l'émetteur vers son nouvel ID client/sa nouvelle clé, puis supprimez l'ancienne relation.
Remarques
- Un compte de service n'a pas d'utilisateur. Les jetons ne portent que l'ID de l'organisation et les portées accordées — pas une identité d'utilisateur.
- Le grant
client_credentialsest réservé aux comptes de service. Les autres clients OAuth (par exemple les Mini Apps interactives) ne peuvent pas l'utiliser. Le grant de jeton machine derrièrescrydon login --service-accountest soumis à la même restriction, vérifiée indépendamment.