Schnellstart
Erstellen Sie im Ironfang-Portal einen API-Schlüssel mit Rig-Berechtigungen und committen Sie dann eine ironfang.rig.yaml neben der Anwendung. Die Datei legt fest, welche externen Identitäten ein Lauf braucht und was der Lauf beobachten muss.
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 }Der Kommandozeilen-Client synchronisiert die Datei, startet einen Lauf, übergibt die Adresse jeder Ressource an den Befehl nach --, führt ihn aus und schließt den Lauf mit einer Bewertung ab.
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/...Derselbe Lauf ist über HTTP verfügbar. Jede Anfrage trägt den Schlüssel als Bearer-Token, und die Basis-URL ist 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" }'Die vollständige OpenAPI-3.1-Beschreibung steht unter https://api.ironfang.uk/rig/openapi.yaml bereit.
Modell
Suites bleiben bestehen, Läufe sind kurzlebig, Ressourcen haben eine ausdrückliche Lebensdauer. Nichts davon führt Ihren Code aus: Ironfang Rig ist die Außenwelt, mit der Ihre Tests sprechen, und die Aufzeichnung dessen, was sie gesehen hat.
| Objekt | Was es ist |
|---|---|
| Projekt | Ein dauerhafter Container für eine Anwendung, benannt durch einen Slug. |
| Suite | Eine versionierte Definition von Ressourcen und Erwartungen innerhalb eines Projekts. Jede Revision wird mit ihrem SHA-256 aufbewahrt; ein Lauf nennt immer die Version, mit der er lief. |
| Lauf | Eine Ausführung der aktuellen Version einer Suite. Er ist active, bis er finished, cancelled oder durch seine TTL expired ist (Standard 30 Minuten, 1 Minute bis 24 Stunden). Ein abgeschlossener Lauf hat das Ergebnis pass, fail oder none. |
| Ressource | Eine externe Identität, die der Lauf erhält: ein Postfach, eine Callback-URL, ein Mock-HTTP-Endpunkt oder eine Route zu einem Connector. Nicht erratbar und nur diesem Lauf zugeordnet, aus dem Internet nur erreichbar, solange der Lauf aktiv ist. |
| Ereignis | Eine unveränderliche Beobachtung auf der Zeitleiste des Laufs, mit einer Sequenznummer, die lückenlos bei 1 beginnt. Die Zeitleiste wird nur fortgeschrieben und ist nach dem Ende des Laufs schreibgeschützt. |
| Erwartung | Eine deterministische Bedingung an die Zeitleiste, mit der Suite gespeichert und bewertet, wenn der Lauf abgeschlossen wird. |
| Störung | Ein deterministischer Eingriff, scharf geschaltet auf einer Ressource: einen weitergeleiteten Callback verzögern, duplizieren, verwerfen, umordnen oder seinen Body ändern; den Status eines Mocks überschreiben, seine Verbindung zurücksetzen, seinen Body drosseln oder ihn vorzeitig abbrechen. |
Alles ist an eine Organisation gebunden. Ein Objekt, das zu einer anderen Organisation gehört, wird als nicht gefunden gemeldet, nie als verboten.
API-Schlüssel und Berechtigungen
Plattform-API-Schlüssel werden im Portal erstellt und beginnen mit if_live_. Die Berechtigungen eines Schlüssels legen fest, was er darf, und er handelt nur in der Organisation, für die er erstellt wurde. Senden Sie ihn als Bearer-Token.
Authorization: Bearer if_live_...rig:readProjekte, Suites, Läufe, Ressourcen, Störungen, Connectors und Ereignisse auflisten und lesen; auf der Zeitleiste warten; Nachweise exportierenrig:writeProjekte und Suites anlegen und überarbeitenrig:runLäufe starten, abschließen und abbrechen; Ressourcen zuweisen; Mock-Regeln ändern; Störungen scharf schalten; Callbacks wiederholenrig:connectorConnectors und ihre Bootstrap-Tokens erstellenrig:*Alles oben Genannte
Ein Warden-Benutzertoken wird ebenfalls akzeptiert, mit der handelnden Organisation in X-Ironfang-Tenant; jede Route braucht dann die passende Mandantenbefugnis (rig.read, rig.write, rig.run, rig.connector).
Fehler
Jeder Fehler ist ein JSON-Objekt mit einem stabilen Code, einer Meldung für Menschen und der Anfrage-ID, die Sie dem Support nennen.
{
"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 ist ein Link auf diesen Abschnitt, und request_id wiederholt den Antwort-Header X-Ironfang-Request-ID.
| Status | Code | Bedeutung |
|---|---|---|
| 400 | invalid_json, invalid_query | Der Body ist nicht genau ein strikter JSON-Wert der dokumentierten Form, oder ein Abfrageparameter ist unbekannt, doppelt oder fehlerhaft. |
| 401 | unauthorized, invalid_api_key | Keine Anmeldedaten, oder solche, die sich nicht auflösen lassen. |
| 403 | forbidden, insufficient_scope | Dem Schlüssel fehlt die Berechtigung, dem Benutzer fehlt die Befugnis, oder die Anfrage nennt eine andere Organisation. |
| 404 | not_found | Kein solches Objekt in dieser Organisation. |
| 409 | conflict, archived, run_not_active | Ein Slug ist vergeben, das Ziel ist archiviert, oder der Lauf ist bereits beendet. |
| 410 | payload_retired | Das Ereignis existiert, aber seine Payload-Bytes haben die Aufbewahrungsfrist überschritten. |
| 422 | invalid_request, not_replayable | Ein Feld ist ungültig; die Meldung nennt es. |
| 429 | too_many_waiters, replay_limit, connector_limit, fault_limit | Eine Grenze pro Organisation oder pro Lauf wurde erreicht; die Meldung sagt, welche. Die Callback-, Mock- und Mail-Adressen eines Laufs antworten auf dieselbe Weise mit run_limit, sobald der Lauf sein Limit erreicht hat. |
Die Suite-Datei
ironfang.rig.yaml liegt im Repository neben der Anwendung, die sie testet. Sie enthält genau die Definition, die die API speichert, sodass ein Lauf aus genau dem entsteht, was ein Entwickler committet. Beim ersten Synchronisieren legt die Datei Projekt und Suite an, und bei jeder Änderung der Definition wird eine neue Suite-Version aufgezeichnet.
| Feld | Typ | Hinweise |
|---|---|---|
version | integer | Immer 1. |
project | string | Slug des Projekts. Wird beim ersten Synchronisieren angelegt. |
suite | string | Slug der Suite, eindeutig innerhalb des Projekts. |
name | string | Anzeigename, bis zu 120 Zeichen. |
defaults.run_ttl | duration | Standard-Lebensdauer eines Laufs, 1m bis 24h. Standard ist 30m. |
resources | object | Name auf Ressourcenspezifikation, 1 bis 32 Einträge. Namen entsprechen ^[a-z][a-z0-9_]{0,63}$ und werden zu Suffixen von Umgebungsvariablen. |
expectations | array | Bis zu 64 Bedingungen, jede mit einer id, einem resource-Namen, einem event-Typ und einem optionalen match. |
Ressourcenspezifikationen
| type | Zusätzliche Felder | Was der Lauf erhält |
|---|---|---|
email | keine | Eine Postfachadresse unter inbox.rig.ironfang.uk. |
callback | connector.route (optional) | Eine öffentliche URL, die jede Anfrage aufzeichnet. Mit einer Route wird jede Anfrage zusätzlich an Ihren Connector weitergeleitet. |
mock_http | rules (optional, bis zu 32) | Eine öffentliche URL, die anhand geordneter Regeln antwortet. |
connector_route | route | Ein Routen-Label ohne öffentliche Adresse, an das sich Connectors binden. |
Routen-Labels entsprechen ^[a-z0-9][a-z0-9-]{0,62}$. Die Plattform nennt immer nur ein Label; wohin es zeigt, wird auf der Kommandozeile des Connectors festgelegt und verlässt Ihren Rechner nie.
Abgleich
Ein match-Objekt ist eine Menge von Bedingungen an die Felder der obersten Ebene in den Daten eines Ereignisses, und jeder Schlüssel muss zutreffen. Ein einfacher Schlüssel wird als JSON verglichen, sodass Zahlen, Booleans, Strings und ganze Objekte nach Wert verglichen werden. Ein Schlüssel, der auf _contains endet, verlangt, dass das Feld ein String ist, der den Wert enthält. Dieselbe Regel wertet die Erwartungen der Suite, den Warte-Endpunkt und --match der CLI aus, sodass eine Bedingung überall dasselbe bedeutet. Bis zu 16 Schlüssel mit je 4096 Zeichen.
Ressourcen
Beim Start eines Laufs wird jede deklarierte Ressource zugewiesen. Jede ist nicht erratbar, gehört allein diesem Lauf und nimmt keine Aktivität mehr an, sobald der Lauf endet. Auf einem aktiven Lauf lassen sich mit POST /v1/runs/{runId}/resources weitere zuweisen.
E-Mail-Postfächer
Eine email-Ressource ist eine Adresse wie run-k7c3m2wp9e4q5r6t@inbox.rig.ironfang.uk. E-Mails dafür werden von mx.rig.ironfang.uk empfangen, geparst und als email.received aufgezeichnet, mit Absender, Empfänger, Betreff, Links, Bestätigungscodes, Anhängen und Transportdetails. Die Rohnachricht wird als Payload des Ereignisses aufbewahrt. Nachrichten bis 10 MiB und 500 Nachrichten pro Lauf werden angenommen; alles darüber wird bereits bei der SMTP-Übergabe abgelehnt, sodass der Absender die Rückweisung sieht.
Jede Nachricht wird außerdem so geprüft, wie es ein empfangender Mailserver tun würde: SPF für die sendende Adresse gegen die Domain des Umschlagabsenders, DKIM für jede enthaltene Signatur und DMARC für die From-Domain mit der Ausrichtung und Richtlinie, die ihr Eintrag verlangt. Die Ergebnisse werden am Ereignis als authentication aufgezeichnet (spf, dkim[], dmarc mit Domain, Richtlinie, Ausrichtung und Gründen) und als die einwortigen Felder spf, dkim und dmarc herausgelöst, sodass eine Erwartung oder ein Wartevorgang nach { "dmarc": "pass" } fragen kann. Sie beobachten, was der Absender zum Zeitpunkt des Empfangs veröffentlicht hatte: Ein DNS-Fehler ist temperror, nie eine Bewertung.
Callback-URLs
Eine callback-Ressource ist eine URL wie https://hooks.rig.ironfang.uk/h/.... Jede Methode und jeder Pfad darunter werden angenommen. Die Anfrage wird als callback.received aufgezeichnet, mit Methode, Pfad, Query, Content-Type, Bytelänge und SHA-256, und der Absender erhält sofort eine 200 mit der Ereignis-ID. Die exakten Bytes sind über den Payload-Endpunkt des Ereignisses abrufbar. Bodys über 64 KiB werden mit 413 abgelehnt und als callback.rejected aufgezeichnet; ein Lauf nimmt bis zu 1000 Callbacks an.
{ "received": true, "run_id": "...", "event_id": "...", "sequence": 7 }Mit einer connector.route wird jede aufgezeichnete Anfrage außerdem für diese Route eingereiht und über Ihren Connector weitergeleitet; siehe Lokaler Connector.
Mock-HTTP-Endpunkte
Eine mock_http-Ressource ist eine Basis-URL wie https://mock.rig.ironfang.uk/m/.... Anfragen darunter beantwortet die erste Regel, deren Match zutrifft; ohne Treffer lautet die Antwort 404 mit dem Code no_mock_rule. Jede Anfrage wird als mock.request.received und ihre Antwort als mock.response.sent mit der passenden Regel aufgezeichnet. Solange der Lauf aktiv ist, lassen sich die Regeln mit PUT /v1/runs/{runId}/resources/{resourceId}/mock ersetzen, was mock.rules.updated aufzeichnet.
| Regelfeld | Hinweise |
|---|---|
match.method | Eine HTTP-Methode, oder * bzw. weggelassen für jede. |
match.path | Exakter Pfad unter der Mock-URL, ein Präfix, das auf /* endet, oder eine Vorlage wie /v1/pets/{id}, deren Segmente in geschweiften Klammern auf jedes einzelne Segment passen; weggelassen für jeden. |
match.headers | Header, die mit genau diesen Werten vorhanden sein müssen. |
match.json | Felder der obersten Ebene, denen ein JSON-Anfrage-Body gleichen muss. |
respond.status | Pflichtfeld, 100 bis 599. |
respond.headers | Antwort-Header. |
respond.body oder respond.json | Ein Text-Body bis 64 KiB, oder ein JSON-Body, der den Content-Type setzt, sofern kein Header es tut. |
respond.delay | Wird vor der Antwort zurückgehalten, höchstens 10s. |
respond.template | Body und Header-Werte aus der Anfrage rendern: {{request.method}}, {{request.path}}, {{request.query.name}}, {{request.header.Name}}, {{request.body}}, {{request.json.a.b.0}}, {{run.id}}, {{resource.name}}, {{step}}, {{received_at}}. In einem JSON-Body steht ein Platzhalter in einem String und wird dafür maskiert; ein unbekannter Name wird schon beim Schreiben der Regeln abgelehnt. |
sequence, repeat | Statt respond: 2 bis 16 Antworten, die die Regel ihren Aufrufen der Reihe nach gibt, danach wieder die letzte oder, mit repeat: cycle, wieder von vorn. Das Antwortereignis zeichnet den step auf; das Ersetzen der Regeln startet jede Sequenz neu. |
Deterministisch: Dieselbe Anfrage gegen dieselben Regeln im selben Schritt erhält dieselbe Antwort, Verzögerung eingeschlossen. Ein Lauf darf bis zu 5000 Mock-Aufrufe machen.
Ein Mock kann statt Regeln eine dokumentierte API vertreten: Geben Sie der Ressource openapi.file (ein Pfad neben der Suite-Datei, den die CLI einbettet) oder openapi.document (der OpenAPI-3-Text, JSON oder YAML, bis 256 KiB). Pro Operation wird in Dokumentreihenfolge eine Regel abgeleitet: Die Pfadvorlage ist der Match, die niedrigste 2xx- oder die Default-Antwort die Antwort, und das dokumentierte Beispiel oder ein aus dem Schema gebildeter Wert (zuerst enum, formatgerechte Strings, Zahlen mit dem Wert Null, ein Array-Element) der Body. Referenzen werden innerhalb des Dokuments aufgelöst, und nichts wird nachgeladen. Ein Mock umfasst höchstens 32 Operationen; nennen Sie die, die eine Suite braucht, in openapi.include als GET /pets/{id}, und setzen Sie openapi.prefer: schema, um die Beispiele zu ignorieren.
Connector-Routen
Eine connector_route hat keine öffentliche Adresse. Sie existiert, damit sich ein Connector an das Label binden und Callbacks es nennen können. Die meisten Suites deklarieren die Route direkt am Callback und brauchen nie eine eigene Ressource.
Zeitleiste und Warten
GET /v1/runs/{runId}/events?since=0&limit=100 liefert die Ereignisse des Laufs in Sequenzreihenfolge nach since, bis zu 500 auf einmal, mit next_since zum Fortsetzen. Sequenzen beginnen lückenlos bei 1 und ändern sich nie, sodass dieselbe Anfrage immer dieselben Ereignisse liefert. Payloads, die größer sind als das, was ein Ereignis trägt, werden über blob_ref referenziert und nie eingebettet.
{
"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 blockiert, bis ein Ereignis nach since zutrifft oder das Timeout abläuft. Der Wartevorgang liest zuerst die Zeitleiste, sodass ein bereits eingetretenes Ereignis sofort beantwortet wird, und wacht dann auf, sobald neue Ereignisse eintreffen.
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"
}'Ein Timeout ist eine 200 mit matched: false, nie ein Fehler: Es ist nichts schiefgegangen, das Erwartete ist nur noch nicht eingetreten, und next_since sagt, wo es weitergeht. Timeouts reichen von 1 bis 90 Sekunden (Standard 30); für längeres Warten wiederholen Sie den Aufruf mit next_since. Deterministisch: Dieselbe Zeitleiste und dieselbe Anfrage liefern immer dasselbe Ereignis. Pro Organisation dürfen höchstens 16 Wartevorgänge gleichzeitig offen sein.
Payloads
GET /v1/runs/{runId}/events/{eventId}/payload liefert die exakten Bytes, die ein Callback oder eine Nachricht trug, als opaken Anhang, gleich was der Absender angegeben hat, sodass Inhalte Dritter nie auf dem API-Origin gerendert werden. Der angegebene Medientyp steht in X-Ironfang-Payload-Media-Type und der SHA-256 in X-Ironfang-Payload-SHA256. Payload-Bytes werden nach dem Ende des Laufs 7 Tage aufbewahrt; danach bleibt das Ereignis bestehen, und der Endpunkt antwortet mit 410.
Ereigniskatalog
Jeder Typ, den eine Erwartung oder ein Wartevorgang nennen kann, mit den Datenfeldern, die ein Match ansprechen kann. Alle Ereignisse tragen außerdem resource (den deklarierten Namen), wo es einen gibt.
| Typ | Wann | Wichtige Daten |
|---|---|---|
run.started | Der Lauf hat begonnen. | suite_version, ttl_seconds, expires_at, external_id |
resource.allocated | Einmal pro Ressource. | name, type, expires_at |
email.received | Eine Nachricht ist für ein Postfach eingegangen. | sender, recipient, subject, from, links, codes, message, transport |
callback.received | Eine Anfrage hat eine Callback-URL erreicht. | method, path, query, content_type, byte_length, sha256, source_ip, route |
callback.rejected | Eine Anfrage wurde abgelehnt, etwa wegen eines Bodys über dem Limit. | reason, limit_bytes |
callback.forwarded | Eine Zustellung wurde an einen Connector übergeben. | delivery_id, event_id, route, connector_id, attempt |
connector.request.completed | Der Connector hat das lokale Ergebnis gemeldet. | outcome (delivered oder failed), status, headers, body_excerpt, duration_ms, error, delivery_id |
callback.replayed | Ein aufgezeichneter Callback wurde auf Anforderung wiederholt. | event_id, replay (1, 2, ...), delivery_id, route, requested_by |
mock.request.received | Eine Anfrage hat einen Mock erreicht. | method, path, query, content_type, byte_length, matched, rule |
mock.response.sent | Der Mock hat geantwortet. | status, original_status, rule, delay_ms, request_event_id |
mock.rules.updated | Die Regeln wurden ersetzt. | rules |
connector.connected, connector.disconnected | Eine Connector-Sitzung wurde geöffnet oder geschlossen. | connector_id, name, routes, reason, requeued_deliveries |
fault.added, fault.removed, fault.injected | Eine Störung wurde scharf geschaltet, entschärft oder ausgelöst. | fault_id, type, fired, persistent, status, event_id |
expectation.passed, expectation.failed | Beim Abschluss bewertet, eines pro Erwartung. | expectation, event |
run.completed, run.cancelled, run.expired | Der Lauf ist beendet. | outcome, passed, failed, total, reason |
Lokaler Connector
Ein Callback mit einer connector.route wird an eine Anwendung auf Ihrem Rechner oder CI-Runner weitergeleitet, ohne einen eingehenden Port zu öffnen. Die Binärdatei ironfang rig connect verbindet sich mit dem Gateway unter wss://connect.rig.ironfang.uk/v1/connect, bindet Routen-Labels und stellt jede weitergeleitete Anfrage an das lokale Ziel, das Sie für dieses Label angegeben haben. Das lokale Ergebnis wird zurückübertragen und als connector.request.completed aufgezeichnet.
Erstellen Sie einen Connector auf einem aktiven Lauf. Die Antwort enthält ein Bootstrap-Token zur einmaligen Verwendung, das nach zehn Minuten abläuft, die Gateway-URL und die zu ergänzende Kommandozeile. Das Token erscheint hier und nirgendwo sonst.
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/stripeDer Connector tauscht das Bootstrap-Token gegen ein Sitzungs-Credential, das an diese Organisation, diesen Lauf und diese Routen gebunden ist und nicht länger gilt als der Lauf. Zustellungen für eine Route warten, bis ein Connector sie hält, und kommen dann der Reihe nach an, jede mit einem lokalen Timeout von 30 Sekunden; das Ergebnis, das der Connector meldet, ist endgültig. Ein Connector, dessen Verbindung mitten im Lauf abbricht, setzt mit seinem Sitzungs-Credential fort, und Zustellungen, die er nicht beantwortet hatte, werden mit erhöhtem Versuchszähler für die nächste Sitzung erneut eingereiht. GET /v1/runs/{runId}/connectors meldet den Zustand jedes Connectors und wie viele Zustellungen noch warten. Ein Lauf kann bis zu 16 Connectors haben.
Weitergeleitete Anfragen tragen die ursprüngliche Methode, Pfad, Query, Header und Body, dazu X-Ironfang-Delivery-ID, X-Ironfang-Event-ID und X-Ironfang-Route, sodass die Anwendung eine Wiederholung oder ein Duplikat von einer ersten Zustellung unterscheiden kann. Frames sind auf 256 KiB begrenzt.
Störungen
Eine Störung ist ein deterministischer Eingriff, der mit POST /v1/runs/{runId}/faults auf einer Ressource eines aktiven Laufs scharf geschaltet wird. Sie löst bei der nächsten Beobachtung aus, auf die sie zutrifft, count-mal (standardmäßig einmal) oder, wenn persistent, bis sie entfernt wird oder der Lauf endet. Jedes Auslösen ist ein fault.injected-Ereignis neben der Beobachtung, auf die es gewirkt hat. Kein Zufall: Dieselben Störungen bei demselben Datenverkehr ergeben dieselbe Zeitleiste.
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 | Wirkt auf | Effekt |
|---|---|---|
delay | Einen Callback mit Connector-Route | Die Zustellung wird für delay, höchstens 30s, zurückgehalten, bevor sie weitergeleitet wird. |
duplicate | Einen Callback mit Connector-Route | Die Zustellung wird copies-mal zusätzlich weitergeleitet (1 bis 5, Standard 1), jede mit eigener Zustellungs-ID. |
drop | Einen Callback mit Connector-Route | Der Callback wird aufgezeichnet, aber nie weitergeleitet. |
status_override | Einen Mock-HTTP-Endpunkt | Der Mock antwortet mit status, gleich was seine Regeln sagten; Body und Header bleiben unverändert, und der ursprüngliche Status wird aufgezeichnet. |
reorder | Einen Callback mit Connector-Route | Zustellungen werden zurückgehalten, bis batch von ihnen (2 bis 10) warten, und dann von der letzten zur ersten freigegeben, sodass der Connector sie in umgekehrter Reihenfolge erhält. Die Störung löst einmal pro Batch aus und nennt die Reihenfolge; ein Batch, der beim Ende des Laufs noch unvollständig ist, verfällt mit dem Ergebnis held. |
payload_mutation | Einen Callback mit Connector-Route | Die Zustellung trägt einen durch mutations veränderten Body, der Reihe nach: set oder remove an einem JSON Pointer, replace von Text oder truncate auf eine Länge. Der empfangene Body bleibt unverändert auf der Zeitleiste; der gesendete Body ist die Payload des fault.injected-Ereignisses, das auch nennt, welche Änderungen angewendet wurden. |
connection_reset | Einen Mock-HTTP-Endpunkt | Die Anfrage wird aufgezeichnet, dann wird die Verbindung ohne Antwort geschlossen. Direkt sieht der Aufrufer einen Reset; über den öffentlichen Edge sieht er die Bad-Gateway-Antwort des Proxys. So oder so gibt es keine gültige Antwort. |
bandwidth_limit | Einen Mock-HTTP-Endpunkt | Der Body wird mit bytes_per_second (64 bis 1048576) gesendet, in Blöcken von je einer Zehntelsekunde. Ein Body, der länger als 30 Sekunden bräuchte, wird mit der Rate gesendet, die hineinpasst, und das Ereignis vermerkt die Begrenzung. |
partial_response | Einen Mock-HTTP-Endpunkt | Die Header mit der vollen Content-Length und die ersten bytes des Bodys werden gesendet, dann schließt die Verbindung: Der Aufrufer sieht einen abgeschnittenen Body. |
Eine aktive Störung je Typ pro Ressource und bis zu 64 Störungen pro Lauf. Wenn mehrere auf dieselbe Zustellung zutreffen, gewinnt drop, dann delay, dann duplicate; ein reorder hält die Zustellung unabhängig von ihrem delay zurück, und eine Payload-Mutation formt jede Kopie. Die Mock-Störungen wirken zusammen in der Reihenfolge, in der sie scharf geschaltet wurden: Ein Status-Override ändert den Status, und ein Reset, eine Drosselung oder ein Abbruch gilt für das, was dann gesendet wird. DELETE /v1/runs/{runId}/faults/{faultId} entschärft eine Störung und zeichnet fault.removed auf; der Datensatz bleibt erhalten, weil die Störungshistorie ein Nachweis ist. Störungen wirken nie auf eine Wiederholung, denn sie ist ein ausdrücklicher Schritt des Tests selbst.
Erwartungen und Bewertungen
Erwartungen werden bewertet, wenn der Lauf abgeschlossen wird, und zwar gegen die gesamte Zeitleiste. Jede ist erfüllt, wenn irgendein Ereignis ihres Typs auf ihrer Ressource ihren Match erfüllt, und das erste solche Ereignis wird mit der Bewertung aufgezeichnet. Das Ergebnis des Laufs wird aus den Bewertungen abgeleitet: pass, wenn jede Erwartung erfüllt ist, fail, wenn eine nicht erfüllt ist, none für eine Suite ohne Erwartungen. Übergeben Sie ein Ergebnis, um die Ableitung zu überschreiben, wenn Ihr eigenes Test-Harness es besser weiß.
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 }
]
}Der Abschluss zeichnet pro Erwartung ein expectation.passed oder expectation.failed auf und danach run.completed. Ein Lauf, der abgebrochen wird oder seine TTL erreicht, endet mit run.cancelled oder run.expired und ohne Bewertungen. Senden Sie beim Start eines Laufs einen Idempotency-Key-Header, damit ein wiederholter CI-Schritt den bereits gestarteten Lauf zurückerhält.
Wiederholung
POST /v1/runs/{runId}/events/{eventId}/replay leitet einen Callback, den der Lauf empfangen hat, erneut an seine Connector-Route weiter, genau wie aufgezeichnet, um nachzuweisen, dass die Anwendung eine Wiederholung verkraftet. Das Ereignis muss ein callback.received auf einer Ressource mit Connector-Route sein, und der Lauf muss aktiv sein.
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": "..." }Die Wiederholung wird als callback.replayed aufgezeichnet und läuft dann wie jede Zustellung: Die Zeitleiste zeigt ihr eigenes callback.forwarded und connector.request.completed zur ursprünglichen Ereignis-ID, und der Abschluss nennt die delivery_id, die Ihnen die Antwort gegeben hat. Scharf geschaltete Störungen wirken nicht auf eine Wiederholung. Höchstens 200 Wiederholungen pro Lauf; ein 422 not_replayable bezeichnet ein Ereignis, das kein weiterleitbarer Callback ist.
Nachweispaket
POST /v1/runs/{runId}/evidence erstellt das Nachweispaket des Laufs aus dem, was er aufgezeichnet hat, und streamt es als ZIP. Es ist schreibgeschützt: Das Paket enthält, was der Aufrufer ohnehin Ereignis für Ereignis lesen kann, so verpackt, dass es an ein Ticket, ein Audit oder ein Release angehängt werden kann.
| Datei | Inhalt |
|---|---|
manifest.json | Der Lauf, Zählwerte sowie Größe und SHA-256 jeder Datei. Wird zuletzt geschrieben, sodass ein vollständiges Manifest ein vollständiges Paket bedeutet. |
events.json | Die gesamte Zeitleiste in Sequenzreihenfolge. |
expectations.json | Jede Erwartung mit ihrer Bewertung, sobald der Lauf abgeschlossen ist. |
faults.json, resources.json, definition.json | Die Störungen mit der Anzahl ihrer Auslösungen, die Ressourcen mit ihren Adressen und die Suite-Version, die der Lauf ausgeführt hat. |
messages/, requests/ | Jede empfangene Nachricht und jeder Callback-Body, benannt nach Sequenz und Ereignis-ID. |
signature.json | Eine Ed25519-Signatur über manifest.json, genau wie geschrieben, mit Schlüssel-ID und öffentlichem Schlüssel, sofern die Plattform einen Signaturschlüssel hat; das Manifest nennt signing in jedem Fall. |
Begrenzt auf 10.000 Ereignisse und 256 MiB Payloads; das Manifest vermerkt, wenn eine Grenze gegriffen hat, und listet Payloads auf, die die Aufbewahrung bereits entfernt hatte. Mit Accept: application/json wird nur das Manifest zurückgegeben, mit dem Pfad, über den sich das Paket herunterladen lässt.
Nachweis der Vorgänge
Jedes Ereignis trägt einen hash: SHA-256 über den Hash des vorherigen Ereignisses, die Lauf-ID, die Sequenz, den Typ, den Zeitstempel und die Daten des Ereignisses in kanonischem JSON (Schlüssel in Bytereihenfolge, ohne Leerraum, Zahlen wie geschrieben), durch Zeilenumbrüche verbunden. Der Lauf trägt den Kopf der Kette als chain_head, das Manifest zeichnet die Kette auf, die es beim Erstellen des Pakets neu berechnet hat, und ein geändertes Byte an beliebiger Stelle bricht die Kette an diesem Ereignis. Ereignisse aus der Zeit vor Einführung der Hashes bilden ein Präfix ohne Hash, das der Bericht nennt.
POST /v1/runs/{runId}/receipt ist eine signierte Aussage über den Lauf: Projekt, Suite und Version, Status und Ergebnis, jede Bewertung, die Anzahl der Ereignisse und der Kopf der Kette, signiert über ihr kanonisches JSON. GET /v1/evidence/keys veröffentlicht die Signaturschlüssel nach ID. Sowohl das Paket als auch die Quittung tragen den Schlüssel, mit dem sie signiert wurden, sodass sie sich überall prüfen lassen:
ironfang rig evidence verify ironfang-rig-$RUN_ID.zip --key <base64 public key>
ironfang rig receipt $RUN_ID --key <base64 public key>Der Befehl verify prüft den Digest jeder Datei gegen das Manifest, berechnet die Kette aus events.json neu und prüft die Signatur; mit --key muss die Signatur von einem Schlüssel stammen, dem Sie vertrauen, ohne diese Option wird der Schlüssel verwendet, den das Paket mitbringt, und der Bericht sagt das. Exit-Code 3 bedeutet, dass eine Prüfung fehlgeschlagen ist.
Die Aufbewahrung entfernt Payloads nach 7 Tagen und Läufe nach 90. PUT /v1/runs/{runId}/hold mit { "until": "..." } (höchstens ein Jahr im Voraus) bewahrt einen Lauf und alles, was er aufgezeichnet hat, bis dahin auf; DELETE hebt die Sperre auf. Beides sind Ereignisse auf der eigenen Zeitleiste des Laufs, retention.held und retention.released.
ironfang rig evidence $RUN_ID -o checkout-$RUN_ID.zip
# prints the bundle's SHA-256Kommandozeile
ironfang rig ist eine einzelne statische Binärdatei für Linux, macOS und Windows, veröffentlicht mit einer SHA-256-Prüfsummendatei pro Release auf der Release-Seite. Sie liest den Schlüssel aus IRONFANG_API_KEY oder --api-key-file, nie aus einem Argument, und spricht mit https://api.ironfang.uk/rig, sofern IRONFANG_API_URL nichts anderes sagt.
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 synchronisiert die Suite, startet einen Lauf und gibt seine Adressen aus. Mit einem Befehl nach -- führt es diesen Befehl mit IRONFANG_RIG_RUN_ID und einer Variablen IRONFANG_RIG_<RESOURCE> pro Ressource aus und schließt den Lauf danach ab. --output env gibt diese Zuweisungen aus, damit eine Shell sie einlesen kann; --output github schreibt sie in die Outputs und die Umgebung des Jobs.
| Exit-Code | Bedeutung |
|---|---|
| 0 | Erfolg; bei run und finish ist das Ergebnis des Laufs nicht fail. |
| 1 | Ein Fehler bei der Kommunikation mit der API oder dem Dateisystem. |
| 2 | Falsche Verwendung: ein fehlendes Argument oder ein ungültiges Flag. |
| 3 | Der Befehl nach -- ist fehlgeschlagen, oder das Ergebnis des Laufs ist fail. |
| 4 | wait hat vor seinem Timeout kein passendes Ereignis gesehen. |
GitHub Actions
Zwei zusammengesetzte Actions im öffentlichen Repository ironfang-ltd/rig-action kapseln die CLI. start synchronisiert die Suite-Datei, startet einen Lauf und exportiert seine Adressen als Step-Outputs und Umgebungsvariablen des Jobs; finish schließt den Lauf ab, gibt die Bewertungen aus und lässt den Schritt fehlschlagen, wenn das Ergebnis fail ist. Speichern Sie den Schlüssel als Repository-Secret.
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 }}| Input | Action | Hinweise |
|---|---|---|
suite-file | start | Pfad zur Suite-Datei. Standard ironfang.rig.yaml. |
ttl | start | Lebensdauer des Laufs, 1m bis 24h. Standard aus der Suite. |
external-id | start | Ihre Referenz für den Lauf. Standard ist die ID des Workflow-Laufs. |
run-id | finish | Pflichtfeld. Der Output run_id des Start-Schritts. |
outcome | finish | pass, fail oder none, um die Bewertungen zu überschreiben. Standard ist das abgeleitete Ergebnis. |
fail-on | finish | fail (Standard) oder never. |
version, binary | beide | Das Release von ironfang rig, das heruntergeladen und gegen seine Prüfsummen verifiziert wird (Standard: das Release, mit dem die Action erstellt wurde), oder der Pfad zu einer vorab gebauten Binärdatei. |
Der Start-Schritt stellt außerdem resources bereit, ein JSON-Objekt von Ressourcenname auf Adresse, für Schritte, die es lieber als Daten lesen.
MCP-Tools
Der Ironfang MCP-Server stellt dasselbe Produkt Coding-Assistenten zur Verfügung, sodass ein Agent einen Lauf starten, die Zeitleiste lesen, eine Störung scharf schalten und die Nachweise exportieren kann, ohne den Editor zu verlassen. Jedes Tool ist an die Organisation der Verbindung gebunden und kostet keine Credits. Tools, die etwas anlegen oder ändern, sagen das in ihren Metadaten.
| Tool | Berechtigung | Funktion |
|---|---|---|
rig.project.list, rig.project.create | rig:read, rig:write | Projekte auflisten; eines per Slug anlegen. |
rig.suite.list, rig.suite.get, rig.suite.upsert | rig:read, rig:write | Suites und ihre aktuelle Definition lesen; eine aus einer Definition anlegen oder überarbeiten. |
rig.run.create, rig.run.get, rig.run.finish, rig.run.cancel | rig:run, rig:read | Einen Lauf starten und seine Adressen erhalten; ihn lesen; ihn für Bewertungen abschließen; ihn abbrechen. |
rig.resource.create | rig:run | Eine weitere Ressource auf einem aktiven Lauf zuweisen. |
rig.event.list, rig.event.wait | rig:read | Die Zeitleiste seitenweise lesen; auf ein passendes Ereignis warten. |
rig.event.replay | rig:run | Einen aufgezeichneten Callback an seine Route wiederholen. |
rig.fault.add, rig.fault.remove | rig:run | Störungen scharf schalten und entschärfen. |
rig.connector.prepare, rig.connector.status | rig:connector, rig:read | Einen Connector erstellen und den lokal auszuführenden Befehl erhalten; sehen, welche Connectors online sind und was wartet. |
rig.evidence.export, rig.evidence.receipt | rig:read | Das Nachweismanifest und wo das Paket heruntergeladen wird, dazu eine signierte Bestätigung dessen, was der Lauf getan hat. |
Payload-Bytes werden nie über die Verbindung zurückgegeben; die Tools liefern, was die Zeitleiste aufgezeichnet hat, und verweisen für den Rest auf die API.
Limits und Aufbewahrung
| Grenze | Wert |
|---|---|
| Lebensdauer eines Laufs | 1 Minute bis 24 Stunden; Standard 30 Minuten |
| Ressourcen pro Suite | 32 |
| Erwartungen pro Suite | 64, je bis zu 16 Match-Schlüssel |
| Nachrichten pro Postfach und Lauf | 500, je bis zu 10 MiB |
| Callbacks pro Lauf | 1000, je Body bis zu 64 KiB |
| Mock-Aufrufe pro Lauf | 5000; 32 Regeln, 64 KiB Body und 10 Sekunden Verzögerung pro Regel |
| Störungen pro Lauf | 64; Verzögerung bis zu 30 Sekunden; bis zu 5 zusätzliche Kopien; count bis zu 100 |
| Connectors pro Lauf | 16; 30 Sekunden lokales Timeout pro Zustellung; Frames von 256 KiB |
| Wiederholungen pro Lauf | 200 |
| Offene Wartevorgänge pro Organisation | 16; Timeouts von 1 bis 90 Sekunden |
| Ereignisse pro Seite | 500 |
| Nachweispaket | 10.000 Ereignisse und 256 MiB Payloads |
| Aufbewahrung von Payloads | 7 Tage nach dem Ende des Laufs |
| Aufbewahrung von Läufen | 90 Tage nach dem Ende des Laufs, dann werden der Lauf und seine Zeitleiste gelöscht |
Exportieren Sie das Nachweispaket, bevor die Aufbewahrungsfrist abläuft, wenn ein Lauf sie überdauern muss. Suites, ihre Versionen und Projekte bleiben bestehen.
API-Referenz
Basis-URL https://api.ironfang.uk/rig. Das OpenAPI-3.1-Dokument unter https://api.ironfang.uk/rig/openapi.yaml enthält jedes Schema, jedes Beispiel und jeden Fehler, mit stabilen Operation-IDs für generierte Clients. IDs sind UUIDs; Listen werden mit cursor und limit (bis 100) seitenweise gelesen.
| Endpunkt | Berechtigung | Funktion |
|---|---|---|
GET /v1/projects | rig:read | Projekte auflisten. |
POST /v1/projects | rig:write | Ein Projekt per Slug anlegen. |
GET /v1/projects/{projectId} | rig:read | Ein Projekt abrufen. |
GET /v1/suites | rig:read | Suites auflisten, optional nach Projekt. |
POST /v1/suites | rig:write | Eine Suite mit ihrer ersten Version anlegen. |
GET /v1/suites/{suiteId} | rig:read | Eine Suite mit ihrer aktuellen Version abrufen. |
PUT /v1/suites/{suiteId} | rig:write | Die Definition überarbeiten; eine unveränderte Definition erzeugt keine neue Version. |
GET /v1/suites/{suiteId}/versions | rig:read | Die Versionen einer Suite auflisten. |
POST /v1/suites/{suiteId}/runs | rig:run | Einen Lauf starten und seine Ressourcen zuweisen. Beachtet Idempotency-Key. |
GET /v1/runs | rig:read | Läufe auflisten, die neuesten zuerst. |
GET /v1/runs/{runId} | rig:read | Einen Lauf abrufen. |
POST /v1/runs/{runId}/finish | rig:run | Den Lauf abschließen und seine Erwartungen bewerten. |
POST /v1/runs/{runId}/cancel | rig:run | Den Lauf ohne Bewertungen abbrechen. |
GET /v1/runs/{runId}/resources | rig:read | Die Ressourcen des Laufs mit ihren Adressen auflisten. |
POST /v1/runs/{runId}/resources | rig:run | Eine weitere Ressource zuweisen. |
PUT /v1/runs/{runId}/resources/{resourceId}/mock | rig:run | Die Regeln eines Mocks ersetzen. |
GET /v1/runs/{runId}/faults | rig:read | Die Störungen des Laufs auflisten und wie oft jede ausgelöst hat. |
POST /v1/runs/{runId}/faults | rig:run | Eine Störung scharf schalten. |
DELETE /v1/runs/{runId}/faults/{faultId} | rig:run | Eine Störung entschärfen. |
GET /v1/runs/{runId}/connectors | rig:read | Connectors und ausstehende Zustellungen auflisten. |
POST /v1/runs/{runId}/connectors | rig:connector | Einen Connector und sein Bootstrap-Token erstellen. |
GET /v1/runs/{runId}/events | rig:read | Die Zeitleiste ab since lesen. |
POST /v1/runs/{runId}/wait | rig:read | Auf ein passendes Ereignis warten. |
GET /v1/runs/{runId}/events/{eventId} | rig:read | Ein Ereignis abrufen. |
GET /v1/runs/{runId}/events/{eventId}/payload | rig:read | Die Payload-Bytes eines Ereignisses herunterladen. |
POST /v1/runs/{runId}/events/{eventId}/replay | rig:run | Einen aufgezeichneten Callback wiederholen. |
POST /v1/runs/{runId}/evidence | rig:read | Das Nachweispaket oder sein Manifest exportieren. |
GET /v1/usage | rig:read | Läufe und Ereignisse in einem Zeitfenster, standardmäßig seit Monatsbeginn. |
GET /v1/environment | rig:read | Hosts, Gateway, Connector-Release, jede Grenze und die Aufbewahrungsfristen. |
GET /v1/home | rig:read | Zählwerte, Meilensteine der Einrichtung und letzte Läufe, so wie das Portal sie zeigt. |
Maschinenschnittstellen
| Schnittstelle | Details |
|---|---|
| Produktseite | https://ironfang.uk/rig |
| Dokumentation | https://ironfang.uk/rig/docs |
| Basis-URL der API | https://api.ironfang.uk/rig |
| OpenAPI-Vertrag | https://api.ironfang.uk/rig/openapi.yaml. Derselbe Vertrag wird als JSON unter https://api.ironfang.uk/rig/openapi.json bereitgestellt. |
| Authentifizierung | Plattform-API-Schlüssel als Bearer-Token |
| Fehler | https://ironfang.uk/rig/docs#errors. Ein JSON-Body mit einem stabilen Code, einer Meldung, diesem Link und der Anfrage-ID. |
| MCP | Verfügbar. Projekte und Suites, Läufe und ihre Ressourcen, die Zeitleiste und Wartevorgänge, Wiederholung, deterministische Fehler, das Bootstrap des lokalen Connectors, Nachweismanifeste und signierte Quittungen. Die Tools heißen rig.*. Referenz des MCP-Servers; jedes Tool und jedes Schema ohne Token unter /.well-known/ironfang-mcp.json |
| Auffindbarkeit | /apis.json, /.well-known/api-catalog und /llms.txt |

