Architecture
flashbay is built as a three-tier system that connects users to real MCU hardware over the internet.
System Overview
Tier 1 — Target Boards
Real MCU development boards (ESP32-S3, STM32, etc.) connected via USB. Each board is individually addressable for flashing and serial communication.
Tier 2 — Pod
A pod master manages a set of target boards at a physical location. It:
- Connects to boards over USB for serial and flashing
- Maintains a persistent WebSocket tunnel to the coordinator
- Executes flash commands using
esptool.py(ESP32) oropenocd(STM32) - Controls board power via USB port power cycling
Pods phone home to the coordinator — no inbound ports or static IPs required. This means pods can run behind NAT, in a home lab, or in a datacenter.
Tier 3 — Cloud Coordinator
The coordinator is the single public entry point. It handles:
- Authentication — API keys for programmatic access, email/password for the web UI
- Session management — reserves a physical board, tracks state and credit usage
- Real-time proxying — WebSocket bridge between the user's browser/CLI and the pod's serial connection
- Billing — credit-based usage tracking
- Web UI — dashboard, serial terminal (xterm.js), flash interface
Session Lifecycle
PENDING ──▶ ALLOCATING ──▶ ACTIVE ◀──▶ IDLE
│ │
▼ ▼
ENDED ◀────────┘- PENDING — session created, looking for a board
- ALLOCATING — board found, pod is setting up
- ACTIVE — board is reserved, serial and flash available
- IDLE — no active WebSocket connection (session still reserved)
- ENDED — session released, credits finalized
Sessions consume credits while active or idle — the board remains reserved until the session ends. Sessions end automatically when credits run out, the idle timeout expires, or the maximum session length is reached.
Data Flow
When a user flashes firmware or reads serial output, the data path is:
User ──WSS──▶ Coordinator ──WSS──▶ Pod ──USB──▶ MCUAll connections use TLS. The coordinator never stores firmware — it streams directly to the pod. Serial data is proxied in real-time with no buffering.
Security Model
- Zero inbound ports on pods — pods initiate outbound connections only
- Per-session isolation — each session locks a single board; no cross-session access
- API key authentication — keys are prefixed (
key_) and hashed at rest - No firmware storage — binaries stream through and are never persisted on the coordinator