2.8.0 with the arm64 image added, and nothing else. There is no change to the code, the chart, the settings or your flows.
The image is built for linux/amd64 and linux/arm64 again, and the 2.8.1, 2.8 and 2 tags hold both.
Nothing else changed: the README and install pages name 2.8.1.
HotLoop Flow 2.8.1 is 2.8.0 with the arm64 image added, and nothing else. 2.8.0 shipped amd64 only so it could get to production and read stable first, and this is the one small bump that builds both. There is no change to the code, the chart, the settings or your flows.
## What changed
- The image is built for linux/amd64 and linux/arm64 again. The `2.8.1`, `2.8` and `2` tags hold both.
- The README and the install pages name 2.8.1 and say amd64 and arm64, as they did before 2.8.0.
## New settings
None.
## Upgrade
A plain `helm upgrade` to the 2.8.1 image and chart, or the new tag in your Quadlet unit. If you are on arm64 and stayed on 2.7.1 while 2.8.0 was amd64 only, this is your move to the analysis nodes, the data acquisition node, the durable MQTT output and the TDMS log: read the 2.8.0 notes for what they are and what isn't proven. Nothing happens on first start and nothing needs migrating.
## What isn't proven
The arm64 image is built the way it was for 2.7.1, under emulation on the runner, and it starts and reports its version in the release run. It has not been run on an arm64 box for this release.
Image: `ghcr.io/hotloop-io/hotloop-flow:2.8.1`, linux/amd64 and linux/arm64. Chart: `https://hotloop.io/hotloop-flow/`. The README at this tag has the rest, with pictures: https://github.com/HotLoop-io/hotloop-flow/blob/v2.8.1/README.md
FlowLab gets analysis nodes, a data acquisition node for NI hardware, an MQTT output that keeps what the broker misses, and a TDMS log. Every flow you have runs the way it did.
Statistics, integral, derivative and Butterworth filter nodes that work on an array of readings.
A data acquisition node that reads NI hardware through NI's gRPC Device Server. It has been run against a stand-in server and not against NI's server or hardware.
A durable MQTT output: a message the broker misses is written to disk and sent in order when the broker is back, even across a restart.
A TDMS log, with a reader and writer written from NI's public format documentation. It has not been run against a file NI's own software wrote.
28 node types in the FlowLab section of the palette, up from 21.
HotLoop Flow 2.8.0 adds four things to FlowLab, the diagram tab for test benches and data loggers: analysis nodes, a data acquisition node for NI hardware, an MQTT output that keeps what the broker misses, and a TDMS log. Flows run exactly as they did, a flow file you have today loads and saves byte for byte, and a tab that isn't a diagram doesn't see any of it.
## What's new
**Analysis.** Four nodes work on an array of readings: statistics (mean, RMS, smallest, largest and standard deviation), integral (the area under the array by the trapezoid rule, as one number or as a running area), derivative (the slope at each sample), and a Butterworth filter of order 1 to 10 as a lowpass, highpass, bandpass or bandstop, with the cutoff in hertz. The code is in `internal/diagram/dsp`, with tests against values worked out by hand.
**A data acquisition node.** `read DAQ task` reads samples from NI hardware, such as a CompactDAQ chassis, through NI's gRPC Device Server. The client is about as small as it can be: Go's own HTTP/2 with hand-written messages, so the binary didn't take on a gRPC library. NI's published protocol definitions are in `third_party/ni-grpc-device` under their license, with a notice in NOTICE.
**An MQTT output that loses nothing.** `mqtt out` publishes through the broker the flow file configures, the same connection the MQTT nodes use. Mark it durable and a message the broker misses is written to disk before the node finishes and sent, oldest first, when the broker is back, even across a restart. Nothing overtakes anything waiting ahead of it. Its sent output says whether the message went straight out.
**A TDMS log.** `log to TDMS file` appends a record to a TDMS file, one channel per field, and the file opens in the tools a lab already has. The reader and writer are in `internal/tdms`, pure Go, written from NI's public format documentation and none of their code. A file whose last write was cut short by a power loss still reads up to the last whole value.
## What changed
- There are now 28 node types in the FlowLab section of the palette, up from 21, and the README says so.
- A test that fails in the CI collector step now prints its output. A step that failed once in the 2.7.1 run printed nothing, and the cause was the collector test comparing a span before the log it reads had all of it; it waits for the whole span now. The OPC UA simulator in CI listens on 4840 and not 50000, a port the kernel hands to outgoing connections. Two more tests were made to wait for what they check. None of that ships.
- The README's pictures were retaken so the top bar says v2.8.0.
- FlowLab grew by about 290 KB in the binary, 41,402,530 bytes at 2.7.0 and 41,693,346 with these four, built the same way on The Beast. The binary and image sizes in the README were read again for this release.
## New settings
None.
## Upgrade
On amd64, a plain `helm upgrade` to the 2.8.0 image and chart, or the new tag in your Quadlet unit. On arm64, stay where you are until 2.8.1, which is this release with arm64 added and nothing else. Nothing happens on first start and there is nothing to migrate.
## What isn't proven
The TDMS reader and writer have not been run against a file written by NI's own software, because I had none. They are checked against the byte layouts in NI's documentation, against my own writer, with fuzzing, and by reading a file this writer made with nptdms 1.13.0, an independent library used as a black box.
The DAQ node has not been run against NI's server or any NI hardware. It is tested against a stand-in server that speaks the same protocol, written from NI's definitions, and a stand-in proves the messages, not the device.
The durable MQTT output can deliver a message twice when a send timed out while the client still believed the link was up, and I forced that on a real broker to check the count. It never loses one that I could make it lose.
What a FlowLab diagram can't do yet: a case structure, records and shared types, waveforms, instrument sessions, sub-diagrams, serial flow control, `hotloop-flow test` and CI checks for diagrams, event handlers, an operator only panel, a panel layout editor, and a diagram as an MCP tool.
Image: `ghcr.io/hotloop-io/hotloop-flow:2.8.0`, linux/amd64 only. I build amd64 first, let it read stable in production, and then one small 2.8.1 with nothing else in it adds arm64. Until then the `2` tag holds the new amd64 image and the arm64 image from 2.7.1, so a box on arm64 that follows `2` or `2.7` keeps what it has, and a box pinned to `2.8.0` needs amd64. Chart: `https://hotloop.io/hotloop-flow/`. The README at this tag has the rest, with pictures: https://github.com/HotLoop-io/hotloop-flow/blob/v2.8.0/README.md
2.7.0 with the arm64 image added, and nothing else. There is no change to the code, the chart, the settings or your flows.
The image is built for linux/amd64 and linux/arm64 again, and the 2.7.1, 2.7 and 2 tags hold both.
Nothing else changed. If you are on arm64 and stayed on 2.6.0 while 2.7.0 was amd64 only, this is your move to FlowLab.
2.7.0 shipped amd64 only so it could get to production and read stable first, and this is the one small bump that builds both. A plain `helm upgrade` to the 2.7.1 image and chart, or the new tag in your Quadlet unit. Nothing happens on first start and nothing needs migrating.
What isn't proven: the arm64 image is built under emulation on the runner, and it starts and reports its version in the release run. It has not been run on an arm64 box for this release.
Image: `ghcr.io/hotloop-io/hotloop-flow:2.7.1`, linux/amd64 and linux/arm64. Chart: `https://hotloop.io/hotloop-flow/`.
The first cut of FlowLab: a second way to run a tab for test benches and data loggers, with loops, an error wire, a serial port, a panel an operator can open on a phone, and a debugger. Every flow you have runs the way it did.
FlowLab diagrams: a tab where every node runs once, when each of its wired inputs has a value, and nodes with no wire between them run at the same time. Add one with the FlowLab button next to the subflow button.
While and for loops that carry a value from one pass to the next, and an error wire: a node with an error coming in does nothing and passes it on, and an error wired into a loop stops it with the source and a code.
A serial port that survives a pulled cable, a reading parser, stable-value detection, and a log to a text file. The example in the repository reads a scale and shows it on a panel.
A panel at /panel/<diagram id> for controls, indicators and charts, a run bar with highlight execution, probes, breakpoints and step, and 21 new node types in the FlowLab section of the palette.
A sessions file that exists but can't be read is no longer overwritten by the next sign-in.
This is the first cut of FlowLab, and it is not all of it. A diagram is a tab where every node runs once, when each wired input has a value, which is what a test bench or a data logger needs: a loop that carries state, an error that travels on a wire of its own, a panel you can open on a phone, and a debugger that can pause a run and show what is on every wire. Flows run exactly as they did, and a flow file you have today loads and saves byte for byte.
The image is amd64 only for this release. I build amd64 first, let it read stable in production, and then one small 2.7.1 with nothing else in it adds arm64. Until then the `2` tag holds the new amd64 image and the arm64 image from 2.6.0, so a box on arm64 that follows `2` or `2.6` keeps what it has. A plain `helm upgrade` is the upgrade on amd64, there is nothing to migrate, and the one new permission, `diagram.run`, matters only if your users have explicit permission lists.
What is not here yet: a case structure, records and shared types, waveforms, TDMS and binary logs, a database or MQTT write, instrument and data acquisition nodes, filters and statistics, sub-diagrams, serial flow control, and checks for diagrams in `hotloop-flow test`. It has been run against a program that writes scale frames on a pseudo terminal, not a physical scale, and not for a day on a Pi. FlowLab does not do hard real time: work with a deadline belongs in a PLC.
A durable wire that stops delivering now says so: a counter you can alert on, and one log line with the numbers. Nothing about how your flows run changes.
A new counter, hotloop_flow_durable_wire_stranded_total, goes up when a durable wire's pump finds nothing to deliver while the wire says messages are waiting, and it stays that way past a recheck. Zero on a healthy wire, so anything above zero is worth a page.
One warning in the runtime log the first time it happens, with how far the pump got, the depth, the rows on disk, what is in flight, and how many were appended, delivered and dropped.
I added it because a drop-oldest wire failed to drain once in a few thousand test runs and I could not catch why. This release is the instrument, not a fix.
If you run durable wires on a plant line, this release gives you a way to know when one has stopped delivering. Nothing about how your flows run changes.
It is a plain image bump from 2.5.0. There is nothing to migrate and no new settings; the counter is on, and there is no switch.
The counter is tested by making the fault by hand, and the test fails with the pump's check removed. It has never fired on a real wire, because I have never seen the real fault, and the cause of the drop-oldest failure is still not found. If it ever fires on your line, the log line is what I need. The full notes are on [the GitHub release](https://github.com/HotLoop-io/hotloop-flow/releases/tag/v2.6.0).
A new editor. Same flows, same engine, same shortcuts, and it looks like it belongs next to the rest of HotLoop. The one cost is a blank page for a moment while it loads.
The editor looks like HotLoop. Same colors and type, light and dark following your system, and orange means you can click it and nothing else.
Debug and runtime moved to a dock under the canvas, so a debug line gets the whole width instead of a skinny column. History, Tests and Trace stay on the right, and the one you are working in comes to the top.
A trace is drawn in blue now, and the review before a deploy marks added, changed, moved and removed nodes in green, amber, blue and red, so a trace and a selection stop sharing a color.
A double-click right after an edit lands. The editor used to redraw every wire after the type check even when nothing changed, and a double-click could hit a wire being swapped out mid-click.
Nothing about your flows changed. A flow file loads and saves byte for byte, and all 60 browser tests pass untouched.
If you wire plants for a living, this is the release where the editor stops looking like it came from a different company. Same flows, same engine, same shortcuts. The difference is a screen that fits what you do all day: put the thing on the canvas, deploy it, and watch it run.
It is a plain image bump from 2.4.0. There is nothing to migrate and no new settings. Reload the editor tab once after the pod restarts so your browser stops showing the old one.
One thing is slower, and I would rather say so. The page is blank for a moment until the editor has loaded, where the old one painted its frame first. With the browser cache off, the sign-in form took about 12 ms longer on one machine, about 100 ms longer over a 20 Mbps link, and about half a second longer over a 1.6 Mbps link with 150 ms of latency. On a plant LAN it is a few milliseconds. On a bad link you will see a white page for a beat.
I have not opened this editor in Firefox or Safari, on a tablet, on a plant HMI screen, or inside the live EmberCORE dashboard frame. The browser tests and the screenshots run in Chrome. The full notes are on [the GitHub release](https://github.com/HotLoop-io/hotloop-flow/releases/tag/v2.5.0).
The EmberCORE dashboard signs people in to Flow, with the role their tenant gave them and no second login. It is off unless the dashboard's key is configured, and nothing that worked before changes.
Sign-in from the dashboard. The dashboard puts a token it signed in X-Embernet-Assertion on every request it proxies to Flow, the editor's websocket included. Flow checks the signature (ES256), the issuer, that the token was made for this Flow in this tenant, and its expiry, about a minute. Wrong on any of those and it is refused, and nothing else on the request rescues it.
Roles come from the tenant. A full-access role gets every permission. read gets the flows, the palette, the settings and the status, and nothing that changes them: no deploy, no inject, no deployment log. Operators and Viewers get read by default, and a role that is neither, or none, is no access. The deployment log and the audit trail show the person as dashboard:<email>.
No session to revoke. The dashboard sends a fresh token on every request, so a role changed there lands on the next request. The editor says to open it from the dashboard instead of offering a sign-in form, and GET /auth/mode is how it asks before anyone has signed in.
Off unless you give it a key. With no key file Flow never reads the header, a helm template of the defaults is what it was, and the admin login and API tokens keep working as the break-glass for staff and automation.
If you run Flow behind the EmberCORE dashboard, this is the one that gets rid of the second login. Someone opens Flow from the dashboard and they are in, with the role their tenant gave them, full access or read-only. A viewer cannot deploy, and nobody has to remember a Flow password.
If you don't, nothing happens. With no key file Flow does not read the header at all, so a plain image bump from 2.3.0 changes nothing on first start. The chart takes the whole thing under embernetSignin, the App Store hands it the dashboard's public key, and the chart mounts it, writes the settings, rolls the pod, and annotates the Service so the dashboard knows to sign people in.
To use it by hand, mount the dashboard's public key (a PEM file) and set auth.assertion.publicKeyFile and auth.assertion.audience, or HOTLOOP_FLOW_ASSERTION_PUBLIC_KEY_FILE and HOTLOOP_FLOW_ASSERTION_AUDIENCE. Flow refuses to start with a key it can't read or with no audience, because a half-configured sign-in that quietly lets everyone through is worse than one that won't boot. The other settings are auth.assertion.issuer, header and hideLogin.
It has not run behind the live dashboard, in a Fleet install, or in a person's browser outside the CI suite. It ran against a real Flow binary behind a signer built from the dashboard's own code, with every refusal exercised and the websocket handshake checked. Treat the first real install as the test that matters. The full notes are on [the GitHub release](https://github.com/HotLoop-io/hotloop-flow/releases/tag/v2.4.0).
Flow talks to HotLoop, an agent can call a flow as an MCP tool, a plugin is a signed WebAssembly file, and a wrong-shaped message gets caught before it does damage.
HotLoop nodes. A connection to a HotLoop is a URL and an account. hotloop in follows the live feed and sends a message for each entity that changes, hotloop state reads one entity, and hotloop script and hotloop recipe run a script or apply a recipe. HotLoop checks every field, runs every write through its write gate and keeps the record, with the reason flow:<node id>.
Writes through HotLoop's gate. The Modbus, OPC UA, S7 and EtherNet/IP write nodes have a Write through HotLoop option. A write the gate refuses never reaches the equipment, and a HotLoop that can't be reached fails the write instead of falling back to writing directly.
MCP in both directions. mcp tool and mcp result serve a flow to an agent at /mcp, and mcp client calls a tool on any MCP server, HotLoop's included. A token is required, the call runs with that token's permissions, every call and refusal is audited under the caller, and an API token can carry a rate limit.
Plugins without npm. A plugin is a WebAssembly module, a descriptor and an ed25519 signature. Unsigned and tampered ones refuse to load, a guest past its memory ceiling or timeout traps to a Catch node, and a plugin that asks for host access nobody granted fails the deploy. With no trusted keys, nothing loads.
Typed wires. Give the json node a JSON Schema and a wrong-shaped value goes to Catch with every bad field named. Nodes can declare what they accept and what each output promises, and a deploy is refused when no message could satisfy both ends of a wire. An inject that sets a literal the next node can never take is refused the same way. The editor draws the type on each wire.
Three durable queue fixes: a removed durable wire refuses a late write and stops waiting on a stuck target, a drop-oldest wire no longer evicts a message twice, and a late hand-back no longer stays charged to the quota.
Nine more node types, 79 in all. The image is 44.8 MB for amd64, built from the release tree and read with podman image inspect, and the README and docs carry Raspberry Pi 5 numbers.
Breaking
The json node used to ignore msg.schema. Now a message that carries msg.schema is checked against it, and a mismatch goes to a Catch node instead of down the wire. A flow that leaves a msg.schema on its messages for some other reason will see that.
From 2.2.0 it's a plain image bump, with no migration and no flag, and a flows.json and config file that ran on 2.2.0 run on 2.3.0. A flow with no schemas anywhere behaves exactly as it did, and a write node with no HotLoop picked writes the way it did in 2.2.0. Going back to 2.2.0 is safe for any flow that doesn't use the new nodes. A HotLoop, MCP or plugin node fails to start there, and a write node with a HotLoop picked writes straight to its equipment on 2.2.0, so take the HotLoop off those nodes before you go back.
MCP is a new way into Flow and it takes a token. Nothing is served until a flow has an mcp tool node, and a call with no token or a made-up one is refused. Plugins are off until you give the runtime a trusted key, and the chart takes all of it under plugins with enabled false by default.
It has never run on a real plant floor. Only the Modbus write was run through a real HotLoop gate, on the published HotLoop 4.18.10 image in CI. The OPC UA, S7 and EtherNet/IP writes send through the same code. The S7 and EtherNet/IP nodes have still only met simulators. The HotLoop reconnect is tested against a stand-in, MCP has no OAuth, stdio, resources, prompts, or sampling, and plugins have never run on a Pi. The schema validator is not Ajv: it refuses a $ref outside the schema and ignores format values it doesn't know. Flow now has Raspberry Pi 5 numbers, and a Pi 4, a Zero 2 W and SD card writes are still not measured. The full notes, with every new setting, are on [the GitHub release](https://github.com/HotLoop-io/hotloop-flow/releases/tag/v2.3.0).
Flow talks to the PLCs, remembers what it knew when it restarts, and shows you where a message went. It is also the first release under HotLoop's Business Source License.
The license changed. 2.2.0 and every release after it is under HotLoop's Business Source License 1.1. Home and lab use is free, and so are schools, nonprofits and government bodies. Business use is free through EmberNet, which is the only business path. 2.1.0 and everything before it stay under the license they shipped with.
Tracing and replay. Every message gets a bounded trace, and clicking a debug message lights the path it took with timing and the payload at each hop. A trace becomes a flow test, or replays into a draft so you can try a fix on the message that broke it. Hops can go to an OpenTelemetry collector as spans, proven against the real collector image.
State that survives a restart. Flow, global and node context live in a SQLite file, state.db, on the data volume. Mark a wire durable and it spills to disk, in order, only when the node behind it stops taking messages. A real InfluxDB killed for ten minutes, with the runtime killed mid-outage and mid-drain, came back with none missing and none doubled.
Plant nodes. Modbus TCP read and write, OPC UA read, write and subscribe, S7 read and write, EtherNet/IP read and write, and Sparkplug B as an edge node and as a host. S7 and EtherNet/IP have only met simulators.
The editor gets copy and paste, import and export of a selection, subflows with their own canvas, nested groups, search across every flow and debug filters. Dragging a wire onto a node works in Chromium now.
A node whose config node is missing is reported on import, on load and on deploy, and fails to start. Before, it quietly never worked.
The image is built and pushed with Podman. Same tags, 2.2.0, 2.2 and 2, still linux/amd64 and linux/arm64.
Breaking
Context persists by default, so a value set before a restart is there after it. A flow that counted on an empty context at start now has to clear what it expects to be clear. Set store.context.persist to false for the old behavior.
From 2.1.0 it's a plain image bump, with no migration and no flag, and a flows.json that ran on 2.1.0 runs on 2.2.0. The first start creates state.db in the data directory. Going back to 2.1.0 leaves it where it is, because 2.1.0 has no code that reads it. Every write to state.db is a write to an SD card or an SSD, so context changes are batched and a hard kill can lose up to 30 seconds of them.
It has never run on a real plant floor. The S7 and EtherNet/IP nodes have not met a Siemens CPU or a Logix controller, durable wires have never been on a Pi, and Modbus RTU, Modbus over TLS and OPC UA events, history and browse are not done. The full notes, with every new setting, are on [the GitHub release](https://github.com/HotLoop-io/hotloop-flow/releases/tag/v2.2.0).
Every deploy is a record you can diff, test and put back, and a save restarts only the nodes you changed.
Deploys keep the record: who, from where, when, the note, and the exact bytes of the flow file and its credentials. Any two diff node by node, in the API, on the command line and inside git diff, and any of them rolls back, a deleted node's broker password included.
A save restarts what you changed. MQTT sessions, listeners and Delay queues on everything else keep running. Moving or rewiring a node doesn't restart it.
Flows get tests. flows.test.yaml sits next to flows.json and runs on the real runtime and the real nodes, with time you move and stand-ins for everything outside the process. Turn on tests.gate and a deploy that fails them is refused with the whole report. Rollbacks are never gated.
JSONata runs and is proven against the published suite, 1673 of 1686 cases with the other 13 pinned by name. Inject fires on a crontab on the same minute Node-RED would. MQTT 5 and the last will, TLS on TCP, HTTP and MQTT, WebSocket listener and client, cookies and multipart on HTTP.
Signing in holds up: two-factor sign-in that is free for anybody who wants it, lockouts, sessions that survive a restart, and an audit log of who did what from where.
A broker or database password can live in a mounted Secret instead of the flow. New settings: tests.gate (HOTLOOP_FLOW_TESTS_GATE), secrets.allowedPaths, API tokens from hotloop-flow token.
The image carries LICENSE, NOTICE and THIRD_PARTY_LICENSES, and NOTICE now lists every file ported from other projects with its license.
A WebSocket token goes in the hotloop-flow.bearer.<token> subprotocol. A script that still sends it in the URL keeps working and gets a warning in the log, because the URL ends up in proxy and access logs.
Nothing in this release changes how a flow file is read or written, so a `flows.json` that ran on 2.0.5 runs on 2.1.0. Upgrading is an image bump. The first start creates `sessions.json`, `audit.log` and a `deployments` directory under the data directory, and everyone signs in once because sessions used to live in memory.
Lockout is on by default: five failures for one account from one address, or twenty from one address, locks it for fifteen minutes. `auth.lockout` changes the numbers.
It has never run on a real plant floor. The tests, the race detector, a real Mosquitto and the browser tests are all behind it, and none of that is a plant. The full notes, with every new setting, are on [the GitHub release](https://github.com/HotLoop-io/hotloop-flow/releases/tag/v2.1.0).
HOTLOOP_FLOW_INSECURE=true finally turns authentication off, and turning discovery on stops handing the pod raw network privileges.
HOTLOOP_FLOW_INSECURE=true never worked. It switched authentication off, the startup check refused any config with authentication off, and the refusal told you to set the variable you had just set. From 0.1.0 through 2.0.4. It works now, and only from the environment: auth.enabled false in the config file still refuses to start on its own, because a config file is where a copy-paste lands.
Running without a login is loud about it. Every boot logs a warning, and the editor shows a NO LOGIN badge where Sign out would be, so whoever opens it next knows the door is open. The credential secret still needs its own opt-out.
The editor asks the runtime whether it needs a login instead of assuming. Before, even a runtime that had started with authentication off would have landed you on a login screen with no users behind it, and the live event stream refused to connect without a token.
The chart no longer adds NET_RAW and NET_ADMIN when discovery is on. The scan node only makes TCP connections, so those were privilege for nothing. Every render keeps all capabilities dropped, and CI fails if one comes back.
The config package had no tests at all, which is how the first bug lived this long. It has them now, and four of them fail on the old check. Both ways, authentication on and off, were driven end to end in a browser against the built binary before this was tagged.
The chart tells the dashboard what it is and what it looks like, so the deployed tile gets its name and icon right.
The pod and the Service now carry the embernet.ai/app-icon annotation. Before, neither did, so the dashboard's deployed tile went hunting for an icon in the app catalog by name, using the release name, which is never in the catalog. The tile came up without one.
The icon defaults to the chart's own icon. It is served from raw GitHub, which sends Access-Control-Allow-Origin: *, so the dashboard's crossorigin image actually draws it. Set embernet.appIcon to use your own, and make sure wherever it lives sends that header too, or the tile is blank.
The embernet.ai/app-name label is the chart name now, not the release name. That is what the dashboard writes on everything it deploys itself, what it matches catalog icons on, and what features like the Ignition gateway list key on.
Which instance a pod belongs to is still in app.kubernetes.io/instance and the Service name, and no selector changed, so upgrading in place is fine.
Rendered against the published 2.0.3 chart at the same version, the only differences are those two labels and the two icon annotations. The program itself did not change, and the image is rebuilt from the same code.
The chart puts the EmberNet dashboard's tenant labels on everything it renders.
When an app is deployed from the EmberNet App Store, the dashboard passes tenantLabels (the tenant, the app id, who deployed it, and the deployment id) and expects them on everything the chart creates. The chart did not read them, so none of the five were there. It puts them on every resource and on the pod now.
The value is empty by default. A plain helm install renders exactly as before, and the selectors are untouched.
Found by deploying it to a tenant cluster through Fleet and looking at what arrived. It has now been deployed that way to a real cluster: the pod runs, login works, and all five labels are on every resource.
CI checks both directions: a default render carries no tenant label, and a chosen one reaches all seven places it belongs.
Nothing else changed in the program. The fix for the generated admin password, from 2.0.2, is included.
The chart's generated admin password now works. It never did, from 0.1.0 through 2.0.1.
The chart generates an admin password, stores it, and the install notes print how to read it. The login it gave did not work in any earlier version, because the hash the app checks was made from a different random password than the one the chart stored. The hash is made from the stored password now.
A release installed with the bug is fixed in place by upgrading to 2.0.2. The password and the credential secret do not change, so nothing stored with your flows is lost.
CI now renders the chart and checks with bcrypt that the generated password matches its hash. Nothing caught this before because both values are random, and nothing rendered the chart before a tag.
It was found by installing the chart on a live k3s cluster and logging in with the password the chart had stored.
Only the generated password was affected. A password you set with auth.password, or a hash you set with auth.passwordHash, worked all along. The program itself is unchanged since 2.0.1, and the image is rebuilt from the same code.
A credentials file from Emberwire 0.1.0 now says what it is, instead of failing with a parsing error.
Starting on a credentials file written by 0.1.0 used to fail with a JSON parsing error. It now names the file, says it was written by Emberwire 0.1.0 and that 2.x cannot read it, and tells you to move it aside and enter the credentials again.
A plaintext credentials file that has a node called "format" in it still loads, and there is a test for that.
Nothing else changed. The old file still cannot be read, because it is encrypted under the old format, and that is on purpose. This only fixes what the operator is told when it happens.
The first release under the HotLoop Flow name. It was Emberwire 0.1.0 before this.
Renamed end to end. The image is ghcr.io/hotloop-io/hotloop-flow, the chart and the binary are hotloop-flow, and the variables are HOTLOOP_FLOW_*.
The editor uses the HotLoop palette and self-hosted Inter and JetBrains Mono, in light and dark, and its top bar works on a phone. Text on an orange fill is dark ink, because white on that orange measured 3.13:1.
Still one static binary in a 25 MB image, with the same 51 node types.
The editor is type-checked in CI now, which it never was, and its design tokens are checked against the canonical copy.
Breaking
The EMBERWIRE_* environment variables are not read. Use HOTLOOP_FLOW_*.
The InfluxDB and PostgreSQL config nodes are hotloop-flow-influxdb and hotloop-flow-postgres. A saved flow that uses the old emberwire- types will not find them.
WASM modules must export hotloop_flow_process, hotloop_flow_alloc, and hotloop_flow_free. A module built against the old exports will not run.
A credentials file written by 0.1.0 cannot be read. It fails to load with a parsing error, so re-enter the credentials.
Metrics are hotloop_flow_* and not emberwire_*, and the deployment header is HotLoop-Flow-Deployment-Rev.
This is a deliberate clean break, since 0.1.0 had no known users, and nothing keeps answering to the old names. The 0.1.0 image is still where it was, at ghcr.io/embernet-ai/emberwire:0.1.0.