Aller au contenu principal

Plan de données

Ce document décrit comment le plan de données STOA traite une requête. STOA est une plateforme souveraine d'API et d'intégration (iPaaS) dotée d'un module MCP ; l'ADR-073 décide que le plan de données utilise Envoy amont, configuré uniquement par xDS par STOA Link, la logique STOA s'exécutant dans des services externes appelés par Envoy. L'ADR-073 laisse ouverts le périmètre détaillé de l'iPaaS et plusieurs détails d'implémentation.

Deux niveaux sont distingués tout au long du document :

  • Décidé — ce que l'ADR-073 et l'ADR-070 fixent comme cible.
  • Dans le dépôt — ce que contient le dépôt public stoa à une révision épinglée ; chaque lien vers le code ci-dessous pointe vers cette révision.

Aucun chiffre de performance ne figure ici. L'ADR-073 indique que toute affirmation de performance sur le plan de données Envoy viendra d'un benchmark exécuté selon la méthodologie de l'ADR-049 ; les mesures réalisées sur l'ancienne passerelle maison ne sont pas reprises.

Composants​

ComposantRôleDécidé (ADR-073)Dans le dépôt
EnvoyÉcoute, route, répartit la charge, termine TLS, exécute les filtres natifsVersion amont non modifiée, aucune extension chargée (ni Wasm, ni Lua, ni module dynamique), configurée uniquement par xDS (§1, §2)Une image amont épinglée est exercée par le harnais d'acceptation hors ligne
STOA Link (stoa-connect)Agent sur site : connexion SSE sortante vers le plan de contrôle, serveur xDS local, remontée SYNCED / FAILED§2, §7Mode Envoy, constructeur d'instantanés xDS, serveur ADS
Service d'autorisationAppelé par le filtre ext_authz d'Envoy avant le routageClés d'API, abonnements, isolation des tenants, politiques OPA, quotas consommateur, liaison du jeton quand Envoy ne la contrôle pas (§4, §5, §10)Adaptateur gRPC envoy.service.auth.v3 placé devant la logique de politiques existante : ExtAuthzService
Service de traitementAppelé par ext_proc pour les fonctions qui ont besoin du corps des requêtes ou des réponses (garde-fous, budgets de jetons, compression, transformation)§4Absent de l'instantané de référence
Module MCPService amont derrière Envoy : protocole MCP, registre d'outils, autorisation par outil§4, §10 ; permissions d'outils refusées par défaut selon l'ADR-070Vérification de l'artefact de politique signé : policy_artifact.rs, tool_permissions.rs
Collecteur de comptage d'usageService de journaux d'accès produisant les événements d'usage vers Kafka§4, transport à confirmerAbsent de l'instantané de référence

Community et Enterprise utilisent la même version d'Envoy ; elles ne diffèrent que par la configuration générée et par les services STOA déployés (ADR-073 §6).

Livraison de la configuration​

Envoy reçoit sa configuration uniquement par xDS, servie sur le site client par STOA Link. Le chemin de déploiement est le chemin unique de l'ADR-059, et le plan de contrôle n'ouvre jamais de connexion vers le site (ADR-073 §2) :

Console → API du plan de contrôle → SSE → STOA Link → xDS → Envoy
↓
rappel SYNCED / FAILED → API du plan de contrôle

Dans le dépôt, le mode Envoy de stoa-connect doit être sélectionné explicitement au moyen de STOA_GATEWAY_TYPE ; la détection automatique ne le choisit jamais. L'écouteur ADS du Link n'écoute que sur une adresse de bouclage, exige du TLS mutuel (TLS 1.3 au minimum) et identifie le client Envoy par l'unique SAN de type URI de sa chaîne de certificats vérifiée ; l'identifiant de nœud déclaré dans les requêtes de découverte n'est jamais une donnée d'authentification. Chaque publication est un instantané complet (state-of-the-world) des clusters, de l'écouteur et des routes, versionné par un condensat de son contenu. Le Link attend les acquittements CDS, LDS et RDS ; un NACK ou un délai dépassé est une erreur de déploiement, et les dernières routes et politiques acquittées sont conservées (constructeur d'instantanés, serveur ADS). Les routes et les politiques arrivent par le point d'accès de configuration des passerelles du plan de contrôle et par les événements SSE. L'adaptateur Envoy refuse les générations périmées et toute perte de route sans marqueur de suppression explicite (tombstone), et réconcilie atomiquement l'ensemble complet des politiques applicables : un inventaire rejeté n'est jamais appliqué partiellement (inventaire du plan de contrôle).

Décidé mais absent du dépôt à cette révision : la traduction UAC → xDS dans un composant dédié du plan de contrôle (§2), le JWKS diffusé par xDS (§10) et le contenu de l'amorçage de chaque instance Envoy (§2, à confirmer). Aujourd'hui, le Link construit l'instantané à partir de l'inventaire de routes et de politiques qu'il reçoit.

