Avant d'ouvrir une PR sur le catalogue de plugins, regardez ce que son gate vérifie réellement

Vous écrivez un plugin, vous ouvrez la PR que le catalogue demande, et la CI revient avec une ligne : le sha pin n’est pas un objet commit dans le repo. Vous fixez votre YAML — vous avez copié ce sha directement depuis la page GitHub. Vous avez copié le sha d’un objet tag, alors que le gate veut le sha d’un objet commit. Dans votre PR, les deux sont identiques.
Le catalogue de plugins est un endroit où d’autres personnes exécutent du code sur leurs propres machines : son gate n’est donc pas une cérémonie — c’est une véritable vérification de chaîne d’approvisionnement. Voici ce qu’il contrôle, pourquoi il se soucie de quelque chose d’aussi innocent qu’un renommage, et ce qu’il faut confirmer avant de soumettre.
Où vit le gate et quand il s’exécute
L’admission est un workflow dédié qui ne se déclenche que sur les PR touchant plugin-catalog/**, il ne peut donc jamais passer au rouge à cause d’un travail sans rapport. Il a deux tâches :
- structural — une vérification de schéma peu coûteuse qui n’exige aucune installation de Hermes : elle valide tout le répertoire
plugin-catalog/, en préservant l’invariant selon lequel tout ce qu’il contient reste valide. - pinned-source-validate — le vrai gate de chaîne d’approvisionnement : le sha que vous avez pin doit être atteignable dans votre repo, et le plugin à ce commit exact doit passer
hermes plugins validate.
Autrement dit, le gate clone réellement votre dépôt, se place sur le commit que vous avez déclaré et y exécute la validation. Il ne lit pas votre YAML en vous croyant sur parole — il lit le code à ce commit.
Trois champs vérifiés un par un
Chaque champ de votre entrée qu’une PR peut contrôler est vérifié avant d’être utilisé :
| Champ | Ce que le gate exige |
|---|---|
repo |
une URL https sans espace blanc |
sha |
40 caractères hexadécimaux que git cat-file -t rapporte comme un objet commit |
subdir |
un chemin relatif simple qui, après résolution, pointe toujours à l’intérieur du clone pin |
C’est de cette vérification du type de sha que vient l’erreur du début : un objet tag est un id d’objet parfaitement légal, mais il se résout vers un commit que le relecteur n’a jamais déclaré comme pin, alors le gate le refuse. La vérification de subdir fonctionne de la même manière — pas une comparaison littérale, mais une vraie résolution de chemin suivie d’un test de confinement, et c’est ce qui rend .. inutile comme échappatoire.
Pourquoi il se soucie d’un renommage
La liste des entrées modifiées utilisait --diff-filter=AM — ajouts et modifications uniquement. Le piège : un fichier d’entrée renommé n’atterrit jamais dans cette liste, et le gate ne contrôle que les entrées de la liste. Renommez une entrée dangereuse et elle glisse entièrement sous le gate.
Le filtre lit désormais AMRT : ajouts, modifications, renommages et changements de type (un fichier qui devient un lien symbolique, par exemple) atteignent tous la liste. À côté, une règle plus brutale : tout lien symbolique, où qu’il soit dans le clone, doit rester à l’intérieur du clone. Cette vérification parcourt volontairement tout le checkout — find ne descend pas dans un répertoire pointant vers un lien symbolique, donc un lien de répertoire à répertoire pourrait cacher une échappatoire qu’un scan limité au répertoire de plugins ne verrait jamais.
Faire en sorte que le code du plugin ne puisse pas s’appuyer sur le gate
C’est la partie la plus intéressante de la conception, parce que le gate exécute du code que vous n’avez pas relu (hermes plugins validate lance la logique d’installation déclarée par le plugin) :
- Les entrées sont lues depuis le fd 3, pas depuis stdin. Un code de plugin qui vide l’entrée standard ferait disparaître le reste de la liste d’entrées et sauterait silencieusement la validation. Passer à un autre descripteur de fichier ferme cette porte.
- Le parseur tourne sous
python3 -I, réinitialise ses variables à chaque entrée et échoue en mode fermé avec une valeur sentinelle à la moindre erreur d’analyse. - Les PR d’entrée doivent être uniquement des données : elles peuvent toucher
plugin-catalog/**etcontributors/emails/**, et rien d’autre. La raison est brutale — le code d’application du gate (le workflow, le validateur, le Hermes compilé) provient du checkout de la PR, donc une PR d’entrée qui modifie aussi l’outillage pourrait neutraliser le gate même qui la contrôle.
La règle trop stricte qui a été resserrée
La première version du correctif était trop large : elle exigeait « données uniquement » dès que quoi que ce soit sous plugin-catalog/ changeait. Selon ce critère, 29 des 134 dernières PR fusionnées du catalogue auraient échoué — celles qui portent les cartes d’e-mails d’attribution — et chaque PR de README, de politique ou de CI touchant le répertoire serait aussi passée au rouge.
La règle est désormais restreinte : elle s’exécute une fois, uniquement quand un YAML d’entrée a réellement changé, et elle autorise contributors/emails/** en même temps que plugin-catalog/**. La même PR a aussi abandonné le clone avec tout l’historique : le diff porte sur le commit de fusion de GitHub comparé à son premier parent, avec seulement deux niveaux de profondeur, et la détection de renommage fonctionne toujours.
Une checklist avant de soumettre
- Pin un sha de commit, pas un sha de tag. Prenez l’id complet à 40 caractères depuis la page du fichier ou la liste des commits, pas depuis la page Releases/Tags.
- Gardez
subdircomme un chemin relatif simple — pas de./, pas de.., pas de chemins absolus, pas de variables. - Une PR, un travail. Une PR d’entrée de catalogue touche
plugin-catalog/**(plus les cartes d’attribution) et rien d’autre — pas l’outillage, pas les workflows, pas la doc. - Lancez le validateur en local. C’est le même script que celui utilisé par la CI :
python3 scripts/validate_plugin_catalog.py plugin-catalog/. - Assurez-vous que le plugin passe au commit pin. Le gate clone votre repo et se place sur ce commit, donc « la dernière version passe mais pas celle qui est pin » est une croix rouge très courante.
Pour comprendre le fonctionnement du catalogue côté utilisateur (parcourir, installer, installation hors ligne), voyez le guide du catalogue de plugins ; les points d’entrée au niveau des commandes sont dans la référence hermes plugins. Si c’est plutôt la frontière de confiance côté MCP qui vous intéresse, le guide de sécurité du catalogue MCP en est le pendant.
À retenir
La philosophie de conception tient en une phrase : tout ce qu’une PR peut contrôler est vérifié avant usage, et il est vérifié après résolution plutôt que littéralement. Renommages, .., objets tag, liens symboliques, jusqu’à stdin vidé — rien de tout cela n’est « un bug dans le code » ; ce sont tous des cas où « le point de contrôle était au mauvais endroit ».
Pour les auteurs de plugins, l’avantage est que les règles sont stables. Pin un objet commit, gardez le subdir relatif, faites une seule chose par PR — et le gate vérifiera à votre place que ce que le relecteur a vu et ce qu’un utilisateur installe sont le même artefact.