Multi-tenant park zone control plane — devices, MQTT, rules, shows, historian, and ops UI for events & theme parks.
Safety boundary: Ride safety interlocks and e-stops stay on SIL-rated PLC hardware. ZoneBus must never be the sole path for safety. It carries status, non-critical commands, show cues, ops telemetry, and experience events only.
ZoneBus is a production-shaped control plane for multi-tenant parks and zones: JWT/RBAC identity, device registry with rotatable credentials, MQTT authn/authz, rules engine, show sequences, event historian, audit log, Prometheus metrics, and an ops web UI.
Use it to prototype park operations, demonstrate event-driven edge topology, or host a consolidated free-tier demo — not as a replacement for certified safety systems.
| Surface | URL |
|---|---|
| Ops web | https://zonebus-web.onrender.com |
| API | https://zonebus-api.onrender.com |
| OpenAPI | https://zonebus-api.onrender.com/docs |
| MQTT WebSocket | wss://zonebus-api.onrender.com/mqtt |
| Health | https://zonebus-api.onrender.com/health |
Free Render web services cold-start (~30–60s after idle). Free Postgres expires 30 days after creation.
- Multi-park / multi-zone tenancy with RBAC (
platform_admin→guest) - Device registry and MQTT identity (HTTP authn/authz to the broker)
- Commands, show sequences, weather-driven outdoor policy
- Rules engine with cooldown and fire actions
- Event historian and full audit trail for control actions
- Prometheus metrics; Grafana dashboards in full local Compose
- OpenAPI at
/docs; ops UI for devices, rules, audit, and admin
Render (live demo) consolidates for free-plan hosting:
| Service | Role |
|---|---|
zonebus-api |
Fastify API + embedded Aedes MQTT (/mqtt) + edge workers |
zonebus-web |
React ops UI (runtime API/MQTT config) |
| Managed Postgres | Control-plane data |
| Managed Key Value | Rate limiting (Redis-compatible) |
Local Docker Compose runs the full topology: EMQX, separate edge services (edge-ride, edge-show, edge-weather, edge-gateway), rules-engine, Prometheus, and Grafana.
web / ops ──JWT──► API control plane ──► Postgres + Redis
│ ▲
└── MQTT (role ACL) ─┴── broker (EMQX local | Aedes on Render)
▲
edge-* + rules-engine
See RENDER.md for deploy details and free-tier limits.
| Layer | Choice |
|---|---|
| Language | TypeScript, Node.js 22+ |
| API | Fastify 5, Zod, bcrypt, JWT |
| Web | React 18, Vite |
| Messaging | MQTT 5 (EMQX locally; embedded Aedes on Render) |
| Data | PostgreSQL 16, Redis 7 / Render Key Value |
| Observability | Prometheus, Grafana (Compose) |
| Deploy | Docker Compose locally; Render Blueprint (render.yaml) |
git clone https://github.com/pradhankukiran/zonebus.git
cd zonebus
npm install
npm run certs # TLS material for MQTTS/WSS
npm run up # docker compose up --build -d
# wait ~30–45s
curl -s http://localhost:3200/health | jq
npm run test:e2e # node tests/e2e/smoke.mjs| Surface | URL |
|---|---|
| Ops wall | http://localhost:5173 |
| API + OpenAPI | http://localhost:3200/docs |
| Grafana | http://localhost:3001 (admin / zonebus_grafana_change_me) |
| Prometheus | http://localhost:9090 |
| EMQX dashboard | http://localhost:18083 (admin / zonebus_dashboard_change_me) |
npm run logs # follow compose logs
npm run down # tear down volumesChange every password before any real or shared use. These are intentionally seeded for demos only.
| User | Password | Role |
|---|---|---|
admin |
admin-change-me-now |
platform_admin |
parkadmin |
parkadmin-change-me |
park_admin |
operator |
operator-change-me |
operator |
viewer |
viewer-change-me |
viewer |
guest |
guest-demo |
guest |
park/{park}/zone/{zone}/ride/{id}/state|cmd/{op}
park/{park}/zone/{zone}/show/cues|status
park/{park}/zone/{zone}/prop/{id}/state|event
park/{park}/zone/{zone}/feeds/{name}
park/{park}/zone/{zone}/ops/alert
park/{park}/zone/{zone}/rules/fired
park/{park}/gateway/{id}/health
park/{park}/system/dlq
- OpenAPI UI:
/docs - Health / ready:
/health,/ready - Prometheus scrape:
/metrics(API; edges expose metrics in Compose) - Grafana provisioned dashboards when running full Compose
apps/api Fastify control plane (+ embedded MQTT/workers on Render)
apps/web React ops UI
apps/edge-* Edge simulators (ride, show, weather, gateway)
apps/rules-engine DB-backed rules with hot reload
packages/core Shared types, topics, utilities
broker/ · infra/ EMQX config, Postgres SQL, Prometheus, Grafana
scripts/ Cert generation
tests/e2e Smoke script against a running stack
render.yaml Render Blueprint
RENDER.md Deploy & free-tier notes
npm install
npm run build # core → api → web
npm run build -w @zonebus/core
npm run build -w @zonebus/api
npm run build -w @zonebus/web
# API against Compose infra:
# cd apps/api && npx tsx src/index.ts
npm test # workspace unit tests (may discover none yet)
npm run test:e2e # requires stack upCI (.github/workflows/ci.yml) builds core, runs topic checks, and smoke-tests Compose on push/PR to main.
Blueprint and step-by-step instructions: RENDER.md.
Summary: managed Postgres + Key Value, consolidated API (embedded Aedes + edge workers), separate web service. Free web cold-starts; free Postgres has a 30-day lifetime.
Before any real park or production traffic:
- Replace all
change-mesecrets (JWT, internal token, DB, MQTT, UI passwords) - Rotate seeded demo users; prefer SSO (OIDC) in front of
/auth/login - EMQX
verify_peer+ client certs for devices (full broker topology) - Terminate TLS at the edge; keep the broker on a private mesh
- HA: broker cluster, Postgres primary/replica, Redis Sentinel / managed HA
- Network policy: only gateways reach the broker
- Never put safety e-stop or interlock sole path on MQTT / ZoneBus
Built-in posture (demo/default stack): bcrypt (cost 12), JWT + short-lived MQTT browser tokens, deny-by-default MQTT ACL, device credential rotation, audit log, historian, rules cooldown, Redis rate limits, Helmet headers, OpenAPI, Prometheus metrics.
Proprietary / demo — set your own license before shipping.
Public demo on Render free tier; not a certified safety product.