@hyperscale0/udl 1.0.0-beta.1 → 1.0.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.
Files changed (179) hide show
  1. package/CHANGELOG.md +78 -25
  2. package/README.md +37 -99
  3. package/conformance/README.md +44 -41
  4. package/conformance/evolution/action-contract.expected.json +10 -0
  5. package/conformance/evolution/action-contract.live.udl +44 -0
  6. package/conformance/evolution/action-contract.next.udl +45 -0
  7. package/conformance/evolution/product-identity.expected.json +10 -0
  8. package/conformance/evolution/product-identity.live.udl +55 -0
  9. package/conformance/evolution/product-identity.next.udl +55 -0
  10. package/conformance/evolution/version-required.expected.json +10 -0
  11. package/conformance/evolution/version-required.live.udl +55 -0
  12. package/conformance/evolution/version-required.next.udl +58 -0
  13. package/conformance/invalid/action-without-transition.expected.json +10 -0
  14. package/conformance/invalid/{verb-without-transition.udl → action-without-transition.udl} +7 -2
  15. package/conformance/invalid/agent-description-too-long.expected.json +10 -0
  16. package/conformance/invalid/agent-description-too-long.udl +57 -0
  17. package/conformance/invalid/blank-title.expected.json +1 -1
  18. package/conformance/invalid/blank-title.udl +6 -2
  19. package/conformance/invalid/composition-dial-duplicate-key.expected.json +10 -0
  20. package/conformance/invalid/composition-dial-duplicate-key.udl +73 -0
  21. package/conformance/invalid/depth-budget.expected.json +1 -1
  22. package/conformance/invalid/duplicate-subject.expected.json +10 -0
  23. package/conformance/invalid/duplicate-subject.udl +230 -0
  24. package/conformance/invalid/forged-effects.expected.json +10 -0
  25. package/conformance/invalid/forged-effects.udl +76 -0
  26. package/conformance/invalid/format-version.expected.json +1 -1
  27. package/conformance/invalid/format-version.udl +6 -2
  28. package/conformance/invalid/instrument-id-not-snake-case.expected.json +10 -0
  29. package/conformance/invalid/{noun-id-not-snake-case.udl → instrument-id-not-snake-case.udl} +6 -2
  30. package/conformance/invalid/invalid-aggregate-gate-shape.expected.json +10 -0
  31. package/conformance/invalid/invalid-aggregate-gate-shape.udl +1819 -0
  32. package/conformance/invalid/invalid-check-duration.expected.json +10 -0
  33. package/conformance/invalid/invalid-check-duration.udl +219 -0
  34. package/conformance/invalid/invalid-dial-anchor.expected.json +10 -0
  35. package/conformance/invalid/invalid-dial-anchor.udl +219 -0
  36. package/conformance/invalid/invalid-exception-parent-ref.expected.json +10 -0
  37. package/conformance/invalid/invalid-exception-parent-ref.udl +2487 -0
  38. package/conformance/invalid/invalid-exposure-shape.expected.json +10 -0
  39. package/conformance/invalid/invalid-exposure-shape.udl +1819 -0
  40. package/conformance/invalid/invalid-remainder.expected.json +10 -0
  41. package/conformance/invalid/invalid-remainder.udl +220 -0
  42. package/conformance/invalid/invalid-schema-keyword.expected.json +10 -0
  43. package/conformance/invalid/invalid-schema-keyword.udl +220 -0
  44. package/conformance/invalid/invalid-utf8.expected.json +1 -1
  45. package/conformance/invalid/malformed-json.expected.json +1 -1
  46. package/conformance/invalid/missing-create-action.expected.json +10 -0
  47. package/conformance/invalid/{missing-create-verb.udl → missing-create-action.udl} +5 -2
  48. package/conformance/invalid/missing-exception-amount-field.expected.json +10 -0
  49. package/conformance/invalid/missing-exception-amount-field.udl +2487 -0
  50. package/conformance/invalid/missing-exception-contract.expected.json +14 -0
  51. package/conformance/invalid/missing-exception-contract.udl +2523 -0
  52. package/conformance/invalid/missing-exception-reason-field.expected.json +10 -0
  53. package/conformance/invalid/missing-exception-reason-field.udl +2487 -0
  54. package/conformance/invalid/not-an-object.expected.json +1 -1
  55. package/conformance/invalid/payout-reconcile-not-a-bank-debit.expected.json +10 -0
  56. package/conformance/invalid/payout-reconcile-not-a-bank-debit.udl +259 -0
  57. package/conformance/invalid/quote-freeze-set-incomplete.expected.json +10 -0
  58. package/conformance/invalid/quote-freeze-set-incomplete.udl +261 -0
  59. package/conformance/invalid/quote-named-reference-gate.expected.json +10 -0
  60. package/conformance/invalid/quote-named-reference-gate.udl +50 -0
  61. package/conformance/invalid/reconcile-named-reference-gate.expected.json +10 -0
  62. package/conformance/invalid/reconcile-named-reference-gate.udl +50 -0
  63. package/conformance/invalid/unknown-key.expected.json +1 -1
  64. package/conformance/invalid/unknown-key.udl +6 -2
  65. package/conformance/invalid/unknown-reference-gate-field.expected.json +10 -0
  66. package/conformance/invalid/unknown-reference-gate-field.udl +1819 -0
  67. package/conformance/invalid/unknown-required-field.expected.json +10 -0
  68. package/conformance/invalid/unknown-required-field.udl +220 -0
  69. package/conformance/invalid/unreachable-state.expected.json +2 -2
  70. package/conformance/invalid/unreachable-state.udl +6 -2
  71. package/conformance/invalid/wrong-exception-amount-field.expected.json +10 -0
  72. package/conformance/invalid/wrong-exception-amount-field.udl +2487 -0
  73. package/conformance/invalid/wrong-exception-reason-field.expected.json +10 -0
  74. package/conformance/invalid/wrong-exception-reason-field.udl +2487 -0
  75. package/conformance/valid/agent-description.expected.json +6 -0
  76. package/conformance/valid/agent-description.udl +66 -0
  77. package/conformance/valid/cards.expected.json +1 -0
  78. package/conformance/valid/cards.udl +843 -356
  79. package/conformance/valid/commerce-escrow.expected.json +1 -0
  80. package/conformance/valid/commerce-escrow.udl +792 -291
  81. package/conformance/valid/compiled-crowdfunding.expected.json +6 -0
  82. package/conformance/valid/compiled-crowdfunding.udl +1843 -0
  83. package/conformance/valid/compiled-watch-club.expected.json +6 -0
  84. package/conformance/valid/compiled-watch-club.udl +2486 -0
  85. package/conformance/valid/complete-contract.expected.json +6 -0
  86. package/conformance/valid/complete-contract.udl +218 -0
  87. package/conformance/valid/effect-signatures.expected.json +6 -0
  88. package/conformance/valid/effect-signatures.udl +75 -0
  89. package/conformance/valid/hand-edited.expected.json +1 -0
  90. package/conformance/valid/hand-edited.udl +1 -1
  91. package/conformance/valid/insured-car-marketplace.expected.json +1 -0
  92. package/conformance/valid/insured-car-marketplace.udl +534 -315
  93. package/conformance/valid/insured-travel.expected.json +2 -1
  94. package/conformance/valid/insured-travel.udl +1489 -641
  95. package/conformance/valid/minimal.expected.json +1 -0
  96. package/conformance/valid/minimal.udl +18 -14
  97. package/conformance/valid/protection.expected.json +1 -0
  98. package/conformance/valid/protection.udl +719 -304
  99. package/conformance/valid/string-escaping.expected.json +6 -0
  100. package/conformance/valid/string-escaping.udl +54 -0
  101. package/dist/canonical.d.ts +2 -0
  102. package/dist/canonical.d.ts.map +1 -1
  103. package/dist/canonical.js +7 -0
  104. package/dist/canonical.js.map +1 -1
  105. package/dist/check-profiles.d.ts +57 -0
  106. package/dist/check-profiles.d.ts.map +1 -0
  107. package/dist/check-profiles.js +62 -0
  108. package/dist/check-profiles.js.map +1 -0
  109. package/dist/cli.js +48 -4
  110. package/dist/cli.js.map +1 -1
  111. package/dist/diagnostics.d.ts +168 -0
  112. package/dist/diagnostics.d.ts.map +1 -0
  113. package/dist/diagnostics.js +164 -0
  114. package/dist/diagnostics.js.map +1 -0
  115. package/dist/effects.d.ts +41 -0
  116. package/dist/effects.d.ts.map +1 -0
  117. package/dist/effects.js +110 -0
  118. package/dist/effects.js.map +1 -0
  119. package/dist/evolution.d.ts +51 -18
  120. package/dist/evolution.d.ts.map +1 -1
  121. package/dist/evolution.js +244 -102
  122. package/dist/evolution.js.map +1 -1
  123. package/dist/finance.d.ts +17 -13
  124. package/dist/finance.d.ts.map +1 -1
  125. package/dist/finance.js +165 -109
  126. package/dist/finance.js.map +1 -1
  127. package/dist/index.d.ts +12 -8
  128. package/dist/index.d.ts.map +1 -1
  129. package/dist/index.js +8 -5
  130. package/dist/index.js.map +1 -1
  131. package/dist/limits.d.ts +2 -2
  132. package/dist/limits.d.ts.map +1 -1
  133. package/dist/limits.js +4 -3
  134. package/dist/limits.js.map +1 -1
  135. package/dist/parser.d.ts.map +1 -1
  136. package/dist/parser.js +6 -16
  137. package/dist/parser.js.map +1 -1
  138. package/dist/schema.d.ts +2059 -135
  139. package/dist/schema.d.ts.map +1 -1
  140. package/dist/schema.js +759 -73
  141. package/dist/schema.js.map +1 -1
  142. package/dist/validation.d.ts +22 -9
  143. package/dist/validation.d.ts.map +1 -1
  144. package/dist/validation.js +1463 -457
  145. package/dist/validation.js.map +1 -1
  146. package/docs/README.md +14 -0
  147. package/docs/guide/01-a-document.md +37 -0
  148. package/docs/guide/02-money-steps.md +23 -0
  149. package/docs/guide/03-laws.md +18 -0
  150. package/docs/guide/04-fees-and-remainder.md +15 -0
  151. package/docs/guide/05-checks-updates-dials.md +7 -0
  152. package/docs/guide/06-effects.md +11 -0
  153. package/docs/guide/07-evolution.md +11 -0
  154. package/docs/guide/08-implementing.md +13 -0
  155. package/docs/llms-full.txt +1241 -0
  156. package/docs/llms.txt +14 -0
  157. package/docs/reference/canonical.md +16 -0
  158. package/docs/reference/clauses.md +986 -0
  159. package/docs/reference/cli.md +22 -0
  160. package/docs/reference/diagnostics.md +32 -0
  161. package/package.json +6 -2
  162. package/skills/udl/SKILL.md +28 -0
  163. package/spec/README.md +82 -51
  164. package/spec/udl.schema.json +1191 -119
  165. package/src/canonical.ts +11 -0
  166. package/src/check-profiles.ts +80 -0
  167. package/src/cli.ts +49 -3
  168. package/src/diagnostics.ts +221 -0
  169. package/src/effects.ts +163 -0
  170. package/src/evolution.ts +375 -125
  171. package/src/finance.ts +255 -160
  172. package/src/index.ts +50 -14
  173. package/src/limits.ts +4 -3
  174. package/src/parser.ts +15 -18
  175. package/src/schema.ts +855 -81
  176. package/src/validation.ts +2666 -560
  177. package/conformance/invalid/missing-create-verb.expected.json +0 -10
  178. package/conformance/invalid/noun-id-not-snake-case.expected.json +0 -10
  179. package/conformance/invalid/verb-without-transition.expected.json +0 -10
