@hyperscale0/hsx 1.0.0-beta.1 → 1.0.0-rc.1

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 (234) hide show
  1. package/CHANGELOG.md +41 -9
  2. package/LICENSING.md +3 -3
  3. package/README.md +37 -149
  4. package/TRADEMARKS.md +4 -4
  5. package/dist/src/ast.d.ts +129 -10
  6. package/dist/src/ast.d.ts.map +1 -1
  7. package/dist/src/cli.d.ts +2 -1
  8. package/dist/src/cli.d.ts.map +1 -1
  9. package/dist/src/cli.js +148 -12
  10. package/dist/src/cli.js.map +1 -1
  11. package/dist/src/compile.d.ts +41 -4
  12. package/dist/src/compile.d.ts.map +1 -1
  13. package/dist/src/compile.js +82 -15
  14. package/dist/src/compile.js.map +1 -1
  15. package/dist/src/cost.d.ts +78 -0
  16. package/dist/src/cost.d.ts.map +1 -0
  17. package/dist/src/cost.js +369 -0
  18. package/dist/src/cost.js.map +1 -0
  19. package/dist/src/diagnostics.d.ts +11 -0
  20. package/dist/src/diagnostics.d.ts.map +1 -0
  21. package/dist/src/diagnostics.js +420 -0
  22. package/dist/src/diagnostics.js.map +1 -0
  23. package/dist/src/emit.d.ts +35 -0
  24. package/dist/src/emit.d.ts.map +1 -0
  25. package/dist/src/emit.js +359 -0
  26. package/dist/src/emit.js.map +1 -0
  27. package/dist/src/entry-overrides.d.ts +17 -3
  28. package/dist/src/entry-overrides.d.ts.map +1 -1
  29. package/dist/src/entry-overrides.js +180 -35
  30. package/dist/src/entry-overrides.js.map +1 -1
  31. package/dist/src/format.d.ts +10 -0
  32. package/dist/src/format.d.ts.map +1 -0
  33. package/dist/src/format.js +183 -0
  34. package/dist/src/format.js.map +1 -0
  35. package/dist/src/index.d.ts +10 -4
  36. package/dist/src/index.d.ts.map +1 -1
  37. package/dist/src/index.js +8 -3
  38. package/dist/src/index.js.map +1 -1
  39. package/dist/src/ir.d.ts +66 -0
  40. package/dist/src/ir.d.ts.map +1 -0
  41. package/dist/src/ir.js +15 -0
  42. package/dist/src/ir.js.map +1 -0
  43. package/dist/src/lex.d.ts +9 -1
  44. package/dist/src/lex.d.ts.map +1 -1
  45. package/dist/src/lex.js +50 -4
  46. package/dist/src/lex.js.map +1 -1
  47. package/dist/src/limits.d.ts +2 -3
  48. package/dist/src/limits.d.ts.map +1 -1
  49. package/dist/src/limits.js +2 -3
  50. package/dist/src/limits.js.map +1 -1
  51. package/dist/src/modules.d.ts +36 -0
  52. package/dist/src/modules.d.ts.map +1 -0
  53. package/dist/src/modules.js +372 -0
  54. package/dist/src/modules.js.map +1 -0
  55. package/dist/src/parse.d.ts.map +1 -1
  56. package/dist/src/parse.js +590 -17
  57. package/dist/src/parse.js.map +1 -1
  58. package/dist/src/typecheck.d.ts +8 -0
  59. package/dist/src/typecheck.d.ts.map +1 -0
  60. package/dist/src/typecheck.js +2958 -0
  61. package/dist/src/typecheck.js.map +1 -0
  62. package/dist/src/version.d.ts +4 -15
  63. package/dist/src/version.d.ts.map +1 -1
  64. package/dist/src/version.js +4 -15
  65. package/dist/src/version.js.map +1 -1
  66. package/docs/README.md +23 -0
  67. package/docs/guide/01-first-program.md +24 -0
  68. package/docs/guide/02-money.md +25 -0
  69. package/docs/guide/03-instruments.md +22 -0
  70. package/docs/guide/04-lifecycles.md +25 -0
  71. package/docs/guide/05-fees-and-splits.md +45 -0
  72. package/docs/guide/06-schedules.md +22 -0
  73. package/docs/guide/07-composition.md +46 -0
  74. package/docs/guide/08-writing-a-module.md +26 -0
  75. package/docs/guide/09-cost.md +24 -0
  76. package/docs/guide/10-diagnostics.md +27 -0
  77. package/docs/llms-full.txt +1738 -0
  78. package/docs/llms.txt +45 -0
  79. package/docs/reference/cli.md +33 -0
  80. package/docs/reference/diagnostics.md +619 -0
  81. package/docs/reference/grammar.md +39 -0
  82. package/docs/reference/std/advance.md +35 -0
  83. package/docs/reference/std/cancellable_booking.md +35 -0
  84. package/docs/reference/std/captured_payment.md +43 -0
  85. package/docs/reference/std/conditional_disbursement.md +33 -0
  86. package/docs/reference/std/credit_facility.md +35 -0
  87. package/docs/reference/std/held_payment.md +64 -0
  88. package/docs/reference/std/instant_transfer.md +30 -0
  89. package/docs/reference/std/metered.md +27 -0
  90. package/docs/reference/std/pooled_split.md +26 -0
  91. package/docs/reference/std/premium_forward.md +39 -0
  92. package/docs/reference/std/reconciled_payout.md +33 -0
  93. package/docs/reference/std/recurring_collection.md +25 -0
  94. package/docs/reference/std/rotating_pool.md +42 -0
  95. package/docs/reference/std/scheduled.md +51 -0
  96. package/docs/reference/std/security_deposit.md +46 -0
  97. package/docs/reference/std/settlement_batch.md +42 -0
  98. package/docs/reference/std/swap.md +46 -0
  99. package/docs/reference/std/threshold_pool.md +47 -0
  100. package/docs/reference/std/weighted_distribution.md +39 -0
  101. package/docs/reference/types.md +20 -0
  102. package/docs/reference/udl-output.md +14 -0
  103. package/docs/sessions/2026-09-02-two-instruments.hsx +21 -0
  104. package/docs/sessions/2026-09-02-two-instruments.md +41 -0
  105. package/examples/01-first-program/README.md +45 -0
  106. package/examples/01-first-program/tip-jar.hsx +17 -0
  107. package/examples/02-imports-and-archetypes/README.md +99 -0
  108. package/examples/02-imports-and-archetypes/photo-booth.hsx +37 -0
  109. package/examples/03-diagnostics/README.md +68 -0
  110. package/examples/03-diagnostics/corner-shop-fixed.hsx +22 -0
  111. package/examples/03-diagnostics/corner-shop.hsx +19 -0
  112. package/examples/04-complete-product/README.md +87 -0
  113. package/examples/04-complete-product/study-hall.hsx +67 -0
  114. package/examples/05-watch-club/README.md +9 -0
  115. package/examples/05-watch-club/watch-club.hsx +124 -0
  116. package/examples/README.md +18 -0
  117. package/examples/advance/README.md +3 -0
  118. package/examples/advance/advance.hsx +13 -0
  119. package/examples/advance/advance.udl +339 -0
  120. package/examples/cancellable_booking/README.md +3 -0
  121. package/examples/cancellable_booking/cancellable_booking.hsx +14 -0
  122. package/examples/cancellable_booking/cancellable_booking.udl +391 -0
  123. package/examples/captured_payment/README.md +3 -0
  124. package/examples/captured_payment/captured_payment.hsx +21 -0
  125. package/examples/captured_payment/captured_payment.udl +677 -0
  126. package/examples/conditional_disbursement/README.md +3 -0
  127. package/examples/conditional_disbursement/conditional_disbursement.hsx +17 -0
  128. package/examples/conditional_disbursement/conditional_disbursement.udl +412 -0
  129. package/examples/cost-table.json +386 -0
  130. package/examples/credit_facility/README.md +3 -0
  131. package/examples/credit_facility/credit_facility.hsx +27 -0
  132. package/examples/credit_facility/credit_facility.udl +1373 -0
  133. package/examples/held_payment/README.md +3 -0
  134. package/examples/held_payment/held_payment.hsx +13 -0
  135. package/examples/held_payment/held_payment.udl +507 -0
  136. package/examples/instant_transfer/README.md +3 -0
  137. package/examples/instant_transfer/instant_transfer.hsx +16 -0
  138. package/examples/instant_transfer/instant_transfer.udl +364 -0
  139. package/examples/metered/README.md +3 -0
  140. package/examples/metered/metered.hsx +13 -0
  141. package/examples/metered/metered.udl +247 -0
  142. package/examples/pooled_split/README.md +3 -0
  143. package/examples/pooled_split/pooled_split.hsx +15 -0
  144. package/examples/pooled_split/pooled_split.udl +425 -0
  145. package/examples/premium_forward/README.md +3 -0
  146. package/examples/premium_forward/premium_forward.hsx +19 -0
  147. package/examples/premium_forward/premium_forward.udl +594 -0
  148. package/examples/reconciled_payout/README.md +3 -0
  149. package/examples/reconciled_payout/reconciled_payout.hsx +13 -0
  150. package/examples/reconciled_payout/reconciled_payout.udl +303 -0
  151. package/examples/recurring_collection/README.md +3 -0
  152. package/examples/recurring_collection/recurring_collection.hsx +21 -0
  153. package/examples/recurring_collection/recurring_collection.udl +1130 -0
  154. package/examples/rotating_pool/README.md +3 -0
  155. package/examples/rotating_pool/rotating_pool.hsx +18 -0
  156. package/examples/rotating_pool/rotating_pool.udl +4352 -0
  157. package/examples/scheduled/README.md +3 -0
  158. package/examples/scheduled/scheduled.hsx +12 -0
  159. package/examples/scheduled/scheduled.udl +335 -0
  160. package/examples/security_deposit/README.md +3 -0
  161. package/examples/security_deposit/security_deposit.hsx +21 -0
  162. package/examples/security_deposit/security_deposit.udl +293 -0
  163. package/examples/settlement_batch/README.md +3 -0
  164. package/examples/settlement_batch/settlement_batch.hsx +19 -0
  165. package/examples/settlement_batch/settlement_batch.udl +753 -0
  166. package/examples/swap/README.md +3 -0
  167. package/examples/swap/swap.hsx +19 -0
  168. package/examples/swap/swap.udl +876 -0
  169. package/examples/threshold_pool/README.md +3 -0
  170. package/examples/threshold_pool/threshold_pool.hsx +16 -0
  171. package/examples/threshold_pool/threshold_pool.udl +667 -0
  172. package/examples/weighted_distribution/README.md +3 -0
  173. package/examples/weighted_distribution/weighted_distribution.hsx +20 -0
  174. package/examples/weighted_distribution/weighted_distribution.udl +337 -0
  175. package/package.json +19 -6
  176. package/skills/hsx/SKILL.md +483 -0
  177. package/src/ast.ts +163 -9
  178. package/src/cli.ts +164 -12
  179. package/src/compile.ts +160 -20
  180. package/src/cost.ts +579 -0
  181. package/src/diagnostics.ts +442 -0
  182. package/src/emit.ts +447 -0
  183. package/src/entry-overrides.ts +263 -48
  184. package/src/format.ts +261 -0
  185. package/src/index.ts +32 -4
  186. package/src/ir.ts +99 -0
  187. package/src/lex.ts +59 -4
  188. package/src/limits.ts +2 -3
  189. package/src/modules.ts +444 -0
  190. package/src/parse.ts +655 -21
  191. package/src/typecheck.ts +3876 -0
  192. package/src/version.ts +4 -16
  193. package/std/SEMANTICS.md +130 -0
  194. package/std/settlements/advance.hsx +177 -0
  195. package/std/settlements/cancellable_booking.hsx +87 -0
  196. package/std/settlements/captured_payment.hsx +144 -0
  197. package/std/settlements/conditional_disbursement.hsx +185 -0
  198. package/std/settlements/credit_facility.hsx +167 -0
  199. package/std/settlements/held_payment.hsx +578 -0
  200. package/std/settlements/index.hsx +3 -0
  201. package/std/settlements/instant_transfer.hsx +190 -0
  202. package/std/settlements/metered.hsx +67 -0
  203. package/std/settlements/pooled_split.hsx +68 -0
  204. package/std/settlements/premium_forward.hsx +257 -0
  205. package/std/settlements/reconciled_payout.hsx +77 -0
  206. package/std/settlements/recurring_collection.hsx +27 -0
  207. package/std/settlements/rotating_pool.hsx +252 -0
  208. package/std/settlements/scheduled.hsx +641 -0
  209. package/std/settlements/security_deposit.hsx +166 -0
  210. package/std/settlements/settlement_batch.hsx +122 -0
  211. package/std/settlements/swap.hsx +1114 -0
  212. package/std/settlements/threshold_pool.hsx +221 -0
  213. package/std/settlements/weighted_distribution.hsx +141 -0
  214. package/dist/src/archetypes.d.ts +0 -17
  215. package/dist/src/archetypes.d.ts.map +0 -1
  216. package/dist/src/archetypes.js +0 -327
  217. package/dist/src/archetypes.js.map +0 -1
  218. package/dist/src/check.d.ts +0 -12
  219. package/dist/src/check.d.ts.map +0 -1
  220. package/dist/src/check.js +0 -1910
  221. package/dist/src/check.js.map +0 -1
  222. package/dist/src/lower.d.ts +0 -146
  223. package/dist/src/lower.d.ts.map +0 -1
  224. package/dist/src/lower.js +0 -4570
  225. package/dist/src/lower.js.map +0 -1
  226. package/dist/src/model.d.ts +0 -467
  227. package/dist/src/model.d.ts.map +0 -1
  228. package/dist/src/model.js +0 -15
  229. package/dist/src/model.js.map +0 -1
  230. package/spec/hsx-ir.schema.json +0 -920
  231. package/src/archetypes.ts +0 -340
  232. package/src/check.ts +0 -2938
  233. package/src/lower.ts +0 -5416
  234. package/src/model.ts +0 -519
