Releases
Faultbox release history. Every tagged version ships with full release notes
on GitHub and a matching entry in
CHANGELOG.md.
For the next version in flight, see the
Issues board filtered by
version label (v0.12.x, etc.).
Current
- v0.13.0 — 2026-05-29 — Five RFCs ship together as one coordinated epic: determinism levels (RFC-040), temporal properties (RFC-041), exploration plan (RFC-042), non-deterministic operators (RFC-043), and spec language simplification (RFC-044). The new
determinism()top-level builtin declares the spec’s reproducibility contract — defaults to L1 (mediated-event determinism) with strict mode on, so any unmediated I/O (clock reads, RNG, DNS to a non-Faultbox resolver,connect()to an undeclared address) fails the test at the first untolerated leak. RFC-041 adds five temporal primitives —eventually(p),always(p, between=),await_event(matcher),await_stable(quiescence_window=), and a rewrittenmonitor(name, on=, state_init=, update=, check=)— plus a declarativetest(name, body=, expect=, timeout=, terminate_when=)builtin and the PASS/FAIL/INCONCLUSIVE three-valued verdict. RFC-042 introducesfaultbox plan(static plan-tree analysis without launching services),plan.jsonin every bundle, the report’s Plan tab,--coverage/--suggest/--check-cost --max-instances N, and the body-re-execution engine that turns namedchoose("name", [opts])axes, syscall-level probability fan-out (max_fires=/mode="exhaustive"), andparallel(..., interleavings=)orderings into multi-leaf test executions with stableLeafIDattribution flowing throughTestResult→ bundle manifest → HTML report. RFC-043 ships the four operators (choose,nondet,halt,assume) with per-leafassume=evaluation and an AST denylist sandbox. RFC-044 withdraws RFC-013 (param()superseded bychoose()) and RFC-002 (domain()—service()/interface()proved sufficient); unifies the three plan-tree fan-out axis kinds under oneNonDeterministicChoiceinterface; collapses the event-source and decoder surfaces underobserve.stdout/observe.stderranddecoder("name", ...); deprecatesfaultbox generatein favor offaultbox plan --suggest. Two new tutorial chapters (Part 4 — Safety & Verification) walk the operator and fan-out vocabulary end-to-end. Full repogo test -race ./...green; Lima sweep 21/21 PASS across the same 6 integration spec suites as v0.12.29.
v0.12.x — TLS-aware proxy
-
v0.12.29 — 2026-05-02 — Remote services (RFC-036). New
service(remote=...)kwarg points Faultbox at an externally-running endpoint — typically a real pod in a customer’s k8s dev cluster — without launching a process. The proxy datapath from RFC-024 dials the remote upstream and the SUT reaches it through the proxy unchanged, so every protocol-level fault (response(),error(),slow(), gRPC method targeting, SQL matchers) keeps working. Process-level kwargs (seed=,reset=,reuse=,volumes=,ports=,args=,seccomp=,observe=,ops=) and syscall-level faults are rejected at spec load with explicit error messages naming the offending kwarg and pointing at protocol faults ormock_service(). Composes with RFC-038tls=tls_cert(...)for TLS-required upstreams (the auto-generated proxy cert covers127.0.0.1so SUT-side verification works against the env-rewritten loopback addr). New typedremotes({"iface": "host:port"})value for services whose interfaces live on different hosts. New@faultbox/discovery/k8s.starstdlib helper exposingk8s.service,k8s.endpoint, andk8s.local— pure string sugar over<name>.<namespace>.svc.cluster.local, no runtime k8s client. The.fbbundle’senv.jsonrecords every(service, interface, host, protocol)tuple from a remote-using run;faultbox replaywarns when replaying such a bundle and points at RFC-037 (the open companion design RFC for the offline-replay determinism story). Cluster connectivity is the user’s responsibility — Telepresence connect, kubectl port-forward, in-cluster execution, or VPN — documented in the new Connectivity guide. 49 new tests across spec-load validation (32), runtime/proxy lifecycle (10 incl. TLS×remote interop), bundle round-trip (2), replay warning (2), and string-grep doc gates (3). Full repogo test ./...green;go vet ./...clean;make demo-containerLima smoke 4/4 PASS (proxy datapath refactor confirmed non-regressive against the seccomp + Postgres + Redis path). -
v0.12.28 — 2026-05-02 — TLS-aware proxy (RFC-038) + proxy traffic observability (RFC-034) + container fault paths (RFC-035). Twelve patch versions consolidated into one release; the per-version detail lives in
CHANGELOG.md. Headline: declareinterface(..., tls=tls_cert(...))on a service interface and the proxy terminates TLS at its listener and re-establishes TLS dialing the upstream — all protocol-aware fault rules (http.error(path=...),grpc.error(method=...),kafka.drop(topic=...),redis.error(key=...)) keep firing on the plaintext between the two TLS legs. Six plugins ship migrated this release (http, http2, gRPC, Kafka, Redis, TCP); the remaining 8 (postgres, mysql, mongodb, cassandra, clickhouse, memcached, nats, amqp) are tracked in RFC-039 — declarations against unmigrated plugins emit aproxy_tls_pendingevent. Thetls_cert(...)builtin is kwargs-only with full spec-load validation (cert/key pairing, file existence, CA PEM parse,insecure=True+ca=exclusion); emptytls_cert()auto-generates a self-signed proxy cert in memory for dev/test. Two TLS plumbing patterns landed across the 6 plugins: listener wrap-and-dial viaproxy.ListenTLS(serverCfg)+proxy.Dial(ctx, target, clientCfg)(http, http2, kafka, redis, tcp) and framework credentials viagrpc.Creds(credentials.NewTLS(...))for gRPC (whose server owns its own TLS handshake). Also in this release: RFC-034 connection lifecycle observability —proxy_conn_open,proxy_conn_closewith byte counts and reason classification,proxy_handshake_complete, andproxy_stall(1Hz watchdog, 5s warn / 30s extend tiers) — wired into 13 of 15 plugins (udp/grpc deferred). RFC-035 container-consumer fault paths on Linux Docker (proxy bind defaults to 0.0.0.0 so container consumers reach proxies viahost.docker.internal). Newstderr()event source. Container-modeobserve=[stdout(...)]now works for container services (was binary-mode only). Race fix ontcp.go::handle— both io.Copy goroutines were writingcloseReasonconcurrently. Newinternal/proxy/{http,grpc,kafka,redis,tcp}_tls_test.gosuites (~30 tests). Full repogo test ./... -racegreen; Lima sweep 21/21 PASS across 6 integration spec suites.
v0.12.x — Scalable HTML Reports
-
v0.12.16 — 2026-04-30 — Report UX overhaul. Driven by inDrive Freight triage feedback on the v0.12.15.x customer report; entirely scoped to
internal/reportand the docs that describe it (no bundle format or spec-language changes). Causal links now follow cause, not chronology —findCausalAncestorsswitched from vector-clock partial order (which on real bundles routinely had only the lifecycle events with complete clocks, so spaghetti pointed atservice_readyinstead ofproxy_fault_applied) to seq-based strict precedence, restricted to faults / violations / errored steps. Hovering an ordinary success step now draws zero lines. New timeline filter bar above every Event Trace block: three presets (Compact default, hides framework lifecycle chatter; Anchors only strips everything except cause-relevant events; All events historical default) plus free-text search across event type / headline / fields.proxy_fault_applied/proxy_fault_removedare now first-class fault markers (red, not default-blue) across markerKind/severityScore/isAnchorEvent/eventHeadline; added to Phase 3 anchorTypes so they survive downsampling. Per-test “Faults applied” section pairs proxy_fault_applied with proxy_fault_removed (one row per assumption: service · protocol · interface · assumption · seq window). Recent block in the Assertion drill-down interleaves fault events between captured step rows by seq, with a fade-and-expand cap (220px max-height + mask-image gradient + Show full assertion toggle, 320ms transition) so long Recent lists / Actual reprs stop dominating the dialog. Group-members table on folded markers (paginated 100/page, sticky header, scrollable) replaces the one-line “collapsed run” hint — runs that hide a 5xx among 99 successes are now legible. Fullscreen toggle on the test details modal (⤢ ↔ ⤡). STDOUT JSON renders as a 2-column key/value table with dot-path flattening for nested objects. Source block falls back tofault_matrix(...)for matrix-generated test names and surfaces three jump links (scenariodef get_order_feed(), faultmysql_slow = fault_assumption(...), matrix call site) — was previously “Could not locate def…” for every matrix cell. Plus tooltip vertical-text fix (width:max-content + four-side viewport clamping), detail panel summary no longer truncates, folded marker click routes throughmarkerEvBySeqso the Group-members table actually appears. -
v0.12.15.2 — 2026-04-30 — Hotfix on top of v0.12.15.1. Customer verified the redis RESP3 fix landed clean (cold-start path green end-to-end, smoke PASS in 16.3 s) but the failure moved to the reuse path: cell 1 of the dbmatrix run passes, cells 2–18 all fail identically with
error connect to db: invalid connection(go-sql-driverErrBadConn) orread: connection reset by peer(go-redis). Root cause:Manager.EnsureProxyrooted each proxy’s Accept goroutine at the caller’s ctx.preStartProxiesruns underRunTest’s per-testtestCtxwhich cancels viadefer cancel()at end of test — at end of cell 1 that cancellation took down the goroutine while the listener fd stayed bound (onlyStop()closes it) and the cachedm.proxies[key]entry stayed in place. Cells 2..N hitEnsureProxy→ cache hit →proxy_active(reused)fired → but nobody was Accept()-ing, so the kernel completed the TCP handshake and then RST-ed. v0.12.15.2 roots the proxy’spCtxatcontext.Background()so its lifetime is bound toManager.StopAll/StopService(which already drive explicit teardown). Why this surfaced now: pre-v0.12.13 no-seccomp containers were destroyed every cell, forcing fresh proxies via the cold path; v0.12.13 fixed reuse so containers AND proxies stay alive across cells, exposing the latent ctx-rooting bug. New regression testTestManagerEnsureProxy_SurvivesCallerCtxCancel. Lima sweep 21/21 PASS. -
v0.12.15.1 — 2026-04-29 — Hotfix on top of v0.12.15. Customer verified the MySQL fix landed clean (Finding H closed) but the failure moved one step forward: truck-api hung 6s on its first Redis
Ping(). Root cause: go-redis v9 unconditionally sendsHELLO 3frominitConn, which switches the server to RESP3; v0.12.15’s redis proxyreadRESPRawonly knew RESP2 framing (+,-,:,$,*) and on a%Nmap header fell through to the default branch — returned just the header line and left the map body unread on the upstream socket. Wire-level proof:redis-cli -p $PROXY -3 PINGtimed out 6s,redis-cli -p 16379 -3 PING(direct) returned PONG in 8ms. v0.12.15.1 extendsreadRESPRawto cover RESP3 aggregates (%map,~set,>push,|attribute) and scalars (_#,(single-line;=!bulk-string-framed). Four new regression tests includingTestRedisProxy_RESP3_HelloMapreproducing the customer’s exact map shape. -
v0.12.15 — 2026-04-29 — Hotfix on top of v0.12.14. Customer verified v0.12.14 didn’t unblock Finding H — both
caching_sha2_passwordandmysql_native_password --default-authstill hung 8s through the proxy. Root cause: v0.12.14’s handshake loop assumed strict client/server alternation, butcaching_sha2_passwordfast-auth-success (taken when the user is in the server’s auth cache) emits two server-side packets back-to-back —AuthMoreData(0x01, 0x03)thenOK(0x00)— with no client packet between. The proxy read theAuthMoreData, tried to read from the client, deadlocked. Customer’sseed_dbpopulated the auth cache via direct MySQL connections, so every proxy connection hit fast-auth. v0.12.15 peeks the second byte of everyAuthMoreDataand treats0x03(fast_auth_success) as “expect another server packet” rather than “expect client reply”. New regression test guards the path. -
v0.12.14 — 2026-04-29 — First attempt at Finding H. Loops the handshake until OK/ERR, alternating directions on
AuthMoreData/AuthSwitchRequest. Fixedcaching_sha2_passwordcold-cache full-auth (covered byTestMySQLProxy_Handshake_CachingSha2FullAuth), but missed fast-auth-success (back-to-back server packets) — superseded by v0.12.15 the same day. Also bumpsstep.summarypreview cap from 80 → 500 chars. -
v0.12.13 — 2026-04-28 — Hotfix on top of v0.12.12. Pre-existing bug (RFC-015 vintage): container services without seccomp filters bypassed
rt.sessionsregistration, sostopServices’reusedset silently ignoredreuse=Truefor proxy-only Docker upstreams — container destroyed every cell, but the proxy inproxyMgrwas kept pointing at the dead host port. Fix populatesrt.sessionsin the no-seccomp branch and nil-guardsClearDynamicFaultRulesin the reuse path. -
v0.12.12 — 2026-04-27 — Proxy-address surface for host-binary SUT + Docker upstream (RFC-033). New
iface.proxy_addr/proxy_host/proxy_portinterface attributes give a working spec-language path for wiring host-binary SUTs through the fault-injection proxy — late-bound at spec-load, resolved atbuildEnvtime, norsplit()games. Also emitsproxy_activeevents in thereuse=Truepath so per-cell trace partitions reflect what’s wired up at cell start. -
v0.12.11 — 2026-04-26 — Compact fold-count labels. Run-marker badges now render counts as
× 3.9k/× 86k/× 4Minstead of full numerals; the exact count remains in the badge’s hover tooltip. Truncates rather than rounds —× 3.9kalways represents ≥ 3900 events. -
v0.12.10 — 2026-04-26 — Spec-anchored event highlighting. The runtime tags
step_send/step_recvevents withfields.spec = <test_name>whenever the call originates from inside the currently-running test function (helper functions still register — the test frame is on the stack). Renderer paints these markers with a warm gold ring, prefixes the balloon / log headline with★, bumps severity by +50 so they win their slot, and bypasses the lane fold so the user’s own calls always render individually against background traffic. -
v0.12.9 — 2026-04-26 — Three UX polishes. Run-marker discs scale with
log10(fold count)— magnitude is visible at-a-glance even when adjacent chips’ badges would otherwise overlap (count text now sits inside the disc). Drill-down “All fields” / “Vector clock” expansion state persists across pin changes. Step summaries pair the directional arrow with explicitcall/replywords —→ call · truck-api.get /orders,← reply · truck-api.get /orders [500]. -
v0.12.8 — 2026-04-26 — Lane filter now folds by key (
target.method.summary) before slot bucketing — 1787 identical SELECT 1 errors collapse to a single× 1787chip instead of 50 indistinguishable red dots. Causal hover lines restored for v0.12.7’s lane routing (cross-lane detection useslaneFor; folded ancestors resolve to their containing chip via_runMembers). Type filter axis becomes click-to-add — the toolbar stays empty until the user clicks a Type cell in the table. -
v0.12.7 — 2026-04-25 — Step events now lane on their target service:
db.exec(...)lands on thedblane,truck-api.get(...)on thetruck-apilane, instead of all of them piling onto the test driver lane. Event-log filter applies to the full event set (not just the first 200 loaded rows), so filtering by a service finds matches anywhere in the trace. -
v0.12.6 — 2026-04-25 — Lane markers color by severity (failed steps + 5xx → red, 4xx → amber); slot picker prefers severity over first-anchor; Recent trail ellipsizes long lines with hover-tooltip; two-axis event-log filter (Service + Type) replaces the v0.11 single-select chip bar — click a cell in the table to filter to its value.
-
v0.12.5 — 2026-04-25 — Hard per-lane marker budget. Walks back the v0.12.2-4 dedup/window approaches (none had an upper bound on DOM node count). New filter buckets each lane’s events into 50 visual slots in seq order; each slot picks one representative (anchor > fold-key head > first event). Hard guarantee: ≤ 50 markers per lane regardless of input size — the customer’s 86874-event lane now renders 50 markers (≈ 250× DOM reduction) at uniformly-spaced visual positions.
-
v0.12.4 — 2026-04-25 — Lane filter rewritten as anchor windows + global cardinality fold (faults / violations / errored steps + ±10 around each render per-event; outside groups by
(target, method, summary)and folds large buckets to a× Nchip at the median rank). Customer’s noisy 80k-event test now shows ~5 distinct chips. Assertion drill-down gains a “Recent” trail snapshotting the last few step events at fail time soresp.status = 500is visible inline. -
v0.12.3 — 2026-04-25 — Drill-down ergonomics. Assertion block now lifts the original expression text from the spec source (
assert_true(resp.status in [200, 201])showsExpression: resp.status in [200, 201], not justActual: False), with a clickablespec.star:42location link. Lane dedup also keys on summary so mixed SQL doesn’t flatten into one chip. Click on a lane marker no longer scrolls the page. -
v0.12.2 — 2026-04-25 — Step-event readability. Runtime enriches
step_send/step_recvwithsql/query/path/args/status_code/duration_ms/errorplus a one-linesummarypreview; lane dedups consecutive(target, method)runs into a single× Nmarker (a 1500-iterationdb.execloop renders one chip instead of 3000). FAQ entry added on bundle freezing — old bundles can’t invent new fields; re-run the suite on v0.12.2 to benefit. -
v0.12.1 — 2026-04-25 — Drill-down polish: structured
assert_eq/assert_trueExpected vs Actual block, services list now shown for proxy-mode runs (event-log fallback), swim-lane switched to rank-based axis with syscalls relegated to the event-log table — keeps timelines legible at 80k+ events. -
v0.12.0 — 2026-04-25 — Report architecture redesign (RFC-031). 23 MB reports become ~150 KB by default;
--full-eventsopt-out preserves every event. Plus panic-safe bundles, binary-digest pinning, actionable lock drift,grpc.retryable(), proxy-coverage CI gate, positioning doc.
v0.11.x — Interactive HTML Reports
- v0.11.3 — 2026-04-25 — MySQL driver EOF noise suppressed, CHANGELOG + per-release pages land.
- v0.11.2 — 2026-04-24 — Hotfix: gRPC proxy passthrough +
fault_matrixmock-target panic.--testglob/regex. Capability matrix in README. - v0.11.1 — 2026-04-24 — Five-outcome matrix:
expectation_violated(amber),fault_bypassed(grey, opt-in viarequire_faults_fire). - v0.11.0 — 2026-04-24 — Interactive single-file HTML reports.
faultbox report <bundle.fb>. Swim-lane trace viewer.
v0.10.x — Reproducibility trio completes
- v0.10.1 — 2026-04-23 — Assumption
ProxyRulesapplied infault_scenario/fault_matrix. testops corpus: Critical tier 100% green. - v0.10.0 — 2026-04-23 —
faultbox replay <bundle>,faultbox lock+faultbox.lock(image-digest pinning, RFC-030).
v0.9.x — Reproducibility, docs, primitives
- v0.9.9 — 2026-04-23 — JWT/JWKS mock, documentation overhaul (~1500 lines, 6 new pages).
- v0.9.8 — 2026-04-23 —
load_file()/load_yaml()/load_json(),expect_*predicates, gRPC status shorthands. - v0.9.7 — 2026-04-22 —
.fbbundle format (RFC-025),faultbox inspect, always-on reproducibility.
Older
See the complete CHANGELOG for entries prior to v0.9.7 and the GitHub Releases page for the canonical per-version notes.