@hyperscale0/hsx 1.0.0 → 1.0.124

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 (316) hide show
  1. package/CHANGELOG.md +5 -256
  2. package/LICENSE.md +356 -0
  3. package/NOTICE.md +8 -0
  4. package/README.md +44 -44
  5. package/bin/hsx.ts +0 -7
  6. package/dist/bin/hsx.d.ts +0 -4
  7. package/dist/bin/hsx.d.ts.map +1 -1
  8. package/dist/bin/hsx.js +0 -6
  9. package/dist/bin/hsx.js.map +1 -1
  10. package/dist/src/ast.d.ts +113 -308
  11. package/dist/src/ast.d.ts.map +1 -1
  12. package/dist/src/ast.js +7 -71
  13. package/dist/src/ast.js.map +1 -1
  14. package/dist/src/attachment-economics.d.ts +5 -0
  15. package/dist/src/attachment-economics.d.ts.map +1 -0
  16. package/dist/src/attachment-economics.js +55 -0
  17. package/dist/src/attachment-economics.js.map +1 -0
  18. package/dist/src/binding-contract.d.ts +22 -0
  19. package/dist/src/binding-contract.d.ts.map +1 -0
  20. package/dist/src/binding-contract.js +74 -0
  21. package/dist/src/binding-contract.js.map +1 -0
  22. package/dist/src/cli.d.ts +4 -19
  23. package/dist/src/cli.d.ts.map +1 -1
  24. package/dist/src/cli.js +89 -276
  25. package/dist/src/cli.js.map +1 -1
  26. package/dist/src/compile.d.ts +34 -66
  27. package/dist/src/compile.d.ts.map +1 -1
  28. package/dist/src/compile.js +2949 -117
  29. package/dist/src/compile.js.map +1 -1
  30. package/dist/src/cost.d.ts +8 -75
  31. package/dist/src/cost.d.ts.map +1 -1
  32. package/dist/src/cost.js +54 -364
  33. package/dist/src/cost.js.map +1 -1
  34. package/dist/src/diagnostics.d.ts +14 -9
  35. package/dist/src/diagnostics.d.ts.map +1 -1
  36. package/dist/src/diagnostics.js +39 -416
  37. package/dist/src/diagnostics.js.map +1 -1
  38. package/dist/src/examples-bundle.d.ts +3 -0
  39. package/dist/src/examples-bundle.d.ts.map +1 -0
  40. package/dist/src/examples-bundle.js +18 -0
  41. package/dist/src/examples-bundle.js.map +1 -0
  42. package/dist/src/examples.d.ts +10 -0
  43. package/dist/src/examples.d.ts.map +1 -0
  44. package/dist/src/examples.js +2 -0
  45. package/dist/src/examples.js.map +1 -0
  46. package/dist/src/format.d.ts +8 -7
  47. package/dist/src/format.d.ts.map +1 -1
  48. package/dist/src/format.js +9 -175
  49. package/dist/src/format.js.map +1 -1
  50. package/dist/src/header-source.d.ts +3 -0
  51. package/dist/src/header-source.d.ts.map +1 -0
  52. package/dist/src/header-source.js +41 -0
  53. package/dist/src/header-source.js.map +1 -0
  54. package/dist/src/headers.d.ts +64 -0
  55. package/dist/src/headers.d.ts.map +1 -0
  56. package/dist/src/headers.js +167 -0
  57. package/dist/src/headers.js.map +1 -0
  58. package/dist/src/index.d.ts +7 -11
  59. package/dist/src/index.d.ts.map +1 -1
  60. package/dist/src/index.js +4 -9
  61. package/dist/src/index.js.map +1 -1
  62. package/dist/src/keywords.d.ts +56 -0
  63. package/dist/src/keywords.d.ts.map +1 -0
  64. package/dist/src/keywords.js +133 -0
  65. package/dist/src/keywords.js.map +1 -0
  66. package/dist/src/language.d.ts +26 -0
  67. package/dist/src/language.d.ts.map +1 -0
  68. package/dist/src/language.js +440 -0
  69. package/dist/src/language.js.map +1 -0
  70. package/dist/src/lex.d.ts +13 -28
  71. package/dist/src/lex.d.ts.map +1 -1
  72. package/dist/src/lex.js +119 -145
  73. package/dist/src/lex.js.map +1 -1
  74. package/dist/src/parse.d.ts +4 -17
  75. package/dist/src/parse.d.ts.map +1 -1
  76. package/dist/src/parse.js +484 -1036
  77. package/dist/src/parse.js.map +1 -1
  78. package/dist/src/std-bundle.d.ts.map +1 -1
  79. package/dist/src/std-bundle.js +11 -84
  80. package/dist/src/std-bundle.js.map +1 -1
  81. package/dist/src/std-library.d.ts +1 -1
  82. package/dist/src/std-library.d.ts.map +1 -1
  83. package/dist/src/std-library.js +1 -5
  84. package/dist/src/std-library.js.map +1 -1
  85. package/dist/src/tunables.d.ts +7 -0
  86. package/dist/src/tunables.d.ts.map +1 -0
  87. package/dist/src/tunables.js +27 -0
  88. package/dist/src/tunables.js.map +1 -0
  89. package/docs/README.md +528 -26
  90. package/docs/assets/brand/hsx-horizontal-white.svg +1 -0
  91. package/docs/assets/brand/hsx-horizontal.svg +1 -0
  92. package/docs/assets/brand/hsx-stacked-white.svg +1 -0
  93. package/docs/assets/brand/hsx-stacked.svg +1 -0
  94. package/docs/assets/brand/manifest.json +30 -0
  95. package/docs/assets/hsx.svg +11 -0
  96. package/examples/cards.hsx +34 -0
  97. package/examples/collections.hsx +37 -0
  98. package/examples/cost-table.json +633 -385
  99. package/examples/escrow.hsx +24 -0
  100. package/examples/financing.hsx +32 -0
  101. package/examples/insurance.hsx +30 -0
  102. package/examples/lending.hsx +57 -0
  103. package/examples/library.hsx +15 -0
  104. package/examples/marketplace.hsx +32 -0
  105. package/examples/money.hsx +19 -0
  106. package/examples/rental-deposit.hsx +60 -0
  107. package/examples/repair-approval.hsx +44 -0
  108. package/examples/reporting.hsx +28 -0
  109. package/examples/savings.hsx +21 -0
  110. package/examples/serviced.hsx +25 -0
  111. package/examples/wallet.hsx +24 -0
  112. package/package.json +25 -23
  113. package/src/ast.ts +83 -440
  114. package/src/attachment-economics.ts +103 -0
  115. package/src/binding-contract.ts +104 -0
  116. package/src/cli.ts +95 -325
  117. package/src/compile.ts +4063 -209
  118. package/src/cost.ts +71 -574
  119. package/src/diagnostics.ts +57 -437
  120. package/src/examples-bundle.ts +19 -0
  121. package/src/examples.ts +9 -0
  122. package/src/format.ts +12 -256
  123. package/src/header-source.ts +54 -0
  124. package/src/headers.ts +195 -0
  125. package/src/index.ts +18 -33
  126. package/src/keywords.ts +134 -0
  127. package/src/language.ts +629 -0
  128. package/src/lex.ts +131 -192
  129. package/src/parse.ts +489 -1195
  130. package/src/std-bundle.ts +12 -88
  131. package/src/std-library.ts +2 -7
  132. package/src/tunables.ts +36 -0
  133. package/std/cards.hsx +85 -0
  134. package/std/collections.hsx +90 -0
  135. package/std/escrow.hsx +73 -0
  136. package/std/financing.hsx +683 -0
  137. package/std/insurance.hsx +89 -0
  138. package/std/lending.hsx +138 -0
  139. package/std/marketplace.hsx +123 -0
  140. package/std/money.hsx +173 -0
  141. package/std/reporting.hsx +753 -0
  142. package/std/savings.hsx +68 -0
  143. package/std/wallet.hsx +57 -0
  144. package/LICENSE +0 -661
  145. package/LICENSING.md +0 -52
  146. package/TRADEMARKS.md +0 -35
  147. package/dist/src/emit.d.ts +0 -34
  148. package/dist/src/emit.d.ts.map +0 -1
  149. package/dist/src/emit.js +0 -137
  150. package/dist/src/emit.js.map +0 -1
  151. package/dist/src/entry-overrides.d.ts +0 -58
  152. package/dist/src/entry-overrides.d.ts.map +0 -1
  153. package/dist/src/entry-overrides.js +0 -284
  154. package/dist/src/entry-overrides.js.map +0 -1
  155. package/dist/src/ir.d.ts +0 -66
  156. package/dist/src/ir.d.ts.map +0 -1
  157. package/dist/src/ir.js +0 -15
  158. package/dist/src/ir.js.map +0 -1
  159. package/dist/src/limits.d.ts +0 -21
  160. package/dist/src/limits.d.ts.map +0 -1
  161. package/dist/src/limits.js +0 -21
  162. package/dist/src/limits.js.map +0 -1
  163. package/dist/src/lsp/server.d.ts +0 -32
  164. package/dist/src/lsp/server.d.ts.map +0 -1
  165. package/dist/src/lsp/server.js +0 -391
  166. package/dist/src/lsp/server.js.map +0 -1
  167. package/dist/src/modules.d.ts +0 -38
  168. package/dist/src/modules.d.ts.map +0 -1
  169. package/dist/src/modules.js +0 -368
  170. package/dist/src/modules.js.map +0 -1
  171. package/dist/src/typecheck.d.ts +0 -8
  172. package/dist/src/typecheck.d.ts.map +0 -1
  173. package/dist/src/typecheck.js +0 -2958
  174. package/dist/src/typecheck.js.map +0 -1
  175. package/dist/src/version.d.ts +0 -5
  176. package/dist/src/version.d.ts.map +0 -1
  177. package/dist/src/version.js +0 -5
  178. package/dist/src/version.js.map +0 -1
  179. package/docs/guide/01-first-program.md +0 -24
  180. package/docs/guide/02-money.md +0 -25
  181. package/docs/guide/03-instruments.md +0 -22
  182. package/docs/guide/04-lifecycles.md +0 -25
  183. package/docs/guide/05-fees-and-splits.md +0 -45
  184. package/docs/guide/06-schedules.md +0 -22
  185. package/docs/guide/07-composition.md +0 -46
  186. package/docs/guide/08-writing-a-module.md +0 -26
  187. package/docs/guide/09-cost.md +0 -24
  188. package/docs/guide/10-diagnostics.md +0 -27
  189. package/docs/llms-full.txt +0 -1739
  190. package/docs/llms.txt +0 -45
  191. package/docs/playground.md +0 -54
  192. package/docs/reference/cli.md +0 -35
  193. package/docs/reference/diagnostics.md +0 -619
  194. package/docs/reference/grammar.md +0 -39
  195. package/docs/reference/std/advance.md +0 -35
  196. package/docs/reference/std/cancellable_booking.md +0 -35
  197. package/docs/reference/std/captured_payment.md +0 -43
  198. package/docs/reference/std/conditional_disbursement.md +0 -33
  199. package/docs/reference/std/credit_facility.md +0 -35
  200. package/docs/reference/std/held_payment.md +0 -64
  201. package/docs/reference/std/instant_transfer.md +0 -30
  202. package/docs/reference/std/metered.md +0 -27
  203. package/docs/reference/std/pooled_split.md +0 -26
  204. package/docs/reference/std/premium_forward.md +0 -39
  205. package/docs/reference/std/reconciled_payout.md +0 -33
  206. package/docs/reference/std/recurring_collection.md +0 -25
  207. package/docs/reference/std/rotating_pool.md +0 -42
  208. package/docs/reference/std/scheduled.md +0 -51
  209. package/docs/reference/std/security_deposit.md +0 -46
  210. package/docs/reference/std/settlement_batch.md +0 -42
  211. package/docs/reference/std/swap.md +0 -46
  212. package/docs/reference/std/threshold_pool.md +0 -47
  213. package/docs/reference/std/weighted_distribution.md +0 -39
  214. package/docs/reference/types.md +0 -20
  215. package/docs/reference/udl-output.md +0 -13
  216. package/docs/sessions/2026-09-02-two-instruments.hsx +0 -21
  217. package/docs/sessions/2026-09-02-two-instruments.md +0 -41
  218. package/examples/01-first-program/README.md +0 -45
  219. package/examples/01-first-program/tip-jar.hsx +0 -17
  220. package/examples/02-imports-and-archetypes/README.md +0 -96
  221. package/examples/02-imports-and-archetypes/photo-booth.hsx +0 -37
  222. package/examples/03-diagnostics/README.md +0 -68
  223. package/examples/03-diagnostics/corner-shop-fixed.hsx +0 -22
  224. package/examples/03-diagnostics/corner-shop.hsx +0 -19
  225. package/examples/04-complete-product/README.md +0 -84
  226. package/examples/04-complete-product/study-hall.hsx +0 -67
  227. package/examples/05-watch-club/README.md +0 -9
  228. package/examples/05-watch-club/watch-club.hsx +0 -124
  229. package/examples/README.md +0 -18
  230. package/examples/advance/README.md +0 -3
  231. package/examples/advance/advance.hsx +0 -13
  232. package/examples/advance/advance.udl +0 -339
  233. package/examples/cancellable_booking/README.md +0 -3
  234. package/examples/cancellable_booking/cancellable_booking.hsx +0 -14
  235. package/examples/cancellable_booking/cancellable_booking.udl +0 -391
  236. package/examples/captured_payment/README.md +0 -3
  237. package/examples/captured_payment/captured_payment.hsx +0 -21
  238. package/examples/captured_payment/captured_payment.udl +0 -677
  239. package/examples/conditional_disbursement/README.md +0 -3
  240. package/examples/conditional_disbursement/conditional_disbursement.hsx +0 -17
  241. package/examples/conditional_disbursement/conditional_disbursement.udl +0 -412
  242. package/examples/credit_facility/README.md +0 -3
  243. package/examples/credit_facility/credit_facility.hsx +0 -27
  244. package/examples/credit_facility/credit_facility.udl +0 -1373
  245. package/examples/held_payment/README.md +0 -3
  246. package/examples/held_payment/held_payment.hsx +0 -13
  247. package/examples/held_payment/held_payment.udl +0 -507
  248. package/examples/instant_transfer/README.md +0 -3
  249. package/examples/instant_transfer/instant_transfer.hsx +0 -16
  250. package/examples/instant_transfer/instant_transfer.udl +0 -364
  251. package/examples/metered/README.md +0 -3
  252. package/examples/metered/metered.hsx +0 -13
  253. package/examples/metered/metered.udl +0 -247
  254. package/examples/pooled_split/README.md +0 -3
  255. package/examples/pooled_split/pooled_split.hsx +0 -15
  256. package/examples/pooled_split/pooled_split.udl +0 -425
  257. package/examples/premium_forward/README.md +0 -3
  258. package/examples/premium_forward/premium_forward.hsx +0 -19
  259. package/examples/premium_forward/premium_forward.udl +0 -594
  260. package/examples/reconciled_payout/README.md +0 -3
  261. package/examples/reconciled_payout/reconciled_payout.hsx +0 -13
  262. package/examples/reconciled_payout/reconciled_payout.udl +0 -303
  263. package/examples/recurring_collection/README.md +0 -3
  264. package/examples/recurring_collection/recurring_collection.hsx +0 -21
  265. package/examples/recurring_collection/recurring_collection.udl +0 -1130
  266. package/examples/rotating_pool/README.md +0 -3
  267. package/examples/rotating_pool/rotating_pool.hsx +0 -18
  268. package/examples/rotating_pool/rotating_pool.udl +0 -4352
  269. package/examples/scheduled/README.md +0 -3
  270. package/examples/scheduled/scheduled.hsx +0 -12
  271. package/examples/scheduled/scheduled.udl +0 -335
  272. package/examples/security_deposit/README.md +0 -3
  273. package/examples/security_deposit/security_deposit.hsx +0 -21
  274. package/examples/security_deposit/security_deposit.udl +0 -293
  275. package/examples/settlement_batch/README.md +0 -3
  276. package/examples/settlement_batch/settlement_batch.hsx +0 -19
  277. package/examples/settlement_batch/settlement_batch.udl +0 -753
  278. package/examples/swap/README.md +0 -3
  279. package/examples/swap/swap.hsx +0 -19
  280. package/examples/swap/swap.udl +0 -876
  281. package/examples/threshold_pool/README.md +0 -3
  282. package/examples/threshold_pool/threshold_pool.hsx +0 -16
  283. package/examples/threshold_pool/threshold_pool.udl +0 -667
  284. package/examples/weighted_distribution/README.md +0 -3
  285. package/examples/weighted_distribution/weighted_distribution.hsx +0 -20
  286. package/examples/weighted_distribution/weighted_distribution.udl +0 -337
  287. package/skills/hsx/SKILL.md +0 -483
  288. package/src/emit.ts +0 -201
  289. package/src/entry-overrides.ts +0 -428
  290. package/src/ir.ts +0 -99
  291. package/src/limits.ts +0 -20
  292. package/src/lsp/server.ts +0 -460
  293. package/src/modules.ts +0 -446
  294. package/src/typecheck.ts +0 -3876
  295. package/src/version.ts +0 -5
  296. package/std/SEMANTICS.md +0 -130
  297. package/std/settlements/advance.hsx +0 -177
  298. package/std/settlements/cancellable_booking.hsx +0 -87
  299. package/std/settlements/captured_payment.hsx +0 -144
  300. package/std/settlements/conditional_disbursement.hsx +0 -185
  301. package/std/settlements/credit_facility.hsx +0 -167
  302. package/std/settlements/held_payment.hsx +0 -578
  303. package/std/settlements/index.hsx +0 -3
  304. package/std/settlements/instant_transfer.hsx +0 -190
  305. package/std/settlements/metered.hsx +0 -67
  306. package/std/settlements/pooled_split.hsx +0 -68
  307. package/std/settlements/premium_forward.hsx +0 -257
  308. package/std/settlements/reconciled_payout.hsx +0 -77
  309. package/std/settlements/recurring_collection.hsx +0 -27
  310. package/std/settlements/rotating_pool.hsx +0 -252
  311. package/std/settlements/scheduled.hsx +0 -641
  312. package/std/settlements/security_deposit.hsx +0 -166
  313. package/std/settlements/settlement_batch.hsx +0 -122
  314. package/std/settlements/swap.hsx +0 -1114
  315. package/std/settlements/threshold_pool.hsx +0 -221
  316. package/std/settlements/weighted_distribution.hsx +0 -141
