An operator-grade UI over a live WebSocket. See every device, drill into any one, queue commands, push firmware, watch OTA progress as it lands. Every state-changing action is signed with the operator’s identity and written to audit. End-customer views with org / fleet / role separation are next.
Per-device dashboards that update on a one-second tick. Every reading shows which transport carried it, how long the round-trip took, and how healthy the device is right now.
Sortable device list with status pill, last-seen relative time, transport indicator, and error-log breadcrumb chip. Events stream over WebSocket; the UI updates in real time without a page reload.
WiFi up/down + SSID/RSSI/IP, cell up/down + CSQ + registration, sends and fails per transport, switches counter. Admin-off pipes show a dash so “down” never reads as a fault.
Each row shows whether WiFi or cellular delivered it, network round-trip time, device uptime, and free heap. Click to expand the full kv detail of any reading.
Today the portal is operator-facing — one operator account, all devices visible. End-customer accounts with org / fleet / role separation are designed, documented, and on the build list. Here’s the cascade we’re shipping.
Every device will belong to 0 or 1 orgs. Data partitioned per-org on disk and in the dashboard. Cross-org leakage structurally impossible, not just policy-bound. Unclaimed devices sit in a platform-wide pool until assigned.
“Building A,” “Pilot customers,” “Bench” — whatever you want. Devices can live in multiple fleets at once. Fleets are for visibility and access, not ownership.
Per-org roles cascade across fleets. Fleet members opt out of the cascade for outside-contractor scoping. Viewers can be elevated to editor on a specific fleet without org-wide permissions.
Send commands from the portal; the device executes on its next check-in and returns the result as an event. The same diagnostics you’d run at the bench, only the unit is on a tower across town.
Type a command, hit send. Goes into the device’s queue. On the next chkin the device pops the queue, runs the command, and posts a cmd_result event back. The operator UI renders it inline with the rest of the event log.
Commands carry a UUID. Server keeps a replay cache — reused IDs are rejected, so a retried submit can’t fire the command twice. Safe to bang on the send button.
Inspect device state, dump the structured error log, toggle WiFi, change the chkin cadence, kick the modem, target a firmware image, force a reboot. Everything the serial console can do, the queue can do.
Every check-in carries an error-log breadcrumb — if a device tripped, the UI shows a colored chip on its row. Queue errlog show <seq> to pull the full entry: source, severity, code, timestamp, kv context.
Every queued command is signed with the operator’s HMAC key and written to audit before it’s queued. Every cmd_result is signed by the device on the way back. Both ends, all the time.
Recent commands are kept in the browser (deduplicated, capped at 50). Up- and down-arrow in the queue-input field recalls what you sent, across devices. The same diagnostic at three in the morning takes one keystroke.
For benches and provisioning. Connect over USB-C and a serial terminal gives you the same command surface directly, no queue round-trip. Useful for first-time bring-up before the device has talked to the portal.
Every state-changing action is recorded with operator identity, target, and detail. The wire is signed both ways — HMAC out of the device, HMAC back from the cloud.
Approve a device, change a label, queue a command, target firmware, set device state — all logged with operator identity, timestamp, and full payload. Per-device JSONL rotated monthly, exportable via tick-cli audit.
Device requests carry HMAC-SHA256 of body + timestamp + nonce. Server responses are signed back with the same secret. A captured response can’t be replayed; a forged request can’t pass.
Operator↔device frames carry an optional FRAME_FLAG_ENCRYPTED bit. When set, the payload is AES-256-GCM with a 12-byte AEAD nonce per frame, HMAC-verified before the GCM tag is checked. Defense in depth on top of TLS.
The operator’s HMAC token is wrapped in localStorage with AES-256-GCM, keyed by a PBKDF2-SHA256 derivation (600k iters, OWASP 2023) of a passphrase entered at login. Plaintext lives in memory only for the session.
Per-device HMAC secrets can be sealed with AES-256-GCM using a KEK loaded at boot. Opt-in via TICK_KEK_PATH; the server falls back to plaintext keys if KEK is absent for development simplicity.
Strict Content Security Policy on the operator UI, X-Frame-Options, replay cache on command IDs, HTTP-to-HTTPS redirect listener, graceful SIGTERM/SIGINT shutdown that drains in-flight requests.
Operator tokens expire after 14 days of inactivity and 90 days of total life, whichever comes first. Stolen creds have a half-life. Operators rotate by signing in again.
Server remembers recently-seen command IDs and refuses reuse. Combined with the bidirectional HMAC, every command is unique, signed, and one-shot.
Five clean states, one unified verb for moving devices between them. A factory-fresh device lands in the unclaimed pool, gets assigned to an org, lives there until you eject it, and shows up in the next org’s pool with a hint about where it came from.
A factory-fresh device’s first valid POST auto-registers it in the unclaimed pool with an auto-named label. Subsequent POSTs are stored against the unclaimed record. A platform operator clicks Approve to bring it into service.
POSTs persist, the device shows on the live device list, queued commands flow on next chkin, firmware can be targeted. Operators can rename, retarget firmware, disable, or restore from the per-device panel.
POSTs from a disabled device are rejected at the HMAC-OK layer; no data is written, and the device’s history stays intact. Restore at any time. Useful for “in transit,” “in storage,” or “under investigation.”
What ships today is the operator UI on the page. Next: end-customer accounts with org / fleet / role separation, server-side alerting, outbound Routes, and a public read-only fleet view.
End-customer accounts. Org as the security boundary, fleets for groupings, roles cascading from org to fleet, fleet members for outside-contractor scoping. Design locked; build underway.
Fleet-level rules. Email and webhook delivery. Threshold breaches, dwell-time, cooldowns, resolved-notifications. The pager-at-3am feature.
The portal pushes events out to your destinations as they arrive. HTTPS first; MQTT, AWS, Azure, Google Cloud, Twilio, Datacake, Blynk, and Qubitro on the path.
One operational fleet exposed unauthenticated, field-scrubbed and rate-limited — the demo as the product. Designed; build in queue behind alerting and Routes.
The portal is operator-only today. Talk to us about a pilot — we’ll issue operator credentials and walk you through your first device.