- Releases
- Ironflow v0.28.0
Ironflow v0.28.0
Ironflow v0.28.0 gives @ironflow/browser a durable offline write queue, so a browser client keeps accepting emit and streams.append while the network is down. An emit retry that silently dropped its dispatch is fixed, every declared audit event type now persists on both backends, and a new travel-booking example tells the saga story end to end.
Breaking Changes
Section titled “Breaking Changes”RetryRunis removed from the proto, all three SDKs, and the MCP tool surface. It was never implemented: the Connect handler returnedUnimplementedunconditionally and no REST route backedPOST /api/v1/runs/{id}/retry. UseResumeRun/resumeRun/ironflow run resumeinstead. No caller can regress, because the method never returned a success on any surface (#1606)
Features
Section titled “Features”- Offline write queue for
@ironflow/browser(ADR 0053). Opt in withcreateClient({ offlineQueue: { identity } }). The client writesemitandstreams.appendto an IndexedDB outbox before it sends, then drains in strict FIFO with jittered backoff, dead-lettering, cross-tab coordination through Web Locks, and token refresh on 401. Each queued write keeps the credentials and the destination it was enqueued with. This is a durable outbox, not background sync (#1605) - Travel-booking showcase example.
examples/travel-booking/books a flight and a hotel as one saga, with a compensation on every step and a chaos panel that drives crash, payment failure, slow payment, and offline from the browser. It covers entity streams, optimistic concurrency, durable steps,step.compensate(), live projections, and time travel (#1602)
- An idempotent emit retry now re-runs dispatch. Emit commits the event row and then dispatches. When dispatch failed, a retry with the same idempotency key found the durable row, returned 200, and never dispatched again — so the matched functions never ran and the caller was told the write succeeded with no run behind it. An idempotency hit now re-runs
DispatchMatchedwhile the row is stillprocessed=false.GetEventByIdempotencyKeyalso missed the entity columns, so an idempotentEmitEntityEventretry returned an event with no entity (#1604) - All 43 audit event types now persist on both backends. The
audit_events.event_typeCHECK constraint was a hand-typed copy of the Go constants and had drifted to 28 values, so 15 types (everycapacity.*,secret.*,kv.*,cluster.*, pluswebhook.source.createdandorg.export) were rejected at INSERT and lost with only a warn log. The constraint is dropped rather than extended, because Go is the source of truth and no user-supplied value reaches the column. Adding an audit type no longer needs a migration. The dashboard filter grows from 9 to 43 options with search (#1603, #1601) GET /api/v1/functions/{id}is registered. Theironflow_get_functionMCP tool had a definition and a passing unit test, and 404’d against a real server (#1606, #1592)- Seven offline-queue defects from the pre-landing review are closed, each with a test that was red first. A sibling tab’s announce now resumes delivery at the
drain()chokepoint, the pending counter can no longer race below zero and hand the cap free room, and a reconcile no longer evicts every watcher but one (#1615, #1609) - Collapsed dashboard sidebar icons are labeled on hover and focus (#1599)
- The docs header logo and spacing match the marketing site (#1598, #1626)
- Four public-mirror links that returned 404 now point at the right place (#1614, #1203)
Improvements
Section titled “Improvements”- New post: “Your Function Outlived Its Host” explains pull-mode workers (#1597)
Ironflow Desktop ships on its own cadence — see the Desktop changelog for its release notes.