Commit Graph
11 Commits
Author SHA1 Message Date
shad 071166cae1 feat(approvals): tenant-scoped queue (no cross-tenant work-items)
Plumbed me.tenant_id through api.ping + loginAs into the store as
tenantId. Approvals.loadQueue filters /api/ea2/work-items by
tenant_id matching the signed-in user so the queue only shows
actionable rows. Probe of EA2 work-items returned 73/80 in canvas's
tenant (a0000000-...), 6 in hms_dev, 1 in hub-cnt-f56ce0 -- those
7 are now hidden.
2026-06-14 16:01:54 +04:00
shad 224c259bfd feat(approvals): real work-item queue + active-step actions wired to EA2
New Approvals scene at landing chip + scene route. Pulls live work
items from /api/ea2/work-items?view=all and renders:

- Status counter (running/waiting/blocked)
- Hub filter (chip row, dynamic from response)
- Queue list (display_name + age + active step + hub + requester)
- Selected case detail: active step, dispatch kind, form fields,
  available actions

Clicking an action POSTs to /api/runtime/transactions/<id>/actions/<id>
with the signed-in user as actor and refreshes both the transaction
and the queue. This proves runtime EA2 writes are working end-to-end
beyond just the wizard.
2026-06-14 15:57:23 +04:00
shad b507ffe7e3 fix(login): split passwordLogin / devLogin so SIGN IN cannot bypass
Oracle round-3 finding: passing password=undefined to api.signIn silently
hit /api/v1/auth/dev-login. With dev-login disabled in a production
build, a buyer typing only their email and pressing SIGN IN would still
have been authenticated as that user.

- api.passwordLogin(email, password) explicitly requires a password and
  always hits /api/v1/auth/login. Throws on missing password.
- api.devLogin(email) explicitly hits /api/v1/auth/dev-login and is the
  only entry point to that endpoint.
- store.loginAs(email, password, { method: 'password' | 'dev' }) routes
  to the right call. Default is password (requires password).
- Login.handleSubmit rejects empty password with 'Password required'
  before any network call.
- Login.handleDevLogin bails when devLoginEnabled is false.
- SSO button is disabled while probe state is 'unknown'.
- Login.test.tsx: regression test 'blocks empty-password SIGN IN —
  must NOT silently call dev-login'. Plus SSO test asserts the button
  starts disabled.

29/29 unit tests green.
2026-06-14 13:34:54 +04:00
shad 8933148719 fix(curation): kill dev-artefact leak + rename agent honestly
Oracle remediation batch 1 — closing gaps #1 (agent overclaim), #4
(demo-data leak), #5 (raw-ID exposure):

- src/lib/flowCuration.ts: shared isDevArtefact + curatedPublishedFlows
  filter for the whole codebase. Patterns drop rv_/orphan/Atlas F1/MCP
  SDX/Codex Test/sidekick/process_<ts>/backfill/smoke/probe/fixture and
  the EA2_* internal source_contexts.
- src/scenes/Hub.tsx: loadPublishedFlows uses the shared curator
- src/lib/agentTools.ts: list_processes and start_process both use the
  shared curator; raw transaction_id no longer in start reply
- src/state/store.ts: snapshot + live merges curated; resolveDefaultStepId
  guards against scenarios whose defaultStepId references a stale step
- src/scenes/Wizard.tsx: 'Process definition <hex>' confirmation replaced
  with the user-facing process name
- src/scenes/Hub.tsx: start toast no longer shows transaction_id prefix
- src/scenes/Agent.tsx + App.tsx + Landing.tsx: rename Pi -> FlowMaster
  Command Assistant. Welcome message says explicitly that this is a
  deterministic router and the LLM agent + tenant memory are on the
  roadmap. Tab label, hub chip, turn author all rebranded.
- src/scenes/GeoAttendance.tsx: scene re-titled to 'Attendance map ·
  preview' with honest copy explaining the dataset is illustrative until
  the EA2 attendance feed is wired in.
- src/data/synthetic.ts: orphaned from runtime (kept in tree for tests).
  Snapshot now sources only the live-cached EA2 read (scenarios.json),
  filtered through the same curator.

29/29 tests green. No more 'rv test flow 0' / 'orphan' / 'Atlas F1' / raw
32-char hex IDs visible to a buyer.
2026-06-14 13:11:54 +04:00
shad fd8c4853df feat(chat): EA2-backed 1:1 messaging surface
New Chat scene at the Chat top-bar tab. Threads and messages are stored
as flow docs (kind=definition, source_context=EA2_CHAT_THREAD / _MSG)
linked by defines edges with role=next — same proven contract as wizard
steps. Persona directory lets the signed-in operator open a thread with
the CEO / HR / IT personas.

- src/lib/chatApi.ts: listThreads / createThread / listMessages / sendMessage
- src/scenes/Chat.tsx: sidebar (threads + new-thread picker) + main pane
  (header, bubbles, composer with Enter-to-send / Shift-Enter newline)
