feint ne se contente pas de répondre : il dit ce qu'il a servi, ce qu'un client a réellement piloté, et ce qu'un vrai cloud renverrait à sa place. Ces trois mécanismes servent le même objectif, savoir si un test prouve quelque chose : une page d'introspection servie par le binaire, un proxy d'enregistrement qui mesure au lieu de deviner, et des snapshots pour rejouer un jeu de données autant de fois que nécessaire.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Lire la page que l'émulateur sert sur lui-même, et ses trois compteurs.
- Distinguer une route montée, une route sondée et une route pilotée.
- Enregistrer ce qu'un client officiel envoie, sans qu'un identifiant fuite.
- Revenir à un état de test connu, autant de fois qu'il le faut.
Comment voir ce que l'émulateur a réellement servi
Section intitulée « Comment voir ce que l'émulateur a réellement servi »feint ui ouvre une page que le binaire sert sur lui-même, à
http://127.0.0.1:4599/_feint/ui. Pas de second port, pas de second processus,
pas d'étape de construction : trois fichiers embarqués dans le binaire. Elle
répond à la question que ni les journaux ni status ne traitent complètement :
qu'est-ce qui a été monté, exercé, et par quoi.
feint ui 
Le haut de la page est un compteur qui ne s'additionne pas, et c'est volontaire. Les trois nombres restent séparés parce qu'ils ne valent pas la même chose : une route montée existe, une route sondée répond correctement au protocole, une route pilotée par un vrai client est la seule dont le comportement soit démontré. La barre affiche la part sondée en hachuré plutôt qu'en plein, pour la même raison.
Le reste de la page montre l'inventaire de la session, lu depuis le magasin interne et non depuis une API de fournisseur, avec les attributs complets et une recherche ; l'écart avec la surface amont, produit par produit, où chaque opération refusée porte sa raison écrite ; et un journal des appels qui signale deux choses qu'aucun autre outil ne remonte : les champs qu'un client a envoyés et qu'aucun gestionnaire n'a lus, et ceux qu'une réponse a portés sans que la description d'API du fournisseur les définisse.
La page est en lecture seule et servie sur la boucle locale uniquement. Hors loopback elle n'est pas cachée, elle n'existe pas. Il n'y a aucune authentification, et c'est un choix argumenté plutôt qu'un oubli : un mot de passe protégerait la mauvaise frontière, puisque le risque est une page malveillante ouverte dans le navigateur de l'opérateur, laquelle hériterait de tout secret détenu par ce même navigateur.
Le même anneau d'événements est lisible par un script, ce qui en fait un mécanisme et pas seulement un écran :
curl -s localhost:4599/_feint/trace \ | jq -r '.exchanges[] | "\(.method) \(.path) \(.status) \(.operation // "aucune route")"'GET /v2/instance-type 200 exoscale/v2.list-instance-typesGET /v2/zone 200 exoscale/v2.list-zonesGET /v2/quota 200 exoscale/v2.list-quotasTrois autres points d'entrée complètent l'ensemble pour l'outillage :
/_feint/conformance porte le détail par opération,
/_feint/resources publie l'inventaire, et /_feint/health répond
l'état et les capacités du mode courant.
Comment revenir à un état connu
Section intitulée « Comment revenir à un état connu »feint snapshot nomme l'état d'un émulateur en cours et permet d'y
revenir. C'est le mécanisme qui rend un jeu de données de test atteignable une
fois puis rejouable autant de fois que nécessaire.
feint snapshot save etat-de-referencefeint snapshot listsaved 21 resources to /home/bob/.local/state/feint/snapshots/etat-de-reference.json
NAME RESOURCES BYTES SAVEDetat-de-reference 21 26472 2026-07-30T09:43:40ZAprès avoir supprimé toutes les ressources, feint snapshot load etat-de-reference répond loaded etat-de-reference: the emulator now holds 21 resources et l'inventaire est reconstitué. Le chargement remplace
l'état, il ne fusionne pas : un jeu de test ne doit pas dépendre de ce que
la session a fait avant lui.
Comment savoir ce qu'un vrai client attend
Section intitulée « Comment savoir ce qu'un vrai client attend »feint proxy s'intercale entre un client officiel et un cloud, et écrit
chaque échange dans un fichier ; feint transcript relit ce fichier par
verbes. Le couple répond à une question que la documentation d'un fournisseur
ne tranche pas : ce que le client appelle réellement, et la forme exacte
des réponses qu'il reçoit.
L'usage prévu est un vrai compte, en lecture seule. La démonstration ci-dessous pointe le proxy sur l'émulateur lui-même, ce qui montre la mécanique sans facture ; seule l'adresse amont change dans le cas réel.
feint proxy --upstream http://127.0.0.1:4599 --record enregistrement.jsonl --provider scalewayeval "$(feint env scaleway --endpoint http://127.0.0.1:4600)"scw instance server create name=via-proxy type=DEV1-S image=ubuntu_jammy zone=fr-par-1feint transcript en tire une file de travail classée par nombre
d'appels, c'est-à-dire les opérations qu'un client réclame et que personne
n'a encore servies :
feint transcript enregistrement.jsonlalready served, and exercised here (6): 2 1888 200,201 instance/v1/API.CreateServer 1 4734 200 instance/v1/API.ListServersTypes 1 506 200 instance/v1/API.GetImage 1 303 201 instance/v1/API.CreateIPLe drapeau --shape donne l'arbre des champs réellement renvoyé, qui
n'est pas ce que le SDK déclare pouvoir renvoyer, et --against compare cet
arbre avec celui de l'émulateur pour lister les champs manquants ou mal typés.
response shape of instance/v1/API.ListServersTypes, as the real cloud returned it:
object servers object servers.DEV1-L string servers.DEV1-L.arch bool servers.DEV1-L.capabilities.block_storageAucun identifiant n'atteint le fichier : la caviardage est une propriété du
type enregistré, pas une étape qu'un appelant pourrait oublier. Les en-têtes
suivent une liste d'autorisation, les corps une liste d'exclusion, parce
qu'un corps est la mesure recherchée alors qu'un en-tête ne l'est pas. Le
proxy n'écoute que sur la boucle locale, sauf --expose-to-network : chaque
requête qui le traverse porte un identifiant valide.
feint shapes prolonge la logique côté vérification : il enregistre l'arbre
des champs d'un vrai cloud, sans valeurs ni identifiants, ce qui rend le
fichier publiable là où une transcription ne l'est pas, puis
feint shapes --check compare l'émulateur à cet enregistrement hors ligne et
sans identifiant.
À retenir
Section intitulée « À retenir »- La page est servie par le binaire, sur la boucle locale, en lecture seule et sans authentification par choix argumenté.
- Servi, sondé et piloté ne s'additionnent pas : seule la dernière catégorie démontre un comportement.
feint proxymesure au lieu de deviner ce qu'un client envoie, et caviarde les identifiants par construction.feint transcriptrépond par verbes : quoi servir ensuite, quelle forme doit avoir la réponse, quels champs manquent.- Un snapshot remplace l'état, il ne le fusionne pas : un jeu de test ne dépend pas de ce qui l'a précédé.