Zum Inhalt springen

Ironfang Rig

Dokumentation für Entwickler

Geben Sie der getesteten Anwendung eine Außenwelt auf Zeit: temporäre Postfachadressen, öffentliche Callback-URLs, Mock-HTTP-Endpunkte und Routen zu Ihrem Rechner, für jeden Lauf neu zugewiesen, mit einer fortlaufend nummerierten Aufzeichnung von allem, was Ironfang beobachtet hat.

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.

ObjektWas es ist
ProjektEin dauerhafter Container für eine Anwendung, benannt durch einen Slug.
SuiteEine 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.
LaufEine 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.
RessourceEine 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.
EreignisEine 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.
ErwartungEine deterministische Bedingung an die Zeitleiste, mit der Suite gespeichert und bewertet, wenn der Lauf abgeschlossen wird.
StörungEin 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 exportieren
  • rig:writeProjekte und Suites anlegen und überarbeiten
  • rig:runLäufe starten, abschließen und abbrechen; Ressourcen zuweisen; Mock-Regeln ändern; Störungen scharf schalten; Callbacks wiederholen
  • rig:connectorConnectors und ihre Bootstrap-Tokens erstellen
  • rig:*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.

StatusCodeBedeutung
400invalid_json, invalid_queryDer Body ist nicht genau ein strikter JSON-Wert der dokumentierten Form, oder ein Abfrageparameter ist unbekannt, doppelt oder fehlerhaft.
401unauthorized, invalid_api_keyKeine Anmeldedaten, oder solche, die sich nicht auflösen lassen.
403forbidden, insufficient_scopeDem Schlüssel fehlt die Berechtigung, dem Benutzer fehlt die Befugnis, oder die Anfrage nennt eine andere Organisation.
404not_foundKein solches Objekt in dieser Organisation.
409conflict, archived, run_not_activeEin Slug ist vergeben, das Ziel ist archiviert, oder der Lauf ist bereits beendet.
410payload_retiredDas Ereignis existiert, aber seine Payload-Bytes haben die Aufbewahrungsfrist überschritten.
422invalid_request, not_replayableEin Feld ist ungültig; die Meldung nennt es.
429too_many_waiters, replay_limit, connector_limit, fault_limitEine 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.

FeldTypHinweise
versionintegerImmer 1.
projectstringSlug des Projekts. Wird beim ersten Synchronisieren angelegt.
suitestringSlug der Suite, eindeutig innerhalb des Projekts.
namestringAnzeigename, bis zu 120 Zeichen.
defaults.run_ttldurationStandard-Lebensdauer eines Laufs, 1m bis 24h. Standard ist 30m.
resourcesobjectName auf Ressourcenspezifikation, 1 bis 32 Einträge. Namen entsprechen ^[a-z][a-z0-9_]{0,63}$ und werden zu Suffixen von Umgebungsvariablen.
expectationsarrayBis zu 64 Bedingungen, jede mit einer id, einem resource-Namen, einem event-Typ und einem optionalen match.

Ressourcenspezifikationen

typeZusätzliche FelderWas der Lauf erhält
emailkeineEine Postfachadresse unter inbox.rig.ironfang.uk.
callbackconnector.route (optional)Eine öffentliche URL, die jede Anfrage aufzeichnet. Mit einer Route wird jede Anfrage zusätzlich an Ihren Connector weitergeleitet.
mock_httprules (optional, bis zu 32)Eine öffentliche URL, die anhand geordneter Regeln antwortet.
connector_routerouteEin 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.

RegelfeldHinweise
match.methodEine HTTP-Methode, oder * bzw. weggelassen für jede.
match.pathExakter 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.headersHeader, die mit genau diesen Werten vorhanden sein müssen.
match.jsonFelder der obersten Ebene, denen ein JSON-Anfrage-Body gleichen muss.
respond.statusPflichtfeld, 100 bis 599.
respond.headersAntwort-Header.
respond.body oder respond.jsonEin Text-Body bis 64 KiB, oder ein JSON-Body, der den Content-Type setzt, sofern kein Header es tut.
respond.delayWird vor der Antwort zurückgehalten, höchstens 10s.
respond.templateBody 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, repeatStatt 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.