- src/index.css: chat-scene grid + bubble + composer styles
- src/App.tsx: Chat tab + scene route
2026-06-14 12:33:43 +04:00
shad 4bc7ae228a feat: rebuild Process Studio into multi-phase Process Creation Wizard\n\n- Replace toy Studio.tsx with proper Wizard.tsx canvas\n- Build 6-step flow: Intake -> Analyze -> Generate -> Validate -> Draft saved -> Publish\n- Implement incremental EA2 writes via wizardApi.ts (flow, batch apply)\n- Use localStorage for draft recovery across reloads\n- Apply industrial-blueprint UI styling matching core doctrine\n- Add Vitest tests for Wizard components and API wrappers 2026-06-14 03:47:26 +04:00
shad cb9291b225 feat: real backend mutations + Studio + Settings + live API console
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)
2026-06-14 01:19:36 +04:00
shad 49639a0857 fix(oracle-r4): validate selectedStepId across live refreshes
Oracle r4 'Watch Out For' caught a real edge case: if a backend graph
changes shape while the scenarioId stays the same, the prior
selectedStepId could survive the merge and point at a step that no
longer exists. Two new vitest regressions in state/store.test.ts now
pin the contract:

- refreshLive() resets selectedStepId to the scenario's defaultStepId
  when the prior step no longer exists in the merged catalog
- refreshLive() preserves a still-valid selectedStepId

runLiveFetch() now derives stepStillThere from the merged scenario's
own steps (not the old store) and falls back to defaultStepId when
stale. Same single-set call as before; no extra renders.

Confidence: high
Scope-risk: narrow
Not-tested: real backend definition with step IDs that disappear
mid-session (covered by stub + assertion above)
2026-06-14 00:34:47 +04:00
shad 2e0e4c08e8 docs+store: oracle r3 follow-ups
- README test/smoke counts: 18→22, 26→28 (drifted across rounds)
- runLiveFetch keepCurrent now checks the MERGED catalog, not the old
  state — fixes the edge case where a scenarioId disappears between
  refreshes (would have orphaned the active scenario)

Constraint: no test changes; pure cleanup
Confidence: high
Scope-risk: narrow
2026-06-14 00:30:57 +04:00
shad e3b4ed62c0 fix(oracle-r2): same-origin baseUrl + refresh actually re-fetches
Oracle round-2 review caught two real bugs:

1. Production baseUrl bypassed the nginx /api proxy
   - api.ts defaulted to https://demo.flow-master.ai in prod
   - Browser would hit cross-origin and CORS-fail
   - Now: baseUrl='' everywhere; nginx.conf already reverse-proxies /api/*
   - vite.config.ts proxy still handles dev

2. Refresh button didn't refresh
   - setMode('live') early-returned when already in live mode
   - Now: setMode() and refreshLive() share runLiveFetch(); refreshLive
     ignores the same-mode guard and always re-runs
   - 4 new vitest regressions in state/store.test.ts cover the contract
   - Smoke now asserts /api/ea2/work-items is called twice after Refresh

Also:
- buildScenarios.ts parallelized: cap N=6 candidates, Promise.all per-
  candidate fetches → live mode now ~3s instead of 30s
- CommandBar + LeftRail preview toasts now name the exact endpoint
  (/api/runtime/transactions/{id}/actions) in the visible text
- Landing 'Go live' button rebound to refreshLive() when already live;
  copy changed to 'Live · refresh'
- README: scenario table now renders (added separator row); deploy
  section points at the real ops PR + the actual overlay path
  (overlays/demo, not overlays/mc.flow-master.ai); CORS doc clarifies
  same-origin requirement

Constraint: browsers reject cross-origin → same-origin /api/* required
Rejected: dev/prod baseUrl divergence | created production bug
Confidence: high
Scope-risk: narrow
Not-tested: production image actually built + served by ops PR (gated by trusted updater + DNS)
2026-06-14 00:26:38 +04:00
shad 3ffd0e68a7 Mission Control demo v2
Polished command-center for FlowMaster with two data modes:
- SNAPSHOT: bundled src/scenarios.json from demo.flow-master.ai
- LIVE: in-browser fetch via src/lib/api.ts (dev-login + bearer)

Scenarios:
- procurement, extra-1, extra-2 (live from EA2)
- ar, hcm, gl, service (industry blueprints, same typed shell)

Honesty pass after Oracle review:
- No invented numbers (Telemetry derives SLA + agent acceptance from real data)
- Preview-only actions fire toasts naming the endpoint to wire them
- Blueprint tours framed as 'industry blueprint', not 'we don't have this yet'
- Mode pill + last-fetch age + refresh in topbar
- Dev CORS dodged via vite proxy; production deploys same-origin

18 vitest tests + 26 playwright smoke assertions + DOM layout audit.

Constraint: cross-origin live mode rejected by browser → fall back to snapshot
Rejected: hardcoded SLA % | dishonest demo metrics
Directive: wire preview-only action handlers to /api/runtime/transactions/{id}/actions to ship them for real
Confidence: high
Scope-risk: narrow
Not-tested: production deployment via flowmaster-ops overlay
2026-06-14 00:09:32 +04:00