# Ce que le moteur lit, et comment le façonner.

> Ce que le moteur lit — OpenAPI 3.0 à 3.2, Swagger 2.0, webhooks — et comment le façonner : Overlay 1.1, correctif côté lecteur, masquage, changelog local.
>
> Source: https://apiglow.dev/fr/docs/schema-support/index.md


Le support OpenAPI maximal est une obligation affichée du projet : une construction non supportée d'une version supportée est traitée comme un défaut, pas comme une limite.

Ce guide dit ce qui est lu, et documente les quatre leviers qui façonnent le document rendu — les overlays déclarés par l'hôte, ceux écrits par le lecteur, le masquage, et le changelog local. La [page Le schéma](/fr/features/schema/) est la version courte.

## Versions et formats

- **OpenAPI 3.0.x, 3.1.x et 3.2.x** sont rendus nativement, y compris la méthode `query` de 3.2, les paramètres `in: querystring` et `$self`. JSON ou YAML.
- **Les mots-clés JSON Schema 2020-12** sont rendus, dans les vues de schéma comme dans les exemples générés.
- **Webhooks et callbacks** sont normalisés et rendus comme des opérations — voir plus bas.
- **Les sections de tags 3.2 sont rendues en entier.** Le `summary` d'un tag titre sa section de nav, `parent` l'imbrique (un parent immédiatement suivi de ses enfants, pastilles de comptage et points de changement couvrant les sous-groupes), et `kind` décide ce qu'un tag *est* : `nav` ou absent fait une section, et toute autre valeur — `badge`, `audience`, ou la vôtre — devient un badge sur les opérations qui le portent. Les deux formes que la spec interdit se détachent toutes deux vers la racine plutôt que de planter : un parent inconnu, et un cycle de parents.
- **Les `links` de réponses et `externalDocs`** sont rendus aussi. Un Link Object reçoit une navigation « aller à l'opération », ses expressions runtime affichées comme documentation plutôt qu'évaluées. `externalDocs` se rend aux niveaux racine, tag, opération et schéma.
- **Les références circulaires** sont gérées partout. Les nœuds cycliques sont marqués dans le modèle, et le rendu déplie paresseusement avec un budget de trois niveaux, puis un « déplier » explicite. Il n'y a aucune récursion sans borne, ni dans la doc ni dans les exemples générés. Une récursion qu'aucune valeur finie ne peut satisfaire fait partie de ce que l'[audit](/fr/docs/audit/) signale.
- **Les valeurs d'enum portent leur sens.** Quand un schéma décrit chaque valeur — avec `x-enum-descriptions` (une liste à côté d'`enum`), `x-enumDescriptions` (une table de la valeur vers son texte), ou sous forme de `oneOf` de constantes portant chacune sa `description` — la documentation liste chaque valeur avec ce qu'elle signifie. Un `oneOf` de constantes se lit comme l'enum qu'il est : une liste déroulante dans la console d'essai, pas un choix entre variantes.
- **Les URL relatives se résolvent par rapport au schéma**, comme le dit OpenAPI 3.1, et non par rapport à la page de documentation : un serveur posé sur un chemin ou une opération (`/v2`), les URL OAuth et OpenID Connect, les exemples externes, `externalDocs`, les liens de licence et de contact. La base est le `$self` du schéma, à défaut l'URL d'où il a été lu.
- **Une `description` ou un `summary` à côté d'un `$ref`** s'affiche, comme le dit OpenAPI 3.1.
- **Un schéma abîmé s'ouvre aussi loin que possible.** Un `$ref` qui ne mène nulle part n'arrête plus la documentation : le reste s'affiche, et l'[audit](/fr/docs/audit/) nomme la référence cassée. Un fichier avec une erreur de syntaxe s'ouvre si on peut la dépasser, et celui qu'on ne peut pas exploiter dit ce qui ne va pas, à sa ligne et sa colonne. Le lecteur tolérant qui fait ce travail, `read-document.js`, ne se charge que pour un tel schéma.

## Swagger 2.0, converti au chargement

Un document déclarant `swagger: "2.0"` est converti en OpenAPI 3.0.4 avant que quoi que ce soit d'autre le lise, donc rien en aval ne sait que 2.0 existe. `host`, `basePath` et `schemes` deviennent des `servers` ; les paramètres `in: body` et `in: formData` deviennent des request bodies ; les `definitions` déménagent dans `components` avec chaque `$ref` réécrit ; les définitions de sécurité et les noms de flows prennent leur forme 3.x.

