IT-RAT the stack/mockryx GitHub ↗
pre-prod plane · wave 2

Mockryx. Prove every guardrail holds, against your own gateway, before real traffic.

A guardrail nobody has ever fired is a guess. Mockryx replays five hostile scenarios (a fake secret in a prompt, a budget burn, a denied tool, a forged delegation chain, an unapproved action) against the one URL you hand it: your own pre-production gateway, with a fake provider behind it. The enforcement path is the real one; the spend is not. CI reads the verdict as an exit code.

statuspre-1.0 · main is supported
coreGo · outbound-only CLI
scenarios5 shipped · YAML
targetyour own gateway · /v1/messages
verdictsexit 0 held · 1 real gap · 2 broken
sixty seconds, five drills

Watch every guardrail answer for itself.

This is a simulation, and the shape is the real drill record: three of these five scenarios ran live against a real gateway on disposable boxes, twice, and held both times, 0 gaps, $0 real spend. The other two are the Wardryx scenarios that ship in the same set. The provider behind the gateway is fake, so the burn the runaway drill attempts never reaches an invoice.

under the hood

One target URL. One report. Three exit codes.

A scenario file names a request in the Anthropic Messages shape, the status it must be answered with, the headers that must ride the response and, optionally, the off-path event that must follow. The runner sends it at your gateway's /v1/messages, reads the gateway's own answer, polls the NDJSON event logs the off-path services write, and folds everything into a report and an exit code a CI gate can act on. It never talks to anything but the gateway you name.

mockryx CLI one scenario = one YAML request body expect.status · header expect.event source · type · <10s emits sim_run · sim_finding outbound-only · one target your pre-prod gateway :8080 TokenFuse + Wardryx + DLP TokenFuse breaker · 402 DLP · 403 on a secret shape Wardryx PEP · deny / hold the real enforcement path never prod · never anyone else's fake provider mock upstream · $0 spend report + exit code human / json · gates CI 0 held · 1 gap · 2 broken watch files Verdryx / Idryx / Qryx NDJSON polled every 200ms POST /v1/messages async reactions expect.event · polled a drill on every merge, instead of a report once a year
what it proves

Not a mock of your gateway. Your gateway.

Scenarios are YAML, not code

One drill is one file: the request to send, the status the guardrail must answer, the headers it must stamp. It reads like the real call it imitates. A malformed file fails the whole load, because a safety check that vanishes silently is worse than one that fails loudly.

In-path checks, on the real path

Assertions read the gateway's own answers: the breaker's 402, DLP's 403, the deny or hold riding the x-fuse-wardryx header. No mocked gateway in the middle, so the code you rehearse is the code production traffic meets.

Async reaction checks

expect.event demands the off-path services actually react: name a source and a type, and the watcher polls the agent-event NDJSON logs Verdryx, Idryx and Qryx already write, correlated by run_id. A gateway that blocks while nobody downstream notices is half a defense.

A skip cannot hide a gap

A guardrail that is off looks exactly like one that is broken. The runner takes the x-fuse header family as evidence a feature is wired in, reports skipped_not_configured when it is not, and --fail-on-skip turns even a skip into a failure when you know the guardrail must be there.

CI-native exit codes

Exit 0: every drill held. Exit 1: a real defensive gap, fail the build. Exit 2: the harness itself is broken (bad flag, unreadable scenarios), so nothing was proven. Gate on 1, fix the pipeline on 2, and never let the two blur.

Zero real spend by design

The provider behind the gateway is fake, so the runaway scenario can burn all it wants: the meter it trips is real, the invoice is not. And every hostile input stays inside your perimeter; Mockryx only ever talks to the one gateway URL you hand it.

an honest comparison

The drill you can afford to run every release.

A yearly pentest does real work Mockryx cannot: people, phishing, infrastructure. What it cannot do is tell you tomorrow morning that yesterday's config change broke the DLP. And unit tests with a mocked gateway mostly prove the mocks still pass. Mockryx drills the assembled thing.

MockryxAnnual pentest“Trust the unit tests”
CadenceEvery releaseYearlyWhenever
Tests the assembled systemReal gateway, real policiesSometimesNo: mocks all the way down
Costs real tokensNon/aSometimes
Proves off-path services reactYes: expect.eventNoNo
Who reads the resultA CI gate, every mergeA PDF for the boardNobody
in the stack

It picks fights with the rest of the stack. On purpose, in pre-prod.

In the request path, Mockryx rehearses TokenFuse: the breaker's 402 and the DLP's 403, provoked deliberately and expected to answer. It does the same to Wardryx, asserting that deny and hold verdicts land in the x-fuse-wardryx header. Off path, expect.event demands that Verdryx, Idryx and Qryx visibly react to what just happened. And every finding it makes travels as sim_run and sim_finding events on the same bus as everything else: the shared contract.

try it now
./bin/mockryx run --gateway http://127.0.0.1:8080 ./scenarios
./bin/mockryx report out/report.json

Add --save out/report.json to keep the evidence. Point it at pre-prod, never at prod: the URL you pass is the only place it will ever send traffic.