Status reports and alerts
Alerts
| Item | Yellow | Red | ROOST-26-0001 | ROOST-26-0002 |
|---|---|---|---|---|
| Chip temperature | ≥ 80 °C | ≥ 90 °C | 46–50 °C | 45–49 °C |
| Mesh resistance | ± 1 % | ± 1.5 % | 100.1 % | 99.9 % |
| Voter quorum | 2 of 3 | < 2 | 3 of 3 | 3 of 3 |
| Time sync | > 100 ms | > 500 ms | 8 ms | 11 ms |
| Battery 2 | < 2.7 V | < 2.5 V | 3.61 V | 2.68 V |
| Signs per minute | > 3× baseline | > 10× baseline | 41 | 38 |
A bound box reports its status once a minute. The report is signed with the box's attestation key (the same key used for binding), so no session or API key is needed.
| Method · Route | Purpose |
|---|---|
POST /api/roost/report | Box status report. Anonymous; { serial, payload, signature }. |
GET /api/org/{slug}/roost/devices/{serial}/telemetry?range=1h|24h|7d | Points for the four graphs. Owner or Roost Admin. |
GET /api/org/{slug}/roost/alerts | Active alerts per box and item, recipients, defaults. Owner or Roost Admin. |
PUT /api/org/{slug}/roost/alerts/recipients | Replace the extra recipients (the Owner and Roost Admins always receive alerts). Owner or Roost Admin. |
POST /api/roost/report
payload— base64url of the UTF-8 JSON below.signature— ECDSA P-256 / SHA-256 over the payload bytes,r‖s(64 bytes), base64url.atis the box clock in Unix seconds. It must be within ±5 minutes of server time (409 REPORT_CLOCK_SKEW) and newer than the last accepted report (409 REPORT_REPLAYED).- An unknown serial, a box without an attestation key, a bad signature or an unbound box all answer
403 REPORT_REJECTED.
{
"v": 1, "typ": "roost-status", "serial": "ROOST-26-0001", "at": 1760860800,
"psu": [true, true], "fans": [4150, 4160, 4200, 4180],
"voters": { "kv260": {"online": true, "kid": "…"}, "polarfire": {"online": true, "kid": "…"}, "machxo3d": {"online": true, "kid": "…"} },
"watcher": true, "signCounter": 89261, "lastSignAt": 1760860620,
"mesh": { "ok": true, "ratioPct": 100.12 }, "lid": true, "light": true, "efp": true,
"zeroize": "Armed", "keysPresent": true,
"battery": [3610, 3605], "activeBattery": 1,
"chipTempC": [46.2, 46.9, 47.4, 48.1, 48.0, 49.3, 49.8], "boardTempC": 31.4,
"v12": 12.03, "v5": 5.01, "v3v3": 3.30,
"ntp": { "ok": true, "driftMs": 8 }, "rtcOk": true,
"slots": { "active": "B", "a": {"version": "1.0.4", "hash": "…", "verified": true}, "b": {"version": "1.1.0", "hash": "…", "verified": true} }
}
Response 200: { serial, acceptedAt, color, nextReportInSeconds }.
Thresholds and colors
The server evaluates every report against the planned bands. Red pages immediately. Yellow pages once the condition has lasted 5 minutes; until then the box still shows green. A condition that keeps going is not re-sent; a return to normal sends one recovery notice. No report for 3 minutes is yellow, for 10 minutes gray.
| Item | Yellow | Red |
|---|---|---|
| Chip temperature (any of 7) | ≤ 5 or ≥ 80 °C | ≤ 0 or ≥ 90 °C |
| Board temperature | ≤ 5 or ≥ 50 °C | ≤ 2 or ≥ 55 °C |
| 12 V input | < 11.4 or > 12.6 V | < 11.0 or > 13.0 V |
| 5 V · 3.3 V | < 4.85 / > 5.15 V · < 3.20 / > 3.40 V | < 4.80 / > 5.20 V · < 3.17 / > 3.43 V |
| Batteries (each) | < 2.7 V | < 2.5 V |
| Mesh resistance ratio | beyond ±1 % | beyond ±1.5 % |
| Voter quorum | 2 of 3 online | fewer than 2 |
| Fans · PSUs | 1 failed · 1 of 2 lost | 2+ failed · both lost |
| Time sync | drift > 100 ms | drift > 500 ms or NTP lost |
| Tamper (zeroize, mesh, lid, light, EFP) | — | immediately |
The box erases its keys on its own bands inside the enclosure; these thresholds only warn people ahead of that.
Alerts are delivered on the existing channels: the organization's real-time feed , the dashboard notification inbox (RoostAlertRaised / RoostAlertCleared) and email to the Owner, Roost Admins and any extra recipients. Audit events roost.alert.raised and roost.alert.cleared record every delivery.
Telemetry
range=1h returns 1-minute points, 24h (default) 10-minute points, 7d hourly averages. Each point is { at, m } with m = { chipTempC[], boardTempC, v12, v5, v3v3, battery1Mv, battery2Mv, meshRatioPct, signCounter, fanRpm[] }. Raw points are kept 7 days and hourly averages one year.