La conversion a des limites, et elle les rapporte. Les quelques valeurs de `collectionFormat` que 3.0 ne sait pas exprimer retombent sur la virgule, l'original est consigné dans le document, et l'[audit](/fr/docs/audit/) rapporte chaque approximation. Le panneau de diagnostics des réglages indique qu'une conversion a eu lieu.

## Overlays : corriger un schéma qui n'est pas à vous

`openapi.overlays` déclare des documents [OpenAPI Overlay 1.1](https://spec.openapis.org/overlay/v1.1.0.html) appliqués au chargement. Chaque entrée est une URL — JSON ou YAML — ou l'objet overlay lui-même, porté par la config :

```json {title="api-doc-config"}
{
  "openapi": {
    "url": "https://vendor.example.com/openapi.json",
    "overlays": [
      {
        "overlay": "1.1.0",
        "info": { "title": "Docs fixes", "version": "1" },
        "actions": [
          { "target": "$.paths['/pets'].get", "update": { "summary": "Lister les animaux" } },
          { "target": "$.paths['/internal']", "remove": true }
        ]
      }
    ]
  }
}
```

Ce que le moteur garantit :

- **Les cibles sont du JSONPath RFC 9535 complet** — filtres, tranches, unions, descente et fonctions d'extension, pas seulement le sous-ensemble enfant/joker des exemples de la spec Overlay.
- **Trois actions.** `update` fusionne : objets récursivement, tableaux par concaténation, primitifs par remplacement. `remove: true` supprime le nœud de son parent. `copy`, nouveauté 1.1, fusionne un nœud du document lui-même dans chaque cible. Un overlay 1.0 est accepté et lu avec les règles 1.1.
- **Les overlays s'appliquent au source parsé, avant la conversion Swagger 2.0.** Un overlay s'écrit contre le fichier que son auteur a sous les yeux, qui peut très bien être un 2.0. Tout l'aval voit un seul document, le document corrigé : l'audit note celui-là, et le bouton de téléchargement du schéma sert celui-là.
- **L'ordre est l'ordre de déclaration.** Les overlays de la racine d'abord, puis ceux de la spec active en [multi-spec](/fr/docs/multi-spec/). Ils s'accumulent, comme `hide`.
- **Rien n'est silencieux.** Une cible qui ne matche rien, un `update` qui ne peut pas fusionner là où il pointe, une URL qui ne charge pas — chaque écart est listé dans les diagnostics des réglages et répété en console. Un overlay ne casse jamais le chargement.

## Quand c'est le lecteur qui est bloqué

La section précédente est le levier de l'intégrateur. Le lecteur dispose du même, à plus petite échelle : un paramètre typé `string` que le serveur refuse tant qu'il n'est pas un nombre, une entrée `servers` jamais remplie, un champ requis que l'API a discrètement cessé d'exiger. Tant que le propriétaire du schéma n'a pas bougé, la console d'essai construit ses requêtes sur un modèle que tout le monde sait faux.

**Corriger ce schéma en local**, une section du panneau de réglages, prend un document Overlay 1.1 écrit par le lecteur et l'applique *après* tout ce que la configuration a déclaré. Même moteur, même JSONPath, mêmes diagnostics.

Quatre boutons :

- **Vérifier** exécute le document à blanc contre le schéma déjà en mémoire et rapporte, action par action, combien de nœuds la cible touche. Rien n'est téléchargé, écrit ni rechargé, donc « la cible ne touche aucun nœud » s'apprend avant de s'y engager.
- **Enregistrer et recharger** persiste le document puis recharge la page. Les overlays s'appliquent au source parsé avant que quoi que ce soit le lise : appliquer un correctif, c'est rejouer le pipeline, la même posture qu'un changement de spec.
- **Télécharger** produit `overlay-{specId}.json`, un fichier Overlay 1.1 standard. Joignez-le au rapport de bug, ouvrez la pull request, ou passez-le à qui maintient `openapi.overlays`.
- **Retirer le correctif** supprime le document et recharge, derrière une confirmation.

L'éditeur prend du **JSON uniquement**. Le canal `openapi.overlays` par URL accepte toujours le YAML, puisqu'il passe par le ref-parser, mais l'app n'embarque aucun sérialiseur YAML : une zone de texte qui lirait du YAML et ne saurait réémettre que du JSON ferait diverger le téléchargement de ce qui a été tapé.

Tant qu'un correctif est actif, l'en-tête porte un badge permanent **« Schéma corrigé »** qui ouvre l'éditeur, et les diagnostics des réglages listent le document du lecteur à côté de ceux de l'hôte, actions et avertissements compris, signalé comme le sien. Le risque que cette fonctionnalité crée, c'est d'oublier qu'on en a posé un.

Le reste du contrat :

- Un document par spec, plafonné à 64 Ko. Au-delà, l'enregistrement est refusé et rien n'est écrit.
- Il est stocké dans le navigateur du lecteur sous la clé de la spec, donc cloisonné par spec et effacé par la purge des réglages.
- L'hôte n'a pas de droit de veto. Cela ne change que la vue d'un lecteur dans un navigateur, et `hide` s'applique toujours ensuite.
- L'[audit](/fr/docs/audit/) note le document corrigé. Le bouton de **téléchargement du schéma** est l'exception et sert toujours le fichier publié par l'API.

Une clé de config existe côté hôte, et elle amorce plutôt qu'elle ne gouverne. `openapi.userOverlay` tend à l'éditeur du lecteur un correctif de départ, `null` par défaut. Par spec, elle remplace le document de la racine au lieu de s'empiler, et ré-amorcer avec un *autre* document jette les modifications locales du lecteur.

## Cacher les endpoints internes

Deux canaux, cumulables :

- **Dans le schéma** — `"x-apiglow-hide": true` sur une opération, un Path Item ou une entrée de `tags`.
- **Dans la config** — des motifs `openapi.hide`, avec `*` comme joker : `"tag:Internal"`, `"DELETE /admin/*"`, `"/admin/*"`, ou un operationId. L'id de repli `{method}-{slug}` matche aussi, donc une opération sans operationId reste nommable.

Le filtrage a lieu à la normalisation du document : une opération cachée est donc absente d'un coup de la nav, de la recherche, de la pagination, du diff du changelog et de chaque export, `llms.txt` compris.

Deux endroits voient encore le document complet : l'[audit](/fr/docs/audit/), où un auteur veut la vue entière et où les constats sur opérations cachées sont étiquetés plutôt que liés, et l'onglet réseau du navigateur.

**C'est du masquage documentaire, pas de la sécurité.** Le navigateur télécharge le schéma complet, et n'importe qui peut le lire. N'en faites jamais un contrôle d'accès.

## Le changelog local du schéma

Le lecteur qui revient obtient « ce qui a changé depuis ma dernière visite ». Au chargement, le document est comparé à une empreinte des opérations que ce lecteur a vues en dernier, stockée dans son propre navigateur. Une modale liste les opérations ajoutées, retirées et modifiées, avec les deux versions du schéma et la date de la dernière visite. Des badges marquent les opérations ajoutées ou modifiées dans la nav et dans la doc, avec un nom accessible, jamais la couleur seule. Ouvrir la modale marque le diff comme vu, et le changelog suivant repart de là.

Il n'y a aucun service derrière et rien à configurer. Les empreintes sont des instantanés compacts par schéma dans l'IndexedDB du lecteur, plafonnés en LRU à vingt schémas, et un enregistrement trop gros n'est simplement pas stocké.

Trois limites découlent de ce design : une première visite n'a rien à comparer, une empreinte évincée coûte un changelog, et le diff compare des empreintes bornées, donc un changement enfoui sous le budget de profondeur n'est pas signalé. Pour des garanties de contrat, diffez les fichiers de schéma en CI. Ceci est une aide à la lecture, pour des humains — la [page de fonctionnalité](/fr/features/schema/) montre ce que voient les lecteurs.

## Webhooks, callbacks, et le simulateur

Les webhooks — la clé `webhooks` de 3.1+ — se rendent comme des opérations, dans leur propre section de nav. Les callbacks se rendent dans l'opération qui les déclare.

À la place d'une console d'essai, une page de webhook porte un **simulateur** : il envoie le payload d'exemple vers une URL de récepteur que vous fournissez, c'est-à-dire votre endpoint en développement plutôt que l'API, pour exercer un récepteur sans attendre l'événement réel.

Le simulateur résout les `{{variables}}` de l'environnement actif dans l'URL, les en-têtes et le payload, et une variable manquante bloque l'envoi comme partout ailleurs. Il n'injecte aucun identifiant, puisque l'appel vise votre récepteur plutôt que l'API. Il honore `tryIt.proxyUrl` quand un proxy est configuré.

Pour un récepteur qui n'autorise aucune origine, une bascule **fire-and-forget** envoie en mode `no-cors` : l'événement est livré et la réponse est opaque. Les en-têtes que ce mode écarte sont nommés avant l'envoi.

