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.
Networks
Section titled “Networks”| Network | Who is on it | Reaches the internet? |
|---|---|---|
rw-ot | the edge reader and field devices (or the simulator) | no |
rw-core | broker, historian, ingest, detectors, vision, agent control plane, local inference | no (internal: true) |
rw-ui | the operator app, reachable from the host’s browser | no outbound; only the operator’s own browser reaches in |
rw-relay | the agent gateway’s relay only | no |
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.
Data flow
Section titled “Data flow”field devices / OT -> rw-edge (read-only) -> rw-broker (MQTT) -> rw-ingest -> historian | rw-detect / rw-vision <-- windows <----+ | rw-app (operator UI) <-- queries <-----+rw-edgeopens 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-ingestvalidates every sample against the signal registry before it reaches the historian, and publishes short-window rollups.rw-detectruns the deterministic, always-on detectors (state, cycle count, energy, vibration health, and so on) bound by the sensor recipes.rw-visiondoes the same for camera-based counting and defect detection. Neither of these calls a language model — see Sensors & recipes and Detectors.rw-appis the only thing an operator’s browser talks to.
The agent control plane
Section titled “The agent control plane”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.
Tenant isolation
Section titled “Tenant isolation”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.