# ryu-hardware
Ryu Hardware Protocol (RHP v1) node backend — an extracted **Core capability crate**.
It is the node half of the protocol in `apps/hardware/PROTOCOL.md`: Ryu devices
(watch / necklace / desk, all ESP32-S3) talk to a node over a WebSocket, either
directly over WiFi (Mode B) or tunneled through the mobile app over BLE (Mode A,
transparent to the node).
## Role in the decomposition
A primitive lifted out of `apps/core`. It owns the paired-device registry, token
lifecycle, the audio codec edge, the per-connection realtime session state machine,
the display-nudge loop, and the device-registry + TRMNL display HTTP surface. The crate
has **zero dependency on `apps/core`** (it depends only on the `ryu-dashboards` and
`ryu-meetings` app-store backends for the display + ambient-meeting bridges).
## Layout / key modules
- `protocol` — serde structs/enums mirroring PROTOCOL.md §3 (the wire contract shared
by the firmware and mobile relay).
- `store` — device registry (SQLite): paired devices, per-device revocable Bearer
tokens, last-seen/battery presence. `DeviceStore`, `DeviceRecord`, `hash_token`.
- `pairing` — pairing-nonce verification and token issuance.
- `codec` — the Opus/WAV codec edge, so the rest of Core sees PCM/WAV.
- `session` — the realtime session state machine (audio buffering + ambient meetings
bridge), the live device-sender registry, `HardwareSession`, `TurnInput`,
`SessionOutput`.
- `nudge` — the live display-nudge loop (dashboard change → device re-poll).
- `api` — device-registry CRUD (`/`, `/:device_id`) + TRMNL display
(`/:device_id`, `/:device_id/image`) axum router.
## What stays Core-side (consumers of this crate's types)
The **public ws/pair ingress route** (a per-device Bearer/nonce that the global
`RYU_TOKEN` `require_auth` cannot gate, plus mesh/SSRF-guarded node-URL resolution) and
the **chat-turn orchestration** (welded to Core's `run_text_turn` / voice ASR / TTS
session loop) stay in `apps/core` and consume this crate's `session`/`protocol` types.
## Placement (Core vs Gateway)
The device registry, token lifecycle, and realtime session decide *what runs* → Core.
## Consumed as
Compiled-into-core crate (non-optional path dependency): the codec is reused by the
voice module and the store backs `ServerState` in every build.