@fluentcommerce/fluent-mcp-extn 0.2.0 → 0.3.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 +924 -804
- package/dist/entity-registry.js +1 -0
- package/dist/fluent-client.js +42 -12
- package/dist/settings-tools.js +281 -4
- package/dist/tools.js +65 -7
- package/dist/workflow-tools.js +286 -0
- package/docs/CONTRIBUTING.md +100 -100
- package/docs/E2E_TESTING.md +739 -429
- package/docs/HANDOVER_ENV.example +29 -29
- package/docs/HANDOVER_GITHUB_COPILOT.md +165 -165
- package/docs/RUNBOOK.md +315 -233
- package/docs/TOOL_REFERENCE.md +1923 -1156
- package/package.json +68 -64
package/docs/E2E_TESTING.md
CHANGED
|
@@ -1,429 +1,739 @@
|
|
|
1
|
-
# End-to-End Testing Guide
|
|
2
|
-
|
|
3
|
-
This guide walks through full validation of `fluent-mcp-extn` from startup to
|
|
4
|
-
real Fluent API operations.
|
|
5
|
-
|
|
6
|
-
##
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
##
|
|
24
|
-
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
- `
|
|
28
|
-
|
|
29
|
-
- `
|
|
30
|
-
- `
|
|
31
|
-
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
npm
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
###
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
1
|
+
# End-to-End Testing Guide
|
|
2
|
+
|
|
3
|
+
This guide walks through full validation of `fluent-mcp-extn` from startup to
|
|
4
|
+
real Fluent API operations.
|
|
5
|
+
|
|
6
|
+
## Script inventory
|
|
7
|
+
|
|
8
|
+
| Script | Type | Purpose |
|
|
9
|
+
|--------|------|---------|
|
|
10
|
+
| `e2e-smoke.ts` | E2E | Full MCP smoke cycle: tool discovery, config, health, events, GraphQL |
|
|
11
|
+
| `e2e-negative.ts` | E2E | Validation error and malformed input handling |
|
|
12
|
+
| `e2e-profile-test.mjs` | E2E | Quick FLUENT_PROFILE integration check |
|
|
13
|
+
| `e2e-full-order.ts` | E2E | Single order lifecycle: create, validate, fulfil, ship, deliver |
|
|
14
|
+
| `e2e-full-multi.ts` | E2E | ORDER::MULTI lifecycle with discovery and fulfilment event sequence |
|
|
15
|
+
| `e2e-agentic.ts` | E2E | All 11 agentic tools: entity CRUD, workflow, settings, environment |
|
|
16
|
+
| `e2e-response-shaping.ts` | E2E | Response budget enforcement and auto-summarization proof |
|
|
17
|
+
| `run-flow-inspect.ts` | Utility | FlowInspect forensics with local analysis, LLM packet, and drilldowns |
|
|
18
|
+
| `order-event-inspect.ts` | Utility | Order-specific event deep dive with audit trail extraction |
|
|
19
|
+
| `check-event-status.ts` | Utility | Event status polling by ID, name, or entity ref |
|
|
20
|
+
|
|
21
|
+
All scripts require a built server (`npm run build`) and valid Fluent credentials.
|
|
22
|
+
|
|
23
|
+
## 1) Test levels
|
|
24
|
+
|
|
25
|
+
- **Level 1: local quality gate** (no network)
|
|
26
|
+
- `npm run build`
|
|
27
|
+
- `npm test`
|
|
28
|
+
- **Level 2: MCP runtime check** (server starts, tools load)
|
|
29
|
+
- `config.validate`
|
|
30
|
+
- `health.ping`
|
|
31
|
+
- `connection.test`
|
|
32
|
+
- **Level 3: Fluent API smoke** (real API calls)
|
|
33
|
+
- `event.send` dry-run and real send
|
|
34
|
+
- `event.get` on sent event ID
|
|
35
|
+
- `graphql.query`
|
|
36
|
+
- `graphql.queryAll` (pagination timeout + aggregation)
|
|
37
|
+
- optional batch flow (`batch.create` -> `batch.send` -> `batch.status`)
|
|
38
|
+
- optional webhook verification (`webhook.validate` with `rawBody`)
|
|
39
|
+
|
|
40
|
+
## 2) Prerequisites
|
|
41
|
+
|
|
42
|
+
- valid Fluent sandbox/prod API base URL
|
|
43
|
+
- auth configured using one of:
|
|
44
|
+
- `FLUENT_PROFILE` (optionally `FLUENT_PROFILE_RETAILER`)
|
|
45
|
+
- OAuth env vars
|
|
46
|
+
- `TOKEN_COMMAND`
|
|
47
|
+
- `FLUENT_ACCESS_TOKEN`
|
|
48
|
+
- known retailer ID or retailer ref for your target environment
|
|
49
|
+
|
|
50
|
+
## 3) Configure `.mcp.json`
|
|
51
|
+
|
|
52
|
+
Use this as a baseline:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"mcpServers": {
|
|
57
|
+
"fluent-mcp-extn": {
|
|
58
|
+
"type": "stdio",
|
|
59
|
+
"command": "node",
|
|
60
|
+
"args": ["fluent-mcp-extn/dist/index.js"],
|
|
61
|
+
"env": {
|
|
62
|
+
"FLUENT_BASE_URL": "https://YOUR_ACCOUNT.sandbox.api.fluentretail.com",
|
|
63
|
+
"FLUENT_RETAILER_ID": "YOUR_RETAILER_ID",
|
|
64
|
+
"TOKEN_COMMAND": "vault read -field=token secret/fluent/client-dev",
|
|
65
|
+
"FLUENT_REQUEST_TIMEOUT_MS": "30000",
|
|
66
|
+
"FLUENT_RETRY_ATTEMPTS": "3"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
After editing `.mcp.json`, reload your IDE so MCP servers restart with new env.
|
|
74
|
+
|
|
75
|
+
Profile-first setup via AI Skills:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npx @fluentcommerce/ai-skills mcp-setup --profile YOUR_PROFILE --profile-retailer YOUR_RETAILER_REF
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Then confirm extension env contains:
|
|
82
|
+
|
|
83
|
+
- `FLUENT_PROFILE=YOUR_PROFILE`
|
|
84
|
+
- `FLUENT_PROFILE_RETAILER=YOUR_RETAILER_REF` (retailer **ref**, not ID)
|
|
85
|
+
|
|
86
|
+
## 4) Build and test locally
|
|
87
|
+
|
|
88
|
+
From `fluent-mcp-extn/`:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm install
|
|
92
|
+
npm run build
|
|
93
|
+
npm test
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Expected: build succeeds and all unit tests pass.
|
|
97
|
+
|
|
98
|
+
Optional automated smoke runner:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
npm run e2e:smoke
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
This runs: tool discovery, config validation, health, event build, event dry-run,
|
|
105
|
+
GraphQL checks, order lookup, real event send, and event retrieval by ID.
|
|
106
|
+
|
|
107
|
+
Profile-driven and multi-retailer variants:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
npm run e2e:smoke -- --wizard
|
|
111
|
+
npm run e2e:smoke -- --profile CLIENT_PROFILE
|
|
112
|
+
npm run e2e:smoke -- --profile CLIENT_PROFILE --retailer RETAILER_REF_OR_ID
|
|
113
|
+
npm run e2e:smoke -- --profile CLIENT_PROFILE --all-retailers
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Notes:
|
|
117
|
+
|
|
118
|
+
- `--wizard` guides profile/account + retailer selection in interactive terminals
|
|
119
|
+
- `--wizard` requires an interactive terminal (TTY); for CI/non-interactive runs use explicit flags (`--profile <name> --retailer <id|ref>` or `--profile <name> --all-retailers`)
|
|
120
|
+
- `--profile` reads from `~/.fluentcommerce/<profile>/`
|
|
121
|
+
- profile defaults are applied only when equivalent env vars are missing
|
|
122
|
+
- `--retailer` accepts retailer ID or retailer ref
|
|
123
|
+
- `--all-retailers` runs one full smoke cycle per retailer file in the profile
|
|
124
|
+
- `--skip-real-send` performs dry-run checks only
|
|
125
|
+
- with `--profile` only (no `--retailer` / `--all-retailers`), smoke may fall back to a retailer that has candidate orders for real-send validation; use `--retailer` for strict retailer scope
|
|
126
|
+
|
|
127
|
+
### All-retailers run behavior
|
|
128
|
+
|
|
129
|
+
`--all-retailers` requires `--profile` and executes one smoke cycle per
|
|
130
|
+
`retailer.<ref>.json` file under `~/.fluentcommerce/<profile>/`. Output labels
|
|
131
|
+
use retailer IDs (for example `retailer-5`).
|
|
132
|
+
|
|
133
|
+
When a retailer has no candidate order, order lookup and real send steps are
|
|
134
|
+
reported as skipped for that retailer (not failed). The command exits non-zero
|
|
135
|
+
only when non-skipped steps fail.
|
|
136
|
+
|
|
137
|
+
#### Interpreting results
|
|
138
|
+
|
|
139
|
+
| Status | Meaning | Action |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| `PASS` | Step completed successfully for that retailer. | No action needed. |
|
|
142
|
+
| `SKIP` | Step was intentionally not executed (for example, no candidate order in `--all-retailers` mode). | Verify preconditions only if you expected execution. |
|
|
143
|
+
| `FAIL` | Step executed and returned an error or unexpected result. | Investigate payload/error details and fix before relying on run output. |
|
|
144
|
+
|
|
145
|
+
## 5) E2E script reference
|
|
146
|
+
|
|
147
|
+
### `e2e-smoke.ts`
|
|
148
|
+
|
|
149
|
+
Full MCP client smoke cycle that exercises the core tool chain end to end.
|
|
150
|
+
|
|
151
|
+
**What it tests:** tool discovery, `config.validate`, `health.ping`, `event.build`,
|
|
152
|
+
`event.send` (dry-run and real), `graphql.query`, `graphql.queryAll`, order lookup,
|
|
153
|
+
`event.get` by ID.
|
|
154
|
+
|
|
155
|
+
**How to run:**
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
npm run e2e:smoke
|
|
159
|
+
npm run e2e:smoke -- --profile HMDEV
|
|
160
|
+
npm run e2e:smoke -- --profile HMDEV --retailer HM_TEST
|
|
161
|
+
npm run e2e:smoke -- --profile HMDEV --all-retailers
|
|
162
|
+
npm run e2e:smoke -- --skip-real-send
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**Environment:** requires `FLUENT_BASE_URL` + auth env vars, or `--profile`.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
### `e2e-negative.ts`
|
|
170
|
+
|
|
171
|
+
Validates that the server returns correct error envelopes for invalid inputs.
|
|
172
|
+
|
|
173
|
+
**What it tests:**
|
|
174
|
+
- `event.send` with missing required `entityRef` field
|
|
175
|
+
- `graphql.query` with malformed GraphQL syntax
|
|
176
|
+
- `event.get` with a nonexistent event ID
|
|
177
|
+
- `graphql.introspect` with a nonexistent mutation name
|
|
178
|
+
- `webhook.validate` with an invalid signature and public key
|
|
179
|
+
|
|
180
|
+
Each test case asserts: `ok: false`, standard error envelope shape
|
|
181
|
+
(`code` + `message` + `retryable`), and expected error code where applicable
|
|
182
|
+
(e.g., `VALIDATION_ERROR`).
|
|
183
|
+
|
|
184
|
+
**How to run:**
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
npx tsx scripts/e2e-negative.ts
|
|
188
|
+
npx tsx scripts/e2e-negative.ts --profile HMDEV
|
|
189
|
+
npx tsx scripts/e2e-negative.ts --profile HMDEV --retailer HM_TEST
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**Environment:** requires `FLUENT_BASE_URL` + auth env vars, or `--profile`.
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
### `e2e-profile-test.mjs`
|
|
197
|
+
|
|
198
|
+
Minimal FLUENT_PROFILE integration check. Loads config, creates SDK client, and
|
|
199
|
+
runs four quick API calls to verify profile-based auth works end to end.
|
|
200
|
+
|
|
201
|
+
**What it tests:**
|
|
202
|
+
1. Config loads correctly with profile auth strategy
|
|
203
|
+
2. GraphQL `me` query returns user and retailer info
|
|
204
|
+
3. `getEvents` returns event results
|
|
205
|
+
4. `getPlugins` returns the plugin registry
|
|
206
|
+
5. `getTransitions` returns user actions for ORDER::HD at CREATED status
|
|
207
|
+
|
|
208
|
+
**How to run:**
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
FLUENT_PROFILE=HMDEV FLUENT_PROFILE_RETAILER=HM_TEST node scripts/e2e-profile-test.mjs
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Environment:** requires `FLUENT_PROFILE` and optionally `FLUENT_PROFILE_RETAILER`
|
|
215
|
+
set as env vars. Uses compiled `dist/` output directly (not MCP stdio transport).
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
### `e2e-full-order.ts`
|
|
220
|
+
|
|
221
|
+
Discovery-first single order lifecycle test. Creates an order with
|
|
222
|
+
`sourcingLocationRef`, then drives it through the full fulfilment workflow.
|
|
223
|
+
|
|
224
|
+
**What it tests:**
|
|
225
|
+
1. Config validation
|
|
226
|
+
2. Discovery: locations, catalogues, products, customers, settings
|
|
227
|
+
3. `createOrder` mutation with sourcing attributes
|
|
228
|
+
4. `ConfirmValidation` event on order
|
|
229
|
+
5. Query order + fulfilments post-validation
|
|
230
|
+
6. Fulfilment events: `ConfirmAllocation`, `CreateInvoice`, `ConfirmPick`,
|
|
231
|
+
`ConfirmShipment`, `ConfirmDelivery`
|
|
232
|
+
7. Final order/fulfilment state verification
|
|
233
|
+
8. Event trace: counts SUCCESS vs FAILED events for the order
|
|
234
|
+
|
|
235
|
+
**How to run:**
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
npx tsx scripts/e2e-full-order.ts --profile SAGIRISH --retailer 2
|
|
239
|
+
FLUENT_PROFILE=SAGIRISH FLUENT_RETAILER_ID=2 npx tsx scripts/e2e-full-order.ts
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**Environment:** requires `FLUENT_PROFILE` + `FLUENT_RETAILER_ID`, or `--profile`
|
|
243
|
+
and `--retailer` flags. Environment must have warehouse locations, product
|
|
244
|
+
catalogue with active products, and at least one customer entity.
|
|
245
|
+
|
|
246
|
+
**Note:** this script creates real orders and fires real events. Use a sandbox.
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
### `e2e-full-multi.ts`
|
|
251
|
+
|
|
252
|
+
ORDER::MULTI lifecycle test. Similar to `e2e-full-order.ts` but targets the
|
|
253
|
+
MULTI order type workflow and includes workflow transition discovery.
|
|
254
|
+
|
|
255
|
+
**What it tests:**
|
|
256
|
+
1. Config validation
|
|
257
|
+
2. Discovery: retailer, locations, catalogues, products, customers, settings
|
|
258
|
+
3. `workflow.transitions` for ORDER::MULTI at ON_VALIDATION status
|
|
259
|
+
4. `createOrder` mutation with MULTI type
|
|
260
|
+
5. `ConfirmValidation` event
|
|
261
|
+
6. Fulfilment creation verification
|
|
262
|
+
7. Fulfilment event sequence: `ConfirmAllocation`, `CreateInvoice`,
|
|
263
|
+
`ConfirmPick`, `ConfirmShipment`, `ConfirmDelivery`
|
|
264
|
+
8. Event trace on failure
|
|
265
|
+
|
|
266
|
+
**How to run:**
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
npx tsx scripts/e2e-full-multi.ts
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**Environment:** defaults to `FLUENT_BASE_URL=https://sagirish.test.api.fluentretail.com`
|
|
273
|
+
and `FLUENT_RETAILER_ID=2`. Override with env vars. Requires OAuth or profile
|
|
274
|
+
credentials.
|
|
275
|
+
|
|
276
|
+
**Note:** creates real orders and fires real events. Use a sandbox.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
### `e2e-agentic.ts`
|
|
281
|
+
|
|
282
|
+
Comprehensive smoke test for all 11 agentic tools against a live environment.
|
|
283
|
+
|
|
284
|
+
**What it tests:**
|
|
285
|
+
- `environment.discover` (retailer + locations, catalogues)
|
|
286
|
+
- `environment.validate` (auth, retailer, locations checks)
|
|
287
|
+
- `entity.create` (dryRun validation, required field rejection, live creation)
|
|
288
|
+
- `entity.get` (by ID, by ref, nonexistent ref)
|
|
289
|
+
- `entity.update` (attribute update)
|
|
290
|
+
- `test.assert` (status match, status mismatch)
|
|
291
|
+
- `setting.upsert` (create new, update existing with previous value)
|
|
292
|
+
- `workflow.diff` (summary format, mermaid format)
|
|
293
|
+
- `workflow.simulate` (status matching, custom rule confidence, no-match)
|
|
294
|
+
- `workflow.upload` (dryRun structure validation)
|
|
295
|
+
|
|
296
|
+
**How to run:**
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
npx tsx scripts/e2e-agentic.ts --profile SAGIRISH
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**Environment:** requires `FLUENT_PROFILE` or `--profile` flag. Defaults to
|
|
303
|
+
`FLUENT_RETAILER_ID=2`.
|
|
304
|
+
|
|
305
|
+
**Note:** creates real orders and settings. Use a sandbox.
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
### `e2e-response-shaping.ts`
|
|
310
|
+
|
|
311
|
+
Proves that response shaping (auto-summarization) works correctly on real API
|
|
312
|
+
responses.
|
|
313
|
+
|
|
314
|
+
**What it proves:**
|
|
315
|
+
1. `event.flowInspect` compact response stays within budget (50k chars)
|
|
316
|
+
2. `event.flowInspect` full mode (`compact: false`) gets auto-summarized, not truncated
|
|
317
|
+
3. `plugin.list` (unfiltered, 500+ rules) gets shaped when large
|
|
318
|
+
4. `event.list` (500 events) gets shaped when large
|
|
319
|
+
5. `_responseMeta` appears with accurate stats (originalChars, shapedChars, reductionPercent)
|
|
320
|
+
6. No `_truncated` markers anywhere (replaced by `_summarized`)
|
|
321
|
+
|
|
322
|
+
**How to run:**
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
npx tsx scripts/e2e-response-shaping.ts --profile SAGIRISH
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
**Environment:** requires `FLUENT_PROFILE` or `--profile`. Uses default budget
|
|
329
|
+
(50k chars). The environment must have enough events and plugins to exceed the
|
|
330
|
+
budget threshold.
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
### `run-flow-inspect.ts`
|
|
335
|
+
|
|
336
|
+
Advanced FlowInspect forensics runner. Calls `event.flowInspect`, then performs
|
|
337
|
+
local analysis: risk scoring, finding extraction, evidence ranking, and optional
|
|
338
|
+
per-event drilldowns via `event.get`.
|
|
339
|
+
|
|
340
|
+
**Outputs:**
|
|
341
|
+
- Raw JSON: full flowInspect response
|
|
342
|
+
- Summary JSON: risk score, status/entity distributions, anomaly counts, webhook
|
|
343
|
+
failure breakdown, exception classes, slow rulesets, mismatch reasons
|
|
344
|
+
- LLM packet (Markdown): compact handoff document for AI consumption
|
|
345
|
+
- Drilldown JSON: classified event details (webhook, mutation, sendEvent, mismatch)
|
|
346
|
+
|
|
347
|
+
**How to run:**
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
npx tsx scripts/run-flow-inspect.ts <ROOT_ENTITY_REF> --profile SAGIRISH
|
|
351
|
+
npx tsx scripts/run-flow-inspect.ts HD-001 --root-type ORDER --profile HMDEV
|
|
352
|
+
npx tsx scripts/run-flow-inspect.ts HD-001 --root-id 12345 --light --no-drilldown
|
|
353
|
+
npx tsx scripts/run-flow-inspect.ts HD-001 --drilldown-classes webhook,mutation --drilldown-limit 20
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
**Options:**
|
|
357
|
+
|
|
358
|
+
| Flag | Default | Description |
|
|
359
|
+
|------|---------|-------------|
|
|
360
|
+
| `--profile <name>` | `SAGIRISH` | Fluent CLI profile |
|
|
361
|
+
| `--root-type <type>` | any | Root entity type (ORDER, FULFILMENT, etc.) |
|
|
362
|
+
| `--root-id <id>` | - | Root entity ID for disambiguation |
|
|
363
|
+
| `--out <path>` | `accounts/<profile>/analysis/EVENT_FLOW_INSPECT_<ref>.json` | Raw output path |
|
|
364
|
+
| `--summary-out <path>` | `<base>.summary.json` | Summary output path |
|
|
365
|
+
| `--packet-out <path>` | `<base>.llm-packet.md` | LLM packet output path |
|
|
366
|
+
| `--drilldown-out <path>` | `<base>.drilldown.json` | Drilldown output path |
|
|
367
|
+
| `--light` | false | Compact mode (fewer audit details) |
|
|
368
|
+
| `--no-drilldown` | false | Skip per-event drilldowns |
|
|
369
|
+
| `--drilldown-limit <n>` | 15 | Max events to drill into |
|
|
370
|
+
| `--drilldown-classes <list>` | all | Comma-separated: webhook,mutation,sendEvent,mismatch,exception,scheduled,slow,status |
|
|
371
|
+
| `--top-n <n>` | 10 | Top-N items per section |
|
|
372
|
+
| `--evidence-limit <n>` | 20 | Max evidence event IDs |
|
|
373
|
+
| `--truncate <n>` | 220 | Max chars for text fields |
|
|
374
|
+
| `--max-pages <n>` | 10 | Max 500-event pages to fetch |
|
|
375
|
+
| `--no-llm-pack` | false | Skip LLM packet generation |
|
|
376
|
+
|
|
377
|
+
**Environment:** requires `FLUENT_PROFILE` or env vars.
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
### `order-event-inspect.ts`
|
|
382
|
+
|
|
383
|
+
Order-specific event deep dive. Looks up an order by ref, then fetches all
|
|
384
|
+
ORCHESTRATION and ORCHESTRATION_AUDIT events, classifying them into webhooks,
|
|
385
|
+
mutations, sendEvent actions, scheduled actions, and ruleset durations.
|
|
386
|
+
|
|
387
|
+
**Outputs:** a single JSON file with:
|
|
388
|
+
- Order entity details (status, attributes, fulfilment choices)
|
|
389
|
+
- Orchestration events (status counts, entity type counts, top event names)
|
|
390
|
+
- Audit trail (webhook actions, mutation actions, sendEvent actions, scheduled
|
|
391
|
+
actions, ruleset durations, exceptions)
|
|
392
|
+
- Drilldown details for NO_MATCH and PENDING events
|
|
393
|
+
|
|
394
|
+
**How to run:**
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
npx tsx scripts/order-event-inspect.ts <ORDER_REF> --profile SAGIRISH
|
|
398
|
+
npx tsx scripts/order-event-inspect.ts HD-001 --profile HMDEV --out /tmp/inspect.json
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
**Environment:** requires `FLUENT_PROFILE` or env vars.
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
### `check-event-status.ts`
|
|
406
|
+
|
|
407
|
+
Lightweight event status checker. Fetches events by ID or lists events by name
|
|
408
|
+
and entity ref.
|
|
409
|
+
|
|
410
|
+
**How to run:**
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
# Fetch specific events by ID
|
|
414
|
+
npx tsx scripts/check-event-status.ts --event-id <uuid> --profile SAGIRISH
|
|
415
|
+
|
|
416
|
+
# List events by name
|
|
417
|
+
npx tsx scripts/check-event-status.ts --event-name ConfirmValidation --profile SAGIRISH
|
|
418
|
+
|
|
419
|
+
# List events by entity ref
|
|
420
|
+
npx tsx scripts/check-event-status.ts --entity-ref HD-001 --profile SAGIRISH
|
|
421
|
+
|
|
422
|
+
# Combine filters
|
|
423
|
+
npx tsx scripts/check-event-status.ts --event-name ConfirmValidation --entity-ref HD-001 --count 20 --profile SAGIRISH
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
**Options:**
|
|
427
|
+
|
|
428
|
+
| Flag | Default | Description |
|
|
429
|
+
|------|---------|-------------|
|
|
430
|
+
| `--profile <name>` | - | Fluent CLI profile |
|
|
431
|
+
| `--retailer <id\|ref>` | from profile/env | Retailer filter |
|
|
432
|
+
| `--event-id <uuid>` | - | Fetch specific event (repeatable) |
|
|
433
|
+
| `--event-name <name>` | - | Event name filter for list |
|
|
434
|
+
| `--entity-ref <ref>` | - | Entity ref filter for list |
|
|
435
|
+
| `--count <n>` | 10 | Max list size (max 500) |
|
|
436
|
+
|
|
437
|
+
**Environment:** requires `FLUENT_BASE_URL` + auth, or `--profile`.
|
|
438
|
+
|
|
439
|
+
## 6) MCP smoke sequence in your IDE
|
|
440
|
+
|
|
441
|
+
Run these tools in order from the assistant:
|
|
442
|
+
|
|
443
|
+
### Step 1: `config.validate`
|
|
444
|
+
|
|
445
|
+
Request:
|
|
446
|
+
|
|
447
|
+
```json
|
|
448
|
+
{}
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
Expected:
|
|
452
|
+
|
|
453
|
+
- `ok: true`
|
|
454
|
+
- `validation.isReadyForApiCalls: true`
|
|
455
|
+
- no blocking errors
|
|
456
|
+
|
|
457
|
+
### Step 2: `health.ping`
|
|
458
|
+
|
|
459
|
+
Request:
|
|
460
|
+
|
|
461
|
+
```json
|
|
462
|
+
{}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
Expected:
|
|
466
|
+
|
|
467
|
+
- `status: "ok"`
|
|
468
|
+
- `sdkClient: "connected"` (or equivalent ready status)
|
|
469
|
+
- config summary present without secret values
|
|
470
|
+
|
|
471
|
+
### Step 3: `connection.test`
|
|
472
|
+
|
|
473
|
+
Request:
|
|
474
|
+
|
|
475
|
+
```json
|
|
476
|
+
{}
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
Expected:
|
|
480
|
+
|
|
481
|
+
- `ok: true`
|
|
482
|
+
- `details` includes user, retailer, and location info
|
|
483
|
+
- confirms end-to-end GraphQL connectivity
|
|
484
|
+
|
|
485
|
+
### Step 4: `event.build`
|
|
486
|
+
|
|
487
|
+
Request:
|
|
488
|
+
|
|
489
|
+
```json
|
|
490
|
+
{
|
|
491
|
+
"name": "ORDER_CREATED",
|
|
492
|
+
"entityRef": "E2E-ORDER-1001",
|
|
493
|
+
"entityType": "ORDER",
|
|
494
|
+
"attributes": {
|
|
495
|
+
"sourceSystem": "e2e-test",
|
|
496
|
+
"testRunId": "run-001"
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
Expected:
|
|
502
|
+
|
|
503
|
+
- `ok: true`
|
|
504
|
+
- complete event payload returned
|
|
505
|
+
- defaults applied (`rootEntityType`, `source`, `type`)
|
|
506
|
+
|
|
507
|
+
### Step 5: `event.send` dry-run
|
|
508
|
+
|
|
509
|
+
Request:
|
|
510
|
+
|
|
511
|
+
```json
|
|
512
|
+
{
|
|
513
|
+
"name": "ORDER_CREATED",
|
|
514
|
+
"entityRef": "E2E-ORDER-1001",
|
|
515
|
+
"entityId": "12345",
|
|
516
|
+
"entityType": "ORDER",
|
|
517
|
+
"dryRun": true
|
|
518
|
+
}
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
Expected:
|
|
522
|
+
|
|
523
|
+
- `ok: true`
|
|
524
|
+
- `dryRun: true`
|
|
525
|
+
- no API call made
|
|
526
|
+
|
|
527
|
+
### Step 6: `event.send` real call
|
|
528
|
+
|
|
529
|
+
Request:
|
|
530
|
+
|
|
531
|
+
```json
|
|
532
|
+
{
|
|
533
|
+
"name": "ORDER_CREATED",
|
|
534
|
+
"entityRef": "E2E-ORDER-1001",
|
|
535
|
+
"entityId": "12345",
|
|
536
|
+
"entityType": "ORDER",
|
|
537
|
+
"retailerId": "YOUR_ENTITY_RETAILER_ID",
|
|
538
|
+
"mode": "async",
|
|
539
|
+
"dryRun": false,
|
|
540
|
+
"attributes": {
|
|
541
|
+
"sourceSystem": "e2e-test",
|
|
542
|
+
"testRunId": "run-001"
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
Expected:
|
|
548
|
+
|
|
549
|
+
- `ok: true`
|
|
550
|
+
- response from Fluent event API
|
|
551
|
+
- retailer ID in payload matches the entity's retailer
|
|
552
|
+
- operation executed once (write tools do not auto-retry)
|
|
553
|
+
|
|
554
|
+
If this fails, investigate before resubmitting to avoid duplicate side effects.
|
|
555
|
+
|
|
556
|
+
### Step 7: `graphql.query` verification
|
|
557
|
+
|
|
558
|
+
Use a query valid for your schema. Example shape:
|
|
559
|
+
|
|
560
|
+
```json
|
|
561
|
+
{
|
|
562
|
+
"query": "query VerifyOrder($ref: String!) { orders(ref: $ref) { edges { node { id ref status } } } }",
|
|
563
|
+
"variables": {
|
|
564
|
+
"ref": "E2E-ORDER-1001"
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
Expected:
|
|
570
|
+
|
|
571
|
+
- `ok: true`
|
|
572
|
+
- Fluent GraphQL response payload returned
|
|
573
|
+
|
|
574
|
+
> Note: exact query fields differ by tenant schema/version.
|
|
575
|
+
|
|
576
|
+
### Step 8: `graphql.queryAll` verification
|
|
577
|
+
|
|
578
|
+
Validate auto-pagination and run-level timeout behavior:
|
|
579
|
+
|
|
580
|
+
```json
|
|
581
|
+
{
|
|
582
|
+
"query": "query($cursor: String) { orders(first: 50, after: $cursor) { edges { cursor node { id ref } } pageInfo { hasNextPage } } }",
|
|
583
|
+
"variables": { "cursor": null },
|
|
584
|
+
"timeoutMs": 120000
|
|
585
|
+
}
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
Expected:
|
|
589
|
+
|
|
590
|
+
- `ok: true`
|
|
591
|
+
- `response.extensions.autoPagination` present
|
|
592
|
+
- `pagination.totalPages` / `pagination.totalRecords` present in tool response
|
|
593
|
+
|
|
594
|
+
### Step 9: `event.get` verification
|
|
595
|
+
|
|
596
|
+
Use an event ID from successful `event.send` (or resolve ID via `event.list`).
|
|
597
|
+
|
|
598
|
+
```json
|
|
599
|
+
{
|
|
600
|
+
"eventId": "EVENT_ID_FROM_SEND_RESPONSE"
|
|
601
|
+
}
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
Expected:
|
|
605
|
+
|
|
606
|
+
- `ok: true`
|
|
607
|
+
- event payload returned from Event API
|
|
608
|
+
- event payload includes expected `name`, `context.entityRef`, and retailer
|
|
609
|
+
|
|
610
|
+
If `event.send` response does not contain `id`, resolve it first with `event.list`:
|
|
611
|
+
|
|
612
|
+
```json
|
|
613
|
+
{
|
|
614
|
+
"name": "ORDER_CREATED",
|
|
615
|
+
"entityRef": "E2E-ORDER-1001",
|
|
616
|
+
"retailerId": "YOUR_ENTITY_RETAILER_ID",
|
|
617
|
+
"count": 1,
|
|
618
|
+
"start": 1
|
|
619
|
+
}
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
### Step 10 (optional): `graphql.introspect`
|
|
623
|
+
|
|
624
|
+
Verify schema introspection access:
|
|
625
|
+
|
|
626
|
+
```json
|
|
627
|
+
{
|
|
628
|
+
"listMutations": true
|
|
629
|
+
}
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
Expected:
|
|
633
|
+
|
|
634
|
+
- `ok: true`
|
|
635
|
+
- `mutations` array returned
|
|
636
|
+
- `count` reflects available mutations in the schema
|
|
637
|
+
|
|
638
|
+
## 7) Optional webhook signature validation
|
|
639
|
+
|
|
640
|
+
Use this when validating webhook integration cryptography:
|
|
641
|
+
|
|
642
|
+
```json
|
|
643
|
+
{
|
|
644
|
+
"payload": {
|
|
645
|
+
"name": "OrderCreated",
|
|
646
|
+
"id": "event-123",
|
|
647
|
+
"retailerId": "5"
|
|
648
|
+
},
|
|
649
|
+
"rawBody": "{\"name\":\"OrderCreated\",\"id\":\"event-123\",\"retailerId\":\"5\"}",
|
|
650
|
+
"signature": "base64-encoded-signature-from-header",
|
|
651
|
+
"publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBI...\n-----END PUBLIC KEY-----"
|
|
652
|
+
}
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
Expected:
|
|
656
|
+
|
|
657
|
+
- `ok: true` when payload and signature are valid
|
|
658
|
+
- `signatureValidation.payloadSource` confirms whether `rawBody` was used
|
|
659
|
+
|
|
660
|
+
## 8) Optional batch E2E
|
|
661
|
+
|
|
662
|
+
### `batch.create`
|
|
663
|
+
|
|
664
|
+
```json
|
|
665
|
+
{
|
|
666
|
+
"name": "e2e-batch-001",
|
|
667
|
+
"entityType": "INVENTORY_POSITION",
|
|
668
|
+
"action": "UPSERT"
|
|
669
|
+
}
|
|
670
|
+
```
|
|
671
|
+
|
|
672
|
+
### `batch.send`
|
|
673
|
+
|
|
674
|
+
```json
|
|
675
|
+
{
|
|
676
|
+
"jobId": "JOB_ID_FROM_CREATE",
|
|
677
|
+
"payload": {
|
|
678
|
+
"action": "UPSERT",
|
|
679
|
+
"entityType": "INVENTORY_POSITION",
|
|
680
|
+
"entities": [
|
|
681
|
+
{
|
|
682
|
+
"locationRef": "LOC-1",
|
|
683
|
+
"skuRef": "SKU-1",
|
|
684
|
+
"qty": 10,
|
|
685
|
+
"type": "LAST_ON_HAND",
|
|
686
|
+
"status": "ACTIVE"
|
|
687
|
+
}
|
|
688
|
+
]
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
### `batch.status`
|
|
694
|
+
|
|
695
|
+
```json
|
|
696
|
+
{
|
|
697
|
+
"jobId": "JOB_ID_FROM_CREATE"
|
|
698
|
+
}
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
## 9) Failure triage quick map
|
|
702
|
+
|
|
703
|
+
- `CONFIG_ERROR`: missing env values -> run `config.validate`
|
|
704
|
+
- `AUTH_ERROR`: invalid creds/token -> verify OAuth or `TOKEN_COMMAND`
|
|
705
|
+
- `VALIDATION_ERROR`: invalid input shape -> fix request payload
|
|
706
|
+
- `TIMEOUT_ERROR` / `NETWORK_ERROR`: tune timeout/retry; verify connectivity
|
|
707
|
+
- `RATE_LIMIT` / `UPSTREAM_UNAVAILABLE`: retry later (built-in retries are applied for read operations; write retries are manual by design)
|
|
708
|
+
|
|
709
|
+
## 10) Exit criteria for successful E2E
|
|
710
|
+
|
|
711
|
+
Mark E2E successful only when:
|
|
712
|
+
|
|
713
|
+
- local build/test passed
|
|
714
|
+
- config/health/connection tools are green
|
|
715
|
+
- at least one real `event.send` succeeded
|
|
716
|
+
- at least one `event.get` succeeded
|
|
717
|
+
- at least one real `graphql.query` succeeded
|
|
718
|
+
- at least one `graphql.queryAll` run succeeded
|
|
719
|
+
- (optional) `graphql.introspect` schema access confirmed
|
|
720
|
+
- (optional) batch cycle completed
|
|
721
|
+
|
|
722
|
+
## 11) CI-triggered smoke (GitHub Actions)
|
|
723
|
+
|
|
724
|
+
Workflow: `.github/workflows/ci.yml`
|
|
725
|
+
|
|
726
|
+
- `build-and-test`: runs on push and pull request
|
|
727
|
+
- `e2e-smoke`: runs on `workflow_dispatch` only
|
|
728
|
+
|
|
729
|
+
Set repository or environment secrets before running `e2e-smoke`:
|
|
730
|
+
|
|
731
|
+
- `FLUENT_BASE_URL`
|
|
732
|
+
- `FLUENT_RETAILER_ID` (optional but recommended)
|
|
733
|
+
- `FLUENT_CLIENT_ID`
|
|
734
|
+
- `FLUENT_CLIENT_SECRET`
|
|
735
|
+
- `FLUENT_USERNAME` (optional for client-credentials flow)
|
|
736
|
+
- `FLUENT_PASSWORD` (optional for client-credentials flow)
|
|
737
|
+
|
|
738
|
+
CI smoke runs are typically env-driven (no `--profile` required). For profile-based runs in CI, pass explicit flags (`--profile <name> --retailer <id|ref>` or `--profile <name> --all-retailers`).
|
|
739
|
+
If real event side effects are not desired, run with `--skip-real-send`.
|