- Releases
- Ironflow v0.30.0
Ironflow v0.30.0
Ironflow v0.30.0 gives the MCP agent operator verbs, so it can resume a run, rebuild a projection, work the outbox DLQ and reset a circuit breaker instead of telling you to open a terminal. The Go SDK gains the five branch-scoped step primitives the JS SDK always had, subscriber CEL evaluation is now bounded and fails closed, and the toolchain moves to Go 1.26.
Breaking Changes
Section titled “Breaking Changes”- Minimum Go toolchain is now 1.26. Both modules and every workflow move together. Only affects building from source or consuming the Go SDK; released binaries are unaffected (#1816)
- Outbox DLQ requeue and discard need the new
outbox:managepermission. Destroying dead-letter rows was previously implied byevents:emit, which is a read-adjacent verb an agent holds in a loop. Built-in roles are unaffected — a custom role grantedevents:emitspecifically to reach the DLQ endpoints must addoutbox:manage(#1803, #1808) - Circuit breakers with an empty
FunctionIDare withheld from environment-scoped callers. They are unattributable and still carry an endpoint URL. They are never pruned, and platform-scoped callers still see them (#1808) cel-gomoved to itscel.dev/cel-gomodule path. Only relevant if you import it transitively alongside Ironflow (#1816)
Features
Section titled “Features”- Eight Tier 1 operator verbs on the MCP server —
resume_run,rebuild_projectionand its status,outbox_dlq_list/_requeue/_discard, andcircuit_breaker_list/_reset.dry_runis now implemented for real rather than advertised,confirmmirrors the CLI’s--yeson destructive verbs, and MCP reads are capped at 8 MiB with narrowing guidance instead of an oversized response (#1803, #1808) GET /api/v1/eventsforwards all nine query parameters through MCP, so the agent can filter and page events rather than pulling a window and sifting it (#1808)- Five branch-scoped step primitives in the Go SDK —
Map,SleepUntil,Invoke,InvokeAsyncandPublishgain*WithBranchtwins. Previously they existed in root form only, so calling one from inside a branch recorded its step at the function’s top level. Exported root signatures are unchanged (#1792, #1813) - Non-durable-branch warning ported to Go.
ParallelandMapnow warn, once per name per run, when a step is claimed on the enclosing context while a fan-out is in flight — the shape where a resume can hand one branch another branch’s output. Opt out withParallelOptions.SkipScopedClientCheck(#1792, #1813)
- Cross-tenant leak in the circuit-breaker list. The environment filter sat inside the
if prunebranch, so a transientListFunctionserror returned every tenant’s function IDs and push URLs — reintroducing what #1645 closed. It now fails closed (#1808) - Subscriber CEL evaluation is bounded to 50 ms with context cancellation, interrupt checks and panic recovery. Filter errors fail closed, and redelivery is preserved when dispatcher cancellation interrupts evaluation (#1815, #1817)
- KV CAS failures return
ErrKeyRevisionMismatch, and HTTP KV keys are validated before NATS is touched. Verified against a replicated three-node NATS cluster for create races, update contention, stale deletes, and arm-versus-sweep (#1815, #1817) - Resume no longer strands runs on a deduplicated publish, and a duplicate resume returns a conflict instead of creating duplicate work (#1808)
- Projection rebuild progress survives a server restart (#1808)
- Two data races in the Go SDK. Neither
stepCountersmap was guarded, so any branch reaching for an enclosing context landed ingenerateStepIDconcurrently — a runtime throwrecover()cannot catch.scopedClientUsedis now anatomic.Bool(#1813) - Nine MCP tool descriptions corrected. For MCP a tool description is the prompt the model acts on:
cursorandbeforewere documented backwards so the “tail” paged into history,discardclaimed one row when it deletes every row sharing anevent_id, andresumeclaimed to restart at the last successful step when the function re-enters at the top (#1808)
Improvements
Section titled “Improvements”- New
(environment_id, dead_at, id)index on the dead-letter query that always needed one (#1808) TestMCPToolPathsAreRegisteredRoutesAST-scans the MCP tool table and asserts every path it builds resolves to a real route — the gate that was missing when a tool once shipped pointing at a nonexistent endpoint (#1592, #1806)- Dependency sweep: nats.go 1.53.1, nats-server 2.14.5, minio-go 7.3.0, testify 1.12.1, testcontainers 0.44.0, mcp-go 0.58.0, sqlite 1.57.0, protobuf 1.36.12, protobuf-es 2.14, vite 8.2.2, vitest 4.1.11, plus TanStack, LangChain and wrangler 4.125.0.
sharpis pinned to the 0.35.3 floor that clears GHSA-f88m-g3jw-g9cj under Astro.THIRD_PARTY_NOTICES.mdrefreshed (#1816) - All 13 nested example lockfiles regenerated against the moved SDK specifiers (#1816)
- ADR-0061 records the
StepContextseam decision behind the branch-scoped primitives (#1813)
Documentation
Section titled “Documentation”- Eight source-verified documentation drifts fixed, each falsifiable against code: an invented
ironflow audit listcommand and a stale “Enterprise” heading in the agent skill tree shipped inside the binary; a Go SDK README claiming five step primitives have no branch variant; an undocumentedGET /functions/{id};/ecosystemand/licenseadvertised as live routes though both have been unrouted since #956; a non-existentironflow projection query; a roadmap row listing Child Workflows as unscheduled whilestep.invokeis marked shipped in the same file; andEnterpriseRequiredErrordescriptions citing a removed licensing tier (#1818) - SDK comparison matrix audited cell by cell against Go, Node, Browser and Python source. Three capability areas had no table at all and now do — Durable Step Primitives, Agents, and Operations — and the top section is 26% smaller with no information lost (#1796)
Ironflow Desktop
Section titled “Ironflow Desktop”Desktop ships on its own cadence — see the Desktop changelog for its releases.