Iterate Kit
apps/kit is the small device installer served at https://k.iterate.com.
The first supported hardware class is selected ESP32-S3 devices installed
through ESP Web Tools.
Firmware model#
The source of truth is
src/firmware/catalog.ts. Device identity,
install method, and release artifact are separate:
installMethodis a discriminated union foresp-web-tools,uf2-download,webusb-dfu, or anexternal-tool.- each release has an independently discriminated artifact;
- ESP releases name every immutable source URL, flash offset, file name, and expected SHA-256, plus the reserved configuration partition.
Only ESP Web Tools is implemented in the UI today. The wider model prevents a future RP2040, Nordic, STM32, or other board from being incorrectly treated as an ESP merely because it can be installed from a browser.
The two devices currently have no releases on purpose. Stock Home Assistant Voice and StackChan firmware does not understand Iterate project credentials, so presenting it as a working Kit image would create a successful flash and a non-working device. Add the first release only when an Iterate-aware build and its partition layout exist.
Bundled assets#
pnpm firmware:sync:
- downloads every catalog artifact over HTTPS;
- rejects any SHA-256 mismatch, unsafe path, or overlapping ESP flash region;
- emits local ESP Web Tools manifests and binaries under
public/firmware; - emits a public, source-URL-free
catalog.json.
pnpm build runs the sync first. Vite and the Cloudflare plugin then include
the generated directory in the Worker's static assets, so a production flash
does not depend on a third-party firmware host. The generated assets are
gitignored; the reviewed catalog and checksums remain the durable source.
Private configuration#
For an ESP release, the page creates a dynamic ESP Web Tools manifest in the browser. It adds one generated binary part at the release's declared configuration offset. Wi-Fi and Iterate credentials therefore travel directly from browser memory to the connected device and never enter a URL or request to the Kit Worker.
The raw iterate-kit/v1 partition is:
| Offset | Value |
|---|---|
0..7 |
ASCII ITERKIT1 |
8..11 |
little-endian payload byte length |
12..15 |
little-endian CRC-32 of the payload |
16.. |
TLV fields, padded with 0xff |
The payload is not JSON — it is a flat run of u8 tag | u16 LE length | bytes, because the firmware parses it before it has a JSON reader and a
mismatch here is unrecoverable in the field. The flasher wrote JSON while the
firmware read TLV once, and the symptom was a board that flashed perfectly and
never joined a network.
| Tag | Field |
|---|---|
| 1 | Wi-Fi SSID |
| 2 | Wi-Fi password (may be empty) |
| 3 | Iterate base URL |
| 4 | project slug |
| 5 | Project API key |
| 6 | device id (optional) |
| 7 | kit mount path (optional) |
Tag 2 is the one field whose value may be zero-length — an open network still
has a password field, it is simply empty — and every other required tag must
carry bytes. OS resolves the immutable slug to its stable project ID before
checking the key revealed from /secrets/project-api-key, so the setup flow
does not expose internal project identity.
Firmware should parse this partition at boot, reject an unknown magic/version or checksum mismatch explicitly, and retain Improv Wi-Fi or a local recovery path for credential rotation.