@almadar/std 16.216.0 → 16.218.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.
@@ -0,0 +1,1164 @@
1
+ {
2
+ "description": "std-data-import — staged CSV import run, source-agnostic: upload → staged review → confirm → handoff. UPLOAD_CSV opens a run and persists an ImportBatch row (status uploaded, fieldMappingJson recorded verbatim for provenance); the host's file UI parses the CSV and answers with STAGE_ROWS, one JSON string per raw row, which the atom bulk-persists into import_rows against the batch id and presents as a staged review (row/error counts + Confirm/Discard). CONFIRM_IMPORT marks the batch confirmed and emits IMPORT_CONFIRMED { batchId, sourceName, rowCount } — the mapping+persist half is the CONSUMER organism's: it listens for IMPORT_CONFIRMED, fetches import_rows where batchId matches, maps each rowJson through its own field mapping, and persists into its own target entity (cross-atom persist into a consumer's entity is not expressible from here). This is deliberately the CSV-file path: the atom never calls a source service — sourceName/fieldMappingJson/targetEntity/historyWindowDays are declarative consumer configs, and any persist failure marks the batch row failed and fires IMPORT_FAILED, never a silent swallow. Compose with std-import for the file-picker menu.",
3
+ "ledger": {
4
+ "entries": {
5
+ "ent_01M2HEYJ1VH5AKFRTFBSJVKWA9": {
6
+ "bakedName": "ImportRow",
7
+ "curName": "ImportRow",
8
+ "id": "ent_01M2HEYJ1VH5AKFRTFBSJVKWA9",
9
+ "kind": "entity",
10
+ "owner": "workspace",
11
+ "renames": []
12
+ },
13
+ "ent_01M2HEYJ1VN5P0D51DQB7RZCQV": {
14
+ "bakedName": "ImportBatch",
15
+ "curName": "ImportBatch",
16
+ "id": "ent_01M2HEYJ1VN5P0D51DQB7RZCQV",
17
+ "kind": "entity",
18
+ "owner": "workspace",
19
+ "renames": []
20
+ },
21
+ "evt_01M2HEYJ1V0BPHK9H0QHNNT4EF": {
22
+ "bakedName": "STAGE_ROWS",
23
+ "curName": "STAGE_ROWS",
24
+ "id": "evt_01M2HEYJ1V0BPHK9H0QHNNT4EF",
25
+ "kind": "event",
26
+ "owner": "workspace",
27
+ "parent": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
28
+ "renames": []
29
+ },
30
+ "evt_01M2HEYJ1V2E7BSYFFZDPQB5DM": {
31
+ "bakedName": "UPLOAD_CSV",
32
+ "curName": "UPLOAD_CSV",
33
+ "id": "evt_01M2HEYJ1V2E7BSYFFZDPQB5DM",
34
+ "kind": "event",
35
+ "owner": "workspace",
36
+ "parent": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
37
+ "renames": []
38
+ },
39
+ "evt_01M2HEYJ1V49JVADDCP4KX22XW": {
40
+ "bakedName": "DISCARD_IMPORT",
41
+ "curName": "DISCARD_IMPORT",
42
+ "id": "evt_01M2HEYJ1V49JVADDCP4KX22XW",
43
+ "kind": "event",
44
+ "owner": "workspace",
45
+ "parent": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
46
+ "renames": []
47
+ },
48
+ "evt_01M2HEYJ1V5JDXEXMVDAF0PVPZ": {
49
+ "bakedName": "BATCH_CREATED",
50
+ "curName": "BATCH_CREATED",
51
+ "id": "evt_01M2HEYJ1V5JDXEXMVDAF0PVPZ",
52
+ "kind": "event",
53
+ "owner": "workspace",
54
+ "parent": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
55
+ "renames": []
56
+ },
57
+ "evt_01M2HEYJ1V7M6C8DP88H0Z23F1": {
58
+ "bakedName": "IMPORT_PERSIST_FAILED",
59
+ "curName": "IMPORT_PERSIST_FAILED",
60
+ "id": "evt_01M2HEYJ1V7M6C8DP88H0Z23F1",
61
+ "kind": "event",
62
+ "owner": "workspace",
63
+ "parent": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
64
+ "renames": []
65
+ },
66
+ "evt_01M2HEYJ1VBJXS0KEXTX9QWJM5": {
67
+ "bakedName": "CONFIRM_IMPORT",
68
+ "curName": "CONFIRM_IMPORT",
69
+ "id": "evt_01M2HEYJ1VBJXS0KEXTX9QWJM5",
70
+ "kind": "event",
71
+ "owner": "workspace",
72
+ "parent": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
73
+ "renames": []
74
+ },
75
+ "evt_01M2HEYJ1VEEH4DZZ4ETPGP44F": {
76
+ "bakedName": "RESET",
77
+ "curName": "RESET",
78
+ "id": "evt_01M2HEYJ1VEEH4DZZ4ETPGP44F",
79
+ "kind": "event",
80
+ "owner": "workspace",
81
+ "parent": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
82
+ "renames": []
83
+ },
84
+ "evt_01M2HEYJ1VK7JZCK3V8PB795PZ": {
85
+ "bakedName": "ROWS_STAGED",
86
+ "curName": "ROWS_STAGED",
87
+ "id": "evt_01M2HEYJ1VK7JZCK3V8PB795PZ",
88
+ "kind": "event",
89
+ "owner": "workspace",
90
+ "parent": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
91
+ "renames": []
92
+ },
93
+ "evt_01M2HEYJ1VPB25TA0Y6J782QHJ": {
94
+ "bakedName": "INIT",
95
+ "curName": "INIT",
96
+ "id": "evt_01M2HEYJ1VPB25TA0Y6J782QHJ",
97
+ "kind": "event",
98
+ "owner": "workspace",
99
+ "parent": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
100
+ "renames": []
101
+ },
102
+ "evt_01M2HEYJ1VS7SGS9STXQGS2V2J": {
103
+ "bakedName": "IMPORT_CONFIRMED",
104
+ "curName": "IMPORT_CONFIRMED",
105
+ "id": "evt_01M2HEYJ1VS7SGS9STXQGS2V2J",
106
+ "kind": "event",
107
+ "owner": "workspace",
108
+ "parent": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
109
+ "renames": []
110
+ },
111
+ "evt_01M2HEYJ1VWSGJ1ZZXZSZ4Q023": {
112
+ "bakedName": "IMPORT_FAILED",
113
+ "curName": "IMPORT_FAILED",
114
+ "id": "evt_01M2HEYJ1VWSGJ1ZZXZSZ4Q023",
115
+ "kind": "event",
116
+ "owner": "workspace",
117
+ "parent": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
118
+ "renames": []
119
+ },
120
+ "orb_01M2HEYJ1VYFXY2G37WFB431EY": {
121
+ "bakedName": "DataImportOrbital",
122
+ "curName": "DataImportOrbital",
123
+ "id": "orb_01M2HEYJ1VYFXY2G37WFB431EY",
124
+ "kind": "orbital",
125
+ "owner": "workspace",
126
+ "renames": []
127
+ },
128
+ "pag_01M2HEYJ1VCJTSRFZHKYWK5FDE": {
129
+ "bakedName": "DataImportPage",
130
+ "curName": "DataImportPage",
131
+ "id": "pag_01M2HEYJ1VCJTSRFZHKYWK5FDE",
132
+ "kind": "page",
133
+ "owner": "workspace",
134
+ "renames": []
135
+ },
136
+ "trt_01M2HEYJ1V70M3EEV69G6ZRGF9": {
137
+ "bakedName": "DataImportLifecycle",
138
+ "curName": "DataImportLifecycle",
139
+ "id": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
140
+ "kind": "trait",
141
+ "owner": "workspace",
142
+ "renames": []
143
+ }
144
+ },
145
+ "schemaVersion": 1
146
+ },
147
+ "name": "std-data-import",
148
+ "orbitals": [
149
+ {
150
+ "auxiliaryEntities": [
151
+ {
152
+ "collection": "import_rows",
153
+ "fields": [
154
+ {
155
+ "name": "id",
156
+ "required": true,
157
+ "type": "string"
158
+ },
159
+ {
160
+ "default": "",
161
+ "description": "ImportBatch id this staged row belongs to.",
162
+ "name": "batchId",
163
+ "synonyms": "batch, import run, parent batch",
164
+ "type": "string"
165
+ },
166
+ {
167
+ "default": "{}",
168
+ "description": "The raw parsed CSV row as a JSON string (source shape, pre-mapping). The consumer maps it into its own entity shape after confirm.",
169
+ "name": "rowJson",
170
+ "synonyms": "row, raw row, staged row, record json",
171
+ "type": "string"
172
+ },
173
+ {
174
+ "default": "staged",
175
+ "description": "staged = awaiting confirm; imported = the consumer persisted it into the target entity; failed = rejected.",
176
+ "name": "status",
177
+ "type": "string",
178
+ "values": [
179
+ "staged",
180
+ "imported",
181
+ "failed"
182
+ ]
183
+ }
184
+ ],
185
+ "id": "ent_01M2HEYJ1VH5AKFRTFBSJVKWA9",
186
+ "name": "ImportRow",
187
+ "persistence": "persistent"
188
+ }
189
+ ],
190
+ "entity": {
191
+ "collection": "import_batches",
192
+ "fields": [
193
+ {
194
+ "name": "id",
195
+ "required": true,
196
+ "type": "string"
197
+ },
198
+ {
199
+ "default": "",
200
+ "description": "Free-form name of the upstream source this run imported from.",
201
+ "name": "sourceName",
202
+ "synonyms": "source, origin, provider name",
203
+ "type": "string"
204
+ },
205
+ {
206
+ "default": "uploaded",
207
+ "description": "Lifecycle position of the import run.",
208
+ "name": "status",
209
+ "type": "string",
210
+ "values": [
211
+ "uploaded",
212
+ "staged",
213
+ "confirmed",
214
+ "failed"
215
+ ]
216
+ },
217
+ {
218
+ "default": 0.0,
219
+ "description": "Number of rows staged for review.",
220
+ "name": "rowCount",
221
+ "synonyms": "rows, staged count, record count",
222
+ "type": "number"
223
+ },
224
+ {
225
+ "default": 0.0,
226
+ "description": "Number of rows the host parser flagged with errors during staging.",
227
+ "name": "errorCount",
228
+ "synonyms": "errors, failed rows, parse errors",
229
+ "type": "number"
230
+ },
231
+ {
232
+ "default": "{}",
233
+ "description": "Source-column → target-field mapping (JSON string), recorded verbatim from config for provenance; the consumer's mapping layer applies it.",
234
+ "name": "mappingJson",
235
+ "synonyms": "field mapping, column mapping, mapping",
236
+ "type": "string"
237
+ },
238
+ {
239
+ "default": 0.0,
240
+ "description": "Run start timestamp.",
241
+ "name": "createdAt",
242
+ "type": "number"
243
+ }
244
+ ],
245
+ "id": "ent_01M2HEYJ1VN5P0D51DQB7RZCQV",
246
+ "name": "ImportBatch",
247
+ "persistence": "persistent"
248
+ },
249
+ "id": "orb_01M2HEYJ1VYFXY2G37WFB431EY",
250
+ "name": "DataImportOrbital",
251
+ "pages": [
252
+ {
253
+ "id": "pag_01M2HEYJ1VCJTSRFZHKYWK5FDE",
254
+ "name": "DataImportPage",
255
+ "path": "/data-import",
256
+ "traits": [
257
+ {
258
+ "ref": "DataImportLifecycle",
259
+ "refId": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9"
260
+ }
261
+ ]
262
+ }
263
+ ],
264
+ "traits": [
265
+ {
266
+ "capabilities": [
267
+ "import"
268
+ ],
269
+ "category": "lifecycle",
270
+ "config": {
271
+ "fieldMappingJson": {
272
+ "default": "{}",
273
+ "description": "JSON object mapping source CSV column names to target field names. Stored verbatim on the batch row (mappingJson) so the consumer's mapping layer applies the same mapping when it persists staged rows into the target entity.",
274
+ "label": "Field mapping (JSON)",
275
+ "synonyms": "field mapping, column mapping, map columns, remap fields, csv columns",
276
+ "tier": "domain",
277
+ "type": "string"
278
+ },
279
+ "historyWindowDays": {
280
+ "default": 0.0,
281
+ "description": "How many days back an import may reach (0 = unbounded). A declared import-config knob for the consumer's staging/mapping layer — the atom stages whatever rows it is handed and never filters by date.",
282
+ "label": "Historical data range (days)",
283
+ "synonyms": "history window, historical range, import range, days back, lookback period",
284
+ "tier": "policy",
285
+ "type": "number"
286
+ },
287
+ "sourceName": {
288
+ "default": "",
289
+ "description": "Free-form name of the upstream source this import pulls from — whatever tool or file export the user names. Recorded on the batch row for provenance and echoed on IMPORT_CONFIRMED.",
290
+ "label": "Source name",
291
+ "synonyms": "source, origin, import from, provider name, data source",
292
+ "tier": "domain",
293
+ "type": "string"
294
+ },
295
+ "targetEntity": {
296
+ "default": "",
297
+ "description": "Name of the consumer organism's entity the staged rows land in after confirm. Declarative contract only — the atom never writes the target entity; the consumer persists on IMPORT_CONFIRMED.",
298
+ "label": "Target entity",
299
+ "synonyms": "destination, import into, target type",
300
+ "tier": "domain",
301
+ "type": "string"
302
+ }
303
+ },
304
+ "effectRow": [
305
+ {
306
+ "kind": "emit",
307
+ "resource": "IMPORT_CONFIRMED"
308
+ },
309
+ {
310
+ "kind": "emit",
311
+ "resource": "IMPORT_FAILED"
312
+ },
313
+ {
314
+ "kind": "persist",
315
+ "resource": "ImportBatch"
316
+ },
317
+ {
318
+ "kind": "persist",
319
+ "resource": "ImportRow"
320
+ },
321
+ {
322
+ "kind": "render-ui",
323
+ "resource": "main"
324
+ },
325
+ {
326
+ "kind": "set",
327
+ "resource": "@entity.createdAt"
328
+ },
329
+ {
330
+ "kind": "set",
331
+ "resource": "@entity.errorCount"
332
+ },
333
+ {
334
+ "kind": "set",
335
+ "resource": "@entity.id"
336
+ },
337
+ {
338
+ "kind": "set",
339
+ "resource": "@entity.mappingJson"
340
+ },
341
+ {
342
+ "kind": "set",
343
+ "resource": "@entity.rowCount"
344
+ },
345
+ {
346
+ "kind": "set",
347
+ "resource": "@entity.sourceName"
348
+ },
349
+ {
350
+ "kind": "set",
351
+ "resource": "@entity.status"
352
+ }
353
+ ],
354
+ "emits": [
355
+ {
356
+ "description": "import_batches persist-create success — rebinds @entity.id to the server-issued id, the fallback for when the host didn't mint a client-side batchId on UPLOAD_CSV",
357
+ "event": "BATCH_CREATED",
358
+ "eventId": "evt_01M2HEYJ1V5JDXEXMVDAF0PVPZ",
359
+ "payloadSchema": [
360
+ {
361
+ "name": "id",
362
+ "required": true,
363
+ "type": "string"
364
+ }
365
+ ],
366
+ "tier": "secondary"
367
+ },
368
+ {
369
+ "description": "import_rows bulk persist-create success signal — payload carries the persisted rows flat; the atom never reads it (self-loop only)",
370
+ "event": "ROWS_STAGED",
371
+ "eventId": "evt_01M2HEYJ1VK7JZCK3V8PB795PZ",
372
+ "tier": "secondary"
373
+ },
374
+ {
375
+ "description": "Any import_batches / import_rows persist failure — the batch row is updated to failed and IMPORT_FAILED emitted, never a silent swallow; the trait stays put so the user can retry or discard",
376
+ "event": "IMPORT_PERSIST_FAILED",
377
+ "eventId": "evt_01M2HEYJ1V7M6C8DP88H0Z23F1",
378
+ "payloadSchema": [
379
+ {
380
+ "name": "error",
381
+ "required": true,
382
+ "type": "string"
383
+ }
384
+ ],
385
+ "tier": "secondary"
386
+ },
387
+ {
388
+ "description": "The user confirmed the staged review and the batch row is persisted as confirmed. Consumers listen, fetch import_rows where batchId matches, map each rowJson through their field mapping, and persist into their own target entity.",
389
+ "event": "IMPORT_CONFIRMED",
390
+ "eventId": "evt_01M2HEYJ1VS7SGS9STXQGS2V2J",
391
+ "payloadSchema": [
392
+ {
393
+ "name": "batchId",
394
+ "required": true,
395
+ "type": "string"
396
+ },
397
+ {
398
+ "name": "sourceName",
399
+ "type": "string"
400
+ },
401
+ {
402
+ "name": "rowCount",
403
+ "type": "number"
404
+ }
405
+ ],
406
+ "scope": "external",
407
+ "synonyms": "import confirmed, commit import, accept staged rows, approve import",
408
+ "tier": "domain"
409
+ },
410
+ {
411
+ "description": "The run failed (persist failure or empty staging); error carries the detail and the batch row was updated to failed",
412
+ "event": "IMPORT_FAILED",
413
+ "eventId": "evt_01M2HEYJ1VWSGJ1ZZXZSZ4Q023",
414
+ "payloadSchema": [
415
+ {
416
+ "name": "batchId",
417
+ "type": "string"
418
+ },
419
+ {
420
+ "name": "error",
421
+ "required": true,
422
+ "type": "string"
423
+ }
424
+ ],
425
+ "scope": "external",
426
+ "synonyms": "import failed, upload failed, staging failed",
427
+ "tier": "domain"
428
+ }
429
+ ],
430
+ "entityContract": {
431
+ "provides": [
432
+ "errorCount",
433
+ "mappingJson",
434
+ "rowCount",
435
+ "sourceName",
436
+ "status"
437
+ ],
438
+ "requires": []
439
+ },
440
+ "entityRebindable": true,
441
+ "entityRefIds": {
442
+ "ImportBatch": "ent_01M2HEYJ1VN5P0D51DQB7RZCQV",
443
+ "ImportRow": "ent_01M2HEYJ1VH5AKFRTFBSJVKWA9"
444
+ },
445
+ "id": "trt_01M2HEYJ1V70M3EEV69G6ZRGF9",
446
+ "linkedEntity": "ImportBatch",
447
+ "linkedEntityId": "ent_01M2HEYJ1VN5P0D51DQB7RZCQV",
448
+ "name": "DataImportLifecycle",
449
+ "scope": "instance",
450
+ "stateMachine": {
451
+ "events": [
452
+ {
453
+ "id": "evt_01M2HEYJ1VPB25TA0Y6J782QHJ",
454
+ "key": "INIT",
455
+ "name": "Initialize"
456
+ },
457
+ {
458
+ "description": "Starts an import run for a CSV file upload. batchId is the client-minted batch id (idempotent upload — the host generates it so a retry never double-creates a batch); when omitted, the server-issued id is bound on BATCH_CREATED instead. The host's file UI (e.g. a sibling std-import menu) only announces the upload — parsing is host work and arrives as STAGE_ROWS.",
459
+ "id": "evt_01M2HEYJ1V2E7BSYFFZDPQB5DM",
460
+ "key": "UPLOAD_CSV",
461
+ "name": "Upload Csv",
462
+ "payloadSchema": [
463
+ {
464
+ "name": "batchId",
465
+ "type": "string"
466
+ },
467
+ {
468
+ "name": "sourceName",
469
+ "type": "string"
470
+ }
471
+ ],
472
+ "synonyms": "upload csv, import csv, start import, import file, bulk import",
473
+ "tier": "domain"
474
+ },
475
+ {
476
+ "description": "import_batches persist-create success — rebinds @entity.id to the server-issued id, the fallback for when the host didn't mint a client-side batchId on UPLOAD_CSV",
477
+ "id": "evt_01M2HEYJ1V5JDXEXMVDAF0PVPZ",
478
+ "key": "BATCH_CREATED",
479
+ "name": "Batch Created",
480
+ "payloadSchema": [
481
+ {
482
+ "name": "id",
483
+ "required": true,
484
+ "type": "string"
485
+ }
486
+ ],
487
+ "tier": "secondary"
488
+ },
489
+ {
490
+ "description": "Host-side CSV parsing finished: rows carries one JSON string per parsed row (raw source shape, pre-mapping); errorCount counts rows the parser flagged. The atom bulk-persists them into import_rows and opens the staged review.",
491
+ "id": "evt_01M2HEYJ1V0BPHK9H0QHNNT4EF",
492
+ "key": "STAGE_ROWS",
493
+ "name": "Stage Rows",
494
+ "payloadSchema": [
495
+ {
496
+ "name": "rows",
497
+ "required": true,
498
+ "type": "[string]"
499
+ },
500
+ {
501
+ "name": "errorCount",
502
+ "type": "number"
503
+ }
504
+ ],
505
+ "tier": "internal"
506
+ },
507
+ {
508
+ "description": "Any import_batches / import_rows persist failure — the batch row is updated to failed and IMPORT_FAILED emitted, never a silent swallow; the trait stays put so the user can retry or discard",
509
+ "id": "evt_01M2HEYJ1V7M6C8DP88H0Z23F1",
510
+ "key": "IMPORT_PERSIST_FAILED",
511
+ "name": "Import Persist Failed",
512
+ "payloadSchema": [
513
+ {
514
+ "name": "error",
515
+ "required": true,
516
+ "type": "string"
517
+ }
518
+ ],
519
+ "tier": "secondary"
520
+ },
521
+ {
522
+ "description": "The user discarded the staged run before confirm; the batch row stays for provenance.",
523
+ "id": "evt_01M2HEYJ1V49JVADDCP4KX22XW",
524
+ "key": "DISCARD_IMPORT",
525
+ "name": "Discard Import",
526
+ "tier": "internal"
527
+ },
528
+ {
529
+ "description": "import_rows bulk persist-create success signal — payload carries the persisted rows flat; the atom never reads it (self-loop only)",
530
+ "id": "evt_01M2HEYJ1VK7JZCK3V8PB795PZ",
531
+ "key": "ROWS_STAGED",
532
+ "name": "Rows Staged",
533
+ "tier": "secondary"
534
+ },
535
+ {
536
+ "description": "The user approved the staged review; the batch is marked confirmed and IMPORT_CONFIRMED fires for the consumer's mapping+persist half.",
537
+ "id": "evt_01M2HEYJ1VBJXS0KEXTX9QWJM5",
538
+ "key": "CONFIRM_IMPORT",
539
+ "name": "Confirm Import",
540
+ "synonyms": "confirm import, approve staged rows, accept import",
541
+ "tier": "domain"
542
+ },
543
+ {
544
+ "description": "Returns the atom to idle from a terminal state",
545
+ "id": "evt_01M2HEYJ1VEEH4DZZ4ETPGP44F",
546
+ "key": "RESET",
547
+ "name": "Reset",
548
+ "tier": "internal"
549
+ },
550
+ {
551
+ "description": "The user confirmed the staged review and the batch row is persisted as confirmed. Consumers listen, fetch import_rows where batchId matches, map each rowJson through their field mapping, and persist into their own target entity.",
552
+ "id": "evt_01M2HEYJ1VS7SGS9STXQGS2V2J",
553
+ "key": "IMPORT_CONFIRMED",
554
+ "name": "Import Confirmed",
555
+ "payloadSchema": [
556
+ {
557
+ "name": "batchId",
558
+ "required": true,
559
+ "type": "string"
560
+ },
561
+ {
562
+ "name": "sourceName",
563
+ "type": "string"
564
+ },
565
+ {
566
+ "name": "rowCount",
567
+ "type": "number"
568
+ }
569
+ ],
570
+ "synonyms": "import confirmed, commit import, accept staged rows, approve import",
571
+ "tier": "domain"
572
+ },
573
+ {
574
+ "description": "The run failed (persist failure or empty staging); error carries the detail and the batch row was updated to failed",
575
+ "id": "evt_01M2HEYJ1VWSGJ1ZZXZSZ4Q023",
576
+ "key": "IMPORT_FAILED",
577
+ "name": "Import Failed",
578
+ "payloadSchema": [
579
+ {
580
+ "name": "batchId",
581
+ "type": "string"
582
+ },
583
+ {
584
+ "name": "error",
585
+ "required": true,
586
+ "type": "string"
587
+ }
588
+ ],
589
+ "synonyms": "import failed, upload failed, staging failed",
590
+ "tier": "domain"
591
+ }
592
+ ],
593
+ "states": [
594
+ {
595
+ "isInitial": true,
596
+ "name": "idle"
597
+ },
598
+ {
599
+ "name": "uploaded"
600
+ },
601
+ {
602
+ "name": "staged"
603
+ },
604
+ {
605
+ "name": "confirmed"
606
+ },
607
+ {
608
+ "name": "failed"
609
+ }
610
+ ],
611
+ "transitions": [
612
+ {
613
+ "effects": [
614
+ [
615
+ "set",
616
+ "@entity.sourceName",
617
+ "@config.sourceName"
618
+ ],
619
+ [
620
+ "set",
621
+ "@entity.status",
622
+ "uploaded"
623
+ ],
624
+ [
625
+ "set",
626
+ "@entity.rowCount",
627
+ 0.0
628
+ ],
629
+ [
630
+ "set",
631
+ "@entity.errorCount",
632
+ 0.0
633
+ ],
634
+ [
635
+ "set",
636
+ "@entity.mappingJson",
637
+ "@config.fieldMappingJson"
638
+ ],
639
+ [
640
+ "set",
641
+ "@entity.createdAt",
642
+ 0.0
643
+ ]
644
+ ],
645
+ "event": "INIT",
646
+ "eventId": "evt_01M2HEYJ1VPB25TA0Y6J782QHJ",
647
+ "from": "idle",
648
+ "to": "idle"
649
+ },
650
+ {
651
+ "effects": [
652
+ [
653
+ "set",
654
+ "@entity.id",
655
+ "@payload.batchId"
656
+ ],
657
+ [
658
+ "set",
659
+ "@entity.sourceName",
660
+ [
661
+ "or",
662
+ "@payload.sourceName",
663
+ "@config.sourceName"
664
+ ]
665
+ ],
666
+ [
667
+ "set",
668
+ "@entity.status",
669
+ "uploaded"
670
+ ],
671
+ [
672
+ "set",
673
+ "@entity.mappingJson",
674
+ "@config.fieldMappingJson"
675
+ ],
676
+ [
677
+ "set",
678
+ "@entity.rowCount",
679
+ 0.0
680
+ ],
681
+ [
682
+ "set",
683
+ "@entity.errorCount",
684
+ 0.0
685
+ ],
686
+ [
687
+ "set",
688
+ "@entity.createdAt",
689
+ [
690
+ "time/now"
691
+ ]
692
+ ],
693
+ [
694
+ "persist",
695
+ "create",
696
+ "ImportBatch",
697
+ {
698
+ "createdAt": "@entity.createdAt",
699
+ "errorCount": 0.0,
700
+ "id": "@entity.id",
701
+ "mappingJson": "@entity.mappingJson",
702
+ "rowCount": 0.0,
703
+ "sourceName": "@entity.sourceName",
704
+ "status": "uploaded"
705
+ },
706
+ {
707
+ "emit": {
708
+ "failure": "IMPORT_PERSIST_FAILED",
709
+ "success": "BATCH_CREATED"
710
+ }
711
+ }
712
+ ]
713
+ ],
714
+ "event": "UPLOAD_CSV",
715
+ "eventId": "evt_01M2HEYJ1V2E7BSYFFZDPQB5DM",
716
+ "from": "idle",
717
+ "to": "uploaded"
718
+ },
719
+ {
720
+ "effects": [
721
+ [
722
+ "set",
723
+ "@entity.id",
724
+ "@payload.id"
725
+ ]
726
+ ],
727
+ "event": "BATCH_CREATED",
728
+ "eventId": "evt_01M2HEYJ1V5JDXEXMVDAF0PVPZ",
729
+ "from": "uploaded",
730
+ "to": "uploaded"
731
+ },
732
+ {
733
+ "effects": [
734
+ [
735
+ "set",
736
+ "@entity.rowCount",
737
+ [
738
+ "array/len",
739
+ "@payload.rows"
740
+ ]
741
+ ],
742
+ [
743
+ "set",
744
+ "@entity.errorCount",
745
+ [
746
+ "or",
747
+ "@payload.errorCount",
748
+ 0.0
749
+ ]
750
+ ],
751
+ [
752
+ "set",
753
+ "@entity.status",
754
+ "staged"
755
+ ],
756
+ [
757
+ "persist",
758
+ "create",
759
+ "ImportRow",
760
+ [
761
+ "array/map",
762
+ "@payload.rows",
763
+ [
764
+ "fn",
765
+ "r",
766
+ {
767
+ "batchId": "@entity.id",
768
+ "rowJson": "@r",
769
+ "status": "staged"
770
+ }
771
+ ]
772
+ ],
773
+ {
774
+ "emit": {
775
+ "failure": "IMPORT_PERSIST_FAILED",
776
+ "success": "ROWS_STAGED"
777
+ }
778
+ }
779
+ ],
780
+ [
781
+ "persist",
782
+ "update",
783
+ "ImportBatch",
784
+ {
785
+ "errorCount": "@entity.errorCount",
786
+ "id": "@entity.id",
787
+ "rowCount": "@entity.rowCount",
788
+ "status": "staged"
789
+ }
790
+ ],
791
+ [
792
+ "render-ui",
793
+ "main",
794
+ {
795
+ "children": [
796
+ {
797
+ "content": [
798
+ "str/concat",
799
+ "Review staged import — ",
800
+ "@entity.sourceName"
801
+ ],
802
+ "type": "typography",
803
+ "variant": "h3"
804
+ },
805
+ {
806
+ "label": "Rows staged",
807
+ "type": "stat-display",
808
+ "value": "@entity.rowCount"
809
+ },
810
+ {
811
+ "label": "Rows with errors",
812
+ "type": "stat-display",
813
+ "value": "@entity.errorCount"
814
+ },
815
+ {
816
+ "children": [
817
+ {
818
+ "action": "CONFIRM_IMPORT",
819
+ "label": "Confirm import",
820
+ "type": "button",
821
+ "variant": "primary"
822
+ },
823
+ {
824
+ "action": "DISCARD_IMPORT",
825
+ "label": "Discard",
826
+ "type": "button",
827
+ "variant": "ghost"
828
+ }
829
+ ],
830
+ "direction": "horizontal",
831
+ "gap": "sm",
832
+ "type": "stack"
833
+ }
834
+ ],
835
+ "direction": "vertical",
836
+ "gap": "md",
837
+ "type": "stack"
838
+ }
839
+ ]
840
+ ],
841
+ "event": "STAGE_ROWS",
842
+ "eventId": "evt_01M2HEYJ1V0BPHK9H0QHNNT4EF",
843
+ "from": "uploaded",
844
+ "guard": [
845
+ ">",
846
+ [
847
+ "array/len",
848
+ "@payload.rows"
849
+ ],
850
+ 0.0
851
+ ],
852
+ "to": "staged"
853
+ },
854
+ {
855
+ "effects": [
856
+ [
857
+ "set",
858
+ "@entity.status",
859
+ "failed"
860
+ ],
861
+ [
862
+ "persist",
863
+ "update",
864
+ "ImportBatch",
865
+ {
866
+ "id": "@entity.id",
867
+ "status": "failed"
868
+ }
869
+ ],
870
+ [
871
+ "emit",
872
+ "IMPORT_FAILED",
873
+ {
874
+ "batchId": "@entity.id",
875
+ "error": "The file parsed to zero rows — nothing to stage."
876
+ }
877
+ ],
878
+ [
879
+ "render-ui",
880
+ "main",
881
+ {
882
+ "message": "The file parsed to zero rows — nothing to stage.",
883
+ "type": "alert",
884
+ "variant": "error"
885
+ }
886
+ ]
887
+ ],
888
+ "event": "STAGE_ROWS",
889
+ "eventId": "evt_01M2HEYJ1V0BPHK9H0QHNNT4EF",
890
+ "from": "uploaded",
891
+ "guard": [
892
+ "<",
893
+ [
894
+ "array/len",
895
+ "@payload.rows"
896
+ ],
897
+ 1.0
898
+ ],
899
+ "to": "failed"
900
+ },
901
+ {
902
+ "effects": [
903
+ [
904
+ "set",
905
+ "@entity.status",
906
+ "failed"
907
+ ],
908
+ [
909
+ "set",
910
+ "@entity.errorCount",
911
+ 1.0
912
+ ],
913
+ [
914
+ "persist",
915
+ "update",
916
+ "ImportBatch",
917
+ {
918
+ "errorCount": 1.0,
919
+ "id": "@entity.id",
920
+ "status": "failed"
921
+ }
922
+ ],
923
+ [
924
+ "emit",
925
+ "IMPORT_FAILED",
926
+ {
927
+ "batchId": "@entity.id",
928
+ "error": "@payload.error"
929
+ }
930
+ ],
931
+ [
932
+ "render-ui",
933
+ "main",
934
+ {
935
+ "message": "@payload.error",
936
+ "type": "alert",
937
+ "variant": "error"
938
+ }
939
+ ]
940
+ ],
941
+ "event": "IMPORT_PERSIST_FAILED",
942
+ "eventId": "evt_01M2HEYJ1V7M6C8DP88H0Z23F1",
943
+ "from": "uploaded",
944
+ "to": "uploaded"
945
+ },
946
+ {
947
+ "effects": [
948
+ [
949
+ "set",
950
+ "@entity.status",
951
+ "uploaded"
952
+ ],
953
+ [
954
+ "set",
955
+ "@entity.rowCount",
956
+ 0.0
957
+ ],
958
+ [
959
+ "set",
960
+ "@entity.errorCount",
961
+ 0.0
962
+ ]
963
+ ],
964
+ "event": "DISCARD_IMPORT",
965
+ "eventId": "evt_01M2HEYJ1V49JVADDCP4KX22XW",
966
+ "from": "uploaded",
967
+ "to": "idle"
968
+ },
969
+ {
970
+ "event": "ROWS_STAGED",
971
+ "eventId": "evt_01M2HEYJ1VK7JZCK3V8PB795PZ",
972
+ "from": "staged",
973
+ "to": "staged"
974
+ },
975
+ {
976
+ "effects": [
977
+ [
978
+ "set",
979
+ "@entity.status",
980
+ "confirmed"
981
+ ],
982
+ [
983
+ "persist",
984
+ "update",
985
+ "ImportBatch",
986
+ {
987
+ "id": "@entity.id",
988
+ "status": "confirmed"
989
+ }
990
+ ],
991
+ [
992
+ "render-ui",
993
+ "main",
994
+ {
995
+ "message": "Import confirmed — staged rows are ready for mapping.",
996
+ "type": "alert",
997
+ "variant": "success"
998
+ }
999
+ ],
1000
+ [
1001
+ "emit",
1002
+ "IMPORT_CONFIRMED",
1003
+ {
1004
+ "batchId": "@entity.id",
1005
+ "rowCount": "@entity.rowCount",
1006
+ "sourceName": "@entity.sourceName"
1007
+ }
1008
+ ]
1009
+ ],
1010
+ "event": "CONFIRM_IMPORT",
1011
+ "eventId": "evt_01M2HEYJ1VBJXS0KEXTX9QWJM5",
1012
+ "from": "staged",
1013
+ "to": "confirmed"
1014
+ },
1015
+ {
1016
+ "effects": [
1017
+ [
1018
+ "set",
1019
+ "@entity.status",
1020
+ "failed"
1021
+ ],
1022
+ [
1023
+ "set",
1024
+ "@entity.errorCount",
1025
+ 1.0
1026
+ ],
1027
+ [
1028
+ "persist",
1029
+ "update",
1030
+ "ImportBatch",
1031
+ {
1032
+ "errorCount": 1.0,
1033
+ "id": "@entity.id",
1034
+ "status": "failed"
1035
+ }
1036
+ ],
1037
+ [
1038
+ "emit",
1039
+ "IMPORT_FAILED",
1040
+ {
1041
+ "batchId": "@entity.id",
1042
+ "error": "@payload.error"
1043
+ }
1044
+ ],
1045
+ [
1046
+ "render-ui",
1047
+ "main",
1048
+ {
1049
+ "message": "@payload.error",
1050
+ "type": "alert",
1051
+ "variant": "error"
1052
+ }
1053
+ ]
1054
+ ],
1055
+ "event": "IMPORT_PERSIST_FAILED",
1056
+ "eventId": "evt_01M2HEYJ1V7M6C8DP88H0Z23F1",
1057
+ "from": "staged",
1058
+ "to": "staged"
1059
+ },
1060
+ {
1061
+ "effects": [
1062
+ [
1063
+ "set",
1064
+ "@entity.status",
1065
+ "uploaded"
1066
+ ],
1067
+ [
1068
+ "set",
1069
+ "@entity.rowCount",
1070
+ 0.0
1071
+ ],
1072
+ [
1073
+ "set",
1074
+ "@entity.errorCount",
1075
+ 0.0
1076
+ ],
1077
+ [
1078
+ "render-ui",
1079
+ "main",
1080
+ null
1081
+ ]
1082
+ ],
1083
+ "event": "DISCARD_IMPORT",
1084
+ "eventId": "evt_01M2HEYJ1V49JVADDCP4KX22XW",
1085
+ "from": "staged",
1086
+ "to": "idle"
1087
+ },
1088
+ {
1089
+ "effects": [
1090
+ [
1091
+ "set",
1092
+ "@entity.status",
1093
+ "uploaded"
1094
+ ],
1095
+ [
1096
+ "set",
1097
+ "@entity.rowCount",
1098
+ 0.0
1099
+ ],
1100
+ [
1101
+ "set",
1102
+ "@entity.errorCount",
1103
+ 0.0
1104
+ ],
1105
+ [
1106
+ "render-ui",
1107
+ "main",
1108
+ null
1109
+ ]
1110
+ ],
1111
+ "event": "RESET",
1112
+ "eventId": "evt_01M2HEYJ1VEEH4DZZ4ETPGP44F",
1113
+ "from": "confirmed",
1114
+ "to": "idle"
1115
+ },
1116
+ {
1117
+ "event": "IMPORT_CONFIRMED",
1118
+ "eventId": "evt_01M2HEYJ1VS7SGS9STXQGS2V2J",
1119
+ "from": "confirmed",
1120
+ "to": "confirmed"
1121
+ },
1122
+ {
1123
+ "effects": [
1124
+ [
1125
+ "set",
1126
+ "@entity.status",
1127
+ "uploaded"
1128
+ ],
1129
+ [
1130
+ "set",
1131
+ "@entity.rowCount",
1132
+ 0.0
1133
+ ],
1134
+ [
1135
+ "set",
1136
+ "@entity.errorCount",
1137
+ 0.0
1138
+ ],
1139
+ [
1140
+ "render-ui",
1141
+ "main",
1142
+ null
1143
+ ]
1144
+ ],
1145
+ "event": "RESET",
1146
+ "eventId": "evt_01M2HEYJ1VEEH4DZZ4ETPGP44F",
1147
+ "from": "failed",
1148
+ "to": "idle"
1149
+ },
1150
+ {
1151
+ "event": "IMPORT_FAILED",
1152
+ "eventId": "evt_01M2HEYJ1VWSGJ1ZZXZSZ4Q023",
1153
+ "from": "failed",
1154
+ "to": "failed"
1155
+ }
1156
+ ]
1157
+ }
1158
+ }
1159
+ ]
1160
+ }
1161
+ ],
1162
+ "schemaVersion": 1,
1163
+ "version": "1.0.0"
1164
+ }