AutoRpa/docs/superpowers/specs/2026-08-10-state-center-web...

139 lines
9.6 KiB
Markdown

# State Center Web State Machine Design
## Goal
Build a browser-based Web application for the state center so users can see where each procurement RPA job is, inspect node details, handle open tasks, and manually advance supported human nodes. The Web app must run the same way on Windows and macOS through a standard browser.
## Scope
The first version is option B: status diagram + task list + node actions.
In scope:
- A React/Vite frontend under `state_center_web/`.
- FastAPI endpoints needed by the frontend for state machine metadata, job search/list, task list, task submit, and manual node completion.
- A visual job detail page showing all 13 nodes, current node, executor owner, completed/running/waiting/failed states, and skipped conditional nodes.
- A task page for open tasks by role and status.
- Basic node action controls for development/demo only: create job, start/complete/fail RPA nodes with token, run product match, submit task actions, and complete manual nodes where allowed.
- Cross-platform scripts based on Node/npm and Python commands only; no Electron or OS-specific shell behavior.
Out of scope for this first version:
- Evidence file browser as a full module.
- Enterprise WeChat login/JWT exchange.
- Real Oracle credentials and real external-system page automation.
- Desktop app packaging.
Because real Oracle credentials are out of scope, local demo must include one explicit fixture path for the goods engine. The fixture loader is development-only and separate from `/api/match/reload-goods`; production still reads goods master data from Oracle only.
## Architecture
The existing FastAPI service remains the single owner of business state. The frontend never computes the next node by itself; it renders the backend state machine metadata and calls backend actions. 艺赛旗 remains a node executor: it calls `start`, `complete`, and `fail`; it does not own the global business state machine.
```mermaid
flowchart LR
Browser["Browser Web App"] --> API["FastAPI State Center"]
API --> MySQL["MySQL rpa_center"]
API -. read only .-> Oracle["Oracle Goods Master"]
ISRPA["iS-RPA"] --> API
Human["Business User"] --> Browser
```
## Backend Design
Keep `state_center/app/main.py` as the current entry point, but add small, focused endpoints instead of changing the existing callback contract.
Add:
- `GET /api/state-machine`: returns `NODE_ORDER`, transitions, executor map, conditional node set, and display labels.
- `GET /api/jobs`: list/search jobs by `status`, `source_type`, `supplier_name`, `date_from`, `date_to`, with compact fields for the dashboard.
- `GET /api/jobs/{job_id}/timeline`: returns all 13 nodes with backend-computed display status for each node: `PENDING`, `RUNNING`, `SUCCESS`, `FAILED`, `WAITING_USER`, `WAITING_EXTERNAL`, or `SKIPPED`.
- `GET /api/tasks/my`: list tasks by `roleCode` and `status`. For v1, this is a role-filtered dev endpoint, not a user-identity endpoint.
- `POST /api/tasks/{task_id}/submit`: accepts `action`, `payload`, `submitToken`, and `operator`.
- `POST /api/jobs/{job_id}/items`: development/data-ingest endpoint for order details before real `ORDER_FETCH` integration. Request body is `{"replace": true, "rows": [...]}`. Each row maps to `order_item`: `orderNo`, `rawProductName`, `platformProductCode`, `spec`, `manufacturer`, `approvalNo`, `qty`, `unitPrice`, and `sourceRowNo`. Repeated ingest with `replace=true` deletes current rows for that job, inserts the new rows, and updates `order_no_list_json` from the payload.
- `POST /api/dev/match/load-fixture-goods`: development-only endpoint that loads a small in-memory goods fixture so `/api/jobs/{job_id}/match/run` can be demonstrated without Oracle.
- `GET /api/jobs/{job_id}/match/unmatched`: not required by v1 if task rows with `candidates_json` cover the UI; this spec treats the task list as the v1 source of truth and supersedes the older unmatched view for this phase.
`replace=true` is only valid before `PRODUCT_MATCH` has produced any durable downstream state, or it must transactionally clear dependent `product_match`, `user_task`, and related node/task state for that job in the same operation. The first version should prefer the pre-match restriction.
Human-node lifecycle rules:
- Human nodes use these roles in v1:
- `SOURCE_ADD` -> `PURCHASER`
- `M5_MANUAL_CONFIRM` -> `PURCHASER`
- `M5_RECEIPT_NOTICE` -> `PURCHASER`
- Entering `SOURCE_ADD`, `M5_MANUAL_CONFIRM`, or `M5_RECEIPT_NOTICE` creates an open `user_task`, inserts a `job_node` row for the node if one does not exist yet, sets `job.status='WAITING_USER'`, and sets `job.current_role` to the matching role.
- Leaving a human node happens through `POST /api/tasks/{task_id}/submit` with `CONFIRM_AND_CONTINUE`, not through the RPA callback path.
- `SOURCE_ADD` completion clears `job.needs_source_add` and advances to the next node.
- `M5_MANUAL_CONFIRM` completion advances to `M5_RECEIPT_NOTICE`.
- `M5_RECEIPT_NOTICE` completion requires `payload.receiptNoticeNo`, writes `job.receipt_notice_no`, and advances to `ARCHIVE_JOB`.
Task submission rules:
- `SELECT_CANDIDATE` payload must include `productMatchId` and `goodsId`; it may include `goodsCode`, `baseUnit`, and `saveAsAlias`.
- `SELECT_CANDIDATE` delegates to the existing `match_confirm` behavior by mapping `productMatchId` to the existing `match_id` path and passing through `goodsId`, `goodsCode`, `baseUnit`, and `saveAsAlias`.
- `CONFIRM_AND_CONTINUE` can complete manual nodes such as `SOURCE_ADD`, `M5_MANUAL_CONFIRM`, and `M5_RECEIPT_NOTICE` when the task is open and the job is on that node.
- `RETRY_CURRENT_NODE`, `TRANSFER_MANUAL`, and `TERMINATE_JOB` are dev-mode task actions only in v1 and must write an event plus task submission record; they do not invent new business routing.
- `TERMINATE_JOB` sets the job to `CANCELLED` with an event.
- `TRANSFER_MANUAL` changes `current_role` on the job and records the requested target role; full reassignment is later.
- `RETRY_CURRENT_NODE` leaves the job on the same node and records the retry request; it does not delete or overwrite `job_node` history.
- `submitToken` is required.
- First submit locks the task row, stores token/action/payload/result, marks the task `SUBMITTED`, and writes the event.
- Repeat submit with the same token returns the stored result.
- Repeat submit with a different token returns HTTP 409.
- `submitted_result_json` is added to `user_task` to hold the replayable response body.
Authentication in this first version uses the existing `X-Agent-Token` for write/action endpoints so the demo remains consistent with current code. Read-only endpoints can stay open for local development unless project authentication is added.
For browser-based business submission in v1, the app is local-dev only and exposes a small operator settings panel where the developer pastes the token once per session. The token stays in browser session state and is never bundled into app code. The dev simulator can use the token directly; ordinary business screens must not hardcode it.
The browser UI must not embed the agent token in normal production flows. RPA callback simulators are allowed only behind an explicit dev flag and must be visually separated from business user actions.
## Frontend Design
Create `state_center_web/` with React, TypeScript, Vite, and plain CSS. The UI is an operational dashboard, not a marketing page.
Views:
- Job list: dense table with job id, supplier, order date, source, status, current node, role, and timestamps.
- Job detail: state-machine diagram across the 13 nodes, plus side panel for job summary, node attempts, open tasks, and allowed actions.
- Tasks: filterable open/submitted task list with role/status controls and submit forms.
- Dev actions: a clearly labeled simulator section for local callback testing only.
Core frontend files:
- `src/api/client.ts`: fetch wrapper and API types.
- `src/stateMachine.ts`: visual labels and derived status helpers only; no next-node business logic.
- `src/App.tsx`: route/view state and page composition.
- `src/components/JobTimeline.tsx`: node diagram.
- `src/components/JobList.tsx`: job table.
- `src/components/TaskList.tsx`: task table/actions.
- `src/styles.css`: responsive operational layout.
## Data Flow
1. User opens the browser app.
2. Frontend loads `/api/state-machine` and `/api/jobs`.
3. User selects a job.
4. Frontend loads `/api/jobs/{job_id}` and `/api/jobs/{job_id}/timeline` and renders node state from backend-computed data.
5. User submits a task/action.
6. Backend updates `user_task`, `job`, `job_node`, and `job_event` as needed.
7. Frontend reloads job/task data.
## Error Handling
The frontend should show backend `detail` messages directly in a compact error area. Conflicts such as out-of-order callbacks remain HTTP 409. Missing order items before product match remains HTTP 400. Missing token remains HTTP 401.
## Testing
Backend tests:
- State machine metadata includes all 13 nodes and conditional nodes.
- Job list returns compact rows.
- Task list filters by role/status.
- Task submit is idempotent by `task_id + submit_token`.
- Manual node submit rejects jobs not currently on that node.
- Timeline response returns all 13 nodes with `SKIPPED` computed server-side.
- Dev action simulator remains disabled unless the dev flag is enabled.
Frontend tests:
- Timeline marks completed, current, waiting, failed, and skipped nodes from API data.
- Task list renders open tasks and calls submit with token/action.
Manual verification:
- Start FastAPI on port 8000.
- Start Vite on port 5173.
- Create a job, ingest fixture order items, simulate callbacks, open job detail, and verify the diagram follows backend state.
- In a local demo build, exercise the dev-only callback simulator without leaking the token into normal business screens.