reachy_mini_central / docs /META_CONTRACT.md
cduss's picture
more info on central page
66918e9
|
Raw History Blame Contribute Delete
3.75 kB
# Producer metadata contract
Every peer registers with `POST /send` `{"type": "setPeerStatus", "roles": [...], "meta": {...}}`.
Central stores `meta` **verbatim** and forwards it unchanged to every
owner-scoped surface: the SSE `list` / `peerStatusChanged` /
`sessionStateChanged` frames, `GET /api/robot-status` and
`GET /api/debug/peers`. Daemons may add fields at any time without a
central change; clients must tolerate unknown keys.
This page lists the few keys central *reads*. Anything not listed is
opaque to the server.
## Keys interpreted by central
| Key | Sent by | Server-side use |
| --- | --- | --- |
| `name` | producer, consumer | Producer: `robotName` in `/api/robot-status`. Consumer: reported as `activeApp` while it holds a session. Display only. |
| `hardware_id` | producer (daemons >= v1.7.2) | Stable per-robot identity: a new registration with the same `hardware_id` under the same HF user evicts the older producer (last-writer-wins). Its presence also marks the daemon as heartbeat-capable, which opts it into the stale-producer sweep. |
| `install_id` | producer (reserved) | Same dedup semantics as `hardware_id`, checked independently. Not emitted by any shipped daemon yet. |
| `kind` | producer | Robot family, used **only** for the public per-kind counters (`/health` `producers_by_kind`, status page). See below. |
| `robot_type` | producer | Alias for `kind`, consulted only when `kind` is absent or empty. |
Keys such as `transport`, `release` or `api_version` are passed through
untouched and never interpreted.
## `kind`
- **Missing means Reachy Mini.** Reachy Mini daemons send no `kind` at
all (their meta is `{name, transport, hardware_id}`), so when neither
`kind` nor `robot_type` holds a non-blank string the producer
classifies as `reachy_mini`. A `kind` that is absent, `null`, blank or
not a string falls through to `robot_type`.
- **Known values:** `reachy_mini`, `microduck`. Matching is
case-insensitive and ignores every character outside `a-z0-9`, so
`Micro-Duck`, `micro duck`, `microduck`, `Reachy Mini`, `reachy-mini`
and `reachymini` all resolve to their canonical kind. A raw value
longer than 64 characters is classified as `other` without any
normalisation.
- **`meta` must be a JSON object.** A `setPeerStatus` whose `meta` is
not an object is rejected with HTTP 400 and leaves the previously
registered `meta` untouched.
- **Anything else counts as `other`** on the public counters. `kind` is
untrusted input (any authenticated HF user can send any meta), so the
public surfaces only ever expose the fixed key set
`{reachy_mini, microduck, other}` - an unknown value can bump the
`other` counter and nothing more. The status page labels for those
keys are server-side constants; no meta string is ever rendered there.
- **The raw value is still forwarded verbatim** to the owner's own
listeners and `/api/*` endpoints. Classification is a read-only view
for the public counters; it never rewrites `meta`.
Adding a robot family is a one-line change to `KNOWN_ROBOT_KINDS` (and a
label in `ROBOT_KIND_LABELS`) in `app.py`; the tests in
`test_robot_kind.py` and `test_routes.py` pin the behaviour above.
## Public counters (`GET /health`)
```json
{
"status": "healthy",
"peers": 3,
"producers": 2,
"sessions": 1,
"producers_by_kind": {"reachy_mini": 1, "microduck": 1, "other": 0},
"started_at": "2026-09-16T08:00:00Z",
"uptime_seconds": 12345
}
```
`peers`, `producers` and `producers_by_kind` count **connected** peers
only. `started_at` / `uptime_seconds` are wall-clock and exist so an
operator can tell a fresh redeploy (all counters reset) from a quiet
fleet. Both `/` and `/health` are served with `Cache-Control: no-store`.