feat(canvas): strip demo data, EA2 is the only source
- Remove src/data/synthetic.ts + its test (AR refund, HCM onboarding, GL close, Service Ops blueprints were hand-modelled fakes). - Remove DataMode='snapshot'; the store now boots straight into live EA2 with no fallback. EA2 errors surface as toasts, not fake data. - Topbar / Settings / CommandBar wording: 'SNAPSHOT'/'LIVE' becomes the unambiguous 'EA2' badge. No more user-facing mode switch. - package.json name flowmaster-mission-control-demo → flowmaster-canvas. - README rewritten — no longer calls the product a demo. - store.test: drop the two tests that relied on synthetic scenarios always being present; add one asserting an EA2-empty response leaves the store cleanly empty (no error-stuck state). All 23 vitest tests pass. tsc + vite build green. Bundle dropped from ~238 kB gz → ~234 kB gz.
This commit is contained in:
@@ -1,168 +1,61 @@
|
||||
# FlowMaster — Mission Control
|
||||
# FlowMaster — Canvas
|
||||
|
||||
**Live at https://canvas.flow-master.ai** · [source on Gitea](https://gitea.flow-master.ai/shad/flowmaster-mission-control-demo)
|
||||
**Live at https://canvas.flow-master.ai** · operations cockpit for every process the company runs.
|
||||
|
||||
The proper FlowMaster frontend: an operations cockpit for every process the
|
||||
company runs. Industrial-blueprint doctrine — paper canvas, navy frame,
|
||||
amber accent, 1px hairlines, square edges, monospace operational density.
|
||||
Canvas is the FlowMaster operator surface. Industrial-blueprint doctrine:
|
||||
paper canvas, navy frame, amber accent, 1px hairlines, square edges,
|
||||
monospace operational density. People, Finance, Procurement, and IT in
|
||||
one frame.
|
||||
|
||||
## What this is (and isn't)
|
||||
## What it is
|
||||
|
||||
**Is:**
|
||||
|
||||
- A single-page React 19 app (Vite + ReactFlow + cmdk + framer-motion + zustand
|
||||
+ dagre).
|
||||
- Polished command-center for any FlowMaster process: graph, queue, inspector,
|
||||
tour, command palette, live-mode toggle, run history.
|
||||
- Two data modes:
|
||||
- **SNAPSHOT** (default): bundled `src/scenarios.json`, captured from
|
||||
`demo.flow-master.ai`. Fast, offline, deterministic.
|
||||
- **LIVE**: in-browser fetch from the same backend via the API client at
|
||||
`src/lib/api.ts` (dev-login → bearer → `/api/ea2/work-items` →
|
||||
`/api/ea2/process-definitions/{k}/graph` → `/api/runtime/transactions/{id}`).
|
||||
Loading and error states are wired through `src/scenes/MissionControl.tsx`.
|
||||
|
||||
**Isn't:**
|
||||
|
||||
- Not a replacement for the existing demo at https://demo.flow-master.ai
|
||||
(Next.js fm-shell). This is a separate command-center experience.
|
||||
- Not multi-tenant. No auth UI, no tenancy switcher, no settings.
|
||||
- Not wired to actually mutate state. Every action button (start runtime,
|
||||
dispatch agent, approve, decline, confirm) is **preview-only** and fires a
|
||||
toast naming the endpoint that would make it real.
|
||||
|
||||
## Scenarios in the catalog
|
||||
|
||||
| id | mode | source |
|
||||
|-------------|-----------|-------------------------------------------------------------------|
|
||||
| procurement | live | Purchase Requisition → PO (`pr_to_po_def` on demo.flow-master.ai) |
|
||||
| extra-1 | live | Atlas F1 Fresh (procurement variant) |
|
||||
| extra-2 | live | Atlas F1 Fresh (procurement variant) |
|
||||
| ar | blueprint | AR · Customer Refund Approval |
|
||||
| hcm | blueprint | HCM · New Hire Onboarding |
|
||||
| gl | blueprint | GL · Period-End Close |
|
||||
| service | blueprint | Service Ops · Customer Incident |
|
||||
|
||||
**Live** = backed by a real EA2 process definition currently in the demo
|
||||
backend, with real runtime transactions and a real work-item queue.
|
||||
|
||||
**Blueprint** = hand-modelled in the same typed format. Identical UI surface;
|
||||
the backend just doesn't have a runnable definition for it yet. Internal
|
||||
metadata carries `isSynthetic: true` for provenance audits.
|
||||
|
||||
## How honesty is enforced in this code
|
||||
|
||||
This pass came out of an Oracle review that called out theatrical bits in the
|
||||
prior version. Safeguards now in place:
|
||||
|
||||
- **No invented numbers.** `src/components/Telemetry.tsx` derives every value
|
||||
from the active scenarios (`SLA = 1 - errored / cases`, agent acceptance =
|
||||
fraction of agent runs not in `proposed`). The throughput sparkline plots
|
||||
the actual `running` rollup over time, not a sine wave. The "ui tick" dot
|
||||
is labelled as a UI heartbeat and tooltip-named as such.
|
||||
- **No fake buttons.** Every preview-only action fires a toast that names the
|
||||
endpoint that would make it real, and carries a `preview` marker.
|
||||
- **No misleading tour copy.** Blueprint tours frame the scenario as an
|
||||
industry blueprint, not "we don't have this yet".
|
||||
- **Mode is always visible.** Topbar has a `SNAPSHOT`/`LIVE` pill, last-fetch
|
||||
age, and a refresh button when live.
|
||||
|
||||
## Live-mode mechanics (the CORS gotcha)
|
||||
|
||||
`demo.flow-master.ai` does not advertise CORS headers for arbitrary origins.
|
||||
`src/lib/api.ts` therefore uses an **empty `baseUrl` everywhere** (both dev
|
||||
and prod). All `/api/*` requests are same-origin from the browser's
|
||||
perspective; whatever is serving the page is responsible for proxying them
|
||||
to the backend.
|
||||
|
||||
- **Dev** (`pnpm dev`): `vite.config.ts` proxies `/api/*` to
|
||||
`${VITE_FM_BASE:-https://demo.flow-master.ai}`.
|
||||
- **Prod** (Docker image): the bundled `nginx.conf` reverse-proxies `/api/*`
|
||||
to `https://demo.flow-master.ai`. The image is intended to sit behind the
|
||||
`canvas.flow-master.ai` ingress (see `FM06/flowmaster-ops` overlay).
|
||||
- **Anywhere else**: set `VITE_FM_BASE=https://your-backend` at build time
|
||||
and accept that browsers will reject the cross-origin call. Live mode then
|
||||
fails gracefully — `setMode("live")` catches the error, raises an
|
||||
`mc-banner-err` banner + error toast, and falls back to snapshot.
|
||||
- React 19 single-page app (Vite + ReactFlow + cmdk + framer-motion +
|
||||
zustand + dagre).
|
||||
- Connected directly to EA2 in the browser via the API client at
|
||||
`src/lib/api.ts`. There is one data source: live EA2. No bundled
|
||||
snapshot, no synthetic blueprints.
|
||||
- Scenes: Landing, Mission Control, Run History, Process Studio, Hubs,
|
||||
Agent, Settings, Login, SSO callback.
|
||||
- Agent scene has a chat surface with per-tenant local memory (`src/lib/agentMemory.ts`)
|
||||
and three intents: navigate, retain a fact, start a process draft.
|
||||
- Hubs surface departmental lenses (People, Finance, Procurement, IT).
|
||||
- Three view-as personas (CEO, Head of People, Head of IT) re-sign in
|
||||
under the persona's email so the operator UI reflects the seat.
|
||||
|
||||
## Run, test, build
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
|
||||
# refresh the bundled snapshot from demo.flow-master.ai
|
||||
pnpm fetch:scenarios
|
||||
|
||||
# dev (with backend proxy for live mode)
|
||||
pnpm dev # → http://127.0.0.1:5173
|
||||
|
||||
# tests
|
||||
pnpm test # vitest, 22 tests across api, live,
|
||||
# synthetic, layout, store
|
||||
pnpm test # vitest
|
||||
|
||||
# build
|
||||
pnpm build # tsc + vite, single chunk ~225 KB gz
|
||||
|
||||
# end-to-end smoke + screenshots
|
||||
pnpm qa:smoke # playwright headless, 28 assertions
|
||||
|
||||
# DOM layout audit
|
||||
pnpm qa:layout
|
||||
```
|
||||
|
||||
## File map
|
||||
|
||||
```
|
||||
src/
|
||||
├── data/ # ProcessScenario domain + snapshot + blueprint catalog
|
||||
├── lib/ # API client + live-scenario builder (+ tests)
|
||||
├── state/store.ts # zustand: scene, mode, scenario, tour, recents, toasts
|
||||
├── graph/layout.ts # dagre LR auto-layout (+ tests)
|
||||
├── components/ # ProcessGraph, Inspector, LeftRail, CommandBar, Tour,
|
||||
│ # Telemetry, Toaster, icons
|
||||
├── scenes/ # Landing, MissionControl, RunHistory
|
||||
├── App.tsx # shell: topbar (mode pill / refresh / tour / ⌘K)
|
||||
├── index.css # design system (~700 lines)
|
||||
├── main.tsx
|
||||
└── scenarios.json # cached snapshot of demo.flow-master.ai
|
||||
|
||||
qa/
|
||||
├── smoke.mjs # Playwright e2e + 9 screenshots
|
||||
└── layout_audit.mjs # programmatic clipping/overlap check
|
||||
|
||||
vite.config.ts # /api → demo.flow-master.ai proxy for dev
|
||||
fetch_scenarios.mjs # Node script to refresh src/scenarios.json
|
||||
pnpm build # tsc + vite, single chunk ~234 KB gz
|
||||
```
|
||||
|
||||
## Deploy
|
||||
|
||||
Production deployment is tracked in
|
||||
[FM06/flowmaster-ops PR #1164](https://gitea.flow-master.ai/FM06/flowmaster-ops/pulls/1164)
|
||||
(merged), which added three resources to `manifests/overlays/demo/`:
|
||||
Deployment is tracked in `FM06/flowmaster-ops`, overlay
|
||||
`manifests/overlays/demo/`:
|
||||
|
||||
- `mc-deployment.yaml` — 2-replica nginx Deployment in the `demo` namespace
|
||||
- `mc-deployment.yaml` — replicated nginx Deployment
|
||||
- `mc-service.yaml` — ClusterIP service on port 80
|
||||
- `mc-ingress.yaml` — Traefik ingress at `canvas.flow-master.ai` with cert-manager DNS-01 cert
|
||||
- `mc-ingress.yaml` — Traefik ingress at `canvas.flow-master.ai` with
|
||||
cert-manager DNS-01 cert
|
||||
|
||||
Cloudflare A record `canvas.flow-master.ai → 65.21.71.186` was added at the
|
||||
same time. The cluster certifies with cert-manager (Let's Encrypt DNS-01)
|
||||
and Traefik fronts the nginx pods. nginx reverse-proxies `/api/*` to
|
||||
`https://demo.flow-master.ai` so the SPA is same-origin (no CORS).
|
||||
nginx in the image reverse-proxies `/api/*` to `https://demo.flow-master.ai`
|
||||
so the SPA is same-origin (no CORS).
|
||||
|
||||
```bash
|
||||
pnpm build # builds dist/
|
||||
docker build -t gitea.flow-master.ai/shad/mission-control-demo:sha-<git> .
|
||||
pnpm build
|
||||
docker buildx build --platform linux/amd64 \
|
||||
-f Dockerfile.runtime \
|
||||
-t gitea.flow-master.ai/shad/mission-control-demo:sha-<git> \
|
||||
--load .
|
||||
docker push gitea.flow-master.ai/shad/mission-control-demo:sha-<git>
|
||||
# Then bump the image pin in manifests/overlays/demo/mc-deployment.yaml.
|
||||
```
|
||||
|
||||
## What's intentionally not here
|
||||
|
||||
- Authentication UI (dev-login is used because this is a demo lane).
|
||||
- Mutation endpoints (every action is preview-only and the toast names the
|
||||
endpoint).
|
||||
- Mobile layout (1440px-and-up demo surface).
|
||||
- Route persistence / deep linking (scene + scenario live in memory).
|
||||
- i18n (English only).
|
||||
|
||||
Small, well-scoped follow-ups — not architectural changes.
|
||||
|
||||
Reference in New Issue
Block a user