Chaîne de traitement d'une requête​

Le diagramme représente l’implémentation de référence à la révision épinglée, pas la cible décidée.

L'instantané de référence installe cette chaîne de filtres HTTP sur l'écouteur : ext_authz d'abord, puis cors, local_ratelimit et rbac dès qu'une route porte une politique, puis le routeur. Le filtre d'autorisation externe refuse les requêtes en cas de défaillance du service d’autorisation et utilise un service gRPC sur un cluster HTTP/2 dédié, et chaque route transmet tenant_id et api_id au service d'autorisation en tant qu'extensions de contexte. L'autorisation s'exécute donc avant CORS et peut refuser une requête de pré-vérification (preflight) sans contacter l'amont (mode Envoy).

Validation des jetons​

  • Décidé. Le filtre jwt_authn d'Envoy valide les signatures et les revendications standard contre le JWKS de Keycloak, diffusé localement par xDS (ADR-073 §5, §10). Reste à vérifier si ce filtre contrôle les jetons liés à un certificat (RFC 8705) et les preuves DPoP (RFC 9449) ; sinon, le service d'autorisation effectue ce contrôle en conservant le contrat d'erreurs de l'ADR-039.
  • Dans le dépôt. L'instantané de référence ne contient pas de filtre jwt_authn ; le service d'autorisation valide lui-même le jeton. Il exige une audience configurée (sinon toute requête est refusée et la passerelle se déclare non prête), valide le jeton Bearer contre le JWKS du fournisseur OIDC avec un délai borné, exige une revendication de tenant égale au tenant_id de la route et exige chaque scope configuré (revendications scope et scp). Un jeton absent donne 401 avec WWW-Authenticate: Bearer ; un jeton invalide 401 ; un tenant ou un scope non conforme 403. En production, lorsque l’écouteur d’autorisation externe est activé, la passerelle refuse de démarrer si l’audience manque ou si la liste de scopes est vide ou contient une entrée blanche.

Autorisation et propagation de l'identité​

Le service d'autorisation normalise les en-têtes (minuscules, pas de doublon, pas de CRLF), puis retire de l'entrée de décision tout en-tête d'identité entrant (x-stoa-*, x-user-*, x-tenant-id, …) ainsi que les en-têtes authorization, cookie et proxy-authorization : un client ne peut pas forger une identité à destination de l'amont. Le moteur de décision partagé évalue politiques et quotas sur une entrée indépendante de la passerelle. En cas d'autorisation, Envoy ajoute x-stoa-tenant-id et x-stoa-api-id à la requête amont et retire les en-têtes d'identité entrants. Chaque décision est journalisée comme événement ext_authz_decision avec un ensemble fermé de motifs de refus, jamais le jeton ni une revendication (ExtAuthzService).

Limitation de débit et quotas​

  • Décidé. Il n'y a pas de service de limitation de débit séparé. Les quotas consommateur sont contrôlés par le service d'autorisation : quotas facturés et budgets MCP par une mise à jour atomique dans PostgreSQL en échec fermé, quotas non facturés par des compteurs écrits par lots avec un mode dégradé borné. Le filtre local_ratelimit d'Envoy ne sert qu'à la protection grossière (ADR-073 §4, §10).
  • Dans le dépôt. Une politique rate_limit (maxRequests, intervalSeconds) devient un seau à jetons local par route et par processus Envoy ; ce n'est ni un quota distribué ni une fenêtre fixe (traduction des politiques). Les décisions de quota consommateur du service d'autorisation portent un en-tête Retry-After calculé à partir de la réinitialisation de la fenêtre (ExtAuthzService).

Politiques​

Les politiques sont générées à partir des objets du plan de contrôle et ne sont jamais modifiées à la main sur Envoy (ADR-073 §3). Le traducteur v1 du dépôt prend en charge trois types ; tout le reste est refusé explicitement plutôt qu'ignoré (mode Envoy, traduction des politiques) :

PolitiqueFiltre EnvoyComportement
corsenvoy.filters.http.corsLes six clés du contrat, par route ; OPTIONS est accepté sur les routes à méthodes restreintes pour la pré-vérification
rate_limitenvoy.filters.http.local_ratelimitSeau à jetons par route et par processus Envoy
ip_filterenvoy.filters.http.rbacAutorisation ou refus sur l'adresse du pair direct (CIDR ou adresse seule) ; les en-têtes d'adresse transmise ne sont pas pris en compte
jwt_validation, logging, caching, transform, OIDC—Non pris en charge : l'inventaire est rejeté et rien n'est publié

