PSI IoT — Machine RMM Initiative

Repo: ProgressiveSurface/psi-iot-poc (GHE) · Status: Tenant Zero pilot LIVE (cloud spine e2e) · Updated: 2026-08-11

Live surfaces: iot.progressivesurface.com (IoT Console — registry + fleet health, app-layer MSAL) · iot-grafana.progressivesurface.com (dashboards, EasyAuth). Cloud: rg-psi-iot (Event Grid MQTT egns-psi-iot, PG16+timescaledb psql-psi-iot), bridge + console + Grafana on the shared App Service plan, PEs .26/.27/.29/.30. Edge: per-device X.509; DEVTEST simulator (L5X-modeled) streaming; wave 1 = 4 ControlLogix thermal sprays. Scope rule: no PLC changes ever — read-only enforced in collector code. PRIMS process data already lands in Azure Files (psproductiondata) — process hygiene is a cloud-side ingest.

An RMM (remote monitoring & management) platform for a machine builder. Target scope: machine hygiene, process hygiene, and OEE telemetry from every PSI machine in the installed fleet — internal and customer-sited — plus remote management where customer security allows. Truly multi-tenant, integrated with the D365 customer-support system.

Full reference architecture lives in the repo: ARCHITECTURE.md.

Architecture in one paragraph

Five layers. Edge: one collector per machine on a dedicated device straddling OT/IT, read-only against the PLC (EtherNet/IP), durable store-and-forward. Ingestion/tenancy: per-device X.509 identity; every message stamped tenant/site/asset where asset = machine serial — joining fleet telemetry to the serial-first engineering knowledge base (BOM, PLC history, drawings). Historian/apps: one long-format multi-tenant readings hypertable (Timescale now, ADX at fleet scale); OEE is a computed view, not a new pipeline. Action: Connected Field Service pattern — telemetry alerts create D365 Cases against the Customer Asset (= serial). Fleet management plane: Balena-class device lifecycle (provision/update/access) + a PSI-built registry + device-management console (device ↔ serial ↔ tenant ↔ tier, fleet health) as part of the IoT app itself — the platform is its own bounded product, not a psi-portal module.

Trust tiers (product-defining)

TierPosture
0Airgapped — local historian, signed diagnostics export
1Monitor-only outbound (data-diode semantics) — default ship config
2+ customer-initiated, recorded remote support sessions
3Full RMM — managed updates, PRIMS image management, config-drift detection

Telemetry and management are separate channels with separate identities; the write path is a different binary a customer can decline to install.

Tenant Zero PoC (current state)

Docker Compose spine: collector (Node/TS; simulator or st-ethernet-ip read-only PLC source) → Mosquitto → bridge → TimescaleDB → Grafana dashboard. Store-and-forward proven by killing the broker mid-run. Deliberate PoC shortcuts (anonymous MQTT/Grafana, plaintext .env password) are documented in the README. Next steps: real PLC reads on an internal machine via a Dell OptiPlex Micro edge box, then a manual telemetry → D365 Case walkthrough in the Sandbox.

Provisioning a new machine (console-owned, 2026-08-11)

The console owns the entire edge-onboarding path — the earlier bench scripts (issue-device-cert.sh, bootstrap-edge.sh) are retired:

  1. OS install — download the Edge installer ISO from the console toolbar (/edge/psi-edge-installer.iso, ~63 MB, generic, no secrets — remastered Debian 12 netboot with initrd preseed). Write to USB with Rufus in dd/image mode and boot the box; the only install prompt is setting the local psiedge admin password, and first boot lands on a tty prompt waiting for the enrollment command from step 3. (A box installed any other way just needs to be a fresh Debian 12.)
  2. Register + Provision in the console — register the device against its serial (the machine’s invariant identity; project numbers are lifecycle entries under the serial — original build + retrofits, same asset model as PSI Explorer), then Provision from the fleet table: the console issues the device X.509 from the pilot CA (Key Vault PsiIot--CaCert/CaKey), registers the Event Grid namespace client via its managed identity, and mints a single-use 24 h enrollment token (bundle encrypted with a token-derived key; only the token hash is stored).
  3. Enroll — paste the generated one-liner at the box’s first-boot prompt (or any root shell): curl -fsSL https://iot.progressivesurface.com/enroll/<token> | sudo bash applies network posture (OT leg static/no-gateway, forwarding off), installs Docker, pulls the collector bundle from the console (no git on the device), writes certs/tag map/.env, and starts the systemd-managed collector.

The device then appears live in the fleet table as soon as telemetry flows.

  • Process Services Fleet — the internal machines Tenant Zero targets
  • PC Fleet / PRIMS Pro — the existing customer HMI-PC fleet practice that converges into tiers 2–3