Skip to content

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.

  • 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:manage permission. Destroying dead-letter rows was previously implied by events:emit, which is a read-adjacent verb an agent holds in a loop. Built-in roles are unaffected — a custom role granted events:emit specifically to reach the DLQ endpoints must add outbox:manage (#1803, #1808)
  • Circuit breakers with an empty FunctionID are 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-go moved to its cel.dev/cel-go module path. Only relevant if you import it transitively alongside Ironflow (#1816)
  • Eight Tier 1 operator verbs on the MCP serverresume_run, rebuild_projection and its status, outbox_dlq_list / _requeue / _discard, and circuit_breaker_list / _reset. dry_run is now implemented for real rather than advertised, confirm mirrors the CLI’s --yes on destructive verbs, and MCP reads are capped at 8 MiB with narrowing guidance instead of an oversized response (#1803, #1808)
  • GET /api/v1/events forwards 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 SDKMap, SleepUntil, Invoke, InvokeAsync and Publish gain *WithBranch twins. 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. Parallel and Map now 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 with ParallelOptions.SkipScopedClientCheck (#1792, #1813)
  • Cross-tenant leak in the circuit-breaker list. The environment filter sat inside the if prune branch, so a transient ListFunctions error 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 stepCounters map was guarded, so any branch reaching for an enclosing context landed in generateStepID concurrently — a runtime throw recover() cannot catch. scopedClientUsed is now an atomic.Bool (#1813)
  • Nine MCP tool descriptions corrected. For MCP a tool description is the prompt the model acts on: cursor and before were documented backwards so the “tail” paged into history, discard claimed one row when it deletes every row sharing an event_id, and resume claimed to restart at the last successful step when the function re-enters at the top (#1808)
  • New (environment_id, dead_at, id) index on the dead-letter query that always needed one (#1808)
  • TestMCPToolPathsAreRegisteredRoutes AST-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. sharp is pinned to the 0.35.3 floor that clears GHSA-f88m-g3jw-g9cj under Astro. THIRD_PARTY_NOTICES.md refreshed (#1816)
  • All 13 nested example lockfiles regenerated against the moved SDK specifiers (#1816)
  • ADR-0061 records the StepContext seam decision behind the branch-scoped primitives (#1813)
  • Eight source-verified documentation drifts fixed, each falsifiable against code: an invented ironflow audit list command 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 undocumented GET /functions/{id}; /ecosystem and /license advertised as live routes though both have been unrouted since #956; a non-existent ironflow projection query; a roadmap row listing Child Workflows as unscheduled while step.invoke is marked shipped in the same file; and EnterpriseRequiredError descriptions 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)

Desktop ships on its own cadence — see the Desktop changelog for its releases.