Démarrage rapide
Créez une clé API avec les portées Rig dans le portail Ironfang, puis committez un ironfang.rig.yaml à côté de l'application. Le fichier déclare les identités externes dont une exécution a besoin et ce que l'exécution doit observer.
version: 1
project: acme-shop
suite: checkout
name: Checkout flow
defaults:
run_ttl: 30m
resources:
customer_email:
type: email
stripe_callback:
type: callback
connector:
route: stripe
shipping_api:
type: mock_http
rules:
- match: { method: POST, path: /v1/ship/* }
respond: { status: 201, json: { tracking: "IF-1" } }
expectations:
- id: order_email
resource: customer_email
event: email.received
match: { subject_contains: "Your order" }
- id: stripe_forwarded
resource: stripe_callback
event: connector.request.completed
match: { outcome: delivered, status: 200 }Le client en ligne de commande synchronise le fichier, démarre une exécution, exporte l'adresse de chaque ressource vers la commande placée après --, l'exécute, puis termine l'exécution avec un verdict.
export IRONFANG_API_KEY=if_live_...
ironfang rig run -- npm test
# In the test process:
# IRONFANG_RIG_RUN_ID the run
# IRONFANG_RIG_CUSTOMER_EMAIL run-....@inbox.rig.ironfang.uk
# IRONFANG_RIG_STRIPE_CALLBACK https://hooks.rig.ironfang.uk/h/...
# IRONFANG_RIG_SHIPPING_API https://mock.rig.ironfang.uk/m/...La même exécution est disponible en HTTP. Chaque requête porte la clé comme jeton bearer, et l'URL de base est https://api.ironfang.uk/rig.
curl -X POST https://api.ironfang.uk/rig/v1/suites/$SUITE_ID/runs \
-H "Authorization: Bearer $IRONFANG_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "ttl": "30m", "external_id": "ci-4821" }'La description OpenAPI 3.1 complète est servie à https://api.ironfang.uk/rig/openapi.yaml.
Modèle
Les suites persistent, les exécutions sont jetables, les ressources ont une durée de vie explicite. Rien ici n'exécute votre code : Ironfang Rig est le monde extérieur auquel vos tests parlent, et l'enregistrement de ce qu'il a vu.
| Objet | Ce que c'est |
|---|---|
| Projet | Un conteneur persistant pour une application, désigné par un slug. |
| Suite | Une définition versionnée de ressources et d'attendus au sein d'un projet. Chaque révision est conservée avec son SHA-256 ; une exécution nomme toujours la version qu'elle a exécutée. |
| Exécution | Une exécution de la version courante d'une suite. Elle est active jusqu'à ce qu'elle soit finished, cancelled ou expired par son TTL (30 minutes par défaut, de 1 minute à 24 heures). Une exécution terminée a pour résultat pass, fail ou none. |
| Ressource | Une identité externe que reçoit l'exécution : une boîte de réception, une URL de callback, un endpoint HTTP simulé ou une route vers un connecteur. Impossible à deviner et propre à l'exécution, joignable depuis Internet uniquement tant que l'exécution est active. |
| Événement | Une observation immuable sur la chronologie de l'exécution, avec un numéro de séquence continu à partir de 1. La chronologie est en ajout seul, et en lecture seule une fois l'exécution terminée. |
| Attendu | Une condition déterministe sur la chronologie, stockée avec la suite et évaluée quand l'exécution est terminée. |
| Panne | Une perturbation déterministe armée sur une ressource : retarder, dupliquer, abandonner, réordonner ou modifier le corps d'un callback transmis ; remplacer le statut d'un mock, réinitialiser sa connexion, brider son corps ou le couper court. |
Tout est rattaché à une organisation. Un objet qui appartient à une autre organisation est signalé comme introuvable, jamais comme interdit.
Clés API et portées
Les clés API de la plateforme sont créées dans le portail et commencent par if_live_. Les portées d'une clé sont ses autorisations, et elle n'agit que dans l'organisation pour laquelle elle a été créée. Envoyez-la comme jeton bearer.
Authorization: Bearer if_live_...rig:readLister et lire les projets, suites, exécutions, ressources, pannes, connecteurs et événements ; attendre sur la chronologie ; exporter les preuvesrig:writeCréer et réviser les projets et les suitesrig:runDémarrer, terminer et annuler les exécutions ; allouer des ressources ; modifier les règles de mock ; armer des pannes ; rejouer des callbacksrig:connectorCréer des connecteurs et leurs jetons d'amorçagerig:*Tout ce qui précède
Un jeton utilisateur Warden est également accepté, avec l'organisation agissante dans X-Ironfang-Tenant ; chaque route exige alors la permission de tenant correspondante (rig.read, rig.write, rig.run, rig.connector).
Erreurs
Chaque erreur est un objet JSON avec un code stable, un message lisible par une personne et l'identifiant de requête à communiquer au support.
{
"error": {
"code": "run_not_active",
"message": "the run has already ended",
"docs": "https://ironfang.uk/rig/docs#errors"
},
"request_id": "01a0c375-7bae-7f02-a3d4-91e6b8c25f70"
}docs est un lien vers cette section, et request_id reprend l'en-tête de réponse X-Ironfang-Request-ID.
| Statut | Code | Signification |
|---|---|---|
| 400 | invalid_json, invalid_query | Le corps n'est pas une unique valeur JSON stricte de la forme documentée, ou un paramètre de requête est inconnu, répété ou mal formé. |
| 401 | unauthorized, invalid_api_key | Aucun identifiant, ou un identifiant qui ne se résout pas. |
| 403 | forbidden, insufficient_scope | La clé n'a pas la portée, l'utilisateur n'a pas la permission, ou la requête nomme une autre organisation. |
| 404 | not_found | Aucun objet de ce type dans cette organisation. |
| 409 | conflict, archived, run_not_active | Un slug est déjà pris, la cible est archivée, ou l'exécution est déjà terminée. |
| 410 | payload_retired | L'événement existe, mais les octets de sa charge utile ont dépassé la durée de conservation. |
| 422 | invalid_request, not_replayable | Un champ est invalide ; le message le nomme. |
| 429 | too_many_waiters, replay_limit, connector_limit, fault_limit | Une limite par organisation ou par exécution a été atteinte ; le message indique laquelle. Les adresses de callback, de mock et de courrier d'une exécution répondent run_limit de la même façon une fois que l'exécution a atteint sa limite. |
Le fichier de suite
ironfang.rig.yaml se trouve dans le dépôt, à côté de l'application qu'il teste. Il contient exactement la définition que l'API stocke, si bien que ce qu'un développeur committe est ce à partir de quoi une exécution est créée. La synchronisation du fichier crée le projet et la suite à la première utilisation et enregistre une nouvelle version de la suite chaque fois que la définition change.
| Champ | Type | Remarques |
|---|---|---|
version | integer | Toujours 1. |
project | string | Slug du projet. Créé à la première synchronisation. |
suite | string | Slug de la suite, unique au sein du projet. |
name | string | Nom d'affichage, jusqu'à 120 caractères. |
defaults.run_ttl | duration | Durée de vie par défaut d'une exécution, de 1m à 24h. Par défaut 30m. |
resources | object | Nom vers spécification de ressource, de 1 à 32 entrées. Les noms respectent ^[a-z][a-z0-9_]{0,63}$ et deviennent des suffixes de variables d'environnement. |
expectations | array | Jusqu'à 64 conditions, chacune avec un id, un nom de resource, un type d'event et un match facultatif. |
Spécifications de ressource
| type | Champs supplémentaires | Ce que reçoit l'exécution |
|---|---|---|
email | aucun | Une adresse de boîte de réception sous inbox.rig.ironfang.uk. |
callback | connector.route (facultatif) | Une URL publique qui enregistre chaque requête. Avec une route, chaque requête est aussi transmise à votre connecteur. |
mock_http | rules (facultatif, jusqu'à 32) | Une URL publique qui répond à partir de règles ordonnées. |
connector_route | route | Un libellé de route sans adresse publique, auquel les connecteurs se lient. |
Les libellés de route respectent ^[a-z0-9][a-z0-9-]{0,62}$. La plateforme ne nomme jamais qu'un libellé ; ce vers quoi il pointe est décidé sur la ligne de commande du connecteur et ne quitte jamais votre machine.
Correspondance
Un objet match est un ensemble de conditions sur les champs de premier niveau des données d'un événement, et chaque clé doit être satisfaite. Une clé simple se compare en JSON : nombres, booléens, chaînes et objets entiers se comparent par valeur. Une clé se terminant par _contains exige que le champ soit une chaîne contenant la valeur. La même règle évalue les attendus de la suite, l'endpoint d'attente et l'option --match de la CLI, si bien qu'une condition a le même sens partout. Jusqu'à 16 clés, de 4096 caractères chacune.
Ressources
Démarrer une exécution alloue chaque ressource déclarée. Chacune est impossible à deviner, n'appartient qu'à cette exécution et cesse d'accepter toute activité quand l'exécution se termine. D'autres peuvent être allouées sur une exécution active avec POST /v1/runs/{runId}/resources.
Boîtes de réception e-mail
Une ressource email est une adresse comme run-k7c3m2wp9e4q5r6t@inbox.rig.ironfang.uk. Le courrier qui lui est destiné est reçu par mx.rig.ironfang.uk, analysé et enregistré comme email.received avec l'expéditeur, le destinataire, l'objet, les liens, les codes de vérification, les pièces jointes et les détails de transport. Le message brut est conservé comme charge utile de l'événement. Les messages jusqu'à 10 MiB et 500 messages par exécution sont acceptés ; au-delà, tout est refusé dès l'échange SMTP, de sorte que l'expéditeur voit le rejet.
Chaque message est aussi vérifié comme le ferait un serveur de messagerie destinataire : SPF pour l'adresse d'envoi par rapport au domaine de l'expéditeur d'enveloppe, DKIM pour chaque signature qu'il porte, et DMARC pour le domaine From avec l'alignement et la politique que demande son enregistrement. Les résultats sont enregistrés sur l'événement sous authentication (spf, dkim[], dmarc avec le domaine, la politique, l'alignement et les motifs) et repris sous forme des champs d'un seul mot spf, dkim et dmarc, pour qu'un attendu ou une attente puisse demander { "dmarc": "pass" }. Ce sont des observations de ce que l'expéditeur publiait au moment de la réception : une défaillance DNS vaut temperror, jamais un verdict.
URL de callback
Une ressource callback est une URL comme https://hooks.rig.ironfang.uk/h/.... Toute méthode et tout chemin sous cette URL sont acceptés. La requête est enregistrée comme callback.received avec sa méthode, son chemin, sa query, son type de contenu, sa longueur en octets et son SHA-256, et l'expéditeur reçoit immédiatement un 200 avec l'identifiant de l'événement. Les octets exacts sont disponibles via l'endpoint de charge utile de l'événement. Les corps de plus de 64 KiB sont refusés avec un 413 et enregistrés comme callback.rejected ; une exécution accepte jusqu'à 1000 callbacks.
{ "received": true, "run_id": "...", "event_id": "...", "sequence": 7 }Avec une connector.route, chaque requête enregistrée est aussi mise en file pour cette route et transmise par votre connecteur ; voir Connecteur local.
Endpoints HTTP simulés
Une ressource mock_http est une URL de base comme https://mock.rig.ironfang.uk/m/.... Les requêtes sous cette URL reçoivent la réponse de la première règle dont le match est satisfait ; sans correspondance, la réponse est un 404 avec le code no_mock_rule. Chaque requête est enregistrée comme mock.request.received et sa réponse comme mock.response.sent avec la règle correspondante. Les règles peuvent être remplacées tant que l'exécution est active avec PUT /v1/runs/{runId}/resources/{resourceId}/mock, ce qui enregistre mock.rules.updated.
| Champ de règle | Remarques |
|---|---|
match.method | Une méthode HTTP, ou * ou absent pour toutes. |
match.path | Chemin exact sous l'URL du mock, préfixe se terminant par /*, ou modèle comme /v1/pets/{id} dont les segments entre accolades correspondent à n'importe quel segment ; absent pour tous. |
match.headers | En-têtes qui doivent être présents avec exactement ces valeurs. |
match.json | Champs de premier niveau auxquels un corps de requête JSON doit être égal. |
respond.status | Obligatoire, de 100 à 599. |
respond.headers | En-têtes de réponse. |
respond.body ou respond.json | Un corps texte jusqu'à 64 KiB, ou un corps JSON qui définit le type de contenu sauf si un en-tête le fait. |
respond.delay | Attente avant de répondre, au plus 10s. |
respond.template | Génère le corps et les valeurs d'en-tête à partir de la requête : {{request.method}}, {{request.path}}, {{request.query.name}}, {{request.header.Name}}, {{request.body}}, {{request.json.a.b.0}}, {{run.id}}, {{resource.name}}, {{step}}, {{received_at}}. Dans un corps JSON, une variable de substitution se trouve dans une chaîne et y est échappée ; un nom inconnu est refusé dès l'écriture des règles. |
sequence, repeat | Au lieu de respond : de 2 à 16 réponses que la règle donne tour à tour à ses appels, puis de nouveau la dernière ou, avec repeat: cycle, à partir de la première. L'événement de réponse enregistre le step ; remplacer les règles fait repartir chaque séquence du début. |
Déterministe : la même requête face aux mêmes règles, à la même étape, obtient la même réponse, délai compris. Une exécution peut faire jusqu'à 5000 appels de mock.
Un mock peut tenir lieu d'une API documentée au lieu de porter des règles : donnez à la ressource openapi.file (un chemin à côté du fichier de suite, que la CLI intègre) ou openapi.document (le texte OpenAPI 3, en JSON ou YAML, jusqu'à 256 KiB). Une règle est dérivée par opération, dans l'ordre du document : le modèle de chemin est le match, la réponse 2xx la plus basse ou la réponse par défaut est la réponse, et l'exemple documenté, ou une valeur construite à partir du schéma (enum d'abord, chaînes conformes au format, nombres à zéro, un élément de tableau), est le corps. Les références sont résolues dans le document et rien n'est téléchargé. Un mock contient au plus 32 opérations ; nommez celles dont une suite a besoin dans openapi.include sous la forme GET /pets/{id}, et définissez openapi.prefer: schema pour ignorer les exemples.
Routes de connecteur
Une connector_route n'a pas d'adresse publique. Elle existe pour qu'un connecteur puisse se lier au libellé et que des callbacks puissent le nommer. La plupart des suites déclarent la route directement sur le callback et n'ont jamais besoin d'une ressource distincte.
Chronologie et attente
GET /v1/runs/{runId}/events?since=0&limit=100 renvoie les événements de l'exécution dans l'ordre de séquence après since, jusqu'à 500 à la fois, avec next_since pour continuer. Les séquences sont continues à partir de 1 et ne changent jamais, si bien que la même requête renvoie toujours les mêmes événements. Les charges utiles plus volumineuses que ce que porte un événement sont référencées par blob_ref, jamais intégrées.
{
"id": "...",
"run_id": "...",
"resource_id": "...",
"type": "callback.received",
"sequence": 7,
"occurred_at": "2026-09-19T09:14:02.118Z",
"data": {
"resource": "stripe_callback",
"method": "POST",
"path": "/",
"content_type": "application/json",
"byte_length": 812,
"sha256": "..."
}
}POST /v1/runs/{runId}/wait bloque jusqu'à ce qu'un événement postérieur à since corresponde, ou que le délai expire. L'attente lit d'abord la chronologie, si bien qu'un événement déjà survenu obtient une réponse immédiate, puis elle se réveille à l'arrivée de nouveaux événements.
curl -X POST https://api.ironfang.uk/rig/v1/runs/$RUN_ID/wait \
-H "Authorization: Bearer $IRONFANG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "email.received",
"resource": "customer_email",
"match": { "subject_contains": "Your order" },
"since": 0,
"timeout": "30s"
}'Un délai expiré est un 200 avec matched: false, jamais une erreur : rien ne s'est mal passé, la chose attendue n'est simplement pas encore arrivée, et next_since indique où reprendre. Les délais vont de 1 à 90 secondes (30 par défaut) ; bouclez avec next_since pour attendre plus longtemps. Déterministe : la même chronologie et la même requête renvoient toujours le même événement. Au plus 16 attentes peuvent être ouvertes en même temps par organisation.
Charges utiles
GET /v1/runs/{runId}/events/{eventId}/payload renvoie les octets exacts qu'un callback ou un message transportait, sous forme de pièce jointe opaque quoi que l'expéditeur ait déclaré, afin que le contenu de tiers ne soit jamais rendu sur l'origine de l'API. Le type de média déclaré figure dans X-Ironfang-Payload-Media-Type et le SHA-256 dans X-Ironfang-Payload-SHA256. Les octets de charge utile sont conservés 7 jours après la fin de l'exécution ; ensuite l'événement demeure et l'endpoint répond 410.
Catalogue des événements
Chaque type qu'un attendu ou une attente peut nommer, avec les champs de données qu'un match peut viser. Tous les événements portent aussi resource (le nom déclaré) lorsqu'il y en a un.
| Type | Quand | Données notables |
|---|---|---|
run.started | L'exécution a commencé. | suite_version, ttl_seconds, expires_at, external_id |
resource.allocated | Une fois par ressource. | name, type, expires_at |
email.received | Un message est arrivé pour une boîte de réception. | sender, recipient, subject, from, links, codes, message, transport |
callback.received | Une requête a atteint une URL de callback. | method, path, query, content_type, byte_length, sha256, source_ip, route |
callback.rejected | Une requête a été refusée, par exemple pour un corps dépassant la limite. | reason, limit_bytes |
callback.forwarded | Une livraison a été remise à un connecteur. | delivery_id, event_id, route, connector_id, attempt |
connector.request.completed | Le connecteur a signalé le résultat local. | outcome (delivered ou failed), status, headers, body_excerpt, duration_ms, error, delivery_id |
callback.replayed | Un callback enregistré a été rejoué à la demande. | event_id, replay (1, 2, ...), delivery_id, route, requested_by |
mock.request.received | Une requête a atteint un mock. | method, path, query, content_type, byte_length, matched, rule |
mock.response.sent | Le mock a répondu. | status, original_status, rule, delay_ms, request_event_id |
mock.rules.updated | Les règles ont été remplacées. | rules |
connector.connected, connector.disconnected | Une session de connecteur s'est ouverte ou fermée. | connector_id, name, routes, reason, requeued_deliveries |
fault.added, fault.removed, fault.injected | Une panne a été armée, désarmée ou déclenchée. | fault_id, type, fired, persistent, status, event_id |
expectation.passed, expectation.failed | Évalué à la clôture, un par attendu. | expectation, event |
run.completed, run.cancelled, run.expired | L'exécution s'est terminée. | outcome, passed, failed, total, reason |
Connecteur local
Un callback doté d'une connector.route est transmis à une application sur votre machine ou votre runner CI sans ouvrir de port entrant. Le binaire ironfang rig connect contacte la passerelle à wss://connect.rig.ironfang.uk/v1/connect, se lie aux libellés de route et adresse chaque requête transmise à la cible locale que vous avez indiquée pour ce libellé. Le résultat local revient et est enregistré comme connector.request.completed.
Créez un connecteur sur une exécution active. La réponse contient un jeton d'amorçage à usage unique qui expire au bout de dix minutes, l'URL de la passerelle et la ligne de commande à compléter. Le jeton apparaît ici et nulle part ailleurs.
curl -X POST https://api.ironfang.uk/rig/v1/runs/$RUN_ID/connectors \
-H "Authorization: Bearer $IRONFANG_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "name": "ci-runner-3", "routes": ["stripe"] }'
# Then, with the token in the environment rather than an argument:
IRONFANG_CONNECT_TOKEN=ift_boot_... ironfang rig connect \
--route stripe=http://127.0.0.1:8080/webhooks/stripeLe connecteur échange le jeton d'amorçage contre un identifiant de session lié à cette organisation, cette exécution et ces routes, qui ne vit pas plus longtemps que l'exécution. Les livraisons pour une route attendent qu'un connecteur la détienne, puis arrivent dans l'ordre, chacune avec un délai local de 30 secondes ; le résultat que signale le connecteur est définitif. Un connecteur qui décroche en cours d'exécution reprend avec son identifiant de session, et les livraisons auxquelles il n'avait pas répondu sont remises en file pour la session suivante avec leur compteur de tentatives incrémenté. GET /v1/runs/{runId}/connectors indique l'état de chaque connecteur et le nombre de livraisons encore en attente. Une exécution peut avoir jusqu'à 16 connecteurs.
Les requêtes transmises portent la méthode, le chemin, la query, les en-têtes et le corps d'origine, plus X-Ironfang-Delivery-ID, X-Ironfang-Event-ID et X-Ironfang-Route, pour que l'application puisse distinguer un rejeu ou un doublon d'une première livraison. Les trames sont limitées à 256 KiB.
Pannes
Une panne est une perturbation déterministe armée sur une ressource d'une exécution active avec POST /v1/runs/{runId}/faults. Elle se déclenche sur la prochaine observation à laquelle elle s'applique, count fois (une fois par défaut) ou, si elle est persistent, jusqu'à son retrait ou la fin de l'exécution. Chaque déclenchement est un événement fault.injected à côté de l'observation sur laquelle il a agi. Aucun hasard : les mêmes pannes face au même trafic donnent la même chronologie.
curl -X POST https://api.ironfang.uk/rig/v1/runs/$RUN_ID/faults \
-H "Authorization: Bearer $IRONFANG_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "type": "duplicate", "resource": "stripe_callback", "copies": 2 }'| type | Agit sur | Effet |
|---|---|---|
delay | Un callback avec une route de connecteur | La livraison est retenue pendant delay, au plus 30s, avant d'être transmise. |
duplicate | Un callback avec une route de connecteur | La livraison est transmise copies fois de plus (de 1 à 5, 1 par défaut), chaque copie avec son propre identifiant de livraison. |
drop | Un callback avec une route de connecteur | Le callback est enregistré mais jamais transmis. |
status_override | Un endpoint HTTP simulé | Le mock répond status quoi que disent ses règles ; le corps et les en-têtes restent inchangés et le statut d'origine est enregistré. |
reorder | Un callback avec une route de connecteur | Les livraisons sont retenues jusqu'à ce que batch d'entre elles (de 2 à 10) soient en attente, puis libérées de la dernière à la première, si bien que le connecteur les reçoit en ordre inverse. La panne se déclenche une fois par lot et nomme l'ordre ; un lot encore incomplet à la fin de l'exécution expire avec le résultat held. |
payload_mutation | Un callback avec une route de connecteur | La livraison porte un corps modifié par mutations, dans l'ordre : set ou remove à un JSON Pointer, replace de texte, ou truncate à une longueur. Le corps reçu reste intact sur la chronologie ; le corps envoyé est la charge utile de l'événement fault.injected, qui indique aussi quelles modifications ont été appliquées. |
connection_reset | Un endpoint HTTP simulé | La requête est enregistrée, puis la connexion est fermée sans réponse. En accès direct, l'appelant voit une réinitialisation ; via la périphérie publique, il voit la réponse bad gateway du proxy. Dans les deux cas, il n'y a pas de réponse valide. |
bandwidth_limit | Un endpoint HTTP simulé | Le corps est envoyé à bytes_per_second (de 64 à 1048576), par blocs d'un dixième de seconde. Un corps qui prendrait plus de 30 secondes est envoyé au débit qui convient, et l'événement indique qu'il a été plafonné. |
partial_response | Un endpoint HTTP simulé | Les en-têtes, avec la longueur de contenu complète, et les premiers bytes du corps sont envoyés, puis la connexion se ferme : l'appelant voit un corps tronqué. |
Une panne active de chaque type par ressource, et jusqu'à 64 pannes par exécution. Quand plusieurs s'appliquent à la même livraison, drop l'emporte, puis delay, puis duplicate ; un reorder retient la livraison quel que soit son delay, et une mutation de charge utile façonne chaque copie. Les pannes de mock agissent ensemble dans l'ordre où elles ont été armées : un remplacement de statut change le statut, et une réinitialisation, un bridage ou une coupure s'applique à ce qui est alors envoyé. DELETE /v1/runs/{runId}/faults/{faultId} en désarme une et enregistre fault.removed ; la ligne est conservée, car l'historique des pannes fait partie des preuves. Les pannes n'agissent jamais sur un rejeu, qui est un acte explicite du test lui-même.
Attendus et verdicts
Les attendus sont évalués quand l'exécution est terminée, sur l'ensemble de la chronologie. Chacun est satisfait si un événement de son type sur sa ressource satisfait son match, et le premier de ces événements est enregistré avec le verdict. Le résultat de l'exécution découle des verdicts : pass quand tous les attendus sont satisfaits, fail quand l'un d'eux échoue, none pour une suite sans attendus. Passez un résultat pour remplacer cette déduction quand votre propre harnais de test en sait davantage.
curl -X POST https://api.ironfang.uk/rig/v1/runs/$RUN_ID/finish \
-H "Authorization: Bearer $IRONFANG_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "npm test exited 0" }'{
"run": { "id": "...", "status": "finished", "outcome": "pass", ... },
"expectations": [
{ "id": "order_email", "resource": "customer_email", "event": "email.received",
"passed": true, "event_id": "...", "sequence": 9 },
{ "id": "stripe_forwarded", "resource": "stripe_callback",
"event": "connector.request.completed", "passed": true, "event_id": "...", "sequence": 12 }
]
}La clôture enregistre un expectation.passed ou un expectation.failed par attendu, puis run.completed. Une exécution annulée ou qui atteint son TTL se termine par run.cancelled ou run.expired, sans verdict. Envoyez un en-tête Idempotency-Key au démarrage d'une exécution pour qu'une étape de CI relancée récupère l'exécution déjà démarrée.
Rejeu
POST /v1/runs/{runId}/events/{eventId}/replay retransmet à sa route de connecteur un callback reçu par l'exécution, exactement tel qu'enregistré, pour prouver que l'application gère une répétition. L'événement doit être un callback.received sur une ressource dotée d'une route de connecteur, et l'exécution doit être active.
curl -X POST https://api.ironfang.uk/rig/v1/runs/$RUN_ID/events/$EVENT_ID/replay \
-H "Authorization: Bearer $IRONFANG_API_KEY"
{ "event": { "type": "callback.replayed", "data": { "event_id": "...", "replay": 1, ... } },
"delivery_id": "..." }Le rejeu est enregistré comme callback.replayed puis circule comme toute livraison : la chronologie montre ses propres callback.forwarded et connector.request.completed rattachés à l'identifiant de l'événement d'origine, et la complétion nomme le delivery_id que la réponse vous a donné. Les pannes armées n'agissent pas sur un rejeu. Au plus 200 rejeux par exécution ; un 422 not_replayable désigne un événement qui n'est pas un callback transmissible.
Paquet de preuves
POST /v1/runs/{runId}/evidence construit le paquet de preuves de l'exécution à partir de ce qu'elle a enregistré et le diffuse en ZIP. Il est en lecture seule : le paquet contient ce que l'appelant peut déjà lire événement par événement, emballé pour être joint à un ticket, un audit ou une version.
| Fichier | Contenu |
|---|---|
manifest.json | L'exécution, les compteurs, ainsi que la taille et le SHA-256 de chaque fichier. Écrit en dernier, si bien qu'un manifeste complet signifie un paquet complet. |
events.json | Toute la chronologie dans l'ordre de séquence. |
expectations.json | Chaque attendu avec son verdict une fois l'exécution terminée. |
faults.json, resources.json, definition.json | Les pannes avec le nombre de déclenchements de chacune, les ressources avec leurs adresses, et la version de suite que l'exécution a exécutée. |
messages/, requests/ | Chaque message reçu et chaque corps de callback, nommés par séquence et identifiant d'événement. |
signature.json | Une signature Ed25519 sur manifest.json tel qu'écrit, avec l'identifiant de la clé et la clé publique, quand la plateforme dispose d'une clé de signature ; le manifeste indique signing dans tous les cas. |
Limité à 10 000 événements et 256 MiB de charges utiles ; le manifeste indique quand une limite a joué et liste les charges utiles que la conservation avait déjà supprimées. Avec Accept: application/json, seul le manifeste est renvoyé, avec le chemin qui télécharge le paquet.
Preuve des actions
Chaque événement porte un hash : SHA-256 sur le hash de l'événement précédent, l'identifiant de l'exécution, la séquence, le type, l'horodatage et les données de l'événement en JSON canonique (clés dans l'ordre des octets, sans espaces, nombres tels qu'écrits), joints par des retours à la ligne. L'exécution porte la tête de la chaîne dans chain_head, le manifeste enregistre la chaîne qu'il a recalculée en construisant le paquet, et un octet modifié n'importe où rompt la chaîne à cet événement. Les événements antérieurs au hachage forment un préfixe non haché, que le rapport signale.
POST /v1/runs/{runId}/receipt est une déclaration signée de l'exécution : projet, suite et version, statut et résultat, chaque verdict, le nombre d'événements et la tête de la chaîne, signée sur son JSON canonique. GET /v1/evidence/keys publie les clés de signature par identifiant. Le paquet comme le reçu portent la clé avec laquelle ils ont été signés, si bien qu'ils se vérifient n'importe où :
ironfang rig evidence verify ironfang-rig-$RUN_ID.zip --key <base64 public key>
ironfang rig receipt $RUN_ID --key <base64 public key>La commande verify contrôle l'empreinte de chaque fichier par rapport au manifeste, recalcule la chaîne à partir de events.json et vérifie la signature ; avec --key, la signature doit provenir d'une clé en laquelle vous avez confiance, sans cette option c'est la clé portée par le paquet qui est utilisée, et le rapport le signale. Le code de sortie 3 signifie qu'une vérification a échoué.
La conservation supprime les charges utiles après 7 jours et les exécutions après 90. PUT /v1/runs/{runId}/hold avec { "until": "..." } (au plus un an à l'avance) conserve une exécution et tout ce qu'elle a enregistré jusqu'à cette date ; DELETE lève le gel. Les deux sont des événements sur la propre chronologie de l'exécution, retention.held et retention.released.
ironfang rig evidence $RUN_ID -o checkout-$RUN_ID.zip
# prints the bundle's SHA-256Ligne de commande
ironfang rig est un binaire statique unique pour Linux, macOS et Windows, publié avec un fichier de sommes de contrôle SHA-256 par version sur la page des versions. Il lit la clé dans IRONFANG_API_KEY ou --api-key-file, jamais dans un argument, et s'adresse à https://api.ironfang.uk/rig sauf si IRONFANG_API_URL indique autre chose.
ironfang rig sync [-f ironfang.rig.yaml]
ironfang rig run [-f file] [--ttl 30m] [--external-id id] [--output text|env|github|json] [-- command args...]
ironfang rig finish <run-id> [--outcome pass|fail|none] [--reason text]
ironfang rig status <run-id>
ironfang rig events <run-id> [--since 0] [--json]
ironfang rig wait <run-id> --type <event type> [--resource name] [--match key=value]... [--since 0] [--timeout 30s]
ironfang rig evidence <run-id> [-o ironfang-rig-<run-id>.zip]
ironfang rig replay <run-id> <event-id>
ironfang rig versionrun synchronise la suite, démarre une exécution et affiche ses adresses. Avec une commande après --, il exécute cette commande avec IRONFANG_RIG_RUN_ID et une variable IRONFANG_RIG_<RESOURCE> par ressource, puis termine l'exécution. --output env affiche ces affectations pour qu'un shell les charge ; --output github les écrit dans les sorties et l'environnement du job.
| Code de sortie | Signification |
|---|---|
| 0 | Succès ; pour run et finish, le résultat de l'exécution n'est pas fail. |
| 1 | Une erreur en communiquant avec l'API ou le système de fichiers. |
| 2 | Usage incorrect : un argument manquant ou une option invalide. |
| 3 | La commande après -- a échoué, ou le résultat de l'exécution est fail. |
| 4 | wait n'a vu aucun événement correspondant avant son délai. |
GitHub Actions
Deux actions composites du dépôt public ironfang-ltd/rig-action encapsulent la CLI. start synchronise le fichier de suite, démarre une exécution et exporte ses adresses comme sorties d'étape et variables d'environnement du job ; finish termine l'exécution, affiche les verdicts et fait échouer l'étape quand le résultat est fail. Stockez la clé comme secret du dépôt.
jobs:
integration:
runs-on: ubuntu-latest
env:
IRONFANG_API_KEY: ${{ secrets.IRONFANG_API_KEY }}
steps:
- uses: actions/checkout@v4
- id: test
uses: ironfang-ltd/rig-action/start@v1
with:
suite-file: ironfang.rig.yaml
ttl: 20m
- run: npm test
# IRONFANG_RIG_RUN_ID and IRONFANG_RIG_<RESOURCE> are in the environment
- if: always()
uses: ironfang-ltd/rig-action/finish@v1
with:
run-id: ${{ steps.test.outputs.run_id }}| Entrée | Action | Remarques |
|---|---|---|
suite-file | start | Chemin du fichier de suite. Par défaut ironfang.rig.yaml. |
ttl | start | Durée de vie de l'exécution, de 1m à 24h. Par défaut, celle de la suite. |
external-id | start | Votre référence pour l'exécution. Par défaut, l'identifiant de l'exécution du workflow. |
run-id | finish | Obligatoire. La sortie run_id de l'étape start. |
outcome | finish | pass, fail ou none pour remplacer les verdicts. Par défaut, le résultat déduit. |
fail-on | finish | fail (par défaut) ou never. |
version, binary | les deux | La version de ironfang rig à télécharger et à vérifier par rapport à ses sommes de contrôle (par défaut : la version avec laquelle l'action a été publiée), ou le chemin d'un binaire préconstruit. |
L'étape start expose aussi resources, un objet JSON associant chaque nom de ressource à son adresse, pour les étapes qui préfèrent le lire comme des données.
Outils MCP
Le serveur MCP Ironfang expose le même produit aux assistants de code, pour qu'un agent puisse démarrer une exécution, lire la chronologie, armer une panne et exporter les preuves sans quitter l'éditeur. Chaque outil est rattaché à l'organisation de la connexion et ne coûte aucun crédit. Les outils qui créent ou modifient quelque chose l'indiquent dans leurs métadonnées.
| Outil | Portée | Rôle |
|---|---|---|
rig.project.list, rig.project.create | rig:read, rig:write | Lister les projets ; en créer un par slug. |
rig.suite.list, rig.suite.get, rig.suite.upsert | rig:read, rig:write | Lire les suites et leur définition courante ; en créer ou en réviser une à partir d'une définition. |
rig.run.create, rig.run.get, rig.run.finish, rig.run.cancel | rig:run, rig:read | Démarrer une exécution et recevoir ses adresses ; la lire ; la terminer pour obtenir les verdicts ; l'annuler. |
rig.resource.create | rig:run | Allouer une ressource de plus sur une exécution active. |
rig.event.list, rig.event.wait | rig:read | Parcourir la chronologie page par page ; attendre un événement correspondant. |
rig.event.replay | rig:run | Rejouer un callback enregistré vers sa route. |
rig.fault.add, rig.fault.remove | rig:run | Armer et désarmer des pannes. |
rig.connector.prepare, rig.connector.status | rig:connector, rig:read | Créer un connecteur et recevoir la commande à lancer en local ; voir quels connecteurs sont en ligne et ce qui attend. |
rig.evidence.export, rig.evidence.receipt | rig:read | Le manifeste de preuves et où télécharger le paquet, ainsi qu'un reçu signé de ce que l'exécution a fait. |
Les octets de charge utile ne sont jamais renvoyés par la connexion ; les outils renvoient ce que la chronologie a enregistré et renvoient vers l'API pour le reste.
Limites et conservation
| Limite | Valeur |
|---|---|
| Durée de vie d'une exécution | De 1 minute à 24 heures ; 30 minutes par défaut |
| Ressources par suite | 32 |
| Attendus par suite | 64, jusqu'à 16 clés de match chacun |
| Messages par boîte de réception et par exécution | 500, chacun jusqu'à 10 MiB |
| Callbacks par exécution | 1000, corps jusqu'à 64 KiB chacun |
| Appels de mock par exécution | 5000 ; 32 règles, corps de 64 KiB et délai de 10 secondes par règle |
| Pannes par exécution | 64 ; délai jusqu'à 30 secondes ; jusqu'à 5 copies en double ; count jusqu'à 100 |
| Connecteurs par exécution | 16 ; délai local de 30 secondes par livraison ; trames de 256 KiB |
| Rejeux par exécution | 200 |
| Attentes ouvertes par organisation | 16 ; délais de 1 à 90 secondes |
| Événements par page | 500 |
| Paquet de preuves | 10 000 événements et 256 MiB de charges utiles |
| Conservation des charges utiles | 7 jours après la fin de l'exécution |
| Conservation des exécutions | 90 jours après la fin de l'exécution, puis l'exécution et sa chronologie sont supprimées |
Exportez le paquet de preuves avant que la conservation ne s'applique si une exécution doit lui survivre. Les suites, leurs versions et les projets persistent.
Référence de l'API
URL de base https://api.ironfang.uk/rig. Le document OpenAPI 3.1 à https://api.ironfang.uk/rig/openapi.yaml contient chaque schéma, exemple et erreur, avec des identifiants d'opération stables pour les clients générés. Les identifiants sont des UUID ; les listes se paginent avec cursor et limit (jusqu'à 100).
| Endpoint | Portée | Rôle |
|---|---|---|
GET /v1/projects | rig:read | Lister les projets. |
POST /v1/projects | rig:write | Créer un projet par slug. |
GET /v1/projects/{projectId} | rig:read | Obtenir un projet. |
GET /v1/suites | rig:read | Lister les suites, éventuellement par projet. |
POST /v1/suites | rig:write | Créer une suite avec sa première version. |
GET /v1/suites/{suiteId} | rig:read | Obtenir une suite avec sa version courante. |
PUT /v1/suites/{suiteId} | rig:write | Réviser la définition ; une définition inchangée ne crée pas de nouvelle version. |
GET /v1/suites/{suiteId}/versions | rig:read | Lister les versions d'une suite. |
POST /v1/suites/{suiteId}/runs | rig:run | Démarrer une exécution et allouer ses ressources. Respecte Idempotency-Key. |
GET /v1/runs | rig:read | Lister les exécutions, les plus récentes en premier. |
GET /v1/runs/{runId} | rig:read | Obtenir une exécution. |
POST /v1/runs/{runId}/finish | rig:run | Terminer l'exécution et évaluer ses attendus. |
POST /v1/runs/{runId}/cancel | rig:run | Annuler l'exécution sans verdict. |
GET /v1/runs/{runId}/resources | rig:read | Lister les ressources de l'exécution avec leurs adresses. |
POST /v1/runs/{runId}/resources | rig:run | Allouer une ressource de plus. |
PUT /v1/runs/{runId}/resources/{resourceId}/mock | rig:run | Remplacer les règles d'un mock. |
GET /v1/runs/{runId}/faults | rig:read | Lister les pannes de l'exécution et le nombre de déclenchements de chacune. |
POST /v1/runs/{runId}/faults | rig:run | Armer une panne. |
DELETE /v1/runs/{runId}/faults/{faultId} | rig:run | Désarmer une panne. |
GET /v1/runs/{runId}/connectors | rig:read | Lister les connecteurs et les livraisons en attente. |
POST /v1/runs/{runId}/connectors | rig:connector | Créer un connecteur et son jeton d'amorçage. |
GET /v1/runs/{runId}/events | rig:read | Lire la chronologie à partir de since. |
POST /v1/runs/{runId}/wait | rig:read | Attendre un événement correspondant. |
GET /v1/runs/{runId}/events/{eventId} | rig:read | Obtenir un événement. |
GET /v1/runs/{runId}/events/{eventId}/payload | rig:read | Télécharger les octets de charge utile d'un événement. |
POST /v1/runs/{runId}/events/{eventId}/replay | rig:run | Rejouer un callback enregistré. |
POST /v1/runs/{runId}/evidence | rig:read | Exporter le paquet de preuves ou son manifeste. |
GET /v1/usage | rig:read | Exécutions et événements sur une période, depuis le début du mois par défaut. |
GET /v1/environment | rig:read | Hôtes, passerelle, version du connecteur, chaque limite et les durées de conservation. |
GET /v1/home | rig:read | Compteurs, étapes de mise en route et exécutions récentes, tels que le portail les affiche. |
Interfaces pour machines
| Interface | Détails |
|---|---|
| Page produit | https://ironfang.uk/rig |
| Documentation | https://ironfang.uk/rig/docs |
| URL de base de l'API | https://api.ironfang.uk/rig |
| Contrat OpenAPI | https://api.ironfang.uk/rig/openapi.yaml. Le même contrat est servi en JSON à https://api.ironfang.uk/rig/openapi.json. |
| Authentification | Clé API de la plateforme comme jeton bearer |
| Erreurs | https://ironfang.uk/rig/docs#errors. Un corps JSON avec un code stable, un message, ce lien et l'identifiant de la requête. |
| MCP | Disponible. Projets et suites, exécutions et leurs ressources, la chronologie et les attentes, le rejeu, les pannes déterministes, l'amorçage du connecteur local, les manifestes de preuves et les reçus signés. Les outils sont nommés rig.*. Référence du serveur MCP ; chaque outil et chaque schéma, sans jeton, à /.well-known/ironfang-mcp.json |
| Découverte | /apis.json, /.well-known/api-catalog et /llms.txt |