@@ -1,1373 +0,0 @@
1
- {
2
- "instruments": [
3
- {
4
- "actionOrder": [
5
- "create",
6
- "approve",
7
- "collect_installment_1",
8
- "mark_installment_1_delinquent",
9
- "collect_installment_2",
10
- "mark_installment_2_delinquent",
11
- "complete",
12
- "write_off"
13
- ],
14
- "actions": {
15
- "approve": {
16
- "agentDescription": "Approve the draft obligation and freeze its principal partition and due anchors. The obligation must be in draft. No money moves. Where the product advances funds, approve is what makes advance available.",
17
- "moves": [],
18
- "publicAction": "approveRepayment",
19
- "steps": [],
20
- "summary": "Approve the immutable principal partition and stored anchors"
21
- },
22
- "collect_installment_1": {
23
- "due": {
24
- "field": "firstDueAt"
25
- },
26
- "effects": {
27
- "reads": [
28
- {
29
- "signature": "reads.requires_aggregate",
30
- "source": "requiresAggregate"
31
- }
32
- ],
33
- "schedules": [
34
- {
35
- "signature": "schedules.due",
36
- "source": "due"
37
- }
38
- ]
39
- },
40
- "moves": [],
41
- "requiresAggregate": [
42
- {
43
- "check": {
44
- "amountField": "amount",
45
- "kind": "sum_exactly",
46
- "targetField": "installment1Amount"
47
- },
48
- "instrumentId": "repayment_installment_1_payment",
49
- "over": "children",
50
- "refField": "repaymentId",
51
- "statuses": [
52
- "paid"
53
- ]
54
- }
55
- ],
56
- "steps": [],
57
- "summary": "Close delinquent installment 1 after linked payments reach its stored amount"
58
- },
59
- "collect_installment_2": {
60
- "due": {
61
- "field": "firstDueAt",
62
- "offset": "P30D"
63
- },
64
- "effects": {
65
- "reads": [
66
- {
67
- "signature": "reads.requires_aggregate",
68
- "source": "requiresAggregate"
69
- }
70
- ],
71
- "schedules": [
72
- {
73
- "signature": "schedules.due",
74
- "source": "due"
75
- }
76
- ]
77
- },
78
- "moves": [],
79
- "requiresAggregate": [
80
- {
81
- "check": {
82
- "amountField": "amount",
83
- "kind": "sum_exactly",
84
- "targetField": "installment2Amount"
85
- },
86
- "instrumentId": "repayment_installment_2_payment",
87
- "over": "children",
88
- "refField": "repaymentId",
89
- "statuses": [
90
- "paid"
91
- ]
92
- }
93
- ],
94
- "steps": [],
95
- "summary": "Close delinquent installment 2 after linked payments reach its stored amount"
96
- },
97
- "complete": {
98
- "due": {
99
- "field": "firstDueAt",
100
- "offset": "P30D"
101
- },
102
- "effects": {
103
- "reads": [
104
- {
105
- "signature": "reads.requires_aggregate",
106
- "source": "requiresAggregate"
107
- }
108
- ],
109
- "schedules": [
110
- {
111
- "signature": "schedules.due",
112
- "source": "due"
113
- }
114
- ]
115
- },
116
- "moves": [],
117
- "requiresAggregate": [
118
- {
119
- "check": {
120
- "amountField": "amount",
121
- "kind": "sum_exactly",
122
- "targetField": "installment1Amount"
123
- },
124
- "instrumentId": "repayment_installment_1_payment",
125
- "over": "children",
126
- "refField": "repaymentId",
127
- "statuses": [
128
- "paid"
129
- ]
130
- },
131
- {
132
- "check": {
133
- "amountField": "amount",
134
- "kind": "sum_exactly",
135
- "targetField": "installment2Amount"
136
- },
137
- "instrumentId": "repayment_installment_2_payment",
138
- "over": "children",
139
- "refField": "repaymentId",
140
- "statuses": [
141
- "paid"
142
- ]
143
- }
144
- ],
145
- "steps": [],
146
- "summary": "Close the obligation only after every stored anchor is paid exactly"
147
- },
148
- "create": {
149
- "agentDescription": "Create the obligation in draft with its principal split across stored installment anchors. Approve is the next call. Where the product declares a derived fee, creating the obligation also moves that fee from its bearer to the platform account.",
150
- "moves": [],
151
- "publicAction": "createRepayment",
152
- "steps": [],
153
- "summary": "Create a repayment obligation"
154
- },
155
- "mark_installment_1_delinquent": {
156
- "due": {
157
- "field": "firstDueAt"
158
- },
159
- "effects": {
160
- "reads": [
161
- {
162
- "signature": "reads.requires_aggregate",
163
- "source": "requiresAggregate"
164
- }
165
- ],
166
- "schedules": [
167
- {
168
- "signature": "schedules.due",
169
- "source": "due"
170
- }
171
- ]
172
- },
173
- "moves": [],
174
- "requiresAggregate": [
175
- {
176
- "check": {
177
- "amountField": "amount",
178
- "kind": "sum_below",
179
- "targetField": "installment1Amount"
180
- },
181
- "instrumentId": "repayment_installment_1_payment",
182
- "over": "children",
183
- "refField": "repaymentId",
184
- "statuses": [
185
- "paid"
186
- ]
187
- }
188
- ],
189
- "setsAt": {
190
- "field": "installment1DelinquentAfter",
191
- "marker": true,
192
- "offset": "PT1S"
193
- },
194
- "steps": [],
195
- "summary": "Mark installment 1 delinquent only when its due anchor is unmet"
196
- },
197
- "mark_installment_2_delinquent": {
198
- "due": {
199
- "field": "firstDueAt",
200
- "offset": "P30D"
201
- },
202
- "effects": {
203
- "reads": [
204
- {
205
- "signature": "reads.requires_aggregate",
206
- "source": "requiresAggregate"
207
- }
208
- ],
209
- "schedules": [
210
- {
211
- "signature": "schedules.due",
212
- "source": "due"
213
- }
214
- ]
215
- },
216
- "moves": [],
217
- "requiresAggregate": [
218
- {
219
- "check": {
220
- "amountField": "amount",
221
- "kind": "sum_below",
222
- "targetField": "installment2Amount"
223
- },
224
- "instrumentId": "repayment_installment_2_payment",
225
- "over": "children",
226
- "refField": "repaymentId",
227
- "statuses": [
228
- "paid"
229
- ]
230
- }
231
- ],
232
- "setsAt": {
233
- "field": "installment2DelinquentAfter",
234
- "marker": true,
235
- "offset": "PT1S"
236
- },
237
- "steps": [],
238
- "summary": "Mark installment 2 delinquent only when its due anchor is unmet"
239
- },
240
- "write_off": {
241
- "agentDescription": "Write off the remaining exposure and stop the obligation. No money moves and nothing is refunded. This is the bookkeeping exit for debt that will not be collected. A written-off obligation never returns to repayment.",
242
- "moves": [],
243
- "publicAction": "writeOffRepayment",
244
- "steps": [],
245
- "summary": "Write off the remaining exposure without moving money"
246
- }
247
- },
248
- "agentDescription": "Reach for scheduled when one payer owes one payee on a calendar. It covers a plan of fixed installments partitioning one total, an obligation whose installments are paid through child payment records and can go delinquent, and an open period charge that repeats until a cancel port fires. Rotating pool is for a group taking turns.",
249
- "aggregateInvariants": [
250
- {
251
- "childField": "amount",
252
- "childInstrumentId": "repayment_installment_1_payment",
253
- "childRefField": "repaymentId",
254
- "childStatuses": [
255
- "paid"
256
- ],
257
- "parentField": "installment1Amount"
258
- },
259
- {
260
- "childField": "amount",
261
- "childInstrumentId": "repayment_installment_2_payment",
262
- "childRefField": "repaymentId",
263
- "childStatuses": [
264
- "paid"
265
- ],
266
- "parentField": "installment2Amount"
267
- }
268
- ],
269
- "description": "Installment obligation for borrower; repayment source pays lender against exact stored anchors",
270
- "fields": {
271
- "borrowerAccountId": {
272
- "description": "The borrower account",
273
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
274
- "type": "string",
275
- "x-hyperscale-reference-filter": {
276
- "column": "role",
277
- "values": [
278
- "customer_balance"
279
- ]
280
- }
281
- },
282
- "currency": {
283
- "description": "ISO 4217 currency code",
284
- "maxLength": 3,
285
- "minLength": 3,
286
- "pattern": "^[A-Z]{3}$",
287
- "type": "string"
288
- },
289
- "firstDueAt": {
290
- "description": "Due date of the first installment; later anchors use fixed offsets of P30D",
291
- "format": "hyperscale-date-time",
292
- "type": "string"
293
- },
294
- "installment1Amount": {
295
- "description": "Stored amount for installment 1 of 2 (carries the integer-division remainder)",
296
- "pattern": "^[1-9][0-9]{0,17}$",
297
- "type": "string"
298
- },
299
- "installment1DelinquentAfter": {
300
- "description": "Machine-set marker proving installment 1 reached its stored due date while unpaid",
301
- "format": "hyperscale-date-time",
302
- "type": "string"
303
- },
304
- "installment2Amount": {
305
- "description": "Stored amount for installment 2 of 2",
306
- "pattern": "^[1-9][0-9]{0,17}$",
307
- "type": "string"
308
- },
309
- "installment2DelinquentAfter": {
310
- "description": "Machine-set marker proving installment 2 reached its stored due date while unpaid",
311
- "format": "hyperscale-date-time",
312
- "type": "string"
313
- },
314
- "lenderAccountId": {
315
- "description": "The lender account",
316
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
317
- "type": "string",
318
- "x-hyperscale-reference-filter": {
319
- "column": "role",
320
- "values": [
321
- "customer_balance"
322
- ]
323
- }
324
- },
325
- "principal": {
326
- "description": "The principal in SAR minor units; the stored installment anchors partition it exactly",
327
- "pattern": "^[1-9][0-9]{0,17}$",
328
- "type": "string"
329
- },
330
- "repaymentSourceAccountId": {
331
- "description": "The repayment source account",
332
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
333
- "type": "string",
334
- "x-hyperscale-reference-filter": {
335
- "column": "role",
336
- "values": [
337
- "customer_balance"
338
- ]
339
- }
340
- }
341
- },
342
- "id": "repayment",
343
- "idPrefix": "repa",
344
- "lifecycle": {
345
- "initial": "draft",
346
- "states": [
347
- "draft",
348
- "active",
349
- "installment_1_delinquent",
350
- "installment_2_delinquent",
351
- "written_off",
352
- "repaid"
353
- ],
354
- "transitions": {
355
- "approve": {
356
- "from": [
357
- "draft"
358
- ],
359
- "to": "active"
360
- },
361
- "collect_installment_1": {
362
- "from": [
363
- "installment_1_delinquent",
364
- "installment_2_delinquent"
365
- ],
366
- "to": "active"
367
- },
368
- "collect_installment_2": {
369
- "from": [
370
- "installment_1_delinquent",
371
- "installment_2_delinquent"
372
- ],
373
- "to": "active"
374
- },
375
- "complete": {
376
- "from": [
377
- "active",
378
- "installment_1_delinquent",
379
- "installment_2_delinquent"
380
- ],
381
- "to": "repaid"
382
- },
383
- "mark_installment_1_delinquent": {
384
- "from": [
385
- "active",
386
- "installment_2_delinquent"
387
- ],
388
- "to": "installment_1_delinquent"
389
- },
390
- "mark_installment_2_delinquent": {
391
- "from": [
392
- "active",
393
- "installment_1_delinquent"
394
- ],
395
- "to": "installment_2_delinquent"
396
- },
397
- "write_off": {
398
- "from": [
399
- "draft",
400
- "active",
401
- "installment_1_delinquent",
402
- "installment_2_delinquent"
403
- ],
404
- "to": "written_off"
405
- }
406
- }
407
- },
408
- "parties": {
409
- "beneficiary": "lenderAccountId",
410
- "payer": "repaymentSourceAccountId"
411
- },
412
- "partitions": [
413
- {
414
- "pieceFields": [
415
- "installment1Amount",
416
- "installment2Amount"
417
- ],
418
- "totalField": "principal"
419
- }
420
- ],
421
- "required": [
422
- "lenderAccountId",
423
- "repaymentSourceAccountId",
424
- "borrowerAccountId",
425
- "currency",
426
- "principal",
427
- "firstDueAt",
428
- "installment1Amount",
429
- "installment2Amount"
430
- ],
431
- "summary": "2-anchor obligation for borrower",
432
- "title": "Repayment"
433
- },
434
- {
435
- "actionOrder": [
436
- "create",
437
- "repay",
438
- "refund"
439
- ],
440
- "actions": {
441
- "create": {
442
- "agentDescription": "Open a payment record against installment 1. The parent obligation must be live. No money moves yet. Repay is what pays.",
443
- "effects": {
444
- "reads": [
445
- {
446
- "signature": "reads.requires_refs",
447
- "source": "requiresRefs"
448
- }
449
- ]
450
- },
451
- "moves": [],
452
- "publicAction": "createRepaymentInstallment1Payment",
453
- "requiresRefs": [
454
- {
455
- "bind": {
456
- "currency": "fields.currency",
457
- "lenderAccountId": "fields.lenderAccountId",
458
- "repaymentSourceAccountId": "fields.repaymentSourceAccountId"
459
- },
460
- "field": "repaymentId",
461
- "statuses": [
462
- "active",
463
- "installment_1_delinquent",
464
- "installment_2_delinquent"
465
- ]
466
- }
467
- ],
468
- "steps": [],
469
- "summary": "Create a payment record for installment 1"
470
- },
471
- "refund": {
472
- "agentDescription": "Return one whole installment 1 payment to the payer. The record must be paid, and the refund is always its full amount, so split a payment across records when a partial refund could be needed. This moves money back.",
473
- "effects": {
474
- "moves": [
475
- {
476
- "signature": "moves.transfer.internal",
477
- "source": "moves[0]"
478
- }
479
- ],
480
- "reads": [
481
- {
482
- "signature": "reads.requires_refs",
483
- "source": "requiresRefs"
484
- }
485
- ]
486
- },
487
- "moves": [
488
- {
489
- "bind": {
490
- "amount": {
491
- "from": "instance",
492
- "path": "fields.amount"
493
- },
494
- "currency": {
495
- "from": "instance",
496
- "path": "fields.currency"
497
- },
498
- "destinationAccountId": {
499
- "from": "instance",
500
- "path": "fields.repaymentSourceAccountId"
501
- },
502
- "metadata.instrumentId": {
503
- "from": "const",
504
- "value": "repayment_installment_1_payment"
505
- },
506
- "metadata.instrumentInstanceId": {
507
- "from": "instance",
508
- "path": "instrumentInstanceId"
509
- },
510
- "metadata.phase": {
511
- "from": "const",
512
- "value": "refund"
513
- },
514
- "productId": {
515
- "from": "instance",
516
- "path": "productId"
517
- },
518
- "sourceAccountId": {
519
- "from": "instance",
520
- "path": "fields.lenderAccountId"
521
- }
522
- },
523
- "capture": {
524
- "refundRefundTransferId": "transferId"
525
- },
526
- "key": "refund",
527
- "operation": "internal_transfer.create"
528
- }
529
- ],
530
- "publicAction": "refundRepaymentInstallment1Payment",
531
- "requiresRefs": [
532
- {
533
- "field": "repaymentId",
534
- "match": {
535
- "fields.currency": "fields.currency",
536
- "fields.lenderAccountId": "fields.lenderAccountId",
537
- "fields.repaymentSourceAccountId": "fields.repaymentSourceAccountId"
538
- },
539
- "statuses": [
540
- "active",
541
- "installment_1_delinquent",
542
- "installment_2_delinquent"
543
- ]
544
- }
545
- ],
546
- "steps": [],
547
- "summary": "Refund this one stored installment 1 payment whole"
548
- },
549
- "repay": {
550
- "agentDescription": "Pay this record's amount toward installment 1. The record must be created and its obligation live. Refused when this amount plus the records already paid against that installment would pass the stored amount. This moves the payer's money. Where a mandate applies, only the payer may call it and an evidence reference is required.",
551
- "effects": {
552
- "moves": [
553
- {
554
- "signature": "moves.transfer.internal",
555
- "source": "moves[0]"
556
- }
557
- ],
558
- "reads": [
559
- {
560
- "signature": "reads.requires_refs",
561
- "source": "requiresRefs"
562
- }
563
- ]
564
- },
565
- "moves": [
566
- {
567
- "bind": {
568
- "amount": {
569
- "from": "instance",
570
- "path": "fields.amount"
571
- },
572
- "currency": {
573
- "from": "instance",
574
- "path": "fields.currency"
575
- },
576
- "destinationAccountId": {
577
- "from": "instance",
578
- "path": "fields.lenderAccountId"
579
- },
580
- "metadata.instrumentId": {
581
- "from": "const",
582
- "value": "repayment_installment_1_payment"
583
- },
584
- "metadata.instrumentInstanceId": {
585
- "from": "instance",
586
- "path": "instrumentInstanceId"
587
- },
588
- "metadata.phase": {
589
- "from": "const",
590
- "value": "repay"
591
- },
592
- "productId": {
593
- "from": "instance",
594
- "path": "productId"
595
- },
596
- "sourceAccountId": {
597
- "from": "instance",
598
- "path": "fields.repaymentSourceAccountId"
599
- }
600
- },
601
- "capture": {
602
- "repayRepaymentTransferId": "transferId"
603
- },
604
- "key": "repayment",
605
- "operation": "internal_transfer.create"
606
- }
607
- ],
608
- "publicAction": "repayRepaymentInstallment1Payment",
609
- "requiresExposure": [
610
- {
611
- "amountField": "amount",
612
- "anchorField": "repaymentId",
613
- "capField": "installment1Amount",
614
- "capOnAnchor": true,
615
- "childInstrumentId": "repayment_installment_1_payment",
616
- "statuses": [
617
- "paid"
618
- ]
619
- }
620
- ],
621
- "requiresRefs": [
622
- {
623
- "field": "repaymentId",
624
- "match": {
625
- "fields.currency": "fields.currency",
626
- "fields.lenderAccountId": "fields.lenderAccountId",
627
- "fields.repaymentSourceAccountId": "fields.repaymentSourceAccountId"
628
- },
629
- "statuses": [
630
- "active",
631
- "installment_1_delinquent",
632
- "installment_2_delinquent"
633
- ]
634
- }
635
- ],
636
- "steps": [],
637
- "summary": "Pay a partial or full amount against installment 1"
638
- }
639
- },
640
- "agentDescription": "One payment against installment 1 of the obligation. Payments can be partial, so create a record, repay it, and the parent installment closes once its paid records sum to the stored anchor amount.",
641
- "description": "One partial or full payment bound to installment 1 of repayment; the operation name fixes the anchor and repaymentId fixes the obligation",
642
- "fields": {
643
- "amount": {
644
- "description": "Positive payment amount capped with its paid siblings at installment1Amount",
645
- "pattern": "^[1-9][0-9]{0,17}$",
646
- "type": "string"
647
- },
648
- "currency": {
649
- "description": "ISO 4217 currency code",
650
- "maxLength": 3,
651
- "minLength": 3,
652
- "pattern": "^[A-Z]{3}$",
653
- "type": "string"
654
- },
655
- "lenderAccountId": {
656
- "description": "The lender account",
657
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
658
- "type": "string",
659
- "x-hyperscale-reference-filter": {
660
- "column": "role",
661
- "values": [
662
- "customer_balance"
663
- ]
664
- }
665
- },
666
- "repaymentId": {
667
- "description": "The exact repayment this payment belongs to",
668
- "pattern": "^repa_(sandbox|live)_[a-z0-9]{8,64}$",
669
- "type": "string"
670
- },
671
- "repaymentSourceAccountId": {
672
- "description": "The repayment source account",
673
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
674
- "type": "string",
675
- "x-hyperscale-reference-filter": {
676
- "column": "role",
677
- "values": [
678
- "customer_balance"
679
- ]
680
- }
681
- }
682
- },
683
- "id": "repayment_installment_1_payment",
684
- "idPrefix": "zzaa",
685
- "lifecycle": {
686
- "initial": "created",
687
- "states": [
688
- "created",
689
- "paid",
690
- "refunded"
691
- ],
692
- "transitions": {
693
- "refund": {
694
- "from": [
695
- "paid"
696
- ],
697
- "to": "refunded"
698
- },
699
- "repay": {
700
- "from": [
701
- "created"
702
- ],
703
- "to": "paid"
704
- }
705
- }
706
- },
707
- "parties": {
708
- "beneficiary": "lenderAccountId",
709
- "payer": "repaymentSourceAccountId"
710
- },
711
- "required": [
712
- "lenderAccountId",
713
- "repaymentSourceAccountId",
714
- "amount",
715
- "currency",
716
- "repaymentId"
717
- ],
718
- "summary": "Anchor-bound payment for installment 1",
719
- "title": "Repayment Installment 1 Payment"
720
- },
721
- {
722
- "actionOrder": [
723
- "create",
724
- "repay",
725
- "refund"
726
- ],
727
- "actions": {
728
- "create": {
729
- "agentDescription": "Open a payment record against installment 2. The parent obligation must be live. No money moves yet. Repay is what pays.",
730
- "effects": {
731
- "reads": [
732
- {
733
- "signature": "reads.requires_refs",
734
- "source": "requiresRefs"
735
- }
736
- ]
737
- },
738
- "moves": [],
739
- "publicAction": "createRepaymentInstallment2Payment",
740
- "requiresRefs": [
741
- {
742
- "bind": {
743
- "currency": "fields.currency",
744
- "lenderAccountId": "fields.lenderAccountId",
745
- "repaymentSourceAccountId": "fields.repaymentSourceAccountId"
746
- },
747
- "field": "repaymentId",
748
- "statuses": [
749
- "active",
750
- "installment_1_delinquent",
751
- "installment_2_delinquent"
752
- ]
753
- }
754
- ],
755
- "steps": [],
756
- "summary": "Create a payment record for installment 2"
757
- },
758
- "refund": {
759
- "agentDescription": "Return one whole installment 2 payment to the payer. The record must be paid, and the refund is always its full amount, so split a payment across records when a partial refund could be needed. This moves money back.",
760
- "effects": {
761
- "moves": [
762
- {
763
- "signature": "moves.transfer.internal",
764
- "source": "moves[0]"
765
- }
766
- ],
767
- "reads": [
768
- {
769
- "signature": "reads.requires_refs",
770
- "source": "requiresRefs"
771
- }
772
- ]
773
- },
774
- "moves": [
775
- {
776
- "bind": {
777
- "amount": {
778
- "from": "instance",
779
- "path": "fields.amount"
780
- },
781
- "currency": {
782
- "from": "instance",
783
- "path": "fields.currency"
784
- },
785
- "destinationAccountId": {
786
- "from": "instance",
787
- "path": "fields.repaymentSourceAccountId"
788
- },
789
- "metadata.instrumentId": {
790
- "from": "const",
791
- "value": "repayment_installment_2_payment"
792
- },
793
- "metadata.instrumentInstanceId": {
794
- "from": "instance",
795
- "path": "instrumentInstanceId"
796
- },
797
- "metadata.phase": {
798
- "from": "const",
799
- "value": "refund"
800
- },
801
- "productId": {
802
- "from": "instance",
803
- "path": "productId"
804
- },
805
- "sourceAccountId": {
806
- "from": "instance",
807
- "path": "fields.lenderAccountId"
808
- }
809
- },
810
- "capture": {
811
- "refundRefundTransferId": "transferId"
812
- },
813
- "key": "refund",
814
- "operation": "internal_transfer.create"
815
- }
816
- ],
817
- "publicAction": "refundRepaymentInstallment2Payment",
818
- "requiresRefs": [
819
- {
820
- "field": "repaymentId",
821
- "match": {
822
- "fields.currency": "fields.currency",
823
- "fields.lenderAccountId": "fields.lenderAccountId",
824
- "fields.repaymentSourceAccountId": "fields.repaymentSourceAccountId"
825
- },
826
- "statuses": [
827
- "active",
828
- "installment_1_delinquent",
829
- "installment_2_delinquent"
830
- ]
831
- }
832
- ],
833
- "steps": [],
834
- "summary": "Refund this one stored installment 2 payment whole"
835
- },
836
- "repay": {
837
- "agentDescription": "Pay this record's amount toward installment 2. The record must be created and its obligation live. Refused when this amount plus the records already paid against that installment would pass the stored amount. This moves the payer's money. Where a mandate applies, only the payer may call it and an evidence reference is required.",
838
- "effects": {
839
- "moves": [
840
- {
841
- "signature": "moves.transfer.internal",
842
- "source": "moves[0]"
843
- }
844
- ],
845
- "reads": [
846
- {
847
- "signature": "reads.requires_refs",
848
- "source": "requiresRefs"
849
- }
850
- ]
851
- },
852
- "moves": [
853
- {
854
- "bind": {
855
- "amount": {
856
- "from": "instance",
857
- "path": "fields.amount"
858
- },
859
- "currency": {
860
- "from": "instance",
861
- "path": "fields.currency"
862
- },
863
- "destinationAccountId": {
864
- "from": "instance",
865
- "path": "fields.lenderAccountId"
866
- },
867
- "metadata.instrumentId": {
868
- "from": "const",
869
- "value": "repayment_installment_2_payment"
870
- },
871
- "metadata.instrumentInstanceId": {
872
- "from": "instance",
873
- "path": "instrumentInstanceId"
874
- },
875
- "metadata.phase": {
876
- "from": "const",
877
- "value": "repay"
878
- },
879
- "productId": {
880
- "from": "instance",
881
- "path": "productId"
882
- },
883
- "sourceAccountId": {
884
- "from": "instance",
885
- "path": "fields.repaymentSourceAccountId"
886
- }
887
- },
888
- "capture": {
889
- "repayRepaymentTransferId": "transferId"
890
- },
891
- "key": "repayment",
892
- "operation": "internal_transfer.create"
893
- }
894
- ],
895
- "publicAction": "repayRepaymentInstallment2Payment",
896
- "requiresExposure": [
897
- {
898
- "amountField": "amount",
899
- "anchorField": "repaymentId",
900
- "capField": "installment2Amount",
901
- "capOnAnchor": true,
902
- "childInstrumentId": "repayment_installment_2_payment",
903
- "statuses": [
904
- "paid"
905
- ]
906
- }
907
- ],
908
- "requiresRefs": [
909
- {
910
- "field": "repaymentId",
911
- "match": {
912
- "fields.currency": "fields.currency",
913
- "fields.lenderAccountId": "fields.lenderAccountId",
914
- "fields.repaymentSourceAccountId": "fields.repaymentSourceAccountId"
915
- },
916
- "statuses": [
917
- "active",
918
- "installment_1_delinquent",
919
- "installment_2_delinquent"
920
- ]
921
- }
922
- ],
923
- "steps": [],
924
- "summary": "Pay a partial or full amount against installment 2"
925
- }
926
- },
927
- "agentDescription": "One payment against installment 2 of the obligation. Payments can be partial, so create a record, repay it, and the parent installment closes once its paid records sum to the stored anchor amount.",
928
- "description": "One partial or full payment bound to installment 2 of repayment; the operation name fixes the anchor and repaymentId fixes the obligation",
929
- "fields": {
930
- "amount": {
931
- "description": "Positive payment amount capped with its paid siblings at installment2Amount",
932
- "pattern": "^[1-9][0-9]{0,17}$",
933
- "type": "string"
934
- },
935
- "currency": {
936
- "description": "ISO 4217 currency code",
937
- "maxLength": 3,
938
- "minLength": 3,
939
- "pattern": "^[A-Z]{3}$",
940
- "type": "string"
941
- },
942
- "lenderAccountId": {
943
- "description": "The lender account",
944
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
945
- "type": "string",
946
- "x-hyperscale-reference-filter": {
947
- "column": "role",
948
- "values": [
949
- "customer_balance"
950
- ]
951
- }
952
- },
953
- "repaymentId": {
954
- "description": "The exact repayment this payment belongs to",
955
- "pattern": "^repa_(sandbox|live)_[a-z0-9]{8,64}$",
956
- "type": "string"
957
- },
958
- "repaymentSourceAccountId": {
959
- "description": "The repayment source account",
960
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
961
- "type": "string",
962
- "x-hyperscale-reference-filter": {
963
- "column": "role",
964
- "values": [
965
- "customer_balance"
966
- ]
967
- }
968
- }
969
- },
970
- "id": "repayment_installment_2_payment",
971
- "idPrefix": "zzab",
972
- "lifecycle": {
973
- "initial": "created",
974
- "states": [
975
- "created",
976
- "paid",
977
- "refunded"
978
- ],
979
- "transitions": {
980
- "refund": {
981
- "from": [
982
- "paid"
983
- ],
984
- "to": "refunded"
985
- },
986
- "repay": {
987
- "from": [
988
- "created"
989
- ],
990
- "to": "paid"
991
- }
992
- }
993
- },
994
- "parties": {
995
- "beneficiary": "lenderAccountId",
996
- "payer": "repaymentSourceAccountId"
997
- },
998
- "required": [
999
- "lenderAccountId",
1000
- "repaymentSourceAccountId",
1001
- "amount",
1002
- "currency",
1003
- "repaymentId"
1004
- ],
1005
- "summary": "Anchor-bound payment for installment 2",
1006
- "title": "Repayment Installment 2 Payment"
1007
- },
1008
- {
1009
- "actionOrder": [
1010
- "create",
1011
- "freeze",
1012
- "close"
1013
- ],
1014
- "actions": {
1015
- "close": {
1016
- "agentDescription": "Close the facility for good. Every draw under it must already be resolved, so clear the outstanding obligations first. No money moves and a closed facility never lends again.",
1017
- "effects": {
1018
- "reads": [
1019
- {
1020
- "signature": "reads.requires_aggregate",
1021
- "source": "requiresAggregate"
1022
- }
1023
- ]
1024
- },
1025
- "moves": [],
1026
- "publicAction": "closeFacility",
1027
- "requiresAggregate": [
1028
- {
1029
- "check": {
1030
- "kind": "all_in"
1031
- },
1032
- "instrumentId": "facility_draw",
1033
- "over": "children",
1034
- "refField": "facilityId",
1035
- "statuses": [
1036
- "resolved"
1037
- ]
1038
- }
1039
- ],
1040
- "steps": [],
1041
- "summary": "Close only when every admitted draw resolved"
1042
- },
1043
- "create": {
1044
- "agentDescription": "Open the facility before any draw exists. The caller supplies the facilityLimit, the currency, the borrower and lender accounts, the draw destination account, and the stored expiry. No money moves.",
1045
- "moves": [],
1046
- "publicAction": "createFacility",
1047
- "steps": [],
1048
- "summary": "Open the facility"
1049
- },
1050
- "freeze": {
1051
- "due": {
1052
- "field": "expiresAt"
1053
- },
1054
- "effects": {
1055
- "schedules": [
1056
- {
1057
- "signature": "schedules.due",
1058
- "source": "due"
1059
- }
1060
- ]
1061
- },
1062
- "moves": [],
1063
- "steps": [],
1064
- "summary": "Freeze new draws at expiry"
1065
- }
1066
- },
1067
- "agentDescription": "Reach for credit facility when the lender gives the borrower reusable capacity up to facilityLimit and every draw is repaid through its own scheduled obligation. Capacity frees up as each obligation resolves. Pick advance for one up-front payment with no reusable limit.",
1068
- "description": "Reusable capacity with repayment delegated to one scheduled obligation",
1069
- "fields": {
1070
- "borrowerAccountId": {
1071
- "description": "The borrower account",
1072
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1073
- "type": "string",
1074
- "x-hyperscale-reference-filter": {
1075
- "column": "role",
1076
- "values": [
1077
- "customer_balance"
1078
- ]
1079
- }
1080
- },
1081
- "currency": {
1082
- "description": "ISO 4217 currency code",
1083
- "maxLength": 3,
1084
- "minLength": 3,
1085
- "pattern": "^[A-Z]{3}$",
1086
- "type": "string"
1087
- },
1088
- "drawDestinationAccountId": {
1089
- "description": "The draw destination account",
1090
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1091
- "type": "string",
1092
- "x-hyperscale-reference-filter": {
1093
- "column": "role",
1094
- "values": [
1095
- "customer_balance"
1096
- ]
1097
- }
1098
- },
1099
- "expiresAt": {
1100
- "description": "Stored draw expiry",
1101
- "format": "hyperscale-date-time",
1102
- "type": "string"
1103
- },
1104
- "facilityLimit": {
1105
- "description": "Facility limit in SAR minor units",
1106
- "pattern": "^[1-9][0-9]{0,17}$",
1107
- "type": "string"
1108
- },
1109
- "lenderAccountId": {
1110
- "description": "The lender account",
1111
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1112
- "type": "string",
1113
- "x-hyperscale-reference-filter": {
1114
- "column": "role",
1115
- "values": [
1116
- "customer_balance"
1117
- ]
1118
- }
1119
- }
1120
- },
1121
- "id": "facility",
1122
- "idPrefix": "faci",
1123
- "lifecycle": {
1124
- "initial": "active",
1125
- "states": [
1126
- "active",
1127
- "frozen",
1128
- "closed"
1129
- ],
1130
- "transitions": {
1131
- "close": {
1132
- "from": [
1133
- "active",
1134
- "frozen"
1135
- ],
1136
- "to": "closed"
1137
- },
1138
- "freeze": {
1139
- "from": [
1140
- "active"
1141
- ],
1142
- "to": "frozen"
1143
- }
1144
- }
1145
- },
1146
- "parties": {
1147
- "beneficiary": "drawDestinationAccountId",
1148
- "payer": "lenderAccountId"
1149
- },
1150
- "required": [
1151
- "borrowerAccountId",
1152
- "drawDestinationAccountId",
1153
- "lenderAccountId",
1154
- "currency",
1155
- "facilityLimit",
1156
- "expiresAt"
1157
- ],
1158
- "summary": "Draw capacity for borrower",
1159
- "title": "Facility"
1160
- },
1161
- {
1162
- "actionOrder": [
1163
- "create",
1164
- "resolve"
1165
- ],
1166
- "actions": {
1167
- "create": {
1168
- "agentDescription": "Draw one amount out of the facility to the draw destination account. The facility must be active, the linked obligation active and bound to no other draw, and the drawn amounts plus this one must stay within facilityLimit. The money leaves the lender straight away.",
1169
- "effects": {
1170
- "moves": [
1171
- {
1172
- "signature": "moves.transfer.internal",
1173
- "source": "moves[0]"
1174
- }
1175
- ],
1176
- "reads": [
1177
- {
1178
- "signature": "reads.requires_refs",
1179
- "source": "requiresRefs"
1180
- }
1181
- ]
1182
- },
1183
- "moves": [
1184
- {
1185
- "bind": {
1186
- "amount": {
1187
- "from": "instance",
1188
- "path": "fields.amount"
1189
- },
1190
- "currency": {
1191
- "from": "instance",
1192
- "path": "fields.currency"
1193
- },
1194
- "destinationAccountId": {
1195
- "from": "instance",
1196
- "path": "fields.drawDestinationAccountId"
1197
- },
1198
- "metadata.instrumentId": {
1199
- "from": "const",
1200
- "value": "facility_draw"
1201
- },
1202
- "metadata.instrumentInstanceId": {
1203
- "from": "instance",
1204
- "path": "instrumentInstanceId"
1205
- },
1206
- "metadata.phase": {
1207
- "from": "const",
1208
- "value": "create"
1209
- },
1210
- "productId": {
1211
- "from": "instance",
1212
- "path": "productId"
1213
- },
1214
- "sourceAccountId": {
1215
- "from": "instance",
1216
- "path": "fields.lenderAccountId"
1217
- }
1218
- },
1219
- "capture": {
1220
- "createDrawTransferId": "transferId"
1221
- },
1222
- "key": "draw",
1223
- "operation": "internal_transfer.create"
1224
- }
1225
- ],
1226
- "publicAction": "createFacilityDraw",
1227
- "requiresExposure": [
1228
- {
1229
- "amountField": "amount",
1230
- "anchorField": "facilityId",
1231
- "capField": "facilityLimit",
1232
- "capOnAnchor": true,
1233
- "childInstrumentId": "facility_draw",
1234
- "statuses": [
1235
- "drawn"
1236
- ]
1237
- }
1238
- ],
1239
- "requiresRefs": [
1240
- {
1241
- "bind": {
1242
- "currency": "fields.currency",
1243
- "drawDestinationAccountId": "fields.drawDestinationAccountId",
1244
- "lenderAccountId": "fields.lenderAccountId"
1245
- },
1246
- "field": "facilityId",
1247
- "statuses": [
1248
- "active"
1249
- ]
1250
- },
1251
- {
1252
- "field": "repaymentId",
1253
- "statuses": [
1254
- "active"
1255
- ],
1256
- "unique": true
1257
- }
1258
- ],
1259
- "steps": [],
1260
- "summary": "Create one draw under the locked facility capacity"
1261
- },
1262
- "resolve": {
1263
- "agentDescription": "Free the drawn capacity back to the facility. The linked obligation must already be repaid or written off. No money moves here, the obligation did the repaying.",
1264
- "effects": {
1265
- "reads": [
1266
- {
1267
- "signature": "reads.requires_refs",
1268
- "source": "requiresRefs"
1269
- }
1270
- ]
1271
- },
1272
- "moves": [],
1273
- "publicAction": "resolveFacilityDraw",
1274
- "requiresRefs": [
1275
- {
1276
- "field": "repaymentId",
1277
- "statuses": [
1278
- "repaid",
1279
- "written_off"
1280
- ]
1281
- }
1282
- ],
1283
- "steps": [],
1284
- "summary": "Release revolving capacity only after the linked obligation resolves"
1285
- }
1286
- },
1287
- "agentDescription": "Reach for this child row to take one draw against a facility. The parent carries the facilityLimit, this row carries one drawn amount and the single obligation that repays it.",
1288
- "description": "One capacity-capped draw linked to obligation",
1289
- "fields": {
1290
- "amount": {
1291
- "description": "One draw amount",
1292
- "pattern": "^[1-9][0-9]{0,17}$",
1293
- "type": "string"
1294
- },
1295
- "currency": {
1296
- "description": "ISO 4217 currency code",
1297
- "maxLength": 3,
1298
- "minLength": 3,
1299
- "pattern": "^[A-Z]{3}$",
1300
- "type": "string"
1301
- },
1302
- "drawDestinationAccountId": {
1303
- "description": "The draw destination account",
1304
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1305
- "type": "string",
1306
- "x-hyperscale-reference-filter": {
1307
- "column": "role",
1308
- "values": [
1309
- "customer_balance"
1310
- ]
1311
- }
1312
- },
1313
- "facilityId": {
1314
- "description": "The exact facility",
1315
- "pattern": "^faci_(sandbox|live)_[a-z0-9]{8,64}$",
1316
- "type": "string"
1317
- },
1318
- "lenderAccountId": {
1319
- "description": "The lender account",
1320
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1321
- "type": "string",
1322
- "x-hyperscale-reference-filter": {
1323
- "column": "role",
1324
- "values": [
1325
- "customer_balance"
1326
- ]
1327
- }
1328
- },
1329
- "repaymentId": {
1330
- "description": "The sole repayment obligation",
1331
- "pattern": "^repa_(sandbox|live)_[a-z0-9]{8,64}$",
1332
- "type": "string"
1333
- }
1334
- },
1335
- "id": "facility_draw",
1336
- "idPrefix": "zzac",
1337
- "lifecycle": {
1338
- "initial": "drawn",
1339
- "states": [
1340
- "drawn",
1341
- "resolved"
1342
- ],
1343
- "transitions": {
1344
- "resolve": {
1345
- "from": [
1346
- "drawn"
1347
- ],
1348
- "to": "resolved"
1349
- }
1350
- }
1351
- },
1352
- "parties": {
1353
- "beneficiary": "drawDestinationAccountId",
1354
- "payer": "lenderAccountId"
1355
- },
1356
- "required": [
1357
- "drawDestinationAccountId",
1358
- "lenderAccountId",
1359
- "amount",
1360
- "currency",
1361
- "facilityId",
1362
- "repaymentId"
1363
- ],
1364
- "summary": "Draw from facility",
1365
- "title": "Facility Draw"
1366
- }
1367
- ],
1368
- "product": "credit_facility_example",
1369
- "subjects": [],
1370
- "title": "Credit facility example",
1371
- "udl": 1,
1372
- "version": 1
1373
- }