Skip to content

Architecture & isolation

ReduceWaste is a set of small services behind a few trust boundaries, designed so that a compromise or a bug in one place stays contained.

NetworkWho is on itReaches the internet?
rw-otthe edge reader and field devices (or the simulator)no
rw-corebroker, historian, ingest, detectors, vision, agent control plane, local inferenceno (internal: true)
rw-uithe operator app, reachable from the host’s browserno outbound; only the operator’s own browser reaches in
rw-relaythe agent gateway’s relay onlyno

No container on rw-core or rw-relay has a route to the internet or to the host. The operator app itself is bound to 127.0.0.1 by default. The only outbound paths that exist anywhere in the system are an opt-in signed update check and an opt-in, time-boxed support tunnel — both off by default and never carrying factory telemetry.

field devices / OT -> rw-edge (read-only) -> rw-broker (MQTT) -> rw-ingest -> historian
|
rw-detect / rw-vision <-- windows <----+
|
rw-app (operator UI) <-- queries <-----+
  • rw-edge opens read-only sessions to PLCs and sensors and publishes plain JSON or Sparkplug B to the broker. It never writes to a field device.
  • rw-ingest validates every sample against the signal registry before it reaches the historian, and publishes short-window rollups.
  • rw-detect runs the deterministic, always-on detectors (state, cycle count, energy, vibration health, and so on) bound by the sensor recipes. rw-vision does the same for camera-based counting and defect detection. Neither of these calls a language model — see Sensors & recipes and Detectors.
  • rw-app is the only thing an operator’s browser talks to.

A small number of workflows (for example, turning a plan into a register map, or answering a question with evidence) run inside an isolated agent sandbox rather than inside the main app process:

  • A sandbox gets no database connection string at all. Every read or write it needs goes through one HTTP call, POST /gw/data/{op}, to a gateway that runs the operation in its own database transaction with the row-level-security role for that site already set. An unrecognised operation is rejected (404); bad arguments are rejected (422).
  • The sandbox reaches that gateway over a relay that only forwards /gw/* and returns 404 for anything else. The relay runs on its own empty network; the only way into it is the specific per-sandbox network the control plane connects for the duration of that sandbox’s run.
  • Each sandbox has its own network and no mounted volumes beyond what that one turn needs. It cannot see other sandboxes, the broker, the historian, or the internet directly.

The result: even a fully compromised or misbehaving agent turn can only call the small set of named, validated operations the gateway exposes — never run arbitrary SQL, never reach a PLC, and never make an outbound network call.

Every site’s data sits behind a Postgres row-level-security role scoped to that site. The gateway sets that role inside the same transaction as the operation it runs, so isolation holds even if a query is built from user input.