package/src/version.ts CHANGED
@@ -1,17 +1,5 @@
1
- /**
2
- * The two versions HSX carries, and the difference between them.
3
- *
4
- * `HSX_VERSION` is the npm package's semver: it moves when this compiler's
5
- * code changes, including changes that only affect diagnostics or docs.
6
- *
7
- * `HSX_IR_VERSION` is the format number stamped into every compiled document
8
- * as its `hsx` field. It moves only when the emitted IR shape changes in a
9
- * way a consumer must notice, so a runtime can refuse a document it does not
10
- * understand by reading one integer. A package release almost never bumps it.
11
- */
1
+ /** Package version reported by the command line. */
2
+ export const HSX_VERSION = "1.0.0-rc.1";
12
3
 
13
- /** Stamped into every compiled HSX-JSON document as `hsx`. */
14
- export const HSX_IR_VERSION = 1;
15
-
16
- /** Kept equal to the package.json version by `test/spec.spec.ts`. */
17
- export const HSX_VERSION = "1.0.0-beta.1";
4
+ /** Canonical UDL contract version emitted by this compiler. */
5
+ export const HSX_TARGET_UDL_VERSION = 1;
@@ -0,0 +1,130 @@
1
+ # Settlement semantics frozen before legacy teardown
2
+
3
+ This note records the behavior that the former archetype branches emitted on
4
+ 2026-09-01. The 48 canonical documents under
5
+ `test/fixtures/general-path-oracle/` are the byte-level authority. This note is
6
+ the human porting index.
7
+
8
+ ## Direct and held payments
9
+
10
+ - `instant_transfer` stores the amount, currency, payer, and payee. Create pays
11
+ through one or more ordered pieces and ends in `paid`. A payer fee is an
12
+ `on_top` move. A payee fee is carved from the base amount. Exact, basis-point,
13
+ and tiered rules produce fee fields and `feeRules`. The finest common
14
+ refinement of all fee cuts produces piece fields and one partition. Floor
15
+ rounding sends the remainder to the named non-fee recipient. A derived
16
+ amount adds a floor percentage field, `derivedAmounts`, a platform party, and
17
+ its own transfer piece.
18
+ - `held_payment` reserves every refined piece before release. It posts release
19
+ pieces, voids cancellation pieces, and keeps payer service fees outside the
20
+ held principal. Release and cancellation fee sides share the finest common
21
+ partition, so each stored piece has one release recipient and one cancel
22
+ recipient. States track each funding, release, cancellation, and abandonment
23
+ step. Abandonment refunds every still-held piece. A deadline release and a
24
+ caller decision release carry the named date or port clause. Retention is the
25
+ same form with one held piece, a release deadline, and cancellation back to
26
+ the contractor. Whole-amount mode funds the principal and on-top fee in one
27
+ action, then releases or cancels the principal whole. A condition and date
28
+ can coexist, with separate early and scheduled release actions.
29
+ - `captured_payment` stores authorization total, reserve and reversal dates,
30
+ and both party accounts. It moves through `created`, `authorized`, optional
31
+ `partially_captured`, `settled`, `voided`, `expired`, `corrected`, or
32
+ `reversed`. Authorize reserves custody. Capture and capture-more consume the
33
+ authorized balance according to the declared mode. Settle posts the captured
34
+ amount. Void and expiry release the reserve. Correction and external reversal
35
+ use their declared ports and windows. Derived fees use the same floor,
36
+ partition, bearer, and position rules as direct payment.
37
+ - `premium_forward` holds premium pieces, then forwards the net pieces after a
38
+ bind decision. It can abandon unbound custody. Policy reference, renewal due,
39
+ endorsement evidence, and lapse actions appear only when declared. Its fee
40
+ partition and floor remainder rules match `held_payment`.
41
+
42
+ ## Decisions and credit
43
+
44
+ - `conditional_disbursement` emits a submitted parent with cap, currency,
45
+ source, destination, and the decision port. Denial terminates the parent. An
46
+ approved-amount child stores a runtime-bounded amount and a parent reference.
47
+ The child captures the port input, moves through `created`, `approved`, and
48
+ `paid`, and refuses reopening. Recovery is a separate transfer.
49
+ - `advance` has two forms. A carved advance references a held settlement and
50
+ its recourse settlement, disburses once, and settles from the referenced
51
+ release without minting new value. A scheduled advance stores advance,
52
+ fee, repayable total, first due date, and one repayment field per fixed
53
+ installment. It partitions repayments to the repayable total and advances
54
+ before collecting each due installment.
55
+ - `credit_facility` stores lender, borrower, draw destination, limit, currency,
56
+ and expiry. The facility can freeze and close. Each draw is a generated child
57
+ with amount, facility reference, and obligation reference. Draw admission
58
+ checks the facility state and aggregate limit. Resolution waits for the
59
+ referenced obligation state.
60
+
61
+ ## Schedules and usage
62
+
63
+ - A finite `scheduled` transfer stores total, first due date, and one money
64
+ field per installment. Floor division creates equal pieces and gives the
65
+ final field the remainder. States and actions unroll in order. Each action
66
+ carries its due rule and cumulative duration offset.
67
+ - Scheduled obligation mode emits a parent plus one generated payment child per
68
+ installment. The parent stores principal, delinquency dates, party accounts,
69
+ partitions, and aggregate invariants. It supports draft approval, optional
70
+ advance, fixed collection and delinquency actions, write-off, and completion.
71
+ Each child binds parent fields, repays once, and can refund once.
72
+ - `recurring_collection` with a finite count uses the scheduled construction.
73
+ Open recurrence stores one amount and anchor, opens one period at a time,
74
+ collects that period, and permits cancellation. It never unrolls an unbounded
75
+ runtime loop.
76
+ - `metered` stores one money field for each declared meter and a period end.
77
+ Every charge moves directly from payer to payee. The instrument never accrues
78
+ custody. Closing the period only changes state.
79
+
80
+ ## Collections and distributions
81
+
82
+ - `pooled_split` stores the pool total, due date, and one share amount and
83
+ account per recipient. Positive shares total exactly 10,000 basis points.
84
+ Floor division assigns each share, and the named remainder recipient absorbs
85
+ minor-unit residue. Funding and distribution actions unroll in roster order.
86
+ - `weighted_distribution` emits an open parent and an entitlement child. The
87
+ parent stores source, total, record date, and maximum recipient count. A port
88
+ freezes the entitlement snapshot. Child rows store recipient, weight, source,
89
+ currency, and parent reference. Largest-remainder distribution pays children
90
+ once. Aggregate clauses cap and total the child set. Withholding is refused
91
+ and correction creates a new distribution. Its `flat` form emits a single
92
+ claim instead. The caller supplies typed pool, weight, and group references,
93
+ their state gates, copy and match maps, and the pool amount path.
94
+ - `threshold_pool` emits a pool parent and commitment child. The parent stores
95
+ target, close date, maximum contributors, beneficiary, and currency. It moves
96
+ through open, active, failed, or settled based on aggregate commitment gates.
97
+ Each commitment can cancel before collection, collect into the round, or
98
+ refund after failure. Its referenced-contribution form accepts a published
99
+ contribution instrument, beneficiary account, and memo and emits no child.
100
+ - `security_deposit` reserves the full amount. A claim port posts either the
101
+ whole hold or a decided amount bounded by the hold. The explicit remainder
102
+ returns to the payer. A return port voids the whole hold. The deadline form
103
+ adds machine expiry and unfunded cancellation. Claim and return targets can
104
+ name either party.
105
+
106
+ ## Composition and unwind
107
+
108
+ - `swap` stores both side amounts, accounts, fees, currency, and optional
109
+ clawback date. Funding is atomic across both sides. Release, settlement,
110
+ cancellation, dispute, abandonment, and clawback preserve the two-sided
111
+ conservation group. Side fees keep their declared bearer and position.
112
+ `distinctParties` prevents self-dealing. Unwind refunds each side and applies
113
+ the declared penalty tiers without changing the principal partition. Fixed
114
+ side names, state order, action bindings, parked-state reasons, and ID prefix
115
+ are general compile-time parameters.
116
+ - `settlement_batch` emits a batch plus capture, credit-adjustment, and
117
+ debit-adjustment children. The batch stores close time, settlement and payout
118
+ accounts, beneficiary reference, and currency. Close freezes intake.
119
+ Calculate signs capture, fee, and reversal entries. Approve rejects a negative
120
+ position when configured. Instruct, acknowledge, and reconcile use the
121
+ declared payout port. Child references and statuses define every aggregate
122
+ and signed-sum input.
123
+ - `rotating_pool` emits one parent plus one contribution child per fixed member.
124
+ The parent unrolls active and ready states for every cycle and checks that each
125
+ member row exists exactly once. Every child unrolls due, funded, defaulted,
126
+ guaranteed, paid, and completed states for every cycle. Due offsets scale the
127
+ fixed recurrence. A funded or guaranteed contribution pays the roster's fixed
128
+ beneficiary for that cycle. The final close requires the escrow account to be
129
+ drained. Its referenced-membership form delegates those member cycles to a
130
+ published membership instrument and emits only the parent.
@@ -0,0 +1,177 @@
1
+ module std.settlements.advance
2
+
3
+ export instrument advance<C>(
4
+ funder: party,
5
+ to: party,
6
+ amount: money<C>,
7
+ fee: optional<percent>,
8
+ count: optional<integer>,
9
+ every: optional<text>,
10
+ first_due: optional<date>,
11
+ against: optional<ref>,
12
+ ) {
13
+ let(amount_path): concat("fields.", amount);
14
+ let(currency_path): "fields.currency";
15
+ let(funder_field): camel(concat(funder, "_account_id"));
16
+ let(to_field): camel(concat(to, "_account_id"));
17
+
18
+ agent_description: "Reach for advance when the {funder} pays the {to} up front and is repaid afterwards, either out of a carved hold release or over scheduled repayments. Pick deposit for a refundable reservation and instant transfer when nobody repays the payer.";
19
+ title: sentence(instrument);
20
+ id_prefix: prefix(instrument);
21
+ parties {
22
+ payer: funder;
23
+ beneficiary: to;
24
+ }
25
+
26
+ when(against) {
27
+ let(hold_name): owner(against);
28
+ summary: "Advance to the {to} repaid by carving the {hold_name} release";
29
+ description: "Advance: the {funder} disburses {amount} to the {to} and is repaid out of the {hold_name} release, which pays the {funder} in the {to}'s place";
30
+ fields {
31
+ amount {
32
+ type: money<C>;
33
+ description: "The advanced amount in {C} minor units, disbursed to the {to} up front";
34
+ }
35
+ carve_hold_id {
36
+ type: ref<hold_name>;
37
+ description: "The {hold_name} bound to this advance";
38
+ pattern: concat("^", prefix(hold_name), "_(sandbox|live)_[a-z0-9]{8,64}$");
39
+ }
40
+ carve_recourse_1_id {
41
+ type: ref<recourse>;
42
+ description: "The recourse bound to this advance";
43
+ pattern: "^reco_(sandbox|live)_[a-z0-9]{8,64}$";
44
+ }
45
+ }
46
+ required: [to_field, funder_field, amount, carveHoldId, carveRecourse1Id, currency];
47
+ lifecycle {
48
+ states created advanced repaid;
49
+ initial created;
50
+ on disburse: created -> advanced;
51
+ on settle: advanced -> repaid;
52
+ }
53
+ action create {
54
+ agent_description: "Open the advance row before any money moves. The caller supplies the {amount}, both party accounts, and the ids of the {hold_name} and the recourse that back repayment. Nothing is disbursed here.";
55
+ summary: concat("Create a ", words(instrument));
56
+ steps: [];
57
+ moves: [];
58
+ }
59
+ action disburse {
60
+ agent_description: "Pay the {amount} from the {funder} to the {to}. The advance must be created, the bound {hold_name} funded, and the recourse active, both matching this amount and currency. The transfer posts straight out and does not unwind.";
61
+ summary: "Disburse the {amount} to the {to}";
62
+ requires refs: [{
63
+ field: carveHoldId;
64
+ match: {
65
+ [currency_path]: currency_path;
66
+ [amount_path]: amount_path;
67
+ };
68
+ statuses: [funded];
69
+ }, {
70
+ field: carveRecourse1Id;
71
+ match: {
72
+ [currency_path]: currency_path;
73
+ [amount_path]: amount_path;
74
+ };
75
+ statuses: [active];
76
+ }];
77
+ moves: [{ amount: amount; from: payer; to: beneficiary; key: transfer; operation: create; }];
78
+ steps: [];
79
+ }
80
+ action settle {
81
+ agent_description: "Close the advance once the {hold_name} has released to the {funder} in the {to}'s place. The advance must already be disbursed. No money moves here, the release did the repaying.";
82
+ summary: concat("Close the advance once the ", hold_name, " has released to the ", funder);
83
+ steps: [];
84
+ moves: [];
85
+ }
86
+ }
87
+
88
+ when_not(against) {
89
+ let(repayment_fields): names("repayment", count, "Amount");
90
+ let(first_target): if_eq(count, 1, "repaid", "repaying_1");
91
+ let(states_key): "states";
92
+ let(first_due_field): camel(first_due);
93
+ summary: concat("Advance to ", to, " repaid over ", count, " anchors");
94
+ description: concat("Advance: the ", funder, " disburses ", amount, " to the ", to, ", repaid over ", count, " scheduled repayments plus the funder's discount");
95
+ fields {
96
+ amount {
97
+ type: money<C>;
98
+ description: "The advanced amount in {C} minor units, disbursed to the {to} up front";
99
+ }
100
+ fee_amount {
101
+ type: money<C>;
102
+ description: concat(fee, " of ", amount, ", the funder's discount repaid on top of the advance");
103
+ }
104
+ repayable_amount {
105
+ type: money<C>;
106
+ description: concat(amount, " + feeAmount: the total the repayment fields below partition exactly");
107
+ }
108
+ [first_due_field] {
109
+ type: date;
110
+ description: concat("Due date of the first repayment; repayment k falls ", every, " after its predecessor");
111
+ }
112
+ repayment_1_amount {
113
+ type: money<C>;
114
+ description: concat("Repayment 1 of ", count, " (carries the integer-division remainder): about 33.34% of repayableAmount, collected on its own stored-date anchor");
115
+ }
116
+ for repayment in sub(count, 1) {
117
+ let(index): add(repayment, 1);
118
+ repayment[index]Amount {
119
+ type: money<C>;
120
+ description: concat("Repayment ", index, " of ", count, ": about 33.33% of repayableAmount, collected on its own stored-date anchor");
121
+ }
122
+ }
123
+ }
124
+ lifecycle {
125
+ states created advanced;
126
+ [states_key]: [first_target];
127
+ initial created;
128
+ on disburse: created -> advanced;
129
+ on collect_repayment_1: advanced -> [first_target];
130
+ for repayment in sub(count, 1) {
131
+ let(index): add(repayment, 1);
132
+ let(previous): concat("repaying_", repayment);
133
+ let(target): if_eq(index, count, "repaid", concat("repaying_", index));
134
+ [states_key]: [target];
135
+ on collect_repayment_[index]: [previous] -> [target];
136
+ }
137
+ }
138
+ partitions: [{
139
+ piece_fields: repayment_fields;
140
+ total_field: repayableAmount;
141
+ }, {
142
+ piece_fields: [amount, feeAmount];
143
+ total_field: repayableAmount;
144
+ }];
145
+ action create {
146
+ agent_description: "Open the advance row before any money moves. The caller supplies the {amount}, the fee amount, the repayable total, and the first repayment date. The repayment fields must partition the repayable total exactly. Nothing is disbursed here.";
147
+ summary: concat("Create a ", words(instrument));
148
+ steps: [];
149
+ moves: [];
150
+ }
151
+ action disburse {
152
+ agent_description: "Pay the {amount} from the {funder} to the {to} and start the repayment schedule. The advance must be created. The transfer posts straight out and does not unwind. Each repayment is collected on its own stored date anchor.";
153
+ summary: "Disburse the {amount} to the {to}";
154
+ moves: [{ amount: amount; from: payer; to: beneficiary; key: transfer; operation: create; }];
155
+ steps: [];
156
+ }
157
+ action collect_repayment_1 {
158
+ summary: concat("Collect repayment 1 of ", count);
159
+ due: { field: first_due_field; };
160
+ moves: [{ amount: repayment1Amount; from: beneficiary; to: payer; key: transfer; operation: create; }];
161
+ steps: [];
162
+ }
163
+ for repayment in sub(count, 1) {
164
+ let(index): add(repayment, 1);
165
+ let(repayment_field): concat("repayment", index, "Amount");
166
+ action collect_repayment_[index] {
167
+ summary: concat("Collect repayment ", index, " of ", count);
168
+ due: {
169
+ field: first_due_field;
170
+ offset: scale_duration(every, sub(index, 1));
171
+ };
172
+ moves: [{ amount: repayment_field; from: beneficiary; to: payer; key: transfer; operation: create; }];
173
+ steps: [];
174
+ }
175
+ }
176
+ }
177
+ }
@@ -0,0 +1,87 @@
1
+ module std.settlements.cancellable_booking
2
+
3
+ export instrument cancellable_booking<C>(
4
+ guest: party,
5
+ host: party,
6
+ amount: money<C>,
7
+ starts_at: date,
8
+ late_penalty_bps: integer,
9
+ late_within: text,
10
+ early_penalty_bps: integer,
11
+ offer_life: text,
12
+ ) {
13
+ let(guest_account_field): camel(concat(guest, "_account_id"));
14
+ let(host_account_field): camel(concat(host, "_account_id"));
15
+ let(reference_filter_key): "x-hyperscale-reference-filter";
16
+ let(owner_id_key): "owner.id";
17
+ let(owner_type_key): "owner.type";
18
+ fields {
19
+ amount { type: money<C>; description: concat("Booking price in minor units, held away from both the ", words(guest), " and the ", words(host), " until the booking ends"); }
20
+ currency { type: text; description: "ISO 4217 currency code"; minLength: 3; maxLength: 3; pattern: "^[A-Z]{3}$"; }
21
+ starts_at { type: date; description: "When the booking starts; the cancellation penalty is priced against the time left before it"; }
22
+ [guest_account_field] { type: account<C>; description: concat("The ", words(guest), " account the booking is taken from and the refund returns to"); pattern: "^acct_(sandbox|live)_[a-z0-9]{8,64}$"; [reference_filter_key]: { column: role; values: [customer_balance]; }; }
23
+ [host_account_field] { type: account<C>; description: concat("The ", words(host), " account the booking and any penalty end up in"); pattern: "^acct_(sandbox|live)_[a-z0-9]{8,64}$"; [reference_filter_key]: { column: role; values: [customer_balance]; }; }
24
+ }
25
+ lifecycle {
26
+ states created held cancellation_quoted canceled settled completed;
27
+ initial created;
28
+ on take: created -> held;
29
+ on complete: held | cancellation_quoted -> completed;
30
+ on cancel: held -> cancellation_quoted;
31
+ on confirm: cancellation_quoted -> canceled;
32
+ on retain: canceled -> settled;
33
+ }
34
+ parties { beneficiary: host_account_field; payer: guest_account_field; }
35
+ required: [amount, currency, guest_account_field, host_account_field, starts_at];
36
+ title: sentence(instrument);
37
+ agent_description: concat("Reach for cancellable booking when the ", words(guest), " pays up front and can back out at a price they see before they agree to it. The money sits in a holding account, the penalty is priced against the time left before the start, and the quote is frozen until it expires. Pick held payment when there is no cancellation price to quote.");
38
+ id_prefix: prefix(instrument);
39
+ summary: concat("Booking the ", words(guest), " can cancel at a price they see before they agree to it");
40
+ description: "A booking whose cancellation is quoted rather than argued: the penalty is priced against the time left before the start, frozen with the terms it was read from, and paid only if the guest confirms while the offer is still alive";
41
+ action create {
42
+ agent_description: concat("Open the booking and provision the holding account the price sits in. No money moves. The price, the currency, the start moment, and both party accounts are fixed here. Call take next to collect from the ", words(guest), ".");
43
+ summary: concat("Open a ", words(instrument), " and its holding account");
44
+ moves: [];
45
+ steps: [{ operation: "account.escrow.provision"; bind: { currency: { from: instance; path: fields.currency; }; [owner_id_key]: { from: instance; path: productId; }; [owner_type_key]: { from: const; value: product; }; productId: { from: instance; path: productId; }; role: { from: const; value: product_escrow; }; }; capture: { bookingHoldingAccountId: accountId; }; }];
46
+ }
47
+ action take {
48
+ agent_description: concat("Move the whole booking price out of the ", words(guest), " account into the holding account. This moves money. Only a created booking takes. Neither party can spend the money until the booking completes or a cancellation is confirmed.");
49
+ summary: concat("Take the booking price from the ", words(guest), " into the holding account");
50
+ moves: [{ key: booking; operation: internal_transfer.create; bind: { amount: { from: instance; path: concat("fields.", amount); }; currency: { from: instance; path: fields.currency; }; destinationAccountId: { from: instance; path: refs.bookingHoldingAccountId; }; productId: { from: instance; path: productId; }; sourceAccountId: { from: instance; path: concat("fields.", guest_account_field); }; }; capture: { bookingTransferId: transferId; }; }];
51
+ steps: [];
52
+ }
53
+ action complete {
54
+ summary: concat("Release the whole booking to the ", words(host), " once the stay has started, even with a cancellation quote parked un-acted");
55
+ due { field: starts_at; }
56
+ moves: [{ key: release; operation: internal_transfer.create; bind: { amount: { from: instance; path: concat("fields.", amount); }; currency: { from: instance; path: fields.currency; }; destinationAccountId: { from: instance; path: concat("fields.", host_account_field); }; productId: { from: instance; path: productId; }; sourceAccountId: { from: instance; path: refs.bookingHoldingAccountId; }; }; capture: { releaseTransferId: transferId; }; }];
57
+ steps: [];
58
+ }
59
+ action cancel {
60
+ agent_description: "Price the cancellation and freeze that price. No money moves. The penalty is computed from the time left before the start, and the quote expires on its own, after which a new cancel prices it again. Call confirm to spend the quote.";
61
+ summary: "Price the cancellation and hold that price open";
62
+ quote {
63
+ anchorField: starts_at;
64
+ baseField: amount;
65
+ chargeRef: cancellationPenaltyAmount;
66
+ charges: [{ bps: late_penalty_bps; withinOffset: late_within; }, { bps: early_penalty_bps; }];
67
+ expires { offset: offer_life; }
68
+ fixes: [amount, guest_account_field];
69
+ netDestinationField: guest_account_field;
70
+ netRef: cancellationRefundAmount;
71
+ }
72
+ moves: []; steps: [];
73
+ }
74
+ action confirm {
75
+ agent_description: concat("Spend the frozen quote and return the net refund to the ", words(guest), ". This moves money and does not reverse. It requires an un-expired quote from cancel, and the penalty the refund left behind is paid to the ", words(host), " by retain.");
76
+ summary: concat("Spend the quoted cancellation and return the net to the ", words(guest));
77
+ commit: cancel;
78
+ moves: [{ key: refund; operation: internal_transfer.create; bind: { amount: { from: instance; path: refs.cancellationRefundAmount; }; currency: { from: instance; path: fields.currency; }; destinationAccountId: { from: instance; path: concat("fields.", guest_account_field); }; productId: { from: instance; path: productId; }; sourceAccountId: { from: instance; path: refs.bookingHoldingAccountId; }; }; capture: { cancellationTransferId: transferId; }; }];
79
+ steps: [];
80
+ }
81
+ action retain {
82
+ agent_description: concat("Pay the quoted cancellation penalty out of the holding account to the ", words(host), ". This moves money and does not reverse. The booking must already be canceled, so the penalty figure is the one the quote fixed.");
83
+ summary: concat("Pay the quoted penalty that the refund left behind to the ", words(host));
84
+ moves: [{ key: penalty; operation: internal_transfer.create; bind: { amount: { from: instance; path: refs.cancellationPenaltyAmount; }; currency: { from: instance; path: fields.currency; }; destinationAccountId: { from: instance; path: concat("fields.", host_account_field); }; productId: { from: instance; path: productId; }; sourceAccountId: { from: instance; path: refs.bookingHoldingAccountId; }; }; capture: { penaltyTransferId: transferId; }; }];
85
+ steps: [];
86
+ }
87
+ }
@@ -0,0 +1,144 @@
1
+ module std.settlements.captured_payment
2
+
3
+ export instrument captured_payment<C>(payer: party, payee: party, amount: money<C>, reserve_until: date, correction: condition, external_reversal: condition, capture_mode: text, correction_mode: text, negative_position: text, timeout: text, derived_amount: optional<block>) {
4
+ let(correction_name): correction;
5
+ let(reversal_name): external_reversal;
6
+ let(reversal_window): external_reversal_within;
7
+ let(instrument_words): words(instrument);
8
+ when(derived_amount) {
9
+ let(derived_field): get(derived_amount, "field");
10
+ let(derived_source): get(derived_amount, "source");
11
+ let(derived_rule): get(derived_amount, "rule");
12
+ let(derived_bearer): get(derived_amount, "bearer");
13
+ }
14
+ agent_description: "Reach for captured payment when the {payee} reserves against the {payer} first and then takes the money in slices before {reserve_until}. Pick instant transfer when the whole amount moves at once, and deposit when the reservation is claimed or returned whole.";
15
+ summary: "Capture reservation from {payer} to {payee}";
16
+ title: sentence(instrument);
17
+ description: "Payer reservation captured by the payee in slices within a fixed window";
18
+ fields {
19
+ when(derived_amount) {
20
+ let(fee_collection_key): "x-hyperscale-fee-collection-port";
21
+ let(reference_filter_key): "x-hyperscale-reference-filter";
22
+ platformAccountId {
23
+ type: account<C>;
24
+ description: "The product fee collection account";
25
+ pattern: "^acct_(sandbox|live)_[a-z0-9]{8,64}$";
26
+ [fee_collection_key]: true;
27
+ [reference_filter_key]: { column: role; values: [customer_balance, product_revenue]; };
28
+ }
29
+ }
30
+ amount { type: money<C>; description: "Maximum captured amount in {C} minor units"; }
31
+ reserve_until { type: date; description: "Reservation expiry that releases any uncaptured remainder"; }
32
+ reversalUntil { type: date; description: "Machine-owned external reversal cutoff anchored when settlement completes"; optional: true; }
33
+ when(derived_amount) {
34
+ [derived_field] { type: money<C>; description: "Machine-computed {derived_rule} of {derived_source}; callers never supply it"; pattern: "^[1-9][0-9]{0,17}$"; optional: true; }
35
+ }
36
+ }
37
+ lifecycle {
38
+ states created authorized partially_captured settled voided expired corrected reversed;
39
+ initial created;
40
+ on authorize: created -> authorized;
41
+ on capture: authorized -> partially_captured;
42
+ on capture_more: partially_captured -> partially_captured;
43
+ on settle: authorized | partially_captured -> settled;
44
+ on void: authorized -> voided;
45
+ on expire: authorized -> expired;
46
+ on settle_on_expiry: partially_captured -> settled;
47
+ on [correction_name]: settled -> corrected;
48
+ on [reversal_name]: settled -> reversed;
49
+ }
50
+ parties {
51
+ payer: payer;
52
+ beneficiary: payee;
53
+ }
54
+ when(derived_amount) {
55
+ computes derived: { field: derived_field; source_field: derived_source; rounding: floor; rule: { kind: percentage_of; bps: derived_rule; }; };
56
+ }
57
+ action create {
58
+ let(metadata_instrument): "metadata.instrumentId";
59
+ let(metadata_instance): "metadata.instrumentInstanceId";
60
+ let(metadata_phase): "metadata.phase";
61
+ agent_description: "Open the payment row before anything is reserved. The caller supplies the {amount}, the currency, and both party accounts. This reserves nothing, call authorize next.";
62
+ summary: "Create a {instrument_words}";
63
+ when(derived_amount) {
64
+ moves: [{ key: "derived_amount"; operation: internal_transfer.create; bind: { amount: { from: instance; path: concat("fields.", derived_field); }; currency: { from: instance; path: fields.currency; }; destinationAccountId: { from: instance; path: fields.platformAccountId; }; [metadata_instrument]: { from: const; value: instrument; }; [metadata_instance]: { from: instance; path: instrumentInstanceId; }; [metadata_phase]: { from: const; value: create; }; productId: { from: instance; path: productId; }; sourceAccountId: { from: instance; path: concat("fields.", camel(derived_bearer), "AccountId"); }; }; capture: { createDerivedAmountTransferId: transferId; }; }];
65
+ }
66
+ steps: [];
67
+ }
68
+ action authorize {
69
+ agent_description: "Reserve the {amount} against the {payer} in the {payee}'s favor until {reserve_until}. The payment must be created. The money is held, not paid: capture and settle post it, void and expiry release it.";
70
+ summary: "Reserve the {amount} until {reserve_until}";
71
+ moves: [{ key: reservation; amount: amount; from: payer; to: beneficiary; operation: reserve; }];
72
+ steps: [];
73
+ }
74
+ action capture {
75
+ agent_description: "Post the first capture slice out of the live reservation. The payment must be authorized and the caller passes captureAmount in minor units. The slice settles for good and void can no longer release the reservation. Call before {reserve_until}.";
76
+ summary: "Post one strict partial capture slice";
77
+ deadline { field: reserve_until; };
78
+ input { type: object; additional_properties: false; properties: { captureAmount: { description: "Positive partial capture amount in minor units"; pattern: "^[1-9][0-9]{0,17}$"; type: string; }; }; required: [captureAmount]; }
79
+ moves: [{ key: post; operation: internal_transfer.post; bind: { amount: { from: input; path: captureAmount; }; currency: { from: instance; path: fields.currency; }; postMode: { from: const; value: partial_only; }; transferId: { from: instance; path: refs.authorizeReservationTransferId; }; }; capture: { capturedAmount: postedAmount; }; }];
80
+ steps: [];
81
+ }
82
+ action capture_more {
83
+ agent_description: "Post another capture slice out of a partly captured reservation. Call this only after capture took the first slice. Each slice settles for good, and the uncaptured remainder still releases at {reserve_until}.";
84
+ summary: "Post another strict partial capture slice";
85
+ deadline { field: reserve_until; };
86
+ input { type: object; additional_properties: false; properties: { captureAmount: { description: "Positive partial capture amount in minor units"; pattern: "^[1-9][0-9]{0,17}$"; type: string; }; }; required: [captureAmount]; }
87
+ moves: [{ key: post; operation: internal_transfer.post; bind: { amount: { from: input; path: captureAmount; }; currency: { from: instance; path: fields.currency; }; postMode: { from: const; value: partial_only; }; transferId: { from: instance; path: refs.authorizeReservationTransferId; }; }; capture: { capturedAmount: postedAmount; }; }];
88
+ steps: [];
89
+ }
90
+ action settle {
91
+ agent_description: "Post the whole reserved remainder and finish the payment. The payment must be authorized or partly captured. The money settles and the external reversal window opens on reversalUntil.";
92
+ summary: "Post the full reserved remainder and settle";
93
+ deadline { field: reserve_until; };
94
+ sets(at) { field: reversalUntil; offset: reversal_window; };
95
+ moves: [{ key: post; operation: internal_transfer.post; bind: { transferId: { from: instance; path: refs.authorizeReservationTransferId; }; }; capture: { capturedAmount: postedAmount; }; }];
96
+ steps: [];
97
+ }
98
+ action void {
99
+ agent_description: "Release the reservation whole and cancel the payment. Only an authorized reservation with nothing captured can void. Once any slice is captured, settle it or let it expire instead.";
100
+ summary: "Release an entirely uncaptured reservation";
101
+ moves: [{ key: void; operation: internal_transfer.void; bind: { reason: { from: const; value: "Reservation voided before any capture"; }; transferId: { from: instance; path: refs.authorizeReservationTransferId; }; }; }];
102
+ steps: [];
103
+ }
104
+ action expire {
105
+ summary: "Release an uncaptured reservation at expiry";
106
+ due { field: reserve_until; };
107
+ moves: [{ key: void; operation: internal_transfer.void; bind: { reason: { from: const; value: "Uncaptured reservation expired"; }; transferId: { from: instance; path: refs.authorizeReservationTransferId; }; }; }];
108
+ steps: [];
109
+ }
110
+ action settle_on_expiry {
111
+ summary: "Release the uncaptured remainder and settle captured slices";
112
+ due { field: reserve_until; };
113
+ sets(at) { field: reversalUntil; offset: reversal_window; };
114
+ moves: [{ key: void; operation: internal_transfer.void; bind: { reason: { from: const; value: "Uncaptured remainder released at expiry"; }; transferId: { from: instance; path: refs.authorizeReservationTransferId; }; }; }];
115
+ steps: [];
116
+ }
117
+ action [correction_name] {
118
+ let(metadata_clawback): "metadata.clawbackOfTransferId";
119
+ let(metadata_instrument): "metadata.instrumentId";
120
+ let(metadata_instance): "metadata.instrumentInstanceId";
121
+ let(metadata_phase): "metadata.phase";
122
+ let(correction_capture): camel(concat(correction_name, "_transfer_transfer_id"));
123
+ agent_description: "Return the whole captured amount to the {payer} after the payment settled. Only a settled payment corrects, and only the party the product authorized may call it. The money moves back and there is no undo.";
124
+ summary: "Return the full captured amount on payee correction";
125
+ port { allowed_parties: [if_eq(at(correction_allowed, 1), payee, "beneficiary", "payer")]; };
126
+ moves: [{ key: transfer; operation: internal_transfer.create; bind: { amount: { from: instance; path: refs.capturedAmount; }; currency: { from: instance; path: fields.currency; }; destinationAccountId: { from: instance; path: concat("fields.", payer, "AccountId"); }; [metadata_clawback]: { from: instance; path: refs.authorizeReservationTransferId; }; [metadata_instrument]: { from: const; value: instrument; }; [metadata_instance]: { from: instance; path: instrumentInstanceId; }; [metadata_phase]: { from: const; value: correction_name; }; productId: { from: instance; path: productId; }; sourceAccountId: { from: instance; path: concat("fields.", payee, "AccountId"); }; }; capture: { [correction_capture]: transferId; }; }];
127
+ steps: [];
128
+ }
129
+ action [reversal_name] {
130
+ let(metadata_clawback): "metadata.clawbackOfTransferId";
131
+ let(metadata_instrument): "metadata.instrumentId";
132
+ let(metadata_instance): "metadata.instrumentInstanceId";
133
+ let(metadata_phase): "metadata.phase";
134
+ let(reversal_capture): camel(concat(reversal_name, "_transfer_transfer_id"));
135
+ agent_description: "Return the whole captured amount to the {payer} on an external reversal. The payment must be settled and the call must land before reversalUntil. The caller passes externalReference, which stays in the receipt. There is no undo.";
136
+ summary: "Return the full captured amount on an external reversal";
137
+ capture(input) { externalReference: externalReference; };
138
+ deadline { field: reversalUntil; };
139
+ input { type: object; additional_properties: false; properties: { externalReference: { description: "Required decision reference retained in the operation receipt"; max_length: 180; min_length: 1; type: string; }; }; required: [externalReference]; }
140
+ port { allowed_parties: [if_eq(at(external_reversal_allowed, 1), payee, "beneficiary", "payer")]; };
141
+ moves: [{ key: transfer; operation: internal_transfer.create; bind: { amount: { from: instance; path: refs.capturedAmount; }; currency: { from: instance; path: fields.currency; }; destinationAccountId: { from: instance; path: concat("fields.", payer, "AccountId"); }; [metadata_clawback]: { from: instance; path: refs.authorizeReservationTransferId; }; [metadata_instrument]: { from: const; value: instrument; }; [metadata_instance]: { from: instance; path: instrumentInstanceId; }; [metadata_phase]: { from: const; value: reversal_name; }; productId: { from: instance; path: productId; }; sourceAccountId: { from: instance; path: concat("fields.", payee, "AccountId"); }; }; capture: { [reversal_capture]: transferId; }; }];
142
+ steps: [];
143
+ }
144
+ }