CentralUI Flow Debugger: run-method pane cannot take array/object parameters (e.g. MesMoveOut WorkOrders) — use ParameterValueForm like the script pane #37

Closed
opened 2026-09-10 14:23:44 -04:00 by dohertj2 · 2 comments
Owner

Summary

In the Central UI Flow Debugger, the Run inbound API method pane cannot take complex values for array / object parameters. Each top-level schema field is rendered as one single-line text box (FlowDebugger.razor ~L220–231) and FlowDebugger.razor.cs Coerce() tries JsonNode.Parse(raw) on whatever was typed for object / array / list fields. There are no per-item editors, no nested-object inputs, no hint that raw JSON is expected, and no inline validation — a parse failure falls back to sending the raw text as a string, and an empty box is silently omitted.

For MesMoveOut (ApiMethods id 3) the WorkOrders field is array of {WorkOrderNumber, PartNumber} objects and is required. From the UI it is effectively impossible to enter it correctly; the run then fails inside the script or at the site with a misleading error.

Evidence

  • QA (vq03, build 2b9a7c3c), 2026-09-10 17:39:21 UTC, root execution E6425C8C-C0F6-49CD-99BF-90456FD6AB75, extra.source = "flow-debugger": the request that reached Central was {"SAPID":"103559_A","ContainerNumber":"100000140892","WorkOrders":[],"OperatorName":"fernanc6","JobSequenceNumber":"50"} — the array could not be supplied from the page, the script routed to Z28061 anyway and the receiver answered "Invalid number of work orders (must be > 0)".
  • The same payload with the four work orders ran fine through the CLI (flow-debug run-method --method-id 3 --params '<json>', root 81db04ad-8c06-4d18-8d20-ccb5597c8279), so the limitation is only the UI input surface, not the runner.

Inconsistency with the script pane

The Run site script pane on the same page already uses Components/Shared/ParameterValueForm.razor, which renders typed inputs for primitives, labeled groups for objects (recursing), an add/remove list of item editors for arrays, $ref:lib: resolution, per-field validation via InboundApiSchema.Validate, and a Monaco raw-JSON escape hatch for unresolved shapes — and emits the coerced value tree that BuildScriptParameters() serializes as-is. The method pane predates it and still uses the flat _inputFields / _inputs / Coerce() path from the original 2026-09-05 Flow Debugger plan.

Proposed follow-up

  1. Switch the method pane to ParameterValueForm driven by the method's ParameterDefinitions (same @key / reset semantics as the script pane so per-method state does not leak across selections), and build the run payload the same way BuildScriptParameters() does. Keep PersistInputsAsync working (persist the value tree as JSON instead of per-field strings, or drop the persisted flat inputs when the schema has any non-scalar field).
  2. Keep a raw-JSON escape hatch for a whole method payload (paste the exact body an external caller would send) — useful for reproducing MES traffic verbatim — with schema validation against the method's ParameterDefinitions before the run.
  3. Surface validation inline and disable Run while the form is invalid, matching _scriptParamsValid on the script side; never send a failed parse as a string.
  4. bUnit coverage: an array-of-object field (the MesMoveOut WorkOrders shape) round-trips from item editors to the RunMethodAsync payload; an invalid raw-JSON entry blocks the run.

Related: #36 (stale CompleteFlag handshake in the same scripts) was found in the same session; not a dependency.

## Summary In the Central UI Flow Debugger, the **Run inbound API method** pane cannot take complex values for `array` / `object` parameters. Each top-level schema field is rendered as one single-line text box (`FlowDebugger.razor` ~L220–231) and `FlowDebugger.razor.cs` `Coerce()` tries `JsonNode.Parse(raw)` on whatever was typed for `object` / `array` / `list` fields. There are no per-item editors, no nested-object inputs, no hint that raw JSON is expected, and no inline validation — a parse failure falls back to sending the raw text **as a string**, and an empty box is silently omitted. For `MesMoveOut` (`ApiMethods` id 3) the `WorkOrders` field is `array` of `{WorkOrderNumber, PartNumber}` objects and is **required**. From the UI it is effectively impossible to enter it correctly; the run then fails inside the script or at the site with a misleading error. ## Evidence - QA (vq03, build `2b9a7c3c`), 2026-09-10 17:39:21 UTC, root execution `E6425C8C-C0F6-49CD-99BF-90456FD6AB75`, `extra.source = "flow-debugger"`: the request that reached Central was `{"SAPID":"103559_A","ContainerNumber":"100000140892","WorkOrders":[],"OperatorName":"fernanc6","JobSequenceNumber":"50"}` — the array could not be supplied from the page, the script routed to Z28061 anyway and the receiver answered `"Invalid number of work orders (must be > 0)"`. - The same payload with the four work orders ran fine through the CLI (`flow-debug run-method --method-id 3 --params '<json>'`, root `81db04ad-8c06-4d18-8d20-ccb5597c8279`), so the limitation is only the UI input surface, not the runner. ## Inconsistency with the script pane The **Run site script** pane on the same page already uses `Components/Shared/ParameterValueForm.razor`, which renders typed inputs for primitives, labeled groups for objects (recursing), an add/remove list of item editors for arrays, `$ref:lib:` resolution, per-field validation via `InboundApiSchema.Validate`, and a Monaco raw-JSON escape hatch for unresolved shapes — and emits the coerced value tree that `BuildScriptParameters()` serializes as-is. The method pane predates it and still uses the flat `_inputFields` / `_inputs` / `Coerce()` path from the original 2026-09-05 Flow Debugger plan. ## Proposed follow-up 1. Switch the method pane to `ParameterValueForm` driven by the method's `ParameterDefinitions` (same `@key` / reset semantics as the script pane so per-method state does not leak across selections), and build the run payload the same way `BuildScriptParameters()` does. Keep `PersistInputsAsync` working (persist the value tree as JSON instead of per-field strings, or drop the persisted flat inputs when the schema has any non-scalar field). 2. Keep a raw-JSON escape hatch for a whole method payload (paste the exact body an external caller would send) — useful for reproducing MES traffic verbatim — with schema validation against the method's `ParameterDefinitions` before the run. 3. Surface validation inline and disable **Run** while the form is invalid, matching `_scriptParamsValid` on the script side; never send a failed parse as a string. 4. bUnit coverage: an `array`-of-`object` field (the `MesMoveOut` `WorkOrders` shape) round-trips from item editors to the `RunMethodAsync` payload; an invalid raw-JSON entry blocks the run. Related: #36 (stale `CompleteFlag` handshake in the same scripts) was found in the same session; not a dependency.
Author
Owner

