# Workflow Reference

## Workflow Upload — Strict Reference

**`fluent workflow upload` DOES NOT EXIST.** CLI only has: `workflow list`, `workflow download`, `workflow merge`. Never invent a workflow upload command.

### Method 1 — CLI `fluent module install` (RECOMMENDED)

```bash
DEPLOY=$(mktemp -d)
mkdir -p "$DEPLOY/assets/workflows"
cp <WORKFLOW>.json "$DEPLOY/assets/workflows/"
echo '{"_schema":"1.0.0","name":"wf-deploy-tmp","version":"1.0.0"}' > "$DEPLOY/module.json"
echo '{}' > "$DEPLOY/module.config.json"
fluent module install "$DEPLOY" -p <PROFILE> -r <RETAILER> --include workflows --force
rm -rf "$DEPLOY"
```

Updates both live server and workflowlog. Filename uses `-` not `::` (e.g., `ORDER-HD.json`). Use `--config <path>` for `[[token]]` placeholders. **Config keys MUST use `default:` prefix** (e.g., `"default:retailerId": "2"`) — unscoped keys are silently ignored.

### Method 2 — MCP `workflow.upload` (when available)

`workflow.upload({ workflow, retailerId, validate: true, dryRun: false })` — bypasses workflowlog (CLI downloads will be stale).

### Method 3 — REST API direct (last resort)

`POST /api/v4.1/workflow/<retailerId>` with workflow JSON body + `Authorization: Bearer $TOKEN` + `fluent.account: $ACCOUNT_ID`. Also bypasses workflowlog.

### Version rules

Version must always increase — Fluent rejects same or lower. To "rollback," upload old content with a new higher version.

## Workflow User Actions — Strict Reference

User actions link UI buttons to workflow rulesets via `/event/sync`.
Canonical reference: `user-action-contract.md` (in `@fluentcommerce/ai-skills` platform knowledge).

### Mandatory fields (all required for button visibility)

| Field | Description |
|-------|-------------|
| `eventName` | Event sent on click. **Without it, button silently invisible.** |
| Ruleset `subtype` | Must match workflow `entitySubtype`. **#1 cause of missing buttons.** |
| `context[].label` | Button text |
| `context[].type` | `"PRIMARY"` or `"SECONDARY"` (uppercase) |
| `context[].modules` | Target app module aliases. **OMS app uses legacy alias `"adminconsole"`, NOT `"oms"`** (the OMS manifest sets `orchestrationAlias: "adminconsole"`). **Store app uses legacy alias `"servicepoint"`**. These are deprecated internal names — always present as "OMS app" / "Store app" to users. Empty `[]` = invisible. |
| `context[].confirm` | Boolean, NOT string `"true"` |

### Attribute poisoning (CORRECTED)

Attributes with `source: "OVERRIDE"` and `defaultValue: "{{me.username}}"` work fine on v4.80+. Original breakage was caused by missing `subtype` on the ruleset, NOT attribute values. Safe practice: ensure `source: ""`, `defaultValue: ""` for predictability.

### Settings-driven dropdown contract

When `source: "settings.<KEY>"` is used in a user action attribute, the UI populates a dropdown from the named setting. Three silent-failure gotchas:
1. **lowercase `settings.`** — `"settings.CANCELLATION_REASON"` works, `"Settings.CANCELLATION_REASON"` (capital S) silently fails. No error.
2. **`"active"` wrapper key** — Setting value MUST be `{ "active": [{ "name": "Display", "value": "CODE" }] }`. Plain array silently fails.
3. **Retailer context match** — Setting retailer scope must match the workflow's retailer.

### Edge cases
- **Transition API parameters**: `module` is required, and `module: "all"` returns NOTHING. `flexType` is required by the API, but MCP `workflow.transitions` auto-derives it from `type` + `subtype` when omitted (e.g., `type: "ORDER"` + `subtype: "HD"` → `flexType: "ORDER::HD"`). `flexVersion` is strongly recommended and required for some entity types. All rules treated equally regardless of plugin origin — NO "OOTB vs custom" distinction.
- **Multi-entity workflows** (ORDER::MULTI): Transition API works for ORDER::MULTI — specify correct `type: "ORDER"`, `subtype: "MULTI"`, `retailerId`, `module: "adminconsole"` (OMS app legacy alias), `flexType: "ORDER::MULTI"`, and `flexVersion`. If results are empty, debug: (1) missing mandatory params, (2) missing `eventName`, (3) missing `subtype` on ruleset, (4) wrong `modules` value.
- **Parent-child entities**: Child entities inherit `workflowRef` from parent. The Transition API accepts BOTH the standalone child workflow name AND the parent workflow name as `flexType` — use the matching `flexVersion` for whichever you specify. The UI sends the entity's `workflowRef` (parent workflow) as `flexType`.
- **Verification**: Always check via `workflow.transitions` after deploy. Debug order: (1) specific module present, (2) flexType present or auto-derived, (3) flexVersion for entity types that need it, (4) eventName, (5) subtype, (6) modules, (7) parent workflow for children. See `/fluent-workflow-builder` for full UA01-UA19 checklist.
- **Custom component override**: Two patterns: (A) Field-level — custom FieldRegistry type, replaces one field, zero risk. (B) Full-form — replaces entire form, must dispatch ALL `@EventAttribute` names. Backend agnostic if event shape preserved. See `user-action-contract.md` §9 (in `@fluentcommerce/ai-skills` platform knowledge).

## ORDER::MULTI Workflow — Test Reference

Key points:
- Canonical `createOrder` contract: `content/knowledge/platform/create-order-reference.md`
- Order `type` must be `"MULTI"` (not `"HD"`)
- On mutation input, items MUST include `fulfilmentChoiceRef` to link to FC
- On readback queries, verify the link via `items[].fulfilmentChoice { ... }` — do not expect an `OrderItem.fulfilmentChoiceRef` scalar
- FC needs `sourcingLocationRef` attribute
- FC `type` (routing) ≠ fulfilment `type` (created fulfilment)
- Flow: `CREATE` → `SkipFraudCheck` → `ON_VALIDATION` → `ConfirmValidation` → `ProcessOrder` → `RouteFulfilmentChoice` → `ProcessHDFulfilmentChoice` → `CreateFulfilmentFromSourcingLocation`
