Expand description
HTTP API for the hardware device registry (/api/hardware/*, PROTOCOL.md §6).
POST /api/hardware/pair— verify the pairing nonce, register the device, return its one-timedevice_token+node_url.GET /api/hardware/devices— list paired devices (presence + battery).PATCH /api/hardware/devices/:id— rename / update prefs.DELETE /api/hardware/devices/:id— revoke (delete the device + its token).
§Auth split (flagged for the router wiring)
pair is public: the proof-of-possession is the pairing nonce shown
out-of-band on the device (QR / BLE), and the companion app may hold only a
better-auth session, not the node’s RYU_TOKEN. devices list/patch/delete
are management routes and sit behind require_auth with the rest of the
protected surface.
Placement (Core vs Gateway): the registry decides which device may drive this node, so it is Core.
Structs§
- Device
Dashboard Update - Request body for
PUT /api/hardware/devices/:id/dashboard. Any field may be omitted; only the present ones are applied.widgets(when present) replaces the bound dashboard’s widget set (the device-scoped analog of the desktop grid). - Hardware
Ctx - Router state for the hardware HTTP surface: the device registry (
DeviceStore) - Image
Query - Query for the image endpoint: the
revthe device already holds (so an unchanged image returns304 Not Modifiedand saves the download).
Functions§
- delete_
device DELETE /api/hardware/devices/:id— revoke a device (delete it + its token).- devices_
routes - Build the PROTECTED device-registry CRUD router (relative paths, state baked in),
returning a state-less
Router<()>the host nests at/api/hardware/devicesbehind the Hardware App gate. These are management routes (desktop +dashboard_builder); the host mounts them INSIDErequire_auth. - display_
image GET /api/hardware/display/:device_id/image?rev=— the rendered image bytes (packed 1-bit for e-ink, RGB565, or PNG). Returns304when the device’srevmatches the freshly-rendered content hash.- display_
manifest GET /api/hardware/display/:device_id— the display manifest. Returns the content hash (rev), the poll interval, the screen geometry, and the image URL the device should fetch. The device skips re-downloading whenrevis unchanged.- display_
routes - Build the PUBLIC TRMNL display router (relative paths, state baked in), returning
a state-less
Router<()>the host nests at/api/hardware/displayon the public router. A device polls these with its OWN per-device Bearer token (which the global-RYU_TOKENrequire_authcannot gate), so each handler authenticates the device token against the registry itself — hence public, ungated. - get_
device_ dashboard GET /api/hardware/devices/:id/dashboard— the device’s dashboard config (the binding + the bound dashboard’s widgets).- list_
devices GET /api/hardware/devices— list paired devices with presence + battery.- nudge_
device_ display - Send the RHP
displayre-poll signal to a connected device over its live WS. Best-effort: a no-op when the device is offline (it will poll on its own cadence). The surface (eink/lcd) is derived from the device class so the firmware knows which panel to refresh. - openapi
- The OpenAPI sub-document for the hardware device-registry + display surface,
merged into Core’s spec. The public ws/pair ingress keeps its own annotations in
apps/core(seeserver::hardware_ws/server::hardware_public). - set_
device_ dashboard PUT /api/hardware/devices/:id/dashboard— set the device’s poll interval and/or replace its widget selection + layout. Reuses the dashboard store so the same widgets the desktop builder authors render on the device. Pushes adisplaynudge so a connected device re-polls immediately.- update_
device PATCH /api/hardware/devices/:id— update a device’s name / prefs.