@fluentcommerce/fluent-mcp-extn 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -14
- package/docs/E2E_TESTING.md +8 -318
- package/docs/RUNBOOK.md +11 -90
- package/docs/TOOL_REFERENCE.md +35 -689
- package/package.json +1 -5
- package/docs/IMPLEMENTATION_GUIDE.md +0 -299
package/docs/TOOL_REFERENCE.md
CHANGED
|
@@ -1114,697 +1114,43 @@ Response:
|
|
|
1114
1114
|
|
|
1115
1115
|
---
|
|
1116
1116
|
|
|
1117
|
-
## `entity.create`
|
|
1118
|
-
|
|
1119
|
-
Type-safe entity creation with built-in validation and gotcha knowledge.
|
|
1120
|
-
|
|
1121
|
-
**Supported entity types:** ORDER, FULFILMENT, LOCATION, NETWORK, CUSTOMER, PRODUCT, INVENTORY_POSITION, VIRTUAL_CATALOGUE, VIRTUAL_POSITION, CATEGORY, CARRIER, SETTING
|
|
1122
|
-
|
|
1123
|
-
- **Required**:
|
|
1124
|
-
- `entityType`: entity type string (see supported list above)
|
|
1125
|
-
- `data`: creation input fields matching the GraphQL create input type
|
|
1126
|
-
- **Optional**:
|
|
1127
|
-
- `returnFields`: array of field names to return (defaults to entity type defaults)
|
|
1128
|
-
- `dryRun`: if `true`, builds and validates the mutation without executing (default `false`)
|
|
1129
|
-
|
|
1130
|
-
**Key behaviors:**
|
|
1131
|
-
|
|
1132
|
-
- Validates required fields BEFORE sending (e.g., Location requires `openingSchedule`)
|
|
1133
|
-
- Encodes compound key rules (ProductKey needs `ref` + `catalogue.ref`)
|
|
1134
|
-
- Auto-resolves `retailerId` from config for retailer-scoped entities
|
|
1135
|
-
- Returns the executed mutation string for audit trail
|
|
1136
|
-
|
|
1137
|
-
**Known gotchas (encoded in validation):**
|
|
1138
|
-
|
|
1139
|
-
- No create inputs have a `status` field — status is auto-set to `CREATED`
|
|
1140
|
-
- `Customer` has NO `ref` field; `username` is the identifier
|
|
1141
|
-
- `Network` uses `name` (not `ref`) in create; `retailers` is a plural array
|
|
1142
|
-
- `Location` requires `openingSchedule` even for 24/7 (use `allHours: true`)
|
|
1143
|
-
- `Product` `gtin` has a 20-character max
|
|
1144
|
-
- `Setting` `context` is a plain String, `contextId` is a separate Int
|
|
1145
|
-
|
|
1146
|
-
**Example** — create a location (dry run):
|
|
1147
|
-
|
|
1148
|
-
```json
|
|
1149
|
-
{
|
|
1150
|
-
"entityType": "LOCATION",
|
|
1151
|
-
"data": {
|
|
1152
|
-
"ref": "LOC_WH_01",
|
|
1153
|
-
"type": "WAREHOUSE",
|
|
1154
|
-
"name": "Main Warehouse",
|
|
1155
|
-
"openingSchedule": { "allHours": true }
|
|
1156
|
-
},
|
|
1157
|
-
"dryRun": true
|
|
1158
|
-
}
|
|
1159
|
-
```
|
|
1160
|
-
|
|
1161
|
-
Response (dry run):
|
|
1162
|
-
|
|
1163
|
-
```json
|
|
1164
|
-
{
|
|
1165
|
-
"ok": true,
|
|
1166
|
-
"dryRun": true,
|
|
1167
|
-
"entityType": "LOCATION",
|
|
1168
|
-
"mutation": "mutation CreateLocation($input: CreateLocationInput!) { createLocation(input: $input) { id ref status type name } }",
|
|
1169
|
-
"inputType": "CreateLocationInput",
|
|
1170
|
-
"variables": { "input": { "ref": "LOC_WH_01", "type": "WAREHOUSE", "name": "Main Warehouse", "openingSchedule": { "allHours": true } } },
|
|
1171
|
-
"requiredFields": ["ref", "type", "name", "openingSchedule"],
|
|
1172
|
-
"gotchas": ["Location requires openingSchedule — use { allHours: true } for 24/7"],
|
|
1173
|
-
"note": "No API call made. Set dryRun=false to execute."
|
|
1174
|
-
}
|
|
1175
|
-
```
|
|
1176
|
-
|
|
1177
|
-
**Example** — create a location (real):
|
|
1178
|
-
|
|
1179
|
-
```json
|
|
1180
|
-
{
|
|
1181
|
-
"entityType": "LOCATION",
|
|
1182
|
-
"data": {
|
|
1183
|
-
"ref": "LOC_WH_01",
|
|
1184
|
-
"type": "WAREHOUSE",
|
|
1185
|
-
"name": "Main Warehouse",
|
|
1186
|
-
"openingSchedule": { "allHours": true }
|
|
1187
|
-
}
|
|
1188
|
-
}
|
|
1189
|
-
```
|
|
1190
|
-
|
|
1191
|
-
Response:
|
|
1192
|
-
|
|
1193
|
-
```json
|
|
1194
|
-
{
|
|
1195
|
-
"ok": true,
|
|
1196
|
-
"entityType": "LOCATION",
|
|
1197
|
-
"entity": { "id": "42", "ref": "LOC_WH_01", "status": "CREATED", "type": "WAREHOUSE", "name": "Main Warehouse" },
|
|
1198
|
-
"mutation": "mutation CreateLocation($input: CreateLocationInput!) { ... }"
|
|
1199
|
-
}
|
|
1200
|
-
```
|
|
1201
|
-
|
|
1202
|
-
---
|
|
1203
|
-
|
|
1204
|
-
## `entity.update`
|
|
1205
|
-
|
|
1206
|
-
Status-aware entity updates with optional transition validation.
|
|
1207
|
-
|
|
1208
|
-
- **Required**:
|
|
1209
|
-
- `entityType`: entity type string
|
|
1210
|
-
- `id`: entity ID (required for updates)
|
|
1211
|
-
- `fields`: object of fields to update (matches GraphQL update input type)
|
|
1212
|
-
- **Optional**:
|
|
1213
|
-
- `returnFields`: array of field names to return
|
|
1214
|
-
- `validateTransition`: if `true` and `status` is being changed, queries `workflow.transitions` to verify the transition is allowed before executing (default `false`)
|
|
1215
|
-
|
|
1216
|
-
**Key behaviors:**
|
|
1217
|
-
|
|
1218
|
-
- Auto-detects the correct GraphQL mutation name from entity type
|
|
1219
|
-
- When `validateTransition` is `true`: fetches current entity state, queries transition API, warns if no workflow transitions exist from the current status
|
|
1220
|
-
- Returns the previous status for audit trail when transition validation is used
|
|
1221
|
-
- Uses no-retry semantics (write operation)
|
|
1222
|
-
|
|
1223
|
-
**Example** — update order status with transition validation:
|
|
1224
|
-
|
|
1225
|
-
```json
|
|
1226
|
-
{
|
|
1227
|
-
"entityType": "ORDER",
|
|
1228
|
-
"id": "12345",
|
|
1229
|
-
"fields": { "status": "COMPLETE" },
|
|
1230
|
-
"validateTransition": true
|
|
1231
|
-
}
|
|
1232
|
-
```
|
|
1233
|
-
|
|
1234
|
-
Response:
|
|
1235
|
-
|
|
1236
|
-
```json
|
|
1237
|
-
{
|
|
1238
|
-
"ok": true,
|
|
1239
|
-
"entityType": "ORDER",
|
|
1240
|
-
"entity": { "id": "12345", "ref": "HD-001", "status": "COMPLETE" },
|
|
1241
|
-
"mutation": "mutation UpdateOrder($input: UpdateOrderInput!) { ... }"
|
|
1242
|
-
}
|
|
1243
|
-
```
|
|
1244
|
-
|
|
1245
|
-
If no workflow transition exists:
|
|
1246
|
-
|
|
1247
|
-
```json
|
|
1248
|
-
{
|
|
1249
|
-
"ok": true,
|
|
1250
|
-
"entityType": "ORDER",
|
|
1251
|
-
"entity": { "id": "12345", "ref": "HD-001", "status": "COMPLETE" },
|
|
1252
|
-
"mutation": "...",
|
|
1253
|
-
"transitionWarning": "No workflow transitions available from status \"BOOKED\" for ORDER. The status update may succeed as a direct mutation but will not trigger workflow orchestration."
|
|
1254
|
-
}
|
|
1255
|
-
```
|
|
1256
|
-
|
|
1257
|
-
---
|
|
1258
|
-
|
|
1259
|
-
## `entity.get`
|
|
1260
|
-
|
|
1261
|
-
Unified entity lookup by ID or ref with optional edge inclusion.
|
|
1262
|
-
|
|
1263
|
-
- **Required**:
|
|
1264
|
-
- `entityType`: entity type string
|
|
1265
|
-
- At least one of `id` or `ref`
|
|
1266
|
-
- **Optional**:
|
|
1267
|
-
- `id`: entity ID (preferred lookup method)
|
|
1268
|
-
- `ref`: entity ref (fallback — not available for CUSTOMER)
|
|
1269
|
-
- `fields`: array of field names to return (defaults to entity type defaults: id, ref, status, type, createdOn, etc.)
|
|
1270
|
-
- `includeEdges`: array of related entity edges to fetch (e.g., `["fulfilments", "items", "attributes"]`)
|
|
1271
|
-
|
|
1272
|
-
**Key behaviors:**
|
|
1273
|
-
|
|
1274
|
-
- Prefers ID-based lookup (single entity query) over ref-based lookup (connection query)
|
|
1275
|
-
- Ref-based lookup uses the connection query pattern (edges/node)
|
|
1276
|
-
- Returns `{ found: false }` when entity is not found (not an error)
|
|
1277
|
-
- CUSTOMER entity type does not support ref-based lookup
|
|
1278
|
-
|
|
1279
|
-
**Example** — get order by ref with fulfilments:
|
|
1280
|
-
|
|
1281
|
-
```json
|
|
1282
|
-
{
|
|
1283
|
-
"entityType": "ORDER",
|
|
1284
|
-
"ref": "HD-001",
|
|
1285
|
-
"includeEdges": ["fulfilments"]
|
|
1286
|
-
}
|
|
1287
|
-
```
|
|
1288
|
-
|
|
1289
|
-
Response:
|
|
1290
|
-
|
|
1291
|
-
```json
|
|
1292
|
-
{
|
|
1293
|
-
"ok": true,
|
|
1294
|
-
"found": true,
|
|
1295
|
-
"entityType": "ORDER",
|
|
1296
|
-
"entity": {
|
|
1297
|
-
"id": "12345",
|
|
1298
|
-
"ref": "HD-001",
|
|
1299
|
-
"status": "BOOKED",
|
|
1300
|
-
"type": "HD",
|
|
1301
|
-
"fulfilments": {
|
|
1302
|
-
"edges": [
|
|
1303
|
-
{ "node": { "id": "67890", "ref": "FUL-001", "status": "CREATED" } }
|
|
1304
|
-
]
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
}
|
|
1308
|
-
```
|
|
1309
|
-
|
|
1310
|
-
---
|
|
1311
|
-
|
|
1312
|
-
## `workflow.upload`
|
|
1313
|
-
|
|
1314
|
-
Deploy a workflow JSON definition to the Fluent environment.
|
|
1315
|
-
|
|
1316
|
-
Uploads via REST API `POST /api/v4.1/workflow/{retailerId}` — the same endpoint the Fluent CLI uses.
|
|
1317
|
-
|
|
1318
|
-
- **Required**:
|
|
1319
|
-
- `workflow`: workflow JSON definition (as object or JSON string)
|
|
1320
|
-
- **Optional**:
|
|
1321
|
-
- `retailerId`: target retailer ID (falls back to `FLUENT_RETAILER_ID`)
|
|
1322
|
-
- `validate`: validate structure before uploading (default `true`)
|
|
1323
|
-
- `dryRun`: validate only, do not deploy (default `false`)
|
|
1324
|
-
|
|
1325
|
-
**Validation checks:**
|
|
1326
|
-
|
|
1327
|
-
- `name` field present
|
|
1328
|
-
- At least one status defined in `statuses` array
|
|
1329
|
-
- All rulesets have `name`, `triggers`, and `rules` (warns if empty)
|
|
1330
|
-
|
|
1331
|
-
**Important:** For production deployments, prefer `fluent module install` via CLI which bundles workflows with settings, rules, and data in a versioned module. Use this tool for interactive editing, hotfixes, or when CLI is unavailable.
|
|
1332
|
-
|
|
1333
|
-
**Example** — dry-run validation:
|
|
1334
|
-
|
|
1335
|
-
```json
|
|
1336
|
-
{
|
|
1337
|
-
"workflow": {
|
|
1338
|
-
"name": "ORDER::HD",
|
|
1339
|
-
"type": "ORDER",
|
|
1340
|
-
"subtype": "HD",
|
|
1341
|
-
"statuses": [{ "name": "CREATED" }, { "name": "BOOKED" }],
|
|
1342
|
-
"rulesets": [
|
|
1343
|
-
{
|
|
1344
|
-
"name": "BookOrder",
|
|
1345
|
-
"triggers": [{ "status": "CREATED" }],
|
|
1346
|
-
"rules": [{ "name": "com.fluentretail.rubix.rule.order.SendEventOnVerifyingState", "props": { "status": "BOOKED" } }]
|
|
1347
|
-
}
|
|
1348
|
-
]
|
|
1349
|
-
},
|
|
1350
|
-
"dryRun": true
|
|
1351
|
-
}
|
|
1352
|
-
```
|
|
1353
|
-
|
|
1354
|
-
Response (dry run — valid):
|
|
1355
|
-
|
|
1356
|
-
```json
|
|
1357
|
-
{
|
|
1358
|
-
"ok": true,
|
|
1359
|
-
"dryRun": true,
|
|
1360
|
-
"valid": true,
|
|
1361
|
-
"workflowName": "ORDER::HD",
|
|
1362
|
-
"retailerId": "5",
|
|
1363
|
-
"note": "Validation passed. Set dryRun=false to deploy."
|
|
1364
|
-
}
|
|
1365
|
-
```
|
|
1366
|
-
|
|
1367
|
-
---
|
|
1368
|
-
|
|
1369
|
-
## `workflow.diff`
|
|
1370
|
-
|
|
1371
|
-
Compare two workflow JSON definitions and identify changes.
|
|
1372
|
-
|
|
1373
|
-
Pure local computation — no API calls.
|
|
1374
|
-
|
|
1375
|
-
- **Required**:
|
|
1376
|
-
- `base`: base workflow JSON (before changes)
|
|
1377
|
-
- `target`: target workflow JSON (after changes)
|
|
1378
|
-
- **Optional**:
|
|
1379
|
-
- `format`: output format — `summary` (default), `detailed`, or `mermaid`
|
|
1380
|
-
|
|
1381
|
-
**Comparison scope:**
|
|
1382
|
-
|
|
1383
|
-
- Rulesets: added, removed, modified (trigger changes, rule additions/removals, prop changes)
|
|
1384
|
-
- Statuses: added, removed
|
|
1385
|
-
- Risk assessment: removing rulesets or statuses = HIGH, modifying props = MEDIUM, adding = LOW
|
|
1386
|
-
|
|
1387
|
-
**Formats:**
|
|
1388
|
-
|
|
1389
|
-
| Format | Returns |
|
|
1390
|
-
|---|---|
|
|
1391
|
-
| `summary` | Change counts, status changes, risk level |
|
|
1392
|
-
| `detailed` | Full `WorkflowDiffResult` object with per-ruleset breakdown |
|
|
1393
|
-
| `mermaid` | `stateDiagram-v2` with color-coded added/removed/modified states and transitions |
|
|
1394
|
-
|
|
1395
|
-
**Example** — summary diff:
|
|
1396
|
-
|
|
1397
|
-
```json
|
|
1398
|
-
{
|
|
1399
|
-
"base": { "name": "ORDER::HD", "statuses": [...], "rulesets": [...] },
|
|
1400
|
-
"target": { "name": "ORDER::HD", "statuses": [...], "rulesets": [...] },
|
|
1401
|
-
"format": "summary"
|
|
1402
|
-
}
|
|
1403
|
-
```
|
|
1404
|
-
|
|
1405
|
-
Response:
|
|
1406
|
-
|
|
1407
|
-
```json
|
|
1408
|
-
{
|
|
1409
|
-
"ok": true,
|
|
1410
|
-
"summary": "3 ruleset change(s): 1 added, 0 removed, 2 modified. 1 status change(s): 1 added, 0 removed. Risk level: MEDIUM.",
|
|
1411
|
-
"riskLevel": "medium",
|
|
1412
|
-
"rulesetChanges": { "added": 1, "removed": 0, "modified": 2 },
|
|
1413
|
-
"statusChanges": { "added": ["AWAITING_PICKUP"], "removed": [] }
|
|
1414
|
-
}
|
|
1415
|
-
```
|
|
1416
|
-
|
|
1417
|
-
---
|
|
1418
|
-
|
|
1419
|
-
## `workflow.simulate`
|
|
1420
|
-
|
|
1421
|
-
Static prediction of workflow event outcomes from workflow JSON.
|
|
1422
|
-
|
|
1423
|
-
Pure local computation — no API calls. Parses workflow JSON to find matching rulesets and predict state transitions, follow-on events, and webhook side effects.
|
|
1424
|
-
|
|
1425
|
-
- **Required**:
|
|
1426
|
-
- `workflow`: workflow JSON definition (as object or JSON string)
|
|
1427
|
-
- `currentStatus`: entity status to simulate from (e.g., `CREATED`, `BOOKED`)
|
|
1428
|
-
- **Optional**:
|
|
1429
|
-
- `eventName`: event name to match against ruleset names (if omitted, returns all rulesets triggered by `currentStatus`)
|
|
1430
|
-
- `entityType`: entity type filter for trigger matching
|
|
1431
|
-
- `entitySubtype`: entity subtype filter for trigger matching
|
|
1432
|
-
|
|
1433
|
-
**What it does:**
|
|
1434
|
-
|
|
1435
|
-
- Finds rulesets whose triggers match `currentStatus` (and optionally `eventName`)
|
|
1436
|
-
- Extracts `SetState`/`ChangeState` rules → predicted next status
|
|
1437
|
-
- Extracts `SendEvent` rules → predicted follow-on events
|
|
1438
|
-
- Extracts `SendWebhook` rules → predicted webhook side effects
|
|
1439
|
-
- Identifies custom Java rules that cannot be statically predicted
|
|
1440
|
-
|
|
1441
|
-
**Important limitations (always disclosed in response):**
|
|
1442
|
-
|
|
1443
|
-
- **STATIC ONLY** — cannot evaluate runtime conditions, entity attributes, or settings values
|
|
1444
|
-
- **CUSTOM RULES OPAQUE** — Java plugin rules may conditionally execute; behavior unknown without live state
|
|
1445
|
-
- **NO CROSS-ENTITY** — does not follow SendEvent chains into child entity workflows
|
|
1446
|
-
- Use `workflow.transitions` for **authoritative live validation** of available actions
|
|
1447
|
-
|
|
1448
|
-
**Example** — simulate from CREATED status:
|
|
1449
|
-
|
|
1450
|
-
```json
|
|
1451
|
-
{
|
|
1452
|
-
"workflow": { "name": "ORDER::HD", "rulesets": [...] },
|
|
1453
|
-
"currentStatus": "CREATED",
|
|
1454
|
-
"eventName": "BookOrder"
|
|
1455
|
-
}
|
|
1456
|
-
```
|
|
1457
|
-
|
|
1458
|
-
Response:
|
|
1459
|
-
|
|
1460
|
-
```json
|
|
1461
|
-
{
|
|
1462
|
-
"ok": true,
|
|
1463
|
-
"workflowName": "ORDER::HD",
|
|
1464
|
-
"currentStatus": "CREATED",
|
|
1465
|
-
"eventName": "BookOrder",
|
|
1466
|
-
"matchedRulesets": 1,
|
|
1467
|
-
"rulesets": [
|
|
1468
|
-
{
|
|
1469
|
-
"name": "BookOrder",
|
|
1470
|
-
"matchType": "statusAndEvent",
|
|
1471
|
-
"predictedStatus": "BOOKED",
|
|
1472
|
-
"predictedEvents": ["SendToFulfilment"],
|
|
1473
|
-
"predictedWebhooks": [],
|
|
1474
|
-
"ruleCount": 3
|
|
1475
|
-
}
|
|
1476
|
-
],
|
|
1477
|
-
"prediction": {
|
|
1478
|
-
"likelyNextStatus": "BOOKED",
|
|
1479
|
-
"followOnEvents": ["SendToFulfilment"],
|
|
1480
|
-
"webhookSideEffects": [],
|
|
1481
|
-
"confidence": "low",
|
|
1482
|
-
"note": "Custom rules present — prediction may be incomplete or wrong."
|
|
1483
|
-
},
|
|
1484
|
-
"limitations": [
|
|
1485
|
-
"STATIC PREDICTION ONLY — does not account for runtime conditions, entity attributes, or settings values.",
|
|
1486
|
-
"1 custom rule(s) found whose behavior cannot be predicted statically: ForwardIfOrderCoordinatesPresent.",
|
|
1487
|
-
"Use workflow.transitions for AUTHORITATIVE live validation of available actions."
|
|
1488
|
-
]
|
|
1489
|
-
}
|
|
1490
|
-
```
|
|
1491
|
-
|
|
1492
|
-
---
|
|
1493
|
-
|
|
1494
|
-
## `setting.upsert`
|
|
1495
|
-
|
|
1496
|
-
Create or update a Fluent Commerce setting with upsert semantics.
|
|
1497
|
-
|
|
1498
|
-
Queries existing settings by `name` + `context` + `contextId` first. Creates if missing, updates if exists.
|
|
1499
|
-
|
|
1500
|
-
- **Required**:
|
|
1501
|
-
- `name`: setting key/name
|
|
1502
|
-
- `value`: setting value (for small values)
|
|
1503
|
-
- `context`: setting scope — `RETAILER`, `ACCOUNT`, `LOCATION`, `NETWORK`, `AGENT`, `CUSTOMER`
|
|
1504
|
-
- **Optional**:
|
|
1505
|
-
- `lobValue`: large object value for JSON payloads > 4KB (mutually exclusive with `value`)
|
|
1506
|
-
- `contextId`: context ID (e.g., retailer ID). Defaults to `FLUENT_RETAILER_ID` for `RETAILER` context.
|
|
1507
|
-
|
|
1508
|
-
**Key gotchas:**
|
|
1509
|
-
|
|
1510
|
-
- `context` is a plain String (`"RETAILER"`), NOT an object
|
|
1511
|
-
- `contextId` is a separate Int field
|
|
1512
|
-
- For large JSON values (> 4KB), use `lobValue` instead of `value`
|
|
1513
|
-
- Returns `created: true/false` for audit trail
|
|
1514
|
-
|
|
1515
|
-
**Example** — create a webhook URL setting:
|
|
1516
|
-
|
|
1517
|
-
```json
|
|
1518
|
-
{
|
|
1519
|
-
"name": "WEBHOOK_ORDER_NOTIFICATION",
|
|
1520
|
-
"value": "https://api.example.com/webhooks/orders",
|
|
1521
|
-
"context": "RETAILER"
|
|
1522
|
-
}
|
|
1523
|
-
```
|
|
1524
|
-
|
|
1525
|
-
Response (created):
|
|
1526
|
-
|
|
1527
|
-
```json
|
|
1528
|
-
{
|
|
1529
|
-
"ok": true,
|
|
1530
|
-
"created": true,
|
|
1531
|
-
"updated": false,
|
|
1532
|
-
"setting": {
|
|
1533
|
-
"id": "99",
|
|
1534
|
-
"name": "WEBHOOK_ORDER_NOTIFICATION",
|
|
1535
|
-
"value": "https://api.example.com/webhooks/orders",
|
|
1536
|
-
"context": "RETAILER",
|
|
1537
|
-
"contextId": 5
|
|
1538
|
-
}
|
|
1539
|
-
}
|
|
1540
|
-
```
|
|
1541
|
-
|
|
1542
|
-
Response (updated existing):
|
|
1543
|
-
|
|
1544
|
-
```json
|
|
1545
|
-
{
|
|
1546
|
-
"ok": true,
|
|
1547
|
-
"created": false,
|
|
1548
|
-
"updated": true,
|
|
1549
|
-
"setting": { "id": "99", "name": "WEBHOOK_ORDER_NOTIFICATION", "value": "https://api.example.com/webhooks/orders-v2", "context": "RETAILER", "contextId": 5 },
|
|
1550
|
-
"previousValue": "https://api.example.com/webhooks/orders"
|
|
1551
|
-
}
|
|
1552
|
-
```
|
|
1553
|
-
|
|
1554
|
-
---
|
|
1555
|
-
|
|
1556
|
-
## `setting.bulkUpsert`
|
|
1557
|
-
|
|
1558
|
-
Batch create or update multiple settings in one call.
|
|
1559
|
-
|
|
1560
|
-
Processes up to 50 settings sequentially with individual error handling. Each setting is an independent upsert — failures on one setting don't block others.
|
|
1561
|
-
|
|
1562
|
-
- **Required**:
|
|
1563
|
-
- `settings`: array of setting objects (min 1, max 50), each with `name`, `value`, `context`, and optional `lobValue` and `contextId`
|
|
1564
|
-
|
|
1565
|
-
**Example** — bulk create 3 settings:
|
|
1566
|
-
|
|
1567
|
-
```json
|
|
1568
|
-
{
|
|
1569
|
-
"settings": [
|
|
1570
|
-
{ "name": "WEBHOOK_ORDER_URL", "value": "https://api.example.com/orders", "context": "RETAILER" },
|
|
1571
|
-
{ "name": "WEBHOOK_FULFILMENT_URL", "value": "https://api.example.com/fulfilments", "context": "RETAILER" },
|
|
1572
|
-
{ "name": "FEATURE_FLAG_RETURNS", "value": "true", "context": "RETAILER" }
|
|
1573
|
-
]
|
|
1574
|
-
}
|
|
1575
|
-
```
|
|
1576
|
-
|
|
1577
|
-
Response:
|
|
1578
|
-
|
|
1579
|
-
```json
|
|
1580
|
-
{
|
|
1581
|
-
"ok": true,
|
|
1582
|
-
"created": 2,
|
|
1583
|
-
"updated": 1,
|
|
1584
|
-
"failed": 0,
|
|
1585
|
-
"total": 3,
|
|
1586
|
-
"results": [
|
|
1587
|
-
{ "name": "WEBHOOK_ORDER_URL", "status": "created" },
|
|
1588
|
-
{ "name": "WEBHOOK_FULFILMENT_URL", "status": "created" },
|
|
1589
|
-
{ "name": "FEATURE_FLAG_RETURNS", "status": "updated" }
|
|
1590
|
-
]
|
|
1591
|
-
}
|
|
1592
|
-
```
|
|
1593
|
-
|
|
1594
|
-
---
|
|
1595
|
-
|
|
1596
|
-
## `environment.discover`
|
|
1597
|
-
|
|
1598
|
-
Full environment snapshot in one call.
|
|
1599
|
-
|
|
1600
|
-
Returns everything an agent needs to understand the Fluent environment: retailer details, locations, networks, catalogues, workflows, settings, modules, and user context.
|
|
1601
|
-
|
|
1602
|
-
- **Optional**:
|
|
1603
|
-
- `include`: array of sections to include. Default: `["retailer", "locations", "networks", "catalogues"]`. Available: `retailer`, `locations`, `networks`, `catalogues`, `workflows`, `settings`, `modules`, `users`
|
|
1604
|
-
|
|
1605
|
-
**Limitations:**
|
|
1606
|
-
|
|
1607
|
-
- Locations and settings return the first 100 items only (no auto-pagination)
|
|
1608
|
-
- Workflows section uses a transition API probe — may miss workflows with no user actions at the initial state. Use `fluent workflow list` via CLI for definitive listing.
|
|
1609
|
-
|
|
1610
|
-
**Example** — discover retailer, locations, and settings:
|
|
1611
|
-
|
|
1612
|
-
```json
|
|
1613
|
-
{
|
|
1614
|
-
"include": ["retailer", "locations", "settings"]
|
|
1615
|
-
}
|
|
1616
|
-
```
|
|
1617
|
-
|
|
1618
|
-
Response:
|
|
1619
|
-
|
|
1620
|
-
```json
|
|
1621
|
-
{
|
|
1622
|
-
"ok": true,
|
|
1623
|
-
"retailer": { "id": "5", "ref": "HM_TEST", "tradingName": "HM Test", "status": "ACTIVE" },
|
|
1624
|
-
"locations": [
|
|
1625
|
-
{ "id": "10", "ref": "LOC_WH_01", "type": "WAREHOUSE", "status": "ACTIVE", "name": "Main Warehouse" }
|
|
1626
|
-
],
|
|
1627
|
-
"settings": [
|
|
1628
|
-
{ "name": "WEBHOOK_ORDER_URL", "value": "https://...", "context": "RETAILER", "contextId": 5 }
|
|
1629
|
-
]
|
|
1630
|
-
}
|
|
1631
|
-
```
|
|
1632
|
-
|
|
1633
|
-
---
|
|
1634
|
-
|
|
1635
|
-
## `environment.validate`
|
|
1636
|
-
|
|
1637
|
-
Pre-flight environment validation. Runs configurable checks before E2E tests or deployments.
|
|
1638
|
-
|
|
1639
|
-
- **Optional**:
|
|
1640
|
-
- `checks`: array of checks to run. Default: `["auth", "retailer", "locations"]`. Available: `auth`, `retailer`, `locations`, `inventory`, `workflows`, `settings`, `modules`
|
|
1641
|
-
|
|
1642
|
-
**Available checks:**
|
|
1643
|
-
|
|
1644
|
-
| Check | What it validates |
|
|
1645
|
-
|---|---|
|
|
1646
|
-
| `auth` | Token valid, permissions sufficient |
|
|
1647
|
-
| `retailer` | Retailer exists and is active |
|
|
1648
|
-
| `locations` | At least one warehouse location exists |
|
|
1649
|
-
| `inventory` | At least one product with stock |
|
|
1650
|
-
| `workflows` | Key workflows deployed (ORDER, FULFILMENT) |
|
|
1651
|
-
| `settings` | Critical settings exist |
|
|
1652
|
-
| `modules` | Expected modules deployed |
|
|
1653
|
-
|
|
1654
|
-
Returns pass/fail per check with severity and actionable messages.
|
|
1655
|
-
|
|
1656
|
-
**Example** — full pre-flight validation:
|
|
1657
|
-
|
|
1658
|
-
```json
|
|
1659
|
-
{
|
|
1660
|
-
"checks": ["auth", "retailer", "locations", "workflows", "settings"]
|
|
1661
|
-
}
|
|
1662
|
-
```
|
|
1663
|
-
|
|
1664
|
-
Response:
|
|
1665
|
-
|
|
1666
|
-
```json
|
|
1667
|
-
{
|
|
1668
|
-
"ok": true,
|
|
1669
|
-
"results": [
|
|
1670
|
-
{ "check": "auth", "passed": true, "severity": "critical", "message": "Authenticated as admin@example.com" },
|
|
1671
|
-
{ "check": "retailer", "passed": true, "severity": "critical", "message": "Retailer HM_TEST (ID 5) is ACTIVE" },
|
|
1672
|
-
{ "check": "locations", "passed": true, "severity": "high", "message": "Found 3 locations (2 warehouses)" },
|
|
1673
|
-
{ "check": "workflows", "passed": false, "severity": "high", "message": "Missing workflow: FULFILMENT_OPTIONS::HD" },
|
|
1674
|
-
{ "check": "settings", "passed": true, "severity": "medium", "message": "12 retailer settings found" }
|
|
1675
|
-
],
|
|
1676
|
-
"summary": { "passed": 4, "failed": 1, "total": 5 }
|
|
1677
|
-
}
|
|
1678
|
-
```
|
|
1679
|
-
|
|
1680
|
-
---
|
|
1681
|
-
|
|
1682
|
-
## `test.assert`
|
|
1683
|
-
|
|
1684
|
-
Assert entity state matches expectations with optional polling.
|
|
1685
|
-
|
|
1686
|
-
Deep assertion on entity fields, attributes, and edge counts/statuses with human-readable failure messages.
|
|
1687
|
-
|
|
1688
|
-
- **Required**:
|
|
1689
|
-
- `entityType`: entity type (ORDER, FULFILMENT, etc.)
|
|
1690
|
-
- `assertions`: object with expected values
|
|
1691
|
-
- **Optional**:
|
|
1692
|
-
- `id`: entity ID (preferred)
|
|
1693
|
-
- `ref`: entity ref (fallback)
|
|
1694
|
-
- `poll`: if `true`, retry until assertions pass or timeout (default `false`)
|
|
1695
|
-
- `timeoutMs`: polling timeout in ms, 1000–300000 (default `60000`)
|
|
1696
|
-
- `intervalMs`: polling interval in ms, 1000–30000 (default `5000`)
|
|
1697
|
-
|
|
1698
|
-
**Assertion types:**
|
|
1699
|
-
|
|
1700
|
-
| Assertion | Description |
|
|
1701
|
-
|---|---|
|
|
1702
|
-
| `status` | Exact match on entity status |
|
|
1703
|
-
| `type` | Exact match on entity type |
|
|
1704
|
-
| `subtype` | Exact match on entity subtype |
|
|
1705
|
-
| `attributes` | Key-value pairs that must be present on the entity |
|
|
1706
|
-
| `edges` | Min/max count and status on related entities (e.g., fulfilments) |
|
|
1707
|
-
|
|
1708
|
-
**Polling mode:** Set `poll: true` to retry assertions on an interval until they pass or the timeout is reached. Useful after sending events when state changes are asynchronous.
|
|
1709
|
-
|
|
1710
|
-
**Example** — assert order is BOOKED with at least 1 fulfilment (polling):
|
|
1711
|
-
|
|
1712
|
-
```json
|
|
1713
|
-
{
|
|
1714
|
-
"entityType": "ORDER",
|
|
1715
|
-
"ref": "HD-001",
|
|
1716
|
-
"assertions": {
|
|
1717
|
-
"status": "BOOKED",
|
|
1718
|
-
"edges": {
|
|
1719
|
-
"fulfilments": { "minCount": 1 }
|
|
1720
|
-
}
|
|
1721
|
-
},
|
|
1722
|
-
"poll": true,
|
|
1723
|
-
"timeoutMs": 60000,
|
|
1724
|
-
"intervalMs": 5000
|
|
1725
|
-
}
|
|
1726
|
-
```
|
|
1727
|
-
|
|
1728
|
-
Response (pass):
|
|
1729
|
-
|
|
1730
|
-
```json
|
|
1731
|
-
{
|
|
1732
|
-
"ok": true,
|
|
1733
|
-
"passed": true,
|
|
1734
|
-
"entityType": "ORDER",
|
|
1735
|
-
"entity": { "id": "12345", "ref": "HD-001", "status": "BOOKED" },
|
|
1736
|
-
"assertions": {
|
|
1737
|
-
"status": { "expected": "BOOKED", "actual": "BOOKED", "passed": true },
|
|
1738
|
-
"edges.fulfilments.minCount": { "expected": 1, "actual": 2, "passed": true }
|
|
1739
|
-
},
|
|
1740
|
-
"polling": { "attempts": 3, "elapsed": 12500 }
|
|
1741
|
-
}
|
|
1742
|
-
```
|
|
1743
|
-
|
|
1744
|
-
Response (fail after timeout):
|
|
1745
|
-
|
|
1746
|
-
```json
|
|
1747
|
-
{
|
|
1748
|
-
"ok": true,
|
|
1749
|
-
"passed": false,
|
|
1750
|
-
"entityType": "ORDER",
|
|
1751
|
-
"entity": { "id": "12345", "ref": "HD-001", "status": "CREATED" },
|
|
1752
|
-
"assertions": {
|
|
1753
|
-
"status": { "expected": "BOOKED", "actual": "CREATED", "passed": false }
|
|
1754
|
-
},
|
|
1755
|
-
"polling": { "attempts": 12, "elapsed": 60000, "timedOut": true },
|
|
1756
|
-
"failureMessage": "Assertion failed: status expected \"BOOKED\" but got \"CREATED\" (timed out after 60000ms)"
|
|
1757
|
-
}
|
|
1758
|
-
```
|
|
1759
|
-
|
|
1760
|
-
---
|
|
1761
|
-
|
|
1762
1117
|
## Retry and idempotency matrix
|
|
1763
1118
|
|
|
1764
1119
|
| Category | Tools | Retry behavior |
|
|
1765
1120
|
|------|----------|-------------|
|
|
1766
|
-
| Read operations | `event.get`, `event.list`, `event.flowInspect`, `metrics.query`, `metrics.healthCheck`, `metrics.sloReport`, `metrics.labelCatalog`, `metrics.topEvents`, `workflow.transitions`, `graphql.query` (query), `graphql.queryAll`, `batch.status`, `batch.batchStatus`, `batch.results`, `graphql.introspect`, `connection.test
|
|
1767
|
-
| Write operations | `event.send`, `batch.create`, `batch.send`, `graphql.query` (mutation), `graphql.batchMutate
|
|
1768
|
-
| Local validation / no API | `config.validate`, `health.ping`, `event.build`, `webhook.validate
|
|
1769
|
-
|
|
1770
|
-
## Tool inventory summary
|
|
1771
|
-
|
|
1772
|
-
| Tool | Category | Requires SDK |
|
|
1773
|
-
|
|
1774
|
-
| `config.validate` |
|
|
1775
|
-
| `health.ping` |
|
|
1776
|
-
| `
|
|
1777
|
-
| `event.
|
|
1778
|
-
| `event.
|
|
1779
|
-
| `event.
|
|
1780
|
-
| `event.
|
|
1781
|
-
| `
|
|
1782
|
-
| `metrics.
|
|
1783
|
-
| `metrics.
|
|
1784
|
-
| `metrics.
|
|
1785
|
-
| `metrics.
|
|
1786
|
-
| `
|
|
1787
|
-
| `
|
|
1788
|
-
| `
|
|
1789
|
-
| `graphql.
|
|
1790
|
-
| `graphql.
|
|
1791
|
-
| `
|
|
1792
|
-
| `
|
|
1793
|
-
| `batch.
|
|
1794
|
-
| `batch.
|
|
1795
|
-
| `batch.
|
|
1796
|
-
| `
|
|
1797
|
-
| `
|
|
1798
|
-
| `webhook.validate` | Webhooks | No |
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
| `entity.get` | Entity | Yes | Yes | Unified entity lookup by ID or ref with optional edge inclusion |
|
|
1802
|
-
| `workflow.upload` | Workflow Mgmt | Yes | No | Deploy workflow JSON via REST API with structure validation |
|
|
1803
|
-
| `workflow.diff` | Workflow Mgmt | No | — | Compare two workflows — rulesets, statuses, risk assessment, mermaid output |
|
|
1804
|
-
| `workflow.simulate` | Workflow Mgmt | No | — | Static prediction of event outcomes from workflow JSON |
|
|
1805
|
-
| `setting.upsert` | Settings | Yes | No | Create or update a setting with upsert semantics |
|
|
1806
|
-
| `setting.bulkUpsert` | Settings | Yes | No | Batch create/update up to 50 settings with per-setting error handling |
|
|
1807
|
-
| `environment.discover` | Environment | Yes | Yes | Full environment snapshot — retailer, locations, networks, catalogues, settings, modules |
|
|
1808
|
-
| `environment.validate` | Environment | Yes | Yes | Pre-flight validation checks: auth, retailer, locations, inventory, workflows |
|
|
1809
|
-
| `test.assert` | Test | Yes | Yes | Assert entity state with status, attribute, and edge assertions + polling mode |
|
|
1121
|
+
| Read operations | `event.get`, `event.list`, `event.flowInspect`, `metrics.query`, `metrics.healthCheck`, `metrics.sloReport`, `metrics.labelCatalog`, `metrics.topEvents`, `workflow.transitions`, `graphql.query` (query), `graphql.queryAll`, `batch.status`, `batch.batchStatus`, `batch.results`, `graphql.introspect`, `connection.test` | retry + backoff |
|
|
1122
|
+
| Write operations | `event.send`, `batch.create`, `batch.send`, `graphql.query` (mutation), `graphql.batchMutate` | timeout-only (no automatic retry) |
|
|
1123
|
+
| Local validation / no API | `config.validate`, `health.ping`, `event.build`, `webhook.validate` | not applicable |
|
|
1124
|
+
|
|
1125
|
+
## Tool inventory summary
|
|
1126
|
+
|
|
1127
|
+
| Tool | Category | Requires SDK | Description |
|
|
1128
|
+
|------|----------|:------------:|-------------|
|
|
1129
|
+
| `config.validate` | Config | No | Validate auth/base URL configuration |
|
|
1130
|
+
| `health.ping` | Config | No | Quick health check with config summary |
|
|
1131
|
+
| `event.build` | Events | No | Build event payload (no API call) |
|
|
1132
|
+
| `event.send` | Events | Yes | Send event (async/sync, supports dryRun) |
|
|
1133
|
+
| `event.get` | Events | Yes | Get single event by ID |
|
|
1134
|
+
| `event.list` | Events | Yes | List/filter events with pagination |
|
|
1135
|
+
| `event.flowInspect` | Events | Yes | One-call root-entity flow forensics (mutations/webhooks/scheduled/exceptions/no-match/rules/snapshots/cross-entity) |
|
|
1136
|
+
| `metrics.query` | Metrics | Yes | Query Prometheus metrics (instant/range) |
|
|
1137
|
+
| `metrics.healthCheck` | Metrics | Yes | One-call anomaly assessment with fallback |
|
|
1138
|
+
| `metrics.sloReport` | Metrics | Yes | SLO snapshot with rates, latency, and threshold findings |
|
|
1139
|
+
| `metrics.labelCatalog` | Metrics | Yes | Label discovery for a metric (live sampling + known hints) |
|
|
1140
|
+
| `metrics.topEvents` | Metrics | Yes | Ranked event analytics using Event API aggregation |
|
|
1141
|
+
| `workflow.transitions` | Workflow | Yes | Query available user actions/transitions at any entity state |
|
|
1142
|
+
| `graphql.query` | GraphQL | Yes | Execute single-page query or mutation |
|
|
1143
|
+
| `graphql.queryAll` | GraphQL | Yes | Auto-paginated query (all records) |
|
|
1144
|
+
| `graphql.batchMutate` | GraphQL | Yes | Multiple aliased mutations in one request |
|
|
1145
|
+
| `graphql.introspect` | GraphQL | Yes | Schema introspection (types, mutations) |
|
|
1146
|
+
| `batch.create` | Batch | Yes | Create ingestion job |
|
|
1147
|
+
| `batch.send` | Batch | Yes | Send records to job |
|
|
1148
|
+
| `batch.status` | Batch | Yes | Check job status |
|
|
1149
|
+
| `batch.batchStatus` | Batch | Yes | Check specific batch status |
|
|
1150
|
+
| `batch.results` | Batch | Yes | Get per-record job outcomes |
|
|
1151
|
+
| `plugin.list` | Orchestration | Yes | List registered rules with optional name filter |
|
|
1152
|
+
| `connection.test` | Diagnostics | Yes | Full connectivity test (user/retailer/location) |
|
|
1153
|
+
| `webhook.validate` | Webhooks | No* | Validate webhook payload + signature |
|
|
1154
|
+
|
|
1155
|
+
\* `webhook.validate` does not call Fluent APIs. Signature validation uses local crypto.
|
|
1810
1156
|
|