Massive overhaul that turns the demo from presenter-mode into a
fully-functional FlowMaster operator surface.
NEW: real backend mutations
- api.executeAction(txId, actionId, actor, values) → POST /api/runtime/transactions/{tx}/actions/{actionId}
- api.startTransaction(defKey, business_subject) → POST /api/runtime/transactions
- api.createProcess(payload) → POST /api/ea2/flow
- store.executeAction / startInstance with toast feedback + auto-refresh
- Inspector Overview action buttons fire real backend calls (Submit/Save Draft/etc)
- LeftRail Confirm/Reject buttons fire real backend calls
- LeftRail 'Start new instance' button starts a real tx for live procurement
- CommandBar 'Real actions' group with 'Start new instance' + 'Execute action on headline tx'
NEW: Process Studio (src/scenes/Studio.tsx)
- in-UI process designer: name + display + hub + description + node list + edge list
- live JSON preview of the EA2 payload
- Publish button calls api.createProcess against demo.flow-master.ai
- Validates locally before publishing
- Auto-refreshes scenarios after publish so the new process shows up
NEW: Settings (src/scenes/Settings.tsx)
- Identity: sign in as any email (loginAs), see actor + display name
- Quick-user buttons for common demo identities
- Backend URL + clear-token diagnostic
- Polling cadence (2-120s)
- Dark/light theme toggle (CSS data-theme attribute)
- Show-console default toggle
- All persisted to localStorage (LS_KEY = fm.mc.prefs.v1)
NEW: Live API console (src/components/Console.tsx)
- Right-side drawer triggered from topbar
- Every fetch (GET/POST/etc) streams in real time with status + duration
- Click any entry to expand request + response JSON
- Filter: all / writes / errors
- Replaces the old guided-tour overlay entirely
NEW: live polling
- store.startPolling()/stopPolling() with setInterval guarded for SSR
- Auto-refresh while in LIVE mode at configurable cadence
REMOVED: Tour.tsx, all startTour() store actions and tour references
- Landing CTA now reads 'Enter Mission Control' / 'Design a process' / 'Open live console'
ALSO:
- api.ts: instrumentedFetch with observer pattern → store.apiLog
- Topbar: user identity chip linking to Settings, Console toggle with badge
- Light theme: minimal CSS data-theme override (text + surfaces only)
- localStorage persistence for mode, scenarioId, email, theme, pollEverySec, consoleOpen, recents
- 24/24 vitest, smoke quick run shows 0 console errors + 7 API calls captured
Confidence: high
Scope-risk: broad (~14 files)
Not-tested: actual end-to-end backend mutation roundtrip (requires LIVE + sign-in; structure proven via probe scripts)
FlowMaster — Mission Control demo
A polished, presenter-ready command-center for FlowMaster. Lives at
shad/flowmaster-mission-control-demo
on Gitea.
What this is (and isn't)
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 fromdemo.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 throughsrc/scenes/MissionControl.tsx.
- SNAPSHOT (default): bundled
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.tsxderives every value from the active scenarios (SLA = 1 - errored / cases, agent acceptance = fraction of agent runs not inproposed). The throughput sparkline plots the actualrunningrollup 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
previewmarker. - 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/LIVEpill, 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.tsproxies/api/*to${VITE_FM_BASE:-https://demo.flow-master.ai}. - Prod (Docker image): the bundled
nginx.confreverse-proxies/api/*tohttps://demo.flow-master.ai. The image is intended to sit behind themc.flow-master.aiingress (seeFM06/flowmaster-opsoverlay). - Anywhere else: set
VITE_FM_BASE=https://your-backendat build time and accept that browsers will reject the cross-origin call. Live mode then fails gracefully —setMode("live")catches the error, raises anmc-banner-errbanner + error toast, and falls back to snapshot.
Run, test, build
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
# 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
Deploy
Production deployment is tracked in
FM06/flowmaster-ops PR #1164,
which adds three resources to manifests/overlays/demo/:
mc-deployment.yaml— 2-replica nginx Deployment in thedemonamespacemc-service.yaml— ClusterIP service on port 80mc-ingress.yaml— Traefik ingress atmc.flow-master.aiwith cert-manager DNS-01 cert
Status: the PR is open and mergeable. The live URL https://mc.flow-master.ai is not yet serving — two pre-merge action items remain for the trusted updater:
- Cloudflare A record
mc.flow-master.ai → 65.21.71.186, 91.98.159.56(same ashakeem.flow-master.ai). - Gitea Actions must have published the first image tag (
gitea.flow-master.ai/shad/mission-control-demo:sha-…) —mc-deployment.yamlpins that explicit SHA, not:latest.
Until the PR merges + DNS is added, the artifact is this repo + the open PR.
pnpm build
# dist/ is the static site. The Dockerfile bakes it into a tiny nginx
# image. CI in .gitea/workflows/build.yml builds + publishes on push to main.
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.