TypWannWichtige Daten
run.startedDer Lauf hat begonnen.suite_version, ttl_seconds, expires_at, external_id
resource.allocatedEinmal pro Ressource.name, type, expires_at
email.receivedEine Nachricht ist für ein Postfach eingegangen.sender, recipient, subject, from, links, codes, message, transport
callback.receivedEine Anfrage hat eine Callback-URL erreicht.method, path, query, content_type, byte_length, sha256, source_ip, route
callback.rejectedEine Anfrage wurde abgelehnt, etwa wegen eines Bodys über dem Limit.reason, limit_bytes
callback.forwardedEine Zustellung wurde an einen Connector übergeben.delivery_id, event_id, route, connector_id, attempt
connector.request.completedDer Connector hat das lokale Ergebnis gemeldet.outcome (delivered oder failed), status, headers, body_excerpt, duration_ms, error, delivery_id
callback.replayedEin aufgezeichneter Callback wurde auf Anforderung wiederholt.event_id, replay (1, 2, ...), delivery_id, route, requested_by
mock.request.receivedEine Anfrage hat einen Mock erreicht.method, path, query, content_type, byte_length, matched, rule
mock.response.sentDer Mock hat geantwortet.status, original_status, rule, delay_ms, request_event_id
mock.rules.updatedDie Regeln wurden ersetzt.rules
connector.connected, connector.disconnectedEine Connector-Sitzung wurde geöffnet oder geschlossen.connector_id, name, routes, reason, requeued_deliveries
fault.added, fault.removed, fault.injectedEine Störung wurde scharf geschaltet, entschärft oder ausgelöst.fault_id, type, fired, persistent, status, event_id
expectation.passed, expectation.failedBeim Abschluss bewertet, eines pro Erwartung.expectation, event
run.completed, run.cancelled, run.expiredDer 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/stripe

Der 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 }'
typeWirkt aufEffekt
delayEinen Callback mit Connector-RouteDie Zustellung wird für delay, höchstens 30s, zurückgehalten, bevor sie weitergeleitet wird.
duplicateEinen Callback mit Connector-RouteDie Zustellung wird copies-mal zusätzlich weitergeleitet (1 bis 5, Standard 1), jede mit eigener Zustellungs-ID.
dropEinen Callback mit Connector-RouteDer Callback wird aufgezeichnet, aber nie weitergeleitet.
status_overrideEinen Mock-HTTP-EndpunktDer Mock antwortet mit status, gleich was seine Regeln sagten; Body und Header bleiben unverändert, und der ursprüngliche Status wird aufgezeichnet.
reorderEinen Callback mit Connector-RouteZustellungen 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_mutationEinen Callback mit Connector-RouteDie 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_resetEinen Mock-HTTP-EndpunktDie 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_limitEinen Mock-HTTP-EndpunktDer 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_responseEinen Mock-HTTP-EndpunktDie 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.

DateiInhalt
manifest.jsonDer 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.jsonDie gesamte Zeitleiste in Sequenzreihenfolge.
expectations.jsonJede Erwartung mit ihrer Bewertung, sobald der Lauf abgeschlossen ist.
faults.json, resources.json, definition.jsonDie 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.jsonEine 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-256

Kommandozeile

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 version

run 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-CodeBedeutung
0Erfolg; bei run und finish ist das Ergebnis des Laufs nicht fail.
1Ein Fehler bei der Kommunikation mit der API oder dem Dateisystem.
2Falsche Verwendung: ein fehlendes Argument oder ein ungültiges Flag.
3Der Befehl nach -- ist fehlgeschlagen, oder das Ergebnis des Laufs ist fail.
4wait 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 }}
InputActionHinweise
suite-filestartPfad zur Suite-Datei. Standard ironfang.rig.yaml.
ttlstartLebensdauer des Laufs, 1m bis 24h. Standard aus der Suite.
external-idstartIhre Referenz für den Lauf. Standard ist die ID des Workflow-Laufs.
run-idfinishPflichtfeld. Der Output run_id des Start-Schritts.
outcomefinishpass, fail oder none, um die Bewertungen zu überschreiben. Standard ist das abgeleitete Ergebnis.
fail-onfinishfail (Standard) oder never.
version, binarybeideDas 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.

ToolBerechtigungFunktion
rig.project.list, rig.project.createrig:read, rig:writeProjekte auflisten; eines per Slug anlegen.
rig.suite.list, rig.suite.get, rig.suite.upsertrig:read, rig:writeSuites und ihre aktuelle Definition lesen; eine aus einer Definition anlegen oder überarbeiten.
rig.run.create, rig.run.get, rig.run.finish, rig.run.cancelrig:run, rig:readEinen Lauf starten und seine Adressen erhalten; ihn lesen; ihn für Bewertungen abschließen; ihn abbrechen.
rig.resource.createrig:runEine weitere Ressource auf einem aktiven Lauf zuweisen.
rig.event.list, rig.event.waitrig:readDie Zeitleiste seitenweise lesen; auf ein passendes Ereignis warten.
rig.event.replayrig:runEinen aufgezeichneten Callback an seine Route wiederholen.
rig.fault.add, rig.fault.removerig:runStörungen scharf schalten und entschärfen.
rig.connector.prepare, rig.connector.statusrig:connector, rig:readEinen Connector erstellen und den lokal auszuführenden Befehl erhalten; sehen, welche Connectors online sind und was wartet.
rig.evidence.export, rig.evidence.receiptrig:readDas 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