@@ -0,0 +1,2486 @@
1
+ {
2
+ "instruments": [
3
+ {
4
+ "actionOrder": [
5
+ "create",
6
+ "pay_piece_1",
7
+ "pay_piece_2",
8
+ "collect_service_fee"
9
+ ],
10
+ "actions": {
11
+ "collect_service_fee": {
12
+ "effects": {
13
+ "moves": [
14
+ {
15
+ "signature": "moves.transfer.internal",
16
+ "source": "moves[0]"
17
+ }
18
+ ]
19
+ },
20
+ "moves": [
21
+ {
22
+ "bind": {
23
+ "amount": {
24
+ "from": "instance",
25
+ "path": "fields.checkoutFee"
26
+ },
27
+ "currency": {
28
+ "from": "instance",
29
+ "path": "fields.currency"
30
+ },
31
+ "destinationAccountId": {
32
+ "from": "instance",
33
+ "path": "fields.platformAccountId"
34
+ },
35
+ "metadata.instrumentId": {
36
+ "from": "const",
37
+ "value": "purchase"
38
+ },
39
+ "metadata.instrumentInstanceId": {
40
+ "from": "instance",
41
+ "path": "instrumentInstanceId"
42
+ },
43
+ "metadata.phase": {
44
+ "from": "const",
45
+ "value": "collect_service_fee"
46
+ },
47
+ "productId": {
48
+ "from": "instance",
49
+ "path": "productId"
50
+ },
51
+ "sourceAccountId": {
52
+ "from": "instance",
53
+ "path": "fields.memberAccountId"
54
+ }
55
+ },
56
+ "capture": {
57
+ "collectServiceFeeTransferTransferId": "transferId"
58
+ },
59
+ "key": "transfer",
60
+ "operation": "internal_transfer.create"
61
+ }
62
+ ],
63
+ "publicAction": "collectServiceFeePurchase",
64
+ "steps": [],
65
+ "summary": "Collect the payer-side service fee"
66
+ },
67
+ "create": {
68
+ "moves": [],
69
+ "publicAction": "createPurchase",
70
+ "steps": [],
71
+ "summary": "Create a purchase payment"
72
+ },
73
+ "pay_piece_1": {
74
+ "effects": {
75
+ "moves": [
76
+ {
77
+ "signature": "moves.transfer.internal",
78
+ "source": "moves[0]"
79
+ }
80
+ ]
81
+ },
82
+ "moves": [
83
+ {
84
+ "bind": {
85
+ "amount": {
86
+ "from": "instance",
87
+ "path": "fields.netOfCarvedFeeAmount"
88
+ },
89
+ "currency": {
90
+ "from": "instance",
91
+ "path": "fields.currency"
92
+ },
93
+ "destinationAccountId": {
94
+ "from": "instance",
95
+ "path": "fields.sellerAccountId"
96
+ },
97
+ "metadata.instrumentId": {
98
+ "from": "const",
99
+ "value": "purchase"
100
+ },
101
+ "metadata.instrumentInstanceId": {
102
+ "from": "instance",
103
+ "path": "instrumentInstanceId"
104
+ },
105
+ "metadata.phase": {
106
+ "from": "const",
107
+ "value": "pay_piece_1"
108
+ },
109
+ "productId": {
110
+ "from": "instance",
111
+ "path": "productId"
112
+ },
113
+ "sourceAccountId": {
114
+ "from": "instance",
115
+ "path": "fields.memberAccountId"
116
+ }
117
+ },
118
+ "capture": {
119
+ "payPiece1TransferTransferId": "transferId"
120
+ },
121
+ "key": "transfer",
122
+ "operation": "internal_transfer.create"
123
+ }
124
+ ],
125
+ "publicAction": "payPiece1Purchase",
126
+ "steps": [],
127
+ "summary": "Pay piece 1 of the amount through"
128
+ },
129
+ "pay_piece_2": {
130
+ "effects": {
131
+ "moves": [
132
+ {
133
+ "signature": "moves.transfer.internal",
134
+ "source": "moves[0]"
135
+ }
136
+ ]
137
+ },
138
+ "moves": [
139
+ {
140
+ "bind": {
141
+ "amount": {
142
+ "from": "instance",
143
+ "path": "fields.carvedFeeAmount"
144
+ },
145
+ "currency": {
146
+ "from": "instance",
147
+ "path": "fields.currency"
148
+ },
149
+ "destinationAccountId": {
150
+ "from": "instance",
151
+ "path": "fields.platformAccountId"
152
+ },
153
+ "metadata.instrumentId": {
154
+ "from": "const",
155
+ "value": "purchase"
156
+ },
157
+ "metadata.instrumentInstanceId": {
158
+ "from": "instance",
159
+ "path": "instrumentInstanceId"
160
+ },
161
+ "metadata.phase": {
162
+ "from": "const",
163
+ "value": "pay_piece_2"
164
+ },
165
+ "productId": {
166
+ "from": "instance",
167
+ "path": "productId"
168
+ },
169
+ "sourceAccountId": {
170
+ "from": "instance",
171
+ "path": "fields.memberAccountId"
172
+ }
173
+ },
174
+ "capture": {
175
+ "payPiece2TransferTransferId": "transferId"
176
+ },
177
+ "key": "transfer",
178
+ "operation": "internal_transfer.create"
179
+ }
180
+ ],
181
+ "publicAction": "payPiece2Purchase",
182
+ "steps": [],
183
+ "summary": "Pay piece 2 of the amount through"
184
+ }
185
+ },
186
+ "description": "Instant transfer: the member pays purchasePrice straight through to the seller, no custody",
187
+ "feeRules": [
188
+ {
189
+ "amountField": "checkoutFee",
190
+ "baseField": "purchasePrice",
191
+ "bearerField": "memberAccountId",
192
+ "position": "on_top",
193
+ "rule": {
194
+ "currencyField": "currency",
195
+ "field": "checkoutFee",
196
+ "kind": "exact"
197
+ }
198
+ },
199
+ {
200
+ "amountField": "carvedFeeAmount",
201
+ "baseField": "purchasePrice",
202
+ "bearerField": "sellerAccountId",
203
+ "position": "carved",
204
+ "rule": {
205
+ "kind": "tiered",
206
+ "tiers": [
207
+ {
208
+ "fromInclusive": "0",
209
+ "rule": {
210
+ "bps": 100,
211
+ "kind": "bps"
212
+ },
213
+ "toExclusive": "10000"
214
+ },
215
+ {
216
+ "fromInclusive": "10000",
217
+ "rule": {
218
+ "currencyField": "currency",
219
+ "field": "highValueFee",
220
+ "kind": "exact"
221
+ }
222
+ }
223
+ ]
224
+ }
225
+ }
226
+ ],
227
+ "fields": {
228
+ "carvedFeeAmount": {
229
+ "description": "The carved platform fee selected from purchasePrice",
230
+ "pattern": "^[1-9][0-9]{0,17}$",
231
+ "type": "string"
232
+ },
233
+ "checkoutFee": {
234
+ "description": "Immutable exact member fee in SAR minor units",
235
+ "pattern": "^[1-9][0-9]{0,17}$",
236
+ "type": "string"
237
+ },
238
+ "currency": {
239
+ "description": "ISO 4217 currency code",
240
+ "maxLength": 3,
241
+ "minLength": 3,
242
+ "pattern": "^[A-Z]{3}$",
243
+ "type": "string"
244
+ },
245
+ "highValueFee": {
246
+ "description": "Immutable exact seller fee in SAR minor units",
247
+ "pattern": "^[1-9][0-9]{0,17}$",
248
+ "type": "string"
249
+ },
250
+ "memberAccountId": {
251
+ "description": "The member account",
252
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
253
+ "type": "string",
254
+ "x-hyperscale-reference-filter": {
255
+ "column": "role",
256
+ "values": [
257
+ "customer_balance"
258
+ ]
259
+ }
260
+ },
261
+ "netOfCarvedFeeAmount": {
262
+ "description": "The remainder of purchasePrice after the carved platform fee",
263
+ "pattern": "^[1-9][0-9]{0,17}$",
264
+ "type": "string"
265
+ },
266
+ "platformAccountId": {
267
+ "description": "The product fee collection account",
268
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
269
+ "type": "string",
270
+ "x-hyperscale-fee-collection-port": true,
271
+ "x-hyperscale-reference-filter": {
272
+ "column": "role",
273
+ "values": [
274
+ "customer_balance",
275
+ "product_revenue"
276
+ ]
277
+ }
278
+ },
279
+ "purchasePrice": {
280
+ "description": "The gross amount in SAR minor units; the piece fields below partition it exactly",
281
+ "pattern": "^[1-9][0-9]{0,17}$",
282
+ "type": "string"
283
+ },
284
+ "sellerAccountId": {
285
+ "description": "The seller account",
286
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
287
+ "type": "string",
288
+ "x-hyperscale-reference-filter": {
289
+ "column": "role",
290
+ "values": [
291
+ "customer_balance"
292
+ ]
293
+ }
294
+ }
295
+ },
296
+ "id": "purchase",
297
+ "idPrefix": "purc",
298
+ "lifecycle": {
299
+ "initial": "created",
300
+ "states": [
301
+ "created",
302
+ "paying_1",
303
+ "paying_2",
304
+ "paid"
305
+ ],
306
+ "transitions": {
307
+ "collect_service_fee": {
308
+ "from": [
309
+ "paying_2"
310
+ ],
311
+ "to": "paid"
312
+ },
313
+ "pay_piece_1": {
314
+ "from": [
315
+ "created"
316
+ ],
317
+ "to": "paying_1"
318
+ },
319
+ "pay_piece_2": {
320
+ "from": [
321
+ "paying_1"
322
+ ],
323
+ "to": "paying_2"
324
+ }
325
+ }
326
+ },
327
+ "parties": {
328
+ "beneficiary": "sellerAccountId",
329
+ "payer": "memberAccountId"
330
+ },
331
+ "partitions": [
332
+ {
333
+ "pieceFields": [
334
+ "netOfCarvedFeeAmount",
335
+ "carvedFeeAmount"
336
+ ],
337
+ "totalField": "purchasePrice"
338
+ }
339
+ ],
340
+ "required": [
341
+ "memberAccountId",
342
+ "sellerAccountId",
343
+ "platformAccountId",
344
+ "purchasePrice",
345
+ "netOfCarvedFeeAmount",
346
+ "checkoutFee",
347
+ "highValueFee",
348
+ "currency"
349
+ ],
350
+ "summary": "Instant payment from member to seller",
351
+ "title": "Purchase"
352
+ },
353
+ {
354
+ "actionOrder": [
355
+ "create",
356
+ "place_deposit",
357
+ "assess_watch",
358
+ "return_deposit"
359
+ ],
360
+ "actions": {
361
+ "assess_watch": {
362
+ "decidedAmount": {
363
+ "boundField": "depositAmount",
364
+ "field": "damageAmount",
365
+ "remainderAction": "return_deposit"
366
+ },
367
+ "effects": {
368
+ "decides": [
369
+ {
370
+ "signature": "decides.tenant_port",
371
+ "source": "port"
372
+ }
373
+ ],
374
+ "moves": [
375
+ {
376
+ "signature": "moves.transfer.internal",
377
+ "source": "moves[0]"
378
+ },
379
+ {
380
+ "signature": "moves.transfer.internal",
381
+ "source": "moves[1]"
382
+ }
383
+ ]
384
+ },
385
+ "input": {
386
+ "additionalProperties": false,
387
+ "properties": {
388
+ "damageAmount": {
389
+ "description": "Caller-decided amount in minor units",
390
+ "pattern": "^(0|[1-9][0-9]{0,17})$",
391
+ "type": "string"
392
+ },
393
+ "evidence": {
394
+ "description": "Required decision reference retained in the operation receipt",
395
+ "maxLength": 180,
396
+ "minLength": 1,
397
+ "type": "string"
398
+ }
399
+ },
400
+ "required": [
401
+ "damageAmount",
402
+ "evidence"
403
+ ],
404
+ "type": "object"
405
+ },
406
+ "moves": [
407
+ {
408
+ "bind": {
409
+ "amount": {
410
+ "from": "input",
411
+ "path": "damageAmount"
412
+ },
413
+ "currency": {
414
+ "from": "instance",
415
+ "path": "fields.currency"
416
+ },
417
+ "postMode": {
418
+ "from": "const",
419
+ "value": "partial_only"
420
+ },
421
+ "transferId": {
422
+ "from": "instance",
423
+ "path": "refs.placeDepositReservationTransferId"
424
+ }
425
+ },
426
+ "key": "post",
427
+ "operation": "internal_transfer.post"
428
+ },
429
+ {
430
+ "bind": {
431
+ "reason": {
432
+ "from": "const",
433
+ "value": "Return the unclaimed deposit remainder"
434
+ },
435
+ "transferId": {
436
+ "from": "instance",
437
+ "path": "refs.placeDepositReservationTransferId"
438
+ }
439
+ },
440
+ "key": "remainder",
441
+ "operation": "internal_transfer.void"
442
+ }
443
+ ],
444
+ "port": {
445
+ "allowedParties": [
446
+ "beneficiary"
447
+ ]
448
+ },
449
+ "publicAction": "assessWatchInspectionDeposit",
450
+ "steps": [],
451
+ "summary": "Claim the deposit for the seller through assess_watch"
452
+ },
453
+ "create": {
454
+ "moves": [],
455
+ "publicAction": "createInspectionDeposit",
456
+ "steps": [],
457
+ "summary": "Create a inspection deposit"
458
+ },
459
+ "place_deposit": {
460
+ "effects": {
461
+ "holds": [
462
+ {
463
+ "signature": "holds.reserve",
464
+ "source": "moves[0]"
465
+ }
466
+ ],
467
+ "moves": [
468
+ {
469
+ "signature": "moves.transfer.internal",
470
+ "source": "moves[0]"
471
+ }
472
+ ]
473
+ },
474
+ "moves": [
475
+ {
476
+ "bind": {
477
+ "amount": {
478
+ "from": "instance",
479
+ "path": "fields.depositAmount"
480
+ },
481
+ "currency": {
482
+ "from": "instance",
483
+ "path": "fields.currency"
484
+ },
485
+ "destinationAccountId": {
486
+ "from": "instance",
487
+ "path": "fields.sellerAccountId"
488
+ },
489
+ "metadata.instrumentId": {
490
+ "from": "const",
491
+ "value": "inspection_deposit"
492
+ },
493
+ "metadata.instrumentInstanceId": {
494
+ "from": "instance",
495
+ "path": "instrumentInstanceId"
496
+ },
497
+ "metadata.phase": {
498
+ "from": "const",
499
+ "value": "place_deposit"
500
+ },
501
+ "productId": {
502
+ "from": "instance",
503
+ "path": "productId"
504
+ },
505
+ "sourceAccountId": {
506
+ "from": "instance",
507
+ "path": "fields.memberAccountId"
508
+ }
509
+ },
510
+ "capture": {
511
+ "placeDepositReservationTransferId": "transferId"
512
+ },
513
+ "key": "reservation",
514
+ "operation": "internal_transfer.reserve"
515
+ }
516
+ ],
517
+ "publicAction": "placeDepositInspectionDeposit",
518
+ "steps": [],
519
+ "summary": "Reserve the depositAmount against the member's account"
520
+ },
521
+ "return_deposit": {
522
+ "effects": {
523
+ "moves": [
524
+ {
525
+ "signature": "moves.transfer.internal",
526
+ "source": "moves[0]"
527
+ }
528
+ ]
529
+ },
530
+ "moves": [
531
+ {
532
+ "bind": {
533
+ "reason": {
534
+ "from": "const",
535
+ "value": "Deposit returned in full"
536
+ },
537
+ "transferId": {
538
+ "from": "instance",
539
+ "path": "refs.placeDepositReservationTransferId"
540
+ }
541
+ },
542
+ "key": "void",
543
+ "operation": "internal_transfer.void"
544
+ }
545
+ ],
546
+ "publicAction": "returnDepositInspectionDeposit",
547
+ "steps": [],
548
+ "summary": "Return the deposit to the member through return_deposit"
549
+ }
550
+ },
551
+ "description": "Deposit: the depositAmount is reserved against the member's account in the seller's favor, then damageAmount is claimed and the exact remainder returned, or the deposit is returned in full",
552
+ "fields": {
553
+ "currency": {
554
+ "description": "ISO 4217 currency code",
555
+ "maxLength": 3,
556
+ "minLength": 3,
557
+ "pattern": "^[A-Z]{3}$",
558
+ "type": "string"
559
+ },
560
+ "depositAmount": {
561
+ "description": "The deposit amount in SAR minor units, reserved in full and fully accounted on claim or return",
562
+ "pattern": "^[1-9][0-9]{0,17}$",
563
+ "type": "string"
564
+ },
565
+ "memberAccountId": {
566
+ "description": "The member account",
567
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
568
+ "type": "string",
569
+ "x-hyperscale-reference-filter": {
570
+ "column": "role",
571
+ "values": [
572
+ "customer_balance"
573
+ ]
574
+ }
575
+ },
576
+ "sellerAccountId": {
577
+ "description": "The seller account",
578
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
579
+ "type": "string",
580
+ "x-hyperscale-reference-filter": {
581
+ "column": "role",
582
+ "values": [
583
+ "customer_balance"
584
+ ]
585
+ }
586
+ }
587
+ },
588
+ "id": "inspection_deposit",
589
+ "idPrefix": "id",
590
+ "lifecycle": {
591
+ "initial": "created",
592
+ "states": [
593
+ "created",
594
+ "held",
595
+ "claimed",
596
+ "returned"
597
+ ],
598
+ "transitions": {
599
+ "assess_watch": {
600
+ "from": [
601
+ "held"
602
+ ],
603
+ "to": "claimed"
604
+ },
605
+ "place_deposit": {
606
+ "from": [
607
+ "created"
608
+ ],
609
+ "to": "held"
610
+ },
611
+ "return_deposit": {
612
+ "from": [
613
+ "held"
614
+ ],
615
+ "to": "returned"
616
+ }
617
+ }
618
+ },
619
+ "parties": {
620
+ "beneficiary": "sellerAccountId",
621
+ "payer": "memberAccountId"
622
+ },
623
+ "required": [
624
+ "memberAccountId",
625
+ "sellerAccountId",
626
+ "depositAmount",
627
+ "currency"
628
+ ],
629
+ "summary": "Refundable deposit from member held for seller",
630
+ "title": "Inspection deposit"
631
+ },
632
+ {
633
+ "actionOrder": [
634
+ "create",
635
+ "open_period",
636
+ "collect_period",
637
+ "cancel_membership"
638
+ ],
639
+ "actions": {
640
+ "cancel_membership": {
641
+ "captureInput": {
642
+ "reason": "reason"
643
+ },
644
+ "effects": {
645
+ "decides": [
646
+ {
647
+ "signature": "decides.tenant_port",
648
+ "source": "port"
649
+ }
650
+ ]
651
+ },
652
+ "input": {
653
+ "additionalProperties": false,
654
+ "properties": {
655
+ "reason": {
656
+ "description": "Required decision reference retained in the operation receipt",
657
+ "maxLength": 180,
658
+ "minLength": 1,
659
+ "type": "string"
660
+ }
661
+ },
662
+ "required": [
663
+ "reason"
664
+ ],
665
+ "type": "object"
666
+ },
667
+ "moves": [],
668
+ "port": {
669
+ "allowedParties": [
670
+ "payer"
671
+ ]
672
+ },
673
+ "publicAction": "cancelMembershipMembership",
674
+ "steps": [],
675
+ "summary": "Cancel the open schedule and drain any period liability"
676
+ },
677
+ "collect_period": {
678
+ "captureInput": {
679
+ "mandateEvidenceReference": "evidenceReference"
680
+ },
681
+ "effects": {
682
+ "decides": [
683
+ {
684
+ "signature": "decides.tenant_port",
685
+ "source": "port"
686
+ }
687
+ ],
688
+ "moves": [
689
+ {
690
+ "signature": "moves.transfer.internal",
691
+ "source": "moves[0]"
692
+ }
693
+ ]
694
+ },
695
+ "input": {
696
+ "additionalProperties": false,
697
+ "properties": {
698
+ "evidenceReference": {
699
+ "description": "Required decision reference retained in the operation receipt",
700
+ "maxLength": 180,
701
+ "minLength": 1,
702
+ "type": "string"
703
+ }
704
+ },
705
+ "required": [
706
+ "evidenceReference"
707
+ ],
708
+ "type": "object"
709
+ },
710
+ "moves": [
711
+ {
712
+ "bind": {
713
+ "amount": {
714
+ "from": "instance",
715
+ "path": "fields.monthlyFee"
716
+ },
717
+ "currency": {
718
+ "from": "instance",
719
+ "path": "fields.currency"
720
+ },
721
+ "destinationAccountId": {
722
+ "from": "instance",
723
+ "path": "fields.clubAccountId"
724
+ },
725
+ "metadata.instrumentId": {
726
+ "from": "const",
727
+ "value": "membership"
728
+ },
729
+ "metadata.instrumentInstanceId": {
730
+ "from": "instance",
731
+ "path": "instrumentInstanceId"
732
+ },
733
+ "metadata.phase": {
734
+ "from": "const",
735
+ "value": "collect_period"
736
+ },
737
+ "productId": {
738
+ "from": "instance",
739
+ "path": "productId"
740
+ },
741
+ "sourceAccountId": {
742
+ "from": "instance",
743
+ "path": "fields.memberAccountId"
744
+ }
745
+ },
746
+ "capture": {
747
+ "collectPeriodPeriodCollectionTransferId": "transferId"
748
+ },
749
+ "key": "period_collection",
750
+ "operation": "internal_transfer.create"
751
+ }
752
+ ],
753
+ "port": {
754
+ "allowedParties": [
755
+ "payer"
756
+ ]
757
+ },
758
+ "publicAction": "collectPeriodMembership",
759
+ "steps": [],
760
+ "summary": "Collect one authored period charge with mandate evidence"
761
+ },
762
+ "create": {
763
+ "moves": [],
764
+ "publicAction": "createMembership",
765
+ "steps": [],
766
+ "summary": "Create the open obligation before its first anchor"
767
+ },
768
+ "open_period": {
769
+ "due": {
770
+ "every": {
771
+ "delinquency": "parent_policy",
772
+ "drainAction": "cancel_membership",
773
+ "liability": "one_open",
774
+ "period": {
775
+ "calendar": "gregorian",
776
+ "monthEnd": "clamp_to_last_day",
777
+ "months": 1
778
+ },
779
+ "untilAction": "cancel_membership"
780
+ },
781
+ "field": "firstPeriodAt"
782
+ },
783
+ "effects": {
784
+ "schedules": [
785
+ {
786
+ "signature": "schedules.due",
787
+ "source": "due"
788
+ }
789
+ ]
790
+ },
791
+ "moves": [],
792
+ "steps": [],
793
+ "summary": "Open exactly one period liability without moving money"
794
+ }
795
+ },
796
+ "description": "Open monthly obligation for member; one period liability at a time",
797
+ "fields": {
798
+ "clubAccountId": {
799
+ "description": "The club account",
800
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
801
+ "type": "string",
802
+ "x-hyperscale-reference-filter": {
803
+ "column": "role",
804
+ "values": [
805
+ "customer_balance"
806
+ ]
807
+ }
808
+ },
809
+ "currency": {
810
+ "const": "SAR",
811
+ "description": "ISO 4217 currency code",
812
+ "type": "string"
813
+ },
814
+ "firstPeriodAt": {
815
+ "description": "First period anchor; missing Gregorian month days clamp to the target month's final day",
816
+ "format": "hyperscale-date-time",
817
+ "type": "string"
818
+ },
819
+ "memberAccountId": {
820
+ "description": "The member account",
821
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
822
+ "type": "string",
823
+ "x-hyperscale-reference-filter": {
824
+ "column": "role",
825
+ "values": [
826
+ "customer_balance"
827
+ ]
828
+ }
829
+ },
830
+ "monthlyFee": {
831
+ "description": "Exact charge for one P1M period in SAR minor units",
832
+ "pattern": "^[1-9][0-9]{0,17}$",
833
+ "type": "string"
834
+ }
835
+ },
836
+ "id": "membership",
837
+ "idPrefix": "memb",
838
+ "lifecycle": {
839
+ "initial": "active",
840
+ "states": [
841
+ "active",
842
+ "period_open",
843
+ "canceled"
844
+ ],
845
+ "transitions": {
846
+ "cancel_membership": {
847
+ "from": [
848
+ "active",
849
+ "period_open"
850
+ ],
851
+ "to": "canceled"
852
+ },
853
+ "collect_period": {
854
+ "from": [
855
+ "period_open"
856
+ ],
857
+ "to": "active"
858
+ },
859
+ "open_period": {
860
+ "from": [
861
+ "active"
862
+ ],
863
+ "to": "period_open"
864
+ }
865
+ }
866
+ },
867
+ "parties": {
868
+ "beneficiary": "clubAccountId",
869
+ "payer": "memberAccountId"
870
+ },
871
+ "required": [
872
+ "memberAccountId",
873
+ "clubAccountId",
874
+ "monthlyFee",
875
+ "currency",
876
+ "firstPeriodAt"
877
+ ],
878
+ "summary": "Open P1M obligation for member",
879
+ "title": "Membership"
880
+ },
881
+ {
882
+ "actionOrder": [
883
+ "abandon",
884
+ "cancel",
885
+ "create",
886
+ "dispute",
887
+ "fund",
888
+ "post",
889
+ "release"
890
+ ],
891
+ "actions": {
892
+ "abandon": {
893
+ "moves": [],
894
+ "publicAction": "abandonMemberTrade",
895
+ "requiresDrainedAccount": {
896
+ "path": "refs.escrowAccountId"
897
+ },
898
+ "steps": [],
899
+ "summary": "Abandon the trade before its atomic funding batch"
900
+ },
901
+ "cancel": {
902
+ "effects": {
903
+ "moves": [
904
+ {
905
+ "signature": "moves.transfer.internal",
906
+ "source": "moves[0]"
907
+ },
908
+ {
909
+ "signature": "moves.transfer.internal",
910
+ "source": "moves[1]"
911
+ }
912
+ ]
913
+ },
914
+ "moves": [
915
+ {
916
+ "bind": {
917
+ "amount": {
918
+ "from": "instance",
919
+ "path": "fields.memberPays"
920
+ },
921
+ "currency": {
922
+ "from": "instance",
923
+ "path": "fields.currency"
924
+ },
925
+ "destinationAccountId": {
926
+ "from": "instance",
927
+ "path": "fields.memberAccountId"
928
+ },
929
+ "metadata.instrumentId": {
930
+ "from": "const",
931
+ "value": "member_trade"
932
+ },
933
+ "metadata.instrumentInstanceId": {
934
+ "from": "instance",
935
+ "path": "instrumentInstanceId"
936
+ },
937
+ "metadata.phase": {
938
+ "from": "const",
939
+ "value": "cancel"
940
+ },
941
+ "productId": {
942
+ "from": "instance",
943
+ "path": "productId"
944
+ },
945
+ "sourceAccountId": {
946
+ "from": "instance",
947
+ "path": "refs.escrowAccountId"
948
+ }
949
+ },
950
+ "capture": {
951
+ "cancelSideARefundTransferId": "transferId"
952
+ },
953
+ "key": "side_a_refund",
954
+ "operation": "internal_transfer.create"
955
+ },
956
+ {
957
+ "bind": {
958
+ "amount": {
959
+ "from": "instance",
960
+ "path": "fields.sellerPays"
961
+ },
962
+ "currency": {
963
+ "from": "instance",
964
+ "path": "fields.currency"
965
+ },
966
+ "destinationAccountId": {
967
+ "from": "instance",
968
+ "path": "fields.sellerAccountId"
969
+ },
970
+ "metadata.instrumentId": {
971
+ "from": "const",
972
+ "value": "member_trade"
973
+ },
974
+ "metadata.instrumentInstanceId": {
975
+ "from": "instance",
976
+ "path": "instrumentInstanceId"
977
+ },
978
+ "metadata.phase": {
979
+ "from": "const",
980
+ "value": "cancel"
981
+ },
982
+ "productId": {
983
+ "from": "instance",
984
+ "path": "productId"
985
+ },
986
+ "sourceAccountId": {
987
+ "from": "instance",
988
+ "path": "refs.escrowAccountId"
989
+ }
990
+ },
991
+ "capture": {
992
+ "cancelSideBRefundTransferId": "transferId"
993
+ },
994
+ "key": "side_b_refund",
995
+ "operation": "internal_transfer.create"
996
+ }
997
+ ],
998
+ "publicAction": "cancelMemberTrade",
999
+ "steps": [],
1000
+ "summary": "Cancel and return both trade principals atomically"
1001
+ },
1002
+ "create": {
1003
+ "moves": [],
1004
+ "publicAction": "createMemberTrade",
1005
+ "steps": [
1006
+ {
1007
+ "bind": {
1008
+ "currency": {
1009
+ "from": "instance",
1010
+ "path": "fields.currency"
1011
+ },
1012
+ "owner.id": {
1013
+ "from": "instance",
1014
+ "path": "productId"
1015
+ },
1016
+ "owner.type": {
1017
+ "from": "const",
1018
+ "value": "product"
1019
+ },
1020
+ "productId": {
1021
+ "from": "instance",
1022
+ "path": "productId"
1023
+ },
1024
+ "role": {
1025
+ "from": "const",
1026
+ "value": "product_escrow"
1027
+ }
1028
+ },
1029
+ "capture": {
1030
+ "escrowAccountId": "accountId"
1031
+ },
1032
+ "operation": "account.escrow.provision"
1033
+ }
1034
+ ],
1035
+ "summary": "Create a member trade atomic trade"
1036
+ },
1037
+ "dispute": {
1038
+ "deadline": {
1039
+ "field": "clawbackAt"
1040
+ },
1041
+ "effects": {
1042
+ "decides": [
1043
+ {
1044
+ "signature": "decides.tenant_port",
1045
+ "source": "port"
1046
+ }
1047
+ ],
1048
+ "moves": [
1049
+ {
1050
+ "signature": "moves.transfer.internal",
1051
+ "source": "moves[0]"
1052
+ },
1053
+ {
1054
+ "signature": "moves.transfer.internal",
1055
+ "source": "moves[1]"
1056
+ },
1057
+ {
1058
+ "signature": "moves.transfer.internal",
1059
+ "source": "moves[2]"
1060
+ },
1061
+ {
1062
+ "signature": "moves.transfer.internal",
1063
+ "source": "moves[3]"
1064
+ }
1065
+ ],
1066
+ "schedules": [
1067
+ {
1068
+ "signature": "schedules.deadline",
1069
+ "source": "deadline"
1070
+ }
1071
+ ]
1072
+ },
1073
+ "moves": [
1074
+ {
1075
+ "bind": {
1076
+ "reason": {
1077
+ "from": "const",
1078
+ "value": "Whole trade disputed inside the clawback window"
1079
+ },
1080
+ "transferId": {
1081
+ "from": "instance",
1082
+ "path": "refs.releaseSideATransferId"
1083
+ }
1084
+ },
1085
+ "key": "side_a_void",
1086
+ "operation": "internal_transfer.void"
1087
+ },
1088
+ {
1089
+ "bind": {
1090
+ "reason": {
1091
+ "from": "const",
1092
+ "value": "Whole trade disputed inside the clawback window"
1093
+ },
1094
+ "transferId": {
1095
+ "from": "instance",
1096
+ "path": "refs.releaseSideBTransferId"
1097
+ }
1098
+ },
1099
+ "key": "side_b_void",
1100
+ "operation": "internal_transfer.void"
1101
+ },
1102
+ {
1103
+ "bind": {
1104
+ "amount": {
1105
+ "from": "instance",
1106
+ "path": "fields.memberPays"
1107
+ },
1108
+ "currency": {
1109
+ "from": "instance",
1110
+ "path": "fields.currency"
1111
+ },
1112
+ "destinationAccountId": {
1113
+ "from": "instance",
1114
+ "path": "fields.memberAccountId"
1115
+ },
1116
+ "metadata.clawbackOfTransferId": {
1117
+ "from": "instance",
1118
+ "path": "refs.releaseSideATransferId"
1119
+ },
1120
+ "metadata.instrumentId": {
1121
+ "from": "const",
1122
+ "value": "member_trade"
1123
+ },
1124
+ "metadata.instrumentInstanceId": {
1125
+ "from": "instance",
1126
+ "path": "instrumentInstanceId"
1127
+ },
1128
+ "metadata.phase": {
1129
+ "from": "const",
1130
+ "value": "dispute"
1131
+ },
1132
+ "productId": {
1133
+ "from": "instance",
1134
+ "path": "productId"
1135
+ },
1136
+ "sourceAccountId": {
1137
+ "from": "instance",
1138
+ "path": "refs.escrowAccountId"
1139
+ }
1140
+ },
1141
+ "capture": {
1142
+ "disputeSideARefundTransferId": "transferId"
1143
+ },
1144
+ "key": "side_a_refund",
1145
+ "operation": "internal_transfer.create"
1146
+ },
1147
+ {
1148
+ "bind": {
1149
+ "amount": {
1150
+ "from": "instance",
1151
+ "path": "fields.sellerPays"
1152
+ },
1153
+ "currency": {
1154
+ "from": "instance",
1155
+ "path": "fields.currency"
1156
+ },
1157
+ "destinationAccountId": {
1158
+ "from": "instance",
1159
+ "path": "fields.sellerAccountId"
1160
+ },
1161
+ "metadata.clawbackOfTransferId": {
1162
+ "from": "instance",
1163
+ "path": "refs.releaseSideBTransferId"
1164
+ },
1165
+ "metadata.instrumentId": {
1166
+ "from": "const",
1167
+ "value": "member_trade"
1168
+ },
1169
+ "metadata.instrumentInstanceId": {
1170
+ "from": "instance",
1171
+ "path": "instrumentInstanceId"
1172
+ },
1173
+ "metadata.phase": {
1174
+ "from": "const",
1175
+ "value": "dispute"
1176
+ },
1177
+ "productId": {
1178
+ "from": "instance",
1179
+ "path": "productId"
1180
+ },
1181
+ "sourceAccountId": {
1182
+ "from": "instance",
1183
+ "path": "refs.escrowAccountId"
1184
+ }
1185
+ },
1186
+ "capture": {
1187
+ "disputeSideBRefundTransferId": "transferId"
1188
+ },
1189
+ "key": "side_b_refund",
1190
+ "operation": "internal_transfer.create"
1191
+ }
1192
+ ],
1193
+ "port": {
1194
+ "allowedParties": [
1195
+ "payer",
1196
+ "beneficiary"
1197
+ ]
1198
+ },
1199
+ "publicAction": "disputeMemberTrade",
1200
+ "steps": [],
1201
+ "summary": "Void both reservations, then refund both principals atomically"
1202
+ },
1203
+ "fund": {
1204
+ "effects": {
1205
+ "moves": [
1206
+ {
1207
+ "signature": "moves.collection.pay_in",
1208
+ "source": "moves[0]"
1209
+ },
1210
+ {
1211
+ "signature": "moves.collection.pay_in",
1212
+ "source": "moves[1]"
1213
+ },
1214
+ {
1215
+ "signature": "moves.transfer.internal",
1216
+ "source": "moves[2]"
1217
+ },
1218
+ {
1219
+ "signature": "moves.transfer.internal",
1220
+ "source": "moves[3]"
1221
+ }
1222
+ ]
1223
+ },
1224
+ "moves": [
1225
+ {
1226
+ "bind": {
1227
+ "amount": {
1228
+ "from": "instance",
1229
+ "path": "fields.memberPays"
1230
+ },
1231
+ "currency": {
1232
+ "from": "instance",
1233
+ "path": "fields.currency"
1234
+ },
1235
+ "destinationAccountId": {
1236
+ "from": "instance",
1237
+ "path": "refs.escrowAccountId"
1238
+ },
1239
+ "metadata.instrumentId": {
1240
+ "from": "const",
1241
+ "value": "member_trade"
1242
+ },
1243
+ "metadata.instrumentInstanceId": {
1244
+ "from": "instance",
1245
+ "path": "instrumentInstanceId"
1246
+ },
1247
+ "metadata.phase": {
1248
+ "from": "const",
1249
+ "value": "fund"
1250
+ },
1251
+ "productId": {
1252
+ "from": "instance",
1253
+ "path": "productId"
1254
+ },
1255
+ "sourceAccountId": {
1256
+ "from": "instance",
1257
+ "path": "fields.memberAccountId"
1258
+ }
1259
+ },
1260
+ "capture": {
1261
+ "fundSideAPrincipalTransferId": "transferId"
1262
+ },
1263
+ "key": "side_a_principal",
1264
+ "operation": "internal_transfer.create"
1265
+ },
1266
+ {
1267
+ "bind": {
1268
+ "amount": {
1269
+ "from": "instance",
1270
+ "path": "fields.sellerPays"
1271
+ },
1272
+ "currency": {
1273
+ "from": "instance",
1274
+ "path": "fields.currency"
1275
+ },
1276
+ "destinationAccountId": {
1277
+ "from": "instance",
1278
+ "path": "refs.escrowAccountId"
1279
+ },
1280
+ "metadata.instrumentId": {
1281
+ "from": "const",
1282
+ "value": "member_trade"
1283
+ },
1284
+ "metadata.instrumentInstanceId": {
1285
+ "from": "instance",
1286
+ "path": "instrumentInstanceId"
1287
+ },
1288
+ "metadata.phase": {
1289
+ "from": "const",
1290
+ "value": "fund"
1291
+ },
1292
+ "productId": {
1293
+ "from": "instance",
1294
+ "path": "productId"
1295
+ },
1296
+ "sourceAccountId": {
1297
+ "from": "instance",
1298
+ "path": "fields.sellerAccountId"
1299
+ }
1300
+ },
1301
+ "capture": {
1302
+ "fundSideBPrincipalTransferId": "transferId"
1303
+ },
1304
+ "key": "side_b_principal",
1305
+ "operation": "internal_transfer.create"
1306
+ },
1307
+ {
1308
+ "bind": {
1309
+ "amount": {
1310
+ "from": "instance",
1311
+ "path": "fields.memberTradeFee"
1312
+ },
1313
+ "currency": {
1314
+ "from": "instance",
1315
+ "path": "fields.currency"
1316
+ },
1317
+ "destinationAccountId": {
1318
+ "from": "instance",
1319
+ "path": "fields.platformAccountId"
1320
+ },
1321
+ "metadata.instrumentId": {
1322
+ "from": "const",
1323
+ "value": "member_trade"
1324
+ },
1325
+ "metadata.instrumentInstanceId": {
1326
+ "from": "instance",
1327
+ "path": "instrumentInstanceId"
1328
+ },
1329
+ "metadata.phase": {
1330
+ "from": "const",
1331
+ "value": "fund"
1332
+ },
1333
+ "productId": {
1334
+ "from": "instance",
1335
+ "path": "productId"
1336
+ },
1337
+ "sourceAccountId": {
1338
+ "from": "instance",
1339
+ "path": "fields.memberAccountId"
1340
+ }
1341
+ },
1342
+ "capture": {
1343
+ "fundSideAServiceFeeTransferId": "transferId"
1344
+ },
1345
+ "key": "side_a_service_fee",
1346
+ "operation": "internal_transfer.create"
1347
+ },
1348
+ {
1349
+ "bind": {
1350
+ "amount": {
1351
+ "from": "instance",
1352
+ "path": "fields.sellerTradeFee"
1353
+ },
1354
+ "currency": {
1355
+ "from": "instance",
1356
+ "path": "fields.currency"
1357
+ },
1358
+ "destinationAccountId": {
1359
+ "from": "instance",
1360
+ "path": "fields.platformAccountId"
1361
+ },
1362
+ "metadata.instrumentId": {
1363
+ "from": "const",
1364
+ "value": "member_trade"
1365
+ },
1366
+ "metadata.instrumentInstanceId": {
1367
+ "from": "instance",
1368
+ "path": "instrumentInstanceId"
1369
+ },
1370
+ "metadata.phase": {
1371
+ "from": "const",
1372
+ "value": "fund"
1373
+ },
1374
+ "productId": {
1375
+ "from": "instance",
1376
+ "path": "productId"
1377
+ },
1378
+ "sourceAccountId": {
1379
+ "from": "instance",
1380
+ "path": "fields.sellerAccountId"
1381
+ }
1382
+ },
1383
+ "capture": {
1384
+ "fundSideBServiceFeeTransferId": "transferId"
1385
+ },
1386
+ "key": "side_b_service_fee",
1387
+ "operation": "internal_transfer.create"
1388
+ }
1389
+ ],
1390
+ "publicAction": "fundMemberTrade",
1391
+ "steps": [],
1392
+ "summary": "Fund both trade sides and collect on-top fees atomically"
1393
+ },
1394
+ "post": {
1395
+ "due": {
1396
+ "field": "clawbackAt"
1397
+ },
1398
+ "effects": {
1399
+ "moves": [
1400
+ {
1401
+ "signature": "moves.transfer.internal",
1402
+ "source": "moves[0]"
1403
+ },
1404
+ {
1405
+ "signature": "moves.transfer.internal",
1406
+ "source": "moves[1]"
1407
+ }
1408
+ ],
1409
+ "schedules": [
1410
+ {
1411
+ "signature": "schedules.due",
1412
+ "source": "due"
1413
+ }
1414
+ ]
1415
+ },
1416
+ "moves": [
1417
+ {
1418
+ "bind": {
1419
+ "transferId": {
1420
+ "from": "instance",
1421
+ "path": "refs.releaseSideATransferId"
1422
+ }
1423
+ },
1424
+ "key": "side_a",
1425
+ "operation": "internal_transfer.post"
1426
+ },
1427
+ {
1428
+ "bind": {
1429
+ "transferId": {
1430
+ "from": "instance",
1431
+ "path": "refs.releaseSideBTransferId"
1432
+ }
1433
+ },
1434
+ "key": "side_b",
1435
+ "operation": "internal_transfer.post"
1436
+ }
1437
+ ],
1438
+ "steps": [],
1439
+ "summary": "Post both trade reservations when the clawback window matures"
1440
+ },
1441
+ "release": {
1442
+ "effects": {
1443
+ "decides": [
1444
+ {
1445
+ "signature": "decides.tenant_port",
1446
+ "source": "port"
1447
+ }
1448
+ ],
1449
+ "holds": [
1450
+ {
1451
+ "signature": "holds.reserve",
1452
+ "source": "moves[0]"
1453
+ },
1454
+ {
1455
+ "signature": "holds.reserve",
1456
+ "source": "moves[1]"
1457
+ }
1458
+ ],
1459
+ "moves": [
1460
+ {
1461
+ "signature": "moves.transfer.internal",
1462
+ "source": "moves[0]"
1463
+ },
1464
+ {
1465
+ "signature": "moves.transfer.internal",
1466
+ "source": "moves[1]"
1467
+ }
1468
+ ]
1469
+ },
1470
+ "moves": [
1471
+ {
1472
+ "bind": {
1473
+ "amount": {
1474
+ "from": "instance",
1475
+ "path": "fields.memberPays"
1476
+ },
1477
+ "currency": {
1478
+ "from": "instance",
1479
+ "path": "fields.currency"
1480
+ },
1481
+ "destinationAccountId": {
1482
+ "from": "instance",
1483
+ "path": "fields.sellerAccountId"
1484
+ },
1485
+ "metadata.clawbackAt": {
1486
+ "from": "instance",
1487
+ "path": "fields.clawbackAt"
1488
+ },
1489
+ "metadata.instrumentId": {
1490
+ "from": "const",
1491
+ "value": "member_trade"
1492
+ },
1493
+ "metadata.instrumentInstanceId": {
1494
+ "from": "instance",
1495
+ "path": "instrumentInstanceId"
1496
+ },
1497
+ "metadata.phase": {
1498
+ "from": "const",
1499
+ "value": "release"
1500
+ },
1501
+ "productId": {
1502
+ "from": "instance",
1503
+ "path": "productId"
1504
+ },
1505
+ "sourceAccountId": {
1506
+ "from": "instance",
1507
+ "path": "refs.escrowAccountId"
1508
+ }
1509
+ },
1510
+ "capture": {
1511
+ "releaseSideATransferId": "transferId"
1512
+ },
1513
+ "key": "side_a",
1514
+ "operation": "internal_transfer.reserve"
1515
+ },
1516
+ {
1517
+ "bind": {
1518
+ "amount": {
1519
+ "from": "instance",
1520
+ "path": "fields.sellerPays"
1521
+ },
1522
+ "currency": {
1523
+ "from": "instance",
1524
+ "path": "fields.currency"
1525
+ },
1526
+ "destinationAccountId": {
1527
+ "from": "instance",
1528
+ "path": "fields.memberAccountId"
1529
+ },
1530
+ "metadata.clawbackAt": {
1531
+ "from": "instance",
1532
+ "path": "fields.clawbackAt"
1533
+ },
1534
+ "metadata.instrumentId": {
1535
+ "from": "const",
1536
+ "value": "member_trade"
1537
+ },
1538
+ "metadata.instrumentInstanceId": {
1539
+ "from": "instance",
1540
+ "path": "instrumentInstanceId"
1541
+ },
1542
+ "metadata.phase": {
1543
+ "from": "const",
1544
+ "value": "release"
1545
+ },
1546
+ "productId": {
1547
+ "from": "instance",
1548
+ "path": "productId"
1549
+ },
1550
+ "sourceAccountId": {
1551
+ "from": "instance",
1552
+ "path": "refs.escrowAccountId"
1553
+ }
1554
+ },
1555
+ "capture": {
1556
+ "releaseSideBTransferId": "transferId"
1557
+ },
1558
+ "key": "side_b",
1559
+ "operation": "internal_transfer.reserve"
1560
+ }
1561
+ ],
1562
+ "port": {
1563
+ "allowedParties": [
1564
+ "payer",
1565
+ "beneficiary"
1566
+ ]
1567
+ },
1568
+ "publicAction": "releaseMemberTrade",
1569
+ "setsAt": {
1570
+ "field": "clawbackAt",
1571
+ "offset": "P14D"
1572
+ },
1573
+ "steps": [],
1574
+ "summary": "Reserve both cross-payments for the whole-trade clawback window"
1575
+ }
1576
+ },
1577
+ "description": "Atomic swap between member and seller; half-funded and half-released states do not exist",
1578
+ "distinctParties": true,
1579
+ "feeRules": [
1580
+ {
1581
+ "amountField": "memberTradeFee",
1582
+ "baseField": "memberPays",
1583
+ "bearerField": "memberAccountId",
1584
+ "position": "on_top",
1585
+ "rule": {
1586
+ "currencyField": "currency",
1587
+ "field": "memberTradeFee",
1588
+ "kind": "exact"
1589
+ }
1590
+ },
1591
+ {
1592
+ "amountField": "sellerTradeFee",
1593
+ "baseField": "sellerPays",
1594
+ "bearerField": "sellerAccountId",
1595
+ "position": "on_top",
1596
+ "rule": {
1597
+ "currencyField": "currency",
1598
+ "field": "sellerTradeFee",
1599
+ "kind": "exact"
1600
+ }
1601
+ }
1602
+ ],
1603
+ "fields": {
1604
+ "clawbackAt": {
1605
+ "description": "Machine-owned end of the P14D whole-trade dispute window",
1606
+ "format": "hyperscale-date-time",
1607
+ "type": "string"
1608
+ },
1609
+ "currency": {
1610
+ "description": "ISO 4217 currency code",
1611
+ "maxLength": 3,
1612
+ "minLength": 3,
1613
+ "pattern": "^[A-Z]{3}$",
1614
+ "type": "string"
1615
+ },
1616
+ "memberAccountId": {
1617
+ "description": "The member account",
1618
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1619
+ "type": "string",
1620
+ "x-hyperscale-reference-filter": {
1621
+ "column": "role",
1622
+ "values": [
1623
+ "customer_balance"
1624
+ ]
1625
+ }
1626
+ },
1627
+ "memberPays": {
1628
+ "description": "Side A amount in SAR minor units, held against the whole trade",
1629
+ "pattern": "^[1-9][0-9]{0,17}$",
1630
+ "type": "string"
1631
+ },
1632
+ "memberTradeFee": {
1633
+ "description": "Immutable exact member service fee in SAR minor units",
1634
+ "pattern": "^[1-9][0-9]{0,17}$",
1635
+ "type": "string"
1636
+ },
1637
+ "platformAccountId": {
1638
+ "description": "The product fee collection account",
1639
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1640
+ "type": "string",
1641
+ "x-hyperscale-fee-collection-port": true,
1642
+ "x-hyperscale-reference-filter": {
1643
+ "column": "role",
1644
+ "values": [
1645
+ "customer_balance",
1646
+ "product_revenue"
1647
+ ]
1648
+ }
1649
+ },
1650
+ "sellerAccountId": {
1651
+ "description": "The seller account",
1652
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1653
+ "type": "string",
1654
+ "x-hyperscale-reference-filter": {
1655
+ "column": "role",
1656
+ "values": [
1657
+ "customer_balance"
1658
+ ]
1659
+ }
1660
+ },
1661
+ "sellerPays": {
1662
+ "description": "Side B amount in SAR minor units, held against the whole trade",
1663
+ "pattern": "^[1-9][0-9]{0,17}$",
1664
+ "type": "string"
1665
+ },
1666
+ "sellerTradeFee": {
1667
+ "description": "Immutable exact seller service fee in SAR minor units",
1668
+ "pattern": "^[1-9][0-9]{0,17}$",
1669
+ "type": "string"
1670
+ }
1671
+ },
1672
+ "id": "member_trade",
1673
+ "idPrefix": "mt",
1674
+ "lifecycle": {
1675
+ "initial": "created",
1676
+ "states": [
1677
+ "created",
1678
+ "abandoned",
1679
+ "funded",
1680
+ "cancelled",
1681
+ "released",
1682
+ "settled",
1683
+ "clawed_back"
1684
+ ],
1685
+ "transitions": {
1686
+ "abandon": {
1687
+ "from": [
1688
+ "created"
1689
+ ],
1690
+ "to": "abandoned"
1691
+ },
1692
+ "cancel": {
1693
+ "from": [
1694
+ "funded"
1695
+ ],
1696
+ "to": "cancelled"
1697
+ },
1698
+ "dispute": {
1699
+ "from": [
1700
+ "released"
1701
+ ],
1702
+ "to": "clawed_back"
1703
+ },
1704
+ "fund": {
1705
+ "from": [
1706
+ "created"
1707
+ ],
1708
+ "to": "funded"
1709
+ },
1710
+ "post": {
1711
+ "from": [
1712
+ "released"
1713
+ ],
1714
+ "to": "settled"
1715
+ },
1716
+ "release": {
1717
+ "from": [
1718
+ "funded"
1719
+ ],
1720
+ "to": "released"
1721
+ }
1722
+ }
1723
+ },
1724
+ "parties": {
1725
+ "beneficiary": "sellerAccountId",
1726
+ "payer": "memberAccountId"
1727
+ },
1728
+ "required": [
1729
+ "memberAccountId",
1730
+ "sellerAccountId",
1731
+ "platformAccountId",
1732
+ "memberPays",
1733
+ "sellerPays",
1734
+ "memberTradeFee",
1735
+ "sellerTradeFee",
1736
+ "currency"
1737
+ ],
1738
+ "summary": "Two-party atomic trade between member and seller",
1739
+ "title": "Member trade"
1740
+ },
1741
+ {
1742
+ "actionOrder": [
1743
+ "create",
1744
+ "close",
1745
+ "calculate",
1746
+ "approve",
1747
+ "instruct",
1748
+ "acknowledge_payout",
1749
+ "reconcile"
1750
+ ],
1751
+ "actions": {
1752
+ "acknowledge_payout": {
1753
+ "captureInput": {
1754
+ "acknowledgementReference": "acknowledgementReference"
1755
+ },
1756
+ "effects": {
1757
+ "decides": [
1758
+ {
1759
+ "signature": "decides.tenant_port",
1760
+ "source": "port"
1761
+ }
1762
+ ]
1763
+ },
1764
+ "input": {
1765
+ "additionalProperties": false,
1766
+ "properties": {
1767
+ "acknowledgementReference": {
1768
+ "description": "Required decision reference retained in the operation receipt",
1769
+ "maxLength": 180,
1770
+ "minLength": 1,
1771
+ "type": "string"
1772
+ }
1773
+ },
1774
+ "required": [
1775
+ "acknowledgementReference"
1776
+ ],
1777
+ "type": "object"
1778
+ },
1779
+ "moves": [],
1780
+ "port": {
1781
+ "allowedParties": [
1782
+ "beneficiary"
1783
+ ]
1784
+ },
1785
+ "publicAction": "acknowledgePayoutSellerPayout",
1786
+ "steps": [],
1787
+ "summary": "Record the tenant's payout acknowledgement in the receipt"
1788
+ },
1789
+ "approve": {
1790
+ "moves": [],
1791
+ "publicAction": "approveSellerPayout",
1792
+ "steps": [],
1793
+ "summary": "Approve the frozen payable without recomputing it"
1794
+ },
1795
+ "calculate": {
1796
+ "moves": [],
1797
+ "publicAction": "calculateSellerPayout",
1798
+ "signedSum": {
1799
+ "amountRef": "netPayable",
1800
+ "onNegative": "refuse",
1801
+ "onZero": "refuse",
1802
+ "sources": [
1803
+ {
1804
+ "amountField": "amount",
1805
+ "instrumentId": "seller_payout_capture_entry",
1806
+ "refField": "sellerPayoutId",
1807
+ "sign": "add",
1808
+ "statuses": [
1809
+ "accrued"
1810
+ ],
1811
+ "subtotalRef": "grossCaptureAmount"
1812
+ },
1813
+ {
1814
+ "amountField": "amount",
1815
+ "instrumentId": "seller_payout_credit_adjustment",
1816
+ "refField": "sellerPayoutId",
1817
+ "sign": "add",
1818
+ "statuses": [
1819
+ "applied"
1820
+ ],
1821
+ "subtotalRef": "creditAdjustmentAmount"
1822
+ },
1823
+ {
1824
+ "amountField": "amount",
1825
+ "instrumentId": "seller_payout_debit_adjustment",
1826
+ "refField": "sellerPayoutId",
1827
+ "sign": "subtract",
1828
+ "statuses": [
1829
+ "applied"
1830
+ ],
1831
+ "subtotalRef": "debitAdjustmentAmount"
1832
+ }
1833
+ ]
1834
+ },
1835
+ "steps": [],
1836
+ "summary": "Prove and freeze the one signed net payable amount"
1837
+ },
1838
+ "close": {
1839
+ "due": {
1840
+ "field": "closeAt"
1841
+ },
1842
+ "effects": {
1843
+ "schedules": [
1844
+ {
1845
+ "signature": "schedules.due",
1846
+ "source": "due"
1847
+ }
1848
+ ]
1849
+ },
1850
+ "moves": [],
1851
+ "steps": [],
1852
+ "summary": "Freeze the batch and stop all new entries"
1853
+ },
1854
+ "create": {
1855
+ "moves": [],
1856
+ "publicAction": "createSellerPayout",
1857
+ "steps": [],
1858
+ "summary": "Open a seller payout"
1859
+ },
1860
+ "instruct": {
1861
+ "effects": {
1862
+ "moves": [
1863
+ {
1864
+ "signature": "moves.payout.external",
1865
+ "source": "payout"
1866
+ }
1867
+ ]
1868
+ },
1869
+ "moves": [],
1870
+ "payout": {
1871
+ "amount": "refs.netPayable",
1872
+ "beneficiaryField": "payoutBeneficiaryId",
1873
+ "beneficiaryPartyField": "payoutDestinationAccountId",
1874
+ "capture": "payoutId",
1875
+ "currencyField": "currency",
1876
+ "sourceAccountField": "clubAccountId",
1877
+ "speed": "standard"
1878
+ },
1879
+ "publicAction": "instructSellerPayout",
1880
+ "steps": [],
1881
+ "summary": "Create one idempotent payout from the frozen net payable"
1882
+ },
1883
+ "reconcile": {
1884
+ "due": {
1885
+ "field": "closeAt",
1886
+ "offset": "P30D"
1887
+ },
1888
+ "effects": {
1889
+ "reads": [
1890
+ {
1891
+ "signature": "reads.reconcile",
1892
+ "source": "reconcile[0]"
1893
+ }
1894
+ ],
1895
+ "schedules": [
1896
+ {
1897
+ "signature": "schedules.due",
1898
+ "source": "due"
1899
+ }
1900
+ ]
1901
+ },
1902
+ "moves": [],
1903
+ "reconcile": [
1904
+ {
1905
+ "amount": "refs.netPayable",
1906
+ "capture": "settlementEvidenceId",
1907
+ "counterpartyRef": "payoutId",
1908
+ "currencyField": "currency",
1909
+ "direction": "debit",
1910
+ "evidence": "statement_line",
1911
+ "exception": {
1912
+ "amountField": "amount",
1913
+ "childInstrumentId": "seller_payout_debit_adjustment",
1914
+ "maxOpen": 1,
1915
+ "reasonField": "adjustmentReference",
1916
+ "refField": "sellerPayoutId"
1917
+ },
1918
+ "match": {
1919
+ "law": "exact"
1920
+ },
1921
+ "within": {
1922
+ "offset": "P30D"
1923
+ }
1924
+ }
1925
+ ],
1926
+ "steps": [],
1927
+ "summary": "Match durable evidence that the payout settled"
1928
+ }
1929
+ },
1930
+ "description": "Immutable batch of capture lineage and signed adjustments that creates one payout",
1931
+ "fields": {
1932
+ "closeAt": {
1933
+ "description": "Date the open batch freezes against later entries",
1934
+ "format": "hyperscale-date-time",
1935
+ "type": "string"
1936
+ },
1937
+ "clubAccountId": {
1938
+ "description": "The club account",
1939
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1940
+ "type": "string",
1941
+ "x-hyperscale-reference-filter": {
1942
+ "column": "role",
1943
+ "values": [
1944
+ "customer_balance"
1945
+ ]
1946
+ }
1947
+ },
1948
+ "currency": {
1949
+ "description": "ISO 4217 currency code",
1950
+ "maxLength": 3,
1951
+ "minLength": 3,
1952
+ "pattern": "^[A-Z]{3}$",
1953
+ "type": "string"
1954
+ },
1955
+ "payoutBeneficiaryId": {
1956
+ "description": "Beneficiary ID for the payout instruction",
1957
+ "pattern": "^ben_(sandbox|live)_[a-z0-9]{8,64}$",
1958
+ "type": "string"
1959
+ },
1960
+ "payoutDestinationAccountId": {
1961
+ "description": "The payout destination account",
1962
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1963
+ "type": "string",
1964
+ "x-hyperscale-reference-filter": {
1965
+ "column": "role",
1966
+ "values": [
1967
+ "customer_balance"
1968
+ ]
1969
+ }
1970
+ }
1971
+ },
1972
+ "id": "seller_payout",
1973
+ "idPrefix": "sp",
1974
+ "lifecycle": {
1975
+ "initial": "open",
1976
+ "states": [
1977
+ "open",
1978
+ "closed",
1979
+ "calculated",
1980
+ "approved",
1981
+ "instructed",
1982
+ "acknowledged",
1983
+ "reconciled"
1984
+ ],
1985
+ "transitions": {
1986
+ "acknowledge_payout": {
1987
+ "from": [
1988
+ "instructed"
1989
+ ],
1990
+ "to": "acknowledged"
1991
+ },
1992
+ "approve": {
1993
+ "from": [
1994
+ "calculated"
1995
+ ],
1996
+ "to": "approved"
1997
+ },
1998
+ "calculate": {
1999
+ "from": [
2000
+ "closed"
2001
+ ],
2002
+ "to": "calculated"
2003
+ },
2004
+ "close": {
2005
+ "from": [
2006
+ "open"
2007
+ ],
2008
+ "to": "closed"
2009
+ },
2010
+ "instruct": {
2011
+ "from": [
2012
+ "approved"
2013
+ ],
2014
+ "to": "instructed"
2015
+ },
2016
+ "reconcile": {
2017
+ "from": [
2018
+ "instructed",
2019
+ "acknowledged"
2020
+ ],
2021
+ "to": "reconciled"
2022
+ }
2023
+ }
2024
+ },
2025
+ "parties": {
2026
+ "beneficiary": "payoutDestinationAccountId",
2027
+ "payer": "clubAccountId"
2028
+ },
2029
+ "required": [
2030
+ "payoutDestinationAccountId",
2031
+ "clubAccountId",
2032
+ "closeAt",
2033
+ "currency",
2034
+ "payoutBeneficiaryId"
2035
+ ],
2036
+ "summary": "Payout batch from club to payout destination",
2037
+ "title": "Seller payout"
2038
+ },
2039
+ {
2040
+ "actionOrder": [
2041
+ "create",
2042
+ "accrue"
2043
+ ],
2044
+ "actions": {
2045
+ "accrue": {
2046
+ "effects": {
2047
+ "reads": [
2048
+ {
2049
+ "signature": "reads.requires_refs",
2050
+ "source": "requiresRefs"
2051
+ }
2052
+ ]
2053
+ },
2054
+ "moves": [],
2055
+ "publicAction": "accrueSellerPayoutCaptureEntry",
2056
+ "requiresRefs": [
2057
+ {
2058
+ "field": "sellerPayoutId",
2059
+ "match": {
2060
+ "fields.currency": "fields.currency"
2061
+ },
2062
+ "statuses": [
2063
+ "open"
2064
+ ]
2065
+ }
2066
+ ],
2067
+ "steps": [],
2068
+ "summary": "Accrue the capture entry into the open batch"
2069
+ },
2070
+ "create": {
2071
+ "effects": {
2072
+ "reads": [
2073
+ {
2074
+ "signature": "reads.requires_refs",
2075
+ "source": "requiresRefs"
2076
+ }
2077
+ ]
2078
+ },
2079
+ "moves": [],
2080
+ "publicAction": "createSellerPayoutCaptureEntry",
2081
+ "requiresRefs": [
2082
+ {
2083
+ "field": "sellerPayoutId",
2084
+ "match": {
2085
+ "fields.currency": "fields.currency"
2086
+ },
2087
+ "statuses": [
2088
+ "open"
2089
+ ]
2090
+ }
2091
+ ],
2092
+ "steps": [],
2093
+ "summary": "Create a capture lineage entry on an open batch"
2094
+ }
2095
+ },
2096
+ "description": "One gross capture entry linked to an open payout batch",
2097
+ "fields": {
2098
+ "amount": {
2099
+ "description": "Gross captured amount in minor units",
2100
+ "pattern": "^[1-9][0-9]{0,17}$",
2101
+ "type": "string"
2102
+ },
2103
+ "captureReference": {
2104
+ "description": "Immutable source capture reference",
2105
+ "maxLength": 180,
2106
+ "minLength": 1,
2107
+ "type": "string"
2108
+ },
2109
+ "currency": {
2110
+ "description": "ISO 4217 currency code",
2111
+ "maxLength": 3,
2112
+ "minLength": 3,
2113
+ "pattern": "^[A-Z]{3}$",
2114
+ "type": "string"
2115
+ },
2116
+ "sellerPayoutId": {
2117
+ "description": "Open batch this capture entry accrues into",
2118
+ "pattern": "^sp_(sandbox|live)_[a-z0-9]{8,64}$",
2119
+ "type": "string"
2120
+ }
2121
+ },
2122
+ "id": "seller_payout_capture_entry",
2123
+ "idPrefix": "spce",
2124
+ "lifecycle": {
2125
+ "initial": "created",
2126
+ "states": [
2127
+ "created",
2128
+ "accrued"
2129
+ ],
2130
+ "transitions": {
2131
+ "accrue": {
2132
+ "from": [
2133
+ "created"
2134
+ ],
2135
+ "to": "accrued"
2136
+ }
2137
+ }
2138
+ },
2139
+ "required": [
2140
+ "amount",
2141
+ "currency",
2142
+ "sellerPayoutId",
2143
+ "captureReference"
2144
+ ],
2145
+ "summary": "Gross capture lineage entry",
2146
+ "title": "Seller payout Capture Entry"
2147
+ },
2148
+ {
2149
+ "actionOrder": [
2150
+ "create",
2151
+ "adjust",
2152
+ "correct"
2153
+ ],
2154
+ "actions": {
2155
+ "adjust": {
2156
+ "effects": {
2157
+ "reads": [
2158
+ {
2159
+ "signature": "reads.requires_refs",
2160
+ "source": "requiresRefs"
2161
+ }
2162
+ ]
2163
+ },
2164
+ "moves": [],
2165
+ "publicAction": "adjustSellerPayoutCreditAdjustment",
2166
+ "requiresRefs": [
2167
+ {
2168
+ "field": "sellerPayoutId",
2169
+ "match": {
2170
+ "fields.currency": "fields.currency"
2171
+ },
2172
+ "statuses": [
2173
+ "open"
2174
+ ]
2175
+ }
2176
+ ],
2177
+ "steps": [],
2178
+ "summary": "Apply the credit adjustment to the open batch"
2179
+ },
2180
+ "correct": {
2181
+ "effects": {
2182
+ "reads": [
2183
+ {
2184
+ "signature": "reads.requires_refs",
2185
+ "source": "requiresRefs"
2186
+ }
2187
+ ]
2188
+ },
2189
+ "moves": [],
2190
+ "publicAction": "correctSellerPayoutCreditAdjustment",
2191
+ "requiresRefs": [
2192
+ {
2193
+ "field": "sellerPayoutId",
2194
+ "match": {
2195
+ "fields.currency": "fields.currency"
2196
+ },
2197
+ "statuses": [
2198
+ "open"
2199
+ ]
2200
+ }
2201
+ ],
2202
+ "steps": [],
2203
+ "summary": "Record a later correction on this open batch instead of changing the closed source batch"
2204
+ },
2205
+ "create": {
2206
+ "effects": {
2207
+ "reads": [
2208
+ {
2209
+ "signature": "reads.requires_refs",
2210
+ "source": "requiresRefs"
2211
+ }
2212
+ ]
2213
+ },
2214
+ "moves": [],
2215
+ "publicAction": "createSellerPayoutCreditAdjustment",
2216
+ "requiresRefs": [
2217
+ {
2218
+ "field": "sellerPayoutId",
2219
+ "match": {
2220
+ "fields.currency": "fields.currency"
2221
+ },
2222
+ "statuses": [
2223
+ "open"
2224
+ ]
2225
+ }
2226
+ ],
2227
+ "steps": [],
2228
+ "summary": "Create a credit adjustment on an open batch"
2229
+ }
2230
+ },
2231
+ "description": "One credit adjustment linked to an open payout batch; closed batches stay unchanged",
2232
+ "fields": {
2233
+ "adjustmentReference": {
2234
+ "description": "Immutable explicit adjustment reference",
2235
+ "maxLength": 180,
2236
+ "minLength": 1,
2237
+ "type": "string"
2238
+ },
2239
+ "amount": {
2240
+ "description": "Credit adjustment amount in minor units",
2241
+ "pattern": "^[1-9][0-9]{0,17}$",
2242
+ "type": "string"
2243
+ },
2244
+ "captureReference": {
2245
+ "description": "Original capture reference that this adjustment corrects",
2246
+ "maxLength": 180,
2247
+ "minLength": 1,
2248
+ "type": "string"
2249
+ },
2250
+ "currency": {
2251
+ "description": "ISO 4217 currency code",
2252
+ "maxLength": 3,
2253
+ "minLength": 3,
2254
+ "pattern": "^[A-Z]{3}$",
2255
+ "type": "string"
2256
+ },
2257
+ "externalReversalReference": {
2258
+ "description": "Optional externally decided reversal reference",
2259
+ "maxLength": 180,
2260
+ "minLength": 1,
2261
+ "type": "string"
2262
+ },
2263
+ "feeReference": {
2264
+ "description": "Optional fee entry reference",
2265
+ "maxLength": 180,
2266
+ "minLength": 1,
2267
+ "type": "string"
2268
+ },
2269
+ "sellerPayoutId": {
2270
+ "description": "Open batch this adjustment applies to",
2271
+ "pattern": "^sp_(sandbox|live)_[a-z0-9]{8,64}$",
2272
+ "type": "string"
2273
+ }
2274
+ },
2275
+ "id": "seller_payout_credit_adjustment",
2276
+ "idPrefix": "spca",
2277
+ "lifecycle": {
2278
+ "initial": "created",
2279
+ "states": [
2280
+ "created",
2281
+ "applied"
2282
+ ],
2283
+ "transitions": {
2284
+ "adjust": {
2285
+ "from": [
2286
+ "created"
2287
+ ],
2288
+ "to": "applied"
2289
+ },
2290
+ "correct": {
2291
+ "from": [
2292
+ "created"
2293
+ ],
2294
+ "to": "applied"
2295
+ }
2296
+ }
2297
+ },
2298
+ "required": [
2299
+ "amount",
2300
+ "currency",
2301
+ "adjustmentReference",
2302
+ "sellerPayoutId",
2303
+ "captureReference"
2304
+ ],
2305
+ "summary": "Credit adjustment with capture lineage",
2306
+ "title": "Seller payout Credit Adjustment"
2307
+ },
2308
+ {
2309
+ "actionOrder": [
2310
+ "create",
2311
+ "adjust",
2312
+ "correct"
2313
+ ],
2314
+ "actions": {
2315
+ "adjust": {
2316
+ "effects": {
2317
+ "reads": [
2318
+ {
2319
+ "signature": "reads.requires_refs",
2320
+ "source": "requiresRefs"
2321
+ }
2322
+ ]
2323
+ },
2324
+ "moves": [],
2325
+ "publicAction": "adjustSellerPayoutDebitAdjustment",
2326
+ "requiresRefs": [
2327
+ {
2328
+ "field": "sellerPayoutId",
2329
+ "match": {
2330
+ "fields.currency": "fields.currency"
2331
+ },
2332
+ "statuses": [
2333
+ "open"
2334
+ ]
2335
+ }
2336
+ ],
2337
+ "steps": [],
2338
+ "summary": "Apply the debit adjustment to the open batch"
2339
+ },
2340
+ "correct": {
2341
+ "effects": {
2342
+ "reads": [
2343
+ {
2344
+ "signature": "reads.requires_refs",
2345
+ "source": "requiresRefs"
2346
+ }
2347
+ ]
2348
+ },
2349
+ "moves": [],
2350
+ "publicAction": "correctSellerPayoutDebitAdjustment",
2351
+ "requiresRefs": [
2352
+ {
2353
+ "field": "sellerPayoutId",
2354
+ "match": {
2355
+ "fields.currency": "fields.currency"
2356
+ },
2357
+ "statuses": [
2358
+ "open"
2359
+ ]
2360
+ }
2361
+ ],
2362
+ "steps": [],
2363
+ "summary": "Record a later correction on this open batch instead of changing the closed source batch"
2364
+ },
2365
+ "create": {
2366
+ "effects": {
2367
+ "reads": [
2368
+ {
2369
+ "signature": "reads.requires_refs",
2370
+ "source": "requiresRefs"
2371
+ }
2372
+ ]
2373
+ },
2374
+ "moves": [],
2375
+ "publicAction": "createSellerPayoutDebitAdjustment",
2376
+ "requiresRefs": [
2377
+ {
2378
+ "field": "sellerPayoutId",
2379
+ "match": {
2380
+ "fields.currency": "fields.currency"
2381
+ },
2382
+ "statuses": [
2383
+ "open"
2384
+ ]
2385
+ }
2386
+ ],
2387
+ "steps": [],
2388
+ "summary": "Create a debit adjustment on an open batch"
2389
+ }
2390
+ },
2391
+ "description": "One debit adjustment linked to an open payout batch; closed batches stay unchanged",
2392
+ "fields": {
2393
+ "adjustmentReference": {
2394
+ "description": "Immutable explicit adjustment reference",
2395
+ "maxLength": 180,
2396
+ "minLength": 1,
2397
+ "type": "string"
2398
+ },
2399
+ "amount": {
2400
+ "description": "Debit adjustment amount in minor units",
2401
+ "pattern": "^[1-9][0-9]{0,17}$",
2402
+ "type": "string"
2403
+ },
2404
+ "captureReference": {
2405
+ "description": "Original capture reference that this adjustment corrects",
2406
+ "maxLength": 180,
2407
+ "minLength": 1,
2408
+ "type": "string"
2409
+ },
2410
+ "currency": {
2411
+ "description": "ISO 4217 currency code",
2412
+ "maxLength": 3,
2413
+ "minLength": 3,
2414
+ "pattern": "^[A-Z]{3}$",
2415
+ "type": "string"
2416
+ },
2417
+ "externalReversalReference": {
2418
+ "description": "Optional externally decided reversal reference",
2419
+ "maxLength": 180,
2420
+ "minLength": 1,
2421
+ "type": "string"
2422
+ },
2423
+ "feeReference": {
2424
+ "description": "Optional fee entry reference",
2425
+ "maxLength": 180,
2426
+ "minLength": 1,
2427
+ "type": "string"
2428
+ },
2429
+ "sellerPayoutId": {
2430
+ "description": "Open batch this adjustment applies to",
2431
+ "pattern": "^sp_(sandbox|live)_[a-z0-9]{8,64}$",
2432
+ "type": "string"
2433
+ }
2434
+ },
2435
+ "id": "seller_payout_debit_adjustment",
2436
+ "idPrefix": "spda",
2437
+ "lifecycle": {
2438
+ "initial": "created",
2439
+ "states": [
2440
+ "created",
2441
+ "applied"
2442
+ ],
2443
+ "transitions": {
2444
+ "adjust": {
2445
+ "from": [
2446
+ "created"
2447
+ ],
2448
+ "to": "applied"
2449
+ },
2450
+ "correct": {
2451
+ "from": [
2452
+ "created"
2453
+ ],
2454
+ "to": "applied"
2455
+ }
2456
+ }
2457
+ },
2458
+ "required": [
2459
+ "amount",
2460
+ "currency",
2461
+ "adjustmentReference",
2462
+ "sellerPayoutId",
2463
+ "captureReference"
2464
+ ],
2465
+ "summary": "Debit adjustment with capture lineage",
2466
+ "title": "Seller payout Debit Adjustment"
2467
+ }
2468
+ ],
2469
+ "product": "watch_club",
2470
+ "subjects": [
2471
+ {
2472
+ "declaredValue": "optional",
2473
+ "kind": "watch",
2474
+ "schema": {
2475
+ "additionalProperties": false,
2476
+ "properties": {},
2477
+ "type": "object"
2478
+ },
2479
+ "title": "Watch",
2480
+ "version": 1
2481
+ }
2482
+ ],
2483
+ "title": "Watch club",
2484
+ "udl": 1,
2485
+ "version": 1
2486
+ }