Files
continuum-schemas/schemas/continuum
octoturgeandClaude Opus 5 14cf7feb88 Add the operator console's telemetry push contract
`/ws/telemetry` is the socket a live fleet view needs and the backend does
not have yet. This is the shape both ends will mirror, written first so
neither invents one.

Which is exactly what happened before: continuum-app's telemetry store
consumes `printerId`, `nozzleTempC`, `bedTempC`, `progressPct`,
`updatedAt` and a closed `idle|printing|paused|error|offline` enum, inside
an envelope `{type: "printer.telemetry", data}` that no backend ever sent.
Every field of it was invented against nothing.

Two deliberate departures from the rest of this repository:

- **camelCase**, where `continuum/v1/edge/` is snake_case. That one is
  shared with a Rust gateway whose serde derives the names directly; this
  one is the backend's own HTTP vocabulary, and the browser already
  consumes camelCase from `GET /printers`. Making it snake_case would buy
  a consistency nobody benefits from at the price of a second model of a
  printer in the client.
- **The payload is the printer resource**, the same shape
  `GET /printers/:id` returns, rather than a telemetry-shaped subset. A
  client can then apply a push to the row it already holds instead of
  reconciling two vocabularies for the same machine.

Every telemetry field is nullable, which is load-bearing rather than
lazy: a printer that has never reported has no temperature, and "no data
yet" is not 0 degrees. A client rendering `?? 0` will draw a cold
printer as a real reading. `vendorState` is a free string and not an
enum for the same class of reason - an unrecognised state must reach the
screen as itself rather than being dropped on the way.

There is a `ready` message, sent once after the socket authenticates,
carrying how many printers the user can see. It exists because an
operator with nothing claimed and an operator whose gateway is offline
both see nothing arrive, and those two need different things said to
them - which is impossible if readiness is inferred from silence.

No Rust mirror: this protocol has no Rust consumer. `npm run typecheck`
and `npm run build` clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-18 19:36:45 +00:00
..