GrenzeWert
Lebensdauer eines Laufs1 Minute bis 24 Stunden; Standard 30 Minuten
Ressourcen pro Suite32
Erwartungen pro Suite64, je bis zu 16 Match-Schlüssel
Nachrichten pro Postfach und Lauf500, je bis zu 10 MiB
Callbacks pro Lauf1000, je Body bis zu 64 KiB
Mock-Aufrufe pro Lauf5000; 32 Regeln, 64 KiB Body und 10 Sekunden Verzögerung pro Regel
Störungen pro Lauf64; Verzögerung bis zu 30 Sekunden; bis zu 5 zusätzliche Kopien; count bis zu 100
Connectors pro Lauf16; 30 Sekunden lokales Timeout pro Zustellung; Frames von 256 KiB
Wiederholungen pro Lauf200
Offene Wartevorgänge pro Organisation16; Timeouts von 1 bis 90 Sekunden
Ereignisse pro Seite500
Nachweispaket10.000 Ereignisse und 256 MiB Payloads
Aufbewahrung von Payloads7 Tage nach dem Ende des Laufs
Aufbewahrung von Läufen90 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.

EndpunktBerechtigungFunktion
GET /v1/projectsrig:readProjekte auflisten.
POST /v1/projectsrig:writeEin Projekt per Slug anlegen.
GET /v1/projects/{projectId}rig:readEin Projekt abrufen.
GET /v1/suitesrig:readSuites auflisten, optional nach Projekt.
POST /v1/suitesrig:writeEine Suite mit ihrer ersten Version anlegen.
GET /v1/suites/{suiteId}rig:readEine Suite mit ihrer aktuellen Version abrufen.
PUT /v1/suites/{suiteId}rig:writeDie Definition überarbeiten; eine unveränderte Definition erzeugt keine neue Version.
GET /v1/suites/{suiteId}/versionsrig:readDie Versionen einer Suite auflisten.
POST /v1/suites/{suiteId}/runsrig:runEinen Lauf starten und seine Ressourcen zuweisen. Beachtet Idempotency-Key.
GET /v1/runsrig:readLäufe auflisten, die neuesten zuerst.
GET /v1/runs/{runId}rig:readEinen Lauf abrufen.
POST /v1/runs/{runId}/finishrig:runDen Lauf abschließen und seine Erwartungen bewerten.
POST /v1/runs/{runId}/cancelrig:runDen Lauf ohne Bewertungen abbrechen.
GET /v1/runs/{runId}/resourcesrig:readDie Ressourcen des Laufs mit ihren Adressen auflisten.
POST /v1/runs/{runId}/resourcesrig:runEine weitere Ressource zuweisen.
PUT /v1/runs/{runId}/resources/{resourceId}/mockrig:runDie Regeln eines Mocks ersetzen.
GET /v1/runs/{runId}/faultsrig:readDie Störungen des Laufs auflisten und wie oft jede ausgelöst hat.
POST /v1/runs/{runId}/faultsrig:runEine Störung scharf schalten.
DELETE /v1/runs/{runId}/faults/{faultId}rig:runEine Störung entschärfen.
GET /v1/runs/{runId}/connectorsrig:readConnectors und ausstehende Zustellungen auflisten.
POST /v1/runs/{runId}/connectorsrig:connectorEinen Connector und sein Bootstrap-Token erstellen.
GET /v1/runs/{runId}/eventsrig:readDie Zeitleiste ab since lesen.
POST /v1/runs/{runId}/waitrig:readAuf ein passendes Ereignis warten.
GET /v1/runs/{runId}/events/{eventId}rig:readEin Ereignis abrufen.
GET /v1/runs/{runId}/events/{eventId}/payloadrig:readDie Payload-Bytes eines Ereignisses herunterladen.
POST /v1/runs/{runId}/events/{eventId}/replayrig:runEinen aufgezeichneten Callback wiederholen.
POST /v1/runs/{runId}/evidencerig:readDas Nachweispaket oder sein Manifest exportieren.
GET /v1/usagerig:readLäufe und Ereignisse in einem Zeitfenster, standardmäßig seit Monatsbeginn.
GET /v1/environmentrig:readHosts, Gateway, Connector-Release, jede Grenze und die Aufbewahrungsfristen.
GET /v1/homerig:readZählwerte, Meilensteine der Einrichtung und letzte Läufe, so wie das Portal sie zeigt.

Maschinenschnittstellen

SchnittstelleDetails
Produktseitehttps://ironfang.uk/rig
Dokumentationhttps://ironfang.uk/rig/docs
Basis-URL der APIhttps://api.ironfang.uk/rig
OpenAPI-Vertraghttps://api.ironfang.uk/rig/openapi.yaml. Derselbe Vertrag wird als JSON unter https://api.ironfang.uk/rig/openapi.json bereitgestellt.
AuthentifizierungPlattform-API-Schlüssel als Bearer-Token
Fehlerhttps://ironfang.uk/rig/docs#errors. Ein JSON-Body mit einem stabilen Code, einer Meldung, diesem Link und der Anfrage-ID.
MCPVerfü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