Fixed on local main @ b5eb08f1 (design 3b1211d7, docs/plans/2026-09-10-flow-debugger-method-params-design.md).

What shipped

  1. The method pane now renders the same shared ParameterValueForm the script pane uses, keyed on the method id (same reset semantics); the page keeps one value tree and BuildParameters() serializes it as-is. The flat _inputs / Coerce() path is deleted — a failed parse can no longer be sent as a string.
  2. Form | Raw JSON toggle: raw mode is a Monaco json editor for the whole request body, fed the method's root schema for completion, parsed + validated with InboundApiSchema.Validate on every edit, error inline. Entering raw mode seeds the editor from the tree; leaving it re-mounts the form over the last valid tree.
  3. Run is disabled while either surface is invalid (a required field left empty disables Run before the first keystroke).
  4. bUnit: the WorkOrders array-of-object shape round-trips from item editors to the RunMethodAsync payload; invalid raw JSON (malformed / schema-invalid / non-object) blocks Run; valid raw JSON is sent verbatim; method switch resets; persisted tree restored, legacy flat entry dropped. Playwright smoke selector moved to #param-Text.

Persistence: the per-method localStorage entry now stores the value tree and is dropped on restore if it no longer validates, which retires the old flat string entries without a version flag.

CentralUI.Tests 1425/1425. Not yet pushed, not yet on the rig or QA — leaving open until verified on QA with MesMoveOut.

Fixed on local main @ b5eb08f1 (design 3b1211d7, `docs/plans/2026-09-10-flow-debugger-method-params-design.md`). **What shipped** 1. The method pane now renders the same shared `ParameterValueForm` the script pane uses, keyed on the method id (same reset semantics); the page keeps one value tree and `BuildParameters()` serializes it as-is. The flat `_inputs` / `Coerce()` path is deleted — a failed parse can no longer be sent as a string. 2. **Form | Raw JSON** toggle: raw mode is a Monaco json editor for the whole request body, fed the method's root schema for completion, parsed + validated with `InboundApiSchema.Validate` on every edit, error inline. Entering raw mode seeds the editor from the tree; leaving it re-mounts the form over the last valid tree. 3. Run is disabled while either surface is invalid (a required field left empty disables Run before the first keystroke). 4. bUnit: the WorkOrders array-of-object shape round-trips from item editors to the `RunMethodAsync` payload; invalid raw JSON (malformed / schema-invalid / non-object) blocks Run; valid raw JSON is sent verbatim; method switch resets; persisted tree restored, legacy flat entry dropped. Playwright smoke selector moved to `#param-Text`. Persistence: the per-method localStorage entry now stores the value tree and is dropped on restore if it no longer validates, which retires the old flat string entries without a version flag. CentralUI.Tests 1425/1425. Not yet pushed, not yet on the rig or QA — leaving open until verified on QA with MesMoveOut.
Author
Owner

Existing merged fix b5eb08f1 is on origin/main 513fa1aa16. Fresh FlowDebuggerPageTests: 47 passed, zero failed, terminal exit0. Coverage includes array-of-object editors reaching RunMethodAsync, required nested-field validation, invalid whole-payload JSON blocking Run, valid JSON/form round-trip, method selection reset, persisted value tree and legacy flat-input rejection. Closing the completed UI input defect; no deployment or MES transaction run performed.

Existing merged fix b5eb08f1 is on origin/main 513fa1aa16099a9a53e1018de90cf3ee9e109a02. Fresh FlowDebuggerPageTests: 47 passed, zero failed, terminal exit0. Coverage includes array-of-object editors reaching RunMethodAsync, required nested-field validation, invalid whole-payload JSON blocking Run, valid JSON/form round-trip, method selection reset, persisted value tree and legacy flat-input rejection. Closing the completed UI input defect; no deployment or MES transaction run performed.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/ScadaBridge#37