L'audit, règle par règle.
L’audit note un schéma OpenAPI : 137 règles en sept catégories, un score par catégorie, une lettre de A à F, et pour chaque constat pourquoi il compte et comment le corriger. Il tourne à deux endroits, sur un seul moteur :
- Dans la documentation, sur
#/audit, à partir du schéma que la page a déjà chargé. Rien n’est envoyé nulle part. - En CI, avec
npx apiglow audit openapi.yaml, qui fait échouer le build sur ce qu’il trouve. Cette moitié a son propre guide : code de sortie, baseline, SARIF, rapports GitHub et GitLab, recettes.
Les deux produisent le même rapport avec les mêmes règles, et lisent la même configuration des règles. Ce guide couvre ce qui est vérifié, comment la note se calcule, et ce que le rapport transporte. La page de fonctionnalité est la vue d’ensemble.
L’ouvrir, et l’éteindre
L’audit s’adresse à l’auteur de l’API plutôt qu’à ses lecteurs : la page n’a donc pas d’entrée de nav. Le point d’entrée est un bloc en bas du tiroir de réglages, qui mène à #/audit — une vraie route, que vous pouvez ouvrir ou copier directement.
Rien n’est calculé, ni même téléchargé, tant que cette page n’est pas ouverte : le moteur vit dans audit.js, à côté d’app.js, et se charge à la première visite de #/audit. Sur un gros schéma, la page montre l’avancement plutôt qu’un écran blanc — dans un onglet en arrière-plan aussi. Le rapport est ensuite gardé en mémoire, par spec.
features: { "audit": false } retire la route, le bloc de réglages et tout calcul. En multi-spec, vous pouvez le faire par spec : une API notée, sa voisine non. Ce réglage ne concerne que la documentation publiée — la ligne de commande l’ignore.
Ce que porte un constat
Chaque constat énonce une sévérité, un message, pourquoi il compte et comment le corriger — quoi écrire, et où. Le correctif figure dans la page, dans l’export Markdown, dans la sortie console de la CLI, et dans le rapport JSON que lit un agent.
| Sévérité | Affirmation |
|---|---|
error | Presque sûrement un bug du schéma |
warning | Nuit probablement aux consommateurs ou à la doc |
info | Bon à savoir |
Un constat sur une opération rendue pointe vers elle. Un constat sur un callback pointe vers l’opération qui le déclare, puisqu’un callback n’a pas de route à lui. Un constat sur une opération cachée montre un badge « caché » au lieu d’un lien : l’audit voit le schéma complet, mais ne lie jamais vers une vue sans route. Les constats situés ailleurs — components, info — affichent leur pointeur JSON.
Les constats sont repliés par règle, chaque ligne portant son compte : une omission répétée à travers un schéma est une seule décision, pas deux mille lignes. Les occurrences se matérialisent cinquante par cinquante au dépliage.
L’audit signale une seule fois ce qui se corrige d’un seul geste. Des propriétés non décrites donnent un constat par schéma, qui les nomme, plutôt qu’un par propriété : le schéma REST de GitHub passe ainsi de 28 324 constats à 2 751.
Tout fichier a son rapport
L’audit lit ce que vous lui donnez, même abîmé. Une clé en double, une tabulation en guise d’indentation, une virgule de trop, un fichier tronqué : chacun devient un constat document-syntax à sa ligne et sa colonne, et la page cite le fichier autour, un caret sous la colonne. Le reste du fichier est noté quand même. Un fichier qui ne contient aucune description OpenAPI — vide, une liste, du texte brut, du Swagger 1.x — reçoit un rapport qui le dit.
Les sept catégories
Exactitude (76 règles) — ce qui contredit la spécification OpenAPI ou le document lui-même, surtout des erreurs. La structure, version par version : un champ que l’objet n’a pas (descripton), un champ requis absent, une valeur du mauvais type (in: body, type: int), des champs qui s’excluent. Chemins et paramètres : un chemin mal formé, deux chemins identiques une fois leurs variables renommées, un paramètre de chemin absent du template, un paramètre déclaré deux fois, un style que son emplacement n’autorise pas. Les références : un $ref qui ne mène nulle part, ou au mauvais type d’objet. Les schémas tenus à leurs propres mots-clés : un enum que son type rejette, des bornes qu’aucune valeur ne satisfait, un pattern qui n’est pas une expression régulière, un mot-clé mal orthographié (maxLenght), une récursion qu’aucune valeur finie ne satisfait. Exemples et défauts confrontés à tout leur schéma, jusqu’à la propriété imbriquée qui casse ($.tags[0].name). Et la sémantique HTTP : un corps sur un GET, du contenu sur un 204, un QUERY 3.2 sans corps.
Sécurité (11 règles) — ce que le document laisse passer, chaque règle rattachée à la RFC ou au risque OWASP qu’elle couvre. Un serveur en http://, des URL OAuth sans TLS, des identifiants envoyés à un serveur en clair, une clé d’API dans la query string, les flows OAuth password et implicit que la RFC 9700 retire, des opérations ouvertes sans authentification, un champ format: password renvoyé dans une réponse, des corps de requête sans taille maximale.
Documentation (15 règles) — ce que le document tait : opérations sans résumé ni description, paramètres, propriétés et tags non décrits, opérations mutantes sans réponse d’erreur, réponses de succès sans exemple, info sans description, contact ou licence. Le texte bouche-trou compte comme absent : une description qui dit « TODO », « string » ou « lorem ipsum », ou qui ne fait que répéter le nom de son champ.
Obsolescence (4 règles) — une dépréciation qui ne nomme ni remplacement ni échéance, un en-tête Deprecation qui n’est pas une date RFC 9745, une échéance fixée avant la dépréciation, une entrée dépréciée toujours requise.
Cohérence (6 règles) — les conventions du document, tenues contre lui-même : noms de paramètres, de propriétés et de segments de chemin hors de la convention dominante (détectée plutôt qu’imposée ; les en-têtes sont exemptés puisqu’ils suivent celle de HTTP), et les noms que les générateurs de code fondent en un seul — pet_status et PetStatus deviennent le même type.
Qualité documentaire (17 règles) — comment le schéma se comporte dans ce moteur de rendu, la catégorie qu’aucun linter générique n’a. Chaque message nomme la dégradation concrète : pas d’operationId donne des liens profonds instables, pas de servers prive l’amorçage d’environnements de matière, un serveur resté sur example.com fait appeler le try-it dans le vide, un flow OAuth2 sans ses URL empêche le bloc « Obtenir un jeton » de tourner, du HTML que l’assainisseur retire n’atteint jamais le lecteur, un en-tête que le navigateur refuse d’envoyer ne peut pas être essayé ici.
Prêt pour les agents (8 règles) — ce qu’obtient un agent IA qui appelle votre API à travers un outil : un pont MCP, une GPT Action, Semantic Kernel. Des entrées sans type ou sans forme, des unions qu’un agent ne sait pas départager, un corps qui n’est pas un objet, des valeurs d’enum que rien n’explique, un paramètre et une propriété du corps sous le même nom, des exemples de requête écrits là où aucun outil ne les voit, des erreurs renvoyées en prose.
Conscience des versions
Les règles jugent le document contre la version qu’il déclare, dans les deux sens. Une graphie qu’une version ultérieure a remplacée (nullable: true, à partir de 3.1) et une construction employée en avance sur la version déclarée (webhooks ou tableaux de types dans un document 3.0, constructions 3.2 dans un 3.1) sont deux constats d’exactitude. Le même nullable dans un document 3.0 passe, parce qu’il y est correct.
Un document Swagger 2.0 converti reçoit en plus un constat par construction que la conversion n’a pu qu’approximer.
La notation
Chaque application de règle est une vérification réussie ou échouée contre une cible : une opération, un paramètre, un component, ou le document.
- La note de catégorie est le taux de réussite pondéré sur ses vérifications applicables. Les poids suivent la sévérité : erreur 3, avertissement 2, info 1.
- Le crédit partiel. Une vérification qui porte sur plusieurs éléments — les propriétés d’un schéma, les valeurs d’un enum, les entrées d’une opération — perd une part de son crédit, d’autant plus qu’il y a de manques, mais de moins en moins pour chaque manque suivant. Un manque sur quinze coûte un quart de la vérification ; les quinze, la totalité.
- Les vérifications non applicables ne comptent pas. Une API sans dépréciation fait 100 % en obsolescence plutôt que zéro, et une catégorie sans aucune vérification applicable est absente du rapport plutôt que notée.
- La lettre vient de la moyenne des notes de catégories : A ≥ 90, B ≥ 80, C ≥ 65, D ≥ 50, F en dessous.
Le rapport s’ouvre sur son verdict : la lettre dans un anneau tracé à la mesure du score, à côté d’une barre par catégorie. Chaque titre de catégorie porte ses propres comptes par sévérité, pour peser une section sans remonter au sommaire.
Configurer les règles
Une vraie API a des exceptions voulues et durables. Le bloc audit de la configuration éteint une règle, ou change sa sévérité, pour tout le document ou sous certains pointeurs JSON seulement :
{
"audit": {
"rules": { "property-described": "off", "parameter-described": "error" },
"overrides": [
{ "paths": ["/paths/~1legacy~1*"], "rules": { "response-example": "off" }, "reason": "frozen legacy API" }
]
}
}rulesassocie un identifiant de règle àerror,warning,infoouoff. Les identifiants figurent dans le rapport, etapiglow audit --list-rulesles imprime tous.overridesapplique les mêmes réglages sous des motifs de pointeurs :*couvre l’intérieur d’un segment,**un nombre quelconque de segments, et un motif couvre tout ce qui se trouve sous ce qu’il désigne.reasonest un texte libre pour le prochain lecteur de la configuration, puisque JSON n’a pas de commentaires.- L’ordre de priorité : la sévérité propre de la règle, puis
rules, puis chaque surcharge qui couvre le pointeur, dans l’ordre de déclaration — la dernière a le dernier mot. - Une règle éteinte ne compte pas du tout — ni comme constat, ni dans le score.
- Par spec, en multi-spec : les
rulesse fusionnent par identifiant, la spec l’emportant ; lesoverridess’additionnent, celles de la racine d’abord.
La page et apiglow audit lisent le même bloc : la note publiée et la note de CI concordent. Une note calculée avec l’un de ces réglages porte la mention Règles personnalisées à côté de la lettre, dans les deux exports et dans le JSON : elle ne passe jamais pour la note par défaut. Une entrée illisible est signalée par la page dans la console du navigateur puis ignorée ; la ligne de commande, elle, refuse de tourner.
Il n’y a pas de règles maison, et la baseline n’est pas une liste d’exclusion : elle change les constats qui font échouer un job de CI, jamais ceux qui sont rapportés.
Le rapport nomme ce qu’il a noté
Un rapport se lit souvent hors contexte — une capture collée, un onglet resté ouvert — donc la page énonce son identité et son périmètre : titre de l’API, info.version et version OpenAPI déclarée, contact et licence quand le document les porte, et le document en chiffres (opérations, groupes, webhooks, schemes de sécurité, schémas).
Les chiffres sont comptés sur le document, opérations cachées comprises. Les zéros sont affichés, puisque « aucun scheme de sécurité » est une chose que le rapport s’apprête à noter.
L’export
« Copier en Markdown » emporte tout ce que la page montre — identité, chiffres, comptes par catégorie, et chaque constat avec pourquoi il compte et comment le corriger — plus un horodatage à la seconde, pour qu’un rapport collé dans un ticket dise quand il a été produit.
Deux écarts avec la page : les pointeurs JSON restent entiers, puisqu’ils localisent le constat dans le fichier que vous allez éditer, et l’export voyage dans la langue où il a été lu.
Collez-le dans une issue, corrigez, rechargez, ré-auditez. Quand le constat vit dans un schéma qui n’est pas à vous, les overlays le corrigent sans fork. Quand vous voulez le contrôle à chaque merge, mettez-le en CI.