Les portées gateway et tenant s'étendent aux routes correspondantes ; la portée api cible des identifiants exacts du catalogue. Deux règles du même type sur une route sont rejetées plutôt que fusionnées ou ordonnées par priorité. Le plan de contrôle attribue à chaque politique scope, cibles, tenant_id et applicable, et une liaison d'API vide n'est jamais élargie à la portée passerelle (inventaire).

Routage​

Chaque route activée devient une correspondance de préfixe sur son chemin (path_prefix, ou /apis/{api_id} par défaut) avec une entrée par méthode autorisée, et un cluster amont par route résolu par adresse statique ou par DNS strict. Un backend https reçoit un contexte TLS amont avec le SNI positionné sur l'hôte et le magasin d'autorités du système comme ancre de confiance (constructeur d'instantanés). Les positions edge-mcp, proxy, sidecar et shadow de l'ADR-024 deviennent des profils de configuration générés par STOA plus l'ensemble des services STOA déployés (ADR-073 §8) ; dans le dépôt, le serveur ADS sert un seul nœud vérifié.

Comportement en cas de panne​

SituationDécidéDans le dépôt
Service d'autorisation injoignable ou délai dépasséEnvoy refuse avec HTTP 503, corps neutre identique au 403, Retry-After borné, aucune relance automatique des méthodes non idempotentes ni des appels MCP tools/call (ADR-073 §10)Les requêtes sont refusées en cas de défaillance de l’autorisation, avec un délai borné fixé par le Link ; le harnais vérifie qu'un échec gRPC ou un délai dépassé renvoie 403 sans atteindre l'amont (constructeur d'instantanés, harnais)
Envoy rejette une configuration (NACK)Le Link remonte FAILED ; la détection de dérive s'appuie sur la version acquittée (§2)Erreur de déploiement ; les dernières routes et politiques acquittées sont conservées (adaptateur)
Plan de contrôle injoignableLes permissions d'outils sont refusées par défaut : autorisation uniquement selon un artefact de politique signé et de courte durée, jusqu'à son expiration, jamais prolongé localement ; une révocation prime sur le cache ; la disponibilité (readiness) reflète l'état réel de l'application des politiques (ADR-070)Vérification d'un artefact JWS compact avec des clés Ed25519 épinglées (policy_artifact.rs) ; rien n'est autorisé après le démarrage tant qu'une politique fraîche n'est pas chargée (tool_permissions.rs)
Audience absente hors production, écouteur d’autorisation externe activé—Requêtes refusées, /ready renvoie 503, la santé gRPC se déclare hors service (disponibilité, démarrage)
Liste de scopes vide hors production, audience valide—Le démarrage émet un avertissement ; les contrôles de scopes sont ignorés et les requêtes peuvent être autorisées. La santé gRPC se déclare en service ; la disponibilité HTTP dépend toujours de ses autres contrôles (validation de configuration, moteur de décision, disponibilité, démarrage)
Audience absente ou liste de scopes vide ou contenant une entrée blanche en production, écouteur d’autorisation externe activé—La validation de configuration refuse le démarrage ; aucun serveur démarré ne produit de réponse (validation de configuration)
JWKS injoignable au démarrage—Le démarrage émet un avertissement et les requêtes restent en échec fermé (démarrage)

L'écouteur gRPC ext_authz du service d'autorisation n'a pas de TLS propre : le code de démarrage avertit lorsqu'il est lié à une adresse autre que de bouclage et suppose un réseau privé de confiance (démarrage).

Vérification dans le dépôt​

Le harnais d'acceptation hors ligne exécute le routeur de déploiement du plan de contrôle, l'agent Go et ses adaptateurs, le serveur ADS en TLS mutuel, un processus Envoy réel issu d'une image épinglée et un témoin gRPC Check indépendant, sans accès réseau externe ; les connexions locales et le pont Docker sont utilisés. Il vérifie, entre autres, que le nombre de routes ne diminue jamais pendant une publication, que seuls des marqueurs de suppression explicites retirent des routes, que la publication d'une passerelle étrangère laisse l'instantané inchangé, que l'ancien instantané continue de servir pendant une coupure SSE, que les comportements CORS, seau à jetons et filtrage d'adresses sont observés sur de vraies réponses, que Check précède le routage et qu'une pré-vérification CORS ne peut pas contourner un refus. Un workflow CI manuel (o1-envoy-real-proof.yml) exécute le même harnais à la demande. Le harnais valide le contrat d'intégration, pas l'autorisation métier STOA ; ses relevés de temps sont des délais de test, pas des affirmations de performance.

Notes de périmètre​

  • La passerelle Rust maison n'est plus le plan de données stratégique et entre en maintenance (ADR-073 §9) ; sa logique de politiques est réutilisée derrière l'adaptateur ext_authz décrit ci-dessus.
  • Les passerelles tierces raccordées par des adaptateurs (ADR-035) n'appellent pas directement le service d'autorisation STOA pour l'instant (ADR-073 §8).