@hyperscale0/hsx 2.4.1 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -408
- package/README.md +3 -92
- package/dist/src/ast.d.ts +99 -310
- package/dist/src/ast.d.ts.map +1 -1
- package/dist/src/ast.js +16 -69
- package/dist/src/ast.js.map +1 -1
- package/dist/src/cli.d.ts +6 -19
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +76 -315
- package/dist/src/cli.js.map +1 -1
- package/dist/src/compile.d.ts +23 -73
- package/dist/src/compile.d.ts.map +1 -1
- package/dist/src/compile.js +1113 -148
- package/dist/src/compile.js.map +1 -1
- package/dist/src/cost.d.ts +8 -77
- package/dist/src/cost.d.ts.map +1 -1
- package/dist/src/cost.js +13 -422
- package/dist/src/cost.js.map +1 -1
- package/dist/src/format.d.ts +8 -7
- package/dist/src/format.d.ts.map +1 -1
- package/dist/src/format.js +9 -175
- package/dist/src/format.js.map +1 -1
- package/dist/src/headers.d.ts +35 -0
- package/dist/src/headers.d.ts.map +1 -0
- package/dist/src/headers.js +108 -0
- package/dist/src/headers.js.map +1 -0
- package/dist/src/index.d.ts +6 -12
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +4 -9
- package/dist/src/index.js.map +1 -1
- package/dist/src/lex.d.ts +8 -28
- package/dist/src/lex.d.ts.map +1 -1
- package/dist/src/lex.js +88 -146
- package/dist/src/lex.js.map +1 -1
- package/dist/src/parse.d.ts +4 -17
- package/dist/src/parse.d.ts.map +1 -1
- package/dist/src/parse.js +402 -1040
- package/dist/src/parse.js.map +1 -1
- package/dist/src/std-bundle.d.ts.map +1 -1
- package/dist/src/std-bundle.js +12 -20
- package/dist/src/std-bundle.js.map +1 -1
- package/dist/src/std-library.d.ts +1 -1
- package/dist/src/std-library.d.ts.map +1 -1
- package/dist/src/std-library.js +1 -5
- package/dist/src/std-library.js.map +1 -1
- package/dist/src/tunables.d.ts +7 -0
- package/dist/src/tunables.d.ts.map +1 -0
- package/dist/src/tunables.js +26 -0
- package/dist/src/tunables.js.map +1 -0
- package/dist/src/version.d.ts +2 -4
- package/dist/src/version.d.ts.map +1 -1
- package/dist/src/version.js +2 -4
- package/dist/src/version.js.map +1 -1
- package/docs/README.md +179 -41
- package/docs/headers.md +44 -0
- package/examples/cost-table.json +99 -751
- package/examples/library.hsx +59 -0
- package/package.json +9 -17
- package/src/ast.ts +82 -441
- package/src/cli.ts +77 -362
- package/src/compile.ts +1535 -247
- package/src/cost.ts +28 -671
- package/src/format.ts +12 -256
- package/src/headers.ts +126 -0
- package/src/index.ts +7 -39
- package/src/lex.ts +99 -195
- package/src/parse.ts +403 -1209
- package/src/std-bundle.ts +12 -20
- package/src/std-library.ts +2 -7
- package/src/tunables.ts +31 -0
- package/src/version.ts +2 -5
- package/std/approvals.hsx +17 -0
- package/std/cards.hsx +63 -0
- package/std/collections.hsx +31 -0
- package/std/escrow.hsx +43 -0
- package/std/financing.hsx +372 -0
- package/std/insurance.hsx +59 -0
- package/std/lending.hsx +115 -0
- package/std/marketplace.hsx +24 -0
- package/std/money.hsx +195 -0
- package/std/savings.hsx +44 -0
- package/std/travel.hsx +98 -0
- package/std/wallet.hsx +41 -0
- package/dist/src/diagnostics.d.ts +0 -13
- package/dist/src/diagnostics.d.ts.map +0 -1
- package/dist/src/diagnostics.js +0 -587
- package/dist/src/diagnostics.js.map +0 -1
- package/dist/src/emit.d.ts +0 -51
- package/dist/src/emit.d.ts.map +0 -1
- package/dist/src/emit.js +0 -192
- package/dist/src/emit.js.map +0 -1
- package/dist/src/entry-overrides.d.ts +0 -58
- package/dist/src/entry-overrides.d.ts.map +0 -1
- package/dist/src/entry-overrides.js +0 -284
- package/dist/src/entry-overrides.js.map +0 -1
- package/dist/src/ir.d.ts +0 -73
- package/dist/src/ir.d.ts.map +0 -1
- package/dist/src/ir.js +0 -15
- package/dist/src/ir.js.map +0 -1
- package/dist/src/limits.d.ts +0 -23
- package/dist/src/limits.d.ts.map +0 -1
- package/dist/src/limits.js +0 -23
- package/dist/src/limits.js.map +0 -1
- package/dist/src/lsp/server.d.ts +0 -32
- package/dist/src/lsp/server.d.ts.map +0 -1
- package/dist/src/lsp/server.js +0 -391
- package/dist/src/lsp/server.js.map +0 -1
- package/dist/src/modules.d.ts +0 -38
- package/dist/src/modules.d.ts.map +0 -1
- package/dist/src/modules.js +0 -372
- package/dist/src/modules.js.map +0 -1
- package/dist/src/typecheck.d.ts +0 -8
- package/dist/src/typecheck.d.ts.map +0 -1
- package/dist/src/typecheck.js +0 -4160
- package/dist/src/typecheck.js.map +0 -1
- package/docs/guide/01-first-program.md +0 -24
- package/docs/guide/02-money.md +0 -25
- package/docs/guide/03-instruments.md +0 -93
- package/docs/guide/04-lifecycles.md +0 -40
- package/docs/guide/05-fees-and-splits.md +0 -45
- package/docs/guide/06-schedules.md +0 -26
- package/docs/guide/07-composition.md +0 -52
- package/docs/guide/08-writing-a-module.md +0 -85
- package/docs/guide/09-cost.md +0 -24
- package/docs/guide/10-diagnostics.md +0 -27
- package/docs/llms-full.txt +0 -3684
- package/docs/llms.txt +0 -44
- package/docs/piece-plans.md +0 -120
- package/docs/playground.md +0 -55
- package/docs/reference/cli.md +0 -36
- package/docs/reference/diagnostics.md +0 -901
- package/docs/reference/grammar.md +0 -38
- package/docs/reference/std/advance.md +0 -112
- package/docs/reference/std/cancellable_booking.md +0 -159
- package/docs/reference/std/captured_payment.md +0 -115
- package/docs/reference/std/conditional_disbursement.md +0 -101
- package/docs/reference/std/credit_facility.md +0 -108
- package/docs/reference/std/held_payment.md +0 -173
- package/docs/reference/std/instant_transfer.md +0 -97
- package/docs/reference/std/metered.md +0 -89
- package/docs/reference/std/pooled_split.md +0 -95
- package/docs/reference/std/premium_forward.md +0 -119
- package/docs/reference/std/reconciled_payout.md +0 -103
- package/docs/reference/std/rotating_pool.md +0 -130
- package/docs/reference/std/scheduled.md +0 -136
- package/docs/reference/std/security_deposit.md +0 -138
- package/docs/reference/std/settlement_batch.md +0 -123
- package/docs/reference/std/swap.md +0 -133
- package/docs/reference/std/threshold_pool.md +0 -138
- package/docs/reference/std/weighted_distribution.md +0 -135
- package/docs/reference/types.md +0 -61
- package/docs/reference/udl-output.md +0 -13
- package/examples/01-first-program/README.md +0 -45
- package/examples/01-first-program/tip-jar.hsx +0 -17
- package/examples/02-imports-and-modules/README.md +0 -96
- package/examples/02-imports-and-modules/photo-booth.hsx +0 -37
- package/examples/03-diagnostics/README.md +0 -68
- package/examples/03-diagnostics/corner-shop-fixed.hsx +0 -22
- package/examples/03-diagnostics/corner-shop.hsx +0 -19
- package/examples/04-complete-product/README.md +0 -84
- package/examples/04-complete-product/study-hall.hsx +0 -67
- package/examples/05-authored-instrument/README.md +0 -5
- package/examples/05-authored-instrument/payment.hsx +0 -37
- package/examples/05-watch-club/README.md +0 -6
- package/examples/05-watch-club/watch-club.hsx +0 -123
- package/examples/README.md +0 -48
- package/examples/advance/README.md +0 -3
- package/examples/advance/advance.hsx +0 -13
- package/examples/advance/advance.udl +0 -367
- package/examples/cancellable_booking/README.md +0 -3
- package/examples/cancellable_booking/cancellable_booking.hsx +0 -14
- package/examples/cancellable_booking/cancellable_booking.udl +0 -413
- package/examples/captured_payment/README.md +0 -3
- package/examples/captured_payment/captured_payment.hsx +0 -17
- package/examples/captured_payment/captured_payment.udl +0 -686
- package/examples/conditional_disbursement/README.md +0 -3
- package/examples/conditional_disbursement/conditional_disbursement.hsx +0 -15
- package/examples/conditional_disbursement/conditional_disbursement.udl +0 -418
- package/examples/credit_facility/README.md +0 -3
- package/examples/credit_facility/credit_facility.hsx +0 -24
- package/examples/credit_facility/credit_facility.udl +0 -1396
- package/examples/held_payment/README.md +0 -3
- package/examples/held_payment/held_payment.hsx +0 -13
- package/examples/held_payment/held_payment.udl +0 -569
- package/examples/instant_transfer/README.md +0 -3
- package/examples/instant_transfer/instant_transfer.hsx +0 -16
- package/examples/instant_transfer/instant_transfer.udl +0 -376
- package/examples/metered/README.md +0 -3
- package/examples/metered/metered.hsx +0 -13
- package/examples/metered/metered.udl +0 -253
- package/examples/pooled_split/README.md +0 -3
- package/examples/pooled_split/pooled_split.hsx +0 -15
- package/examples/pooled_split/pooled_split.udl +0 -432
- package/examples/premium_forward/README.md +0 -3
- package/examples/premium_forward/premium_forward.hsx +0 -19
- package/examples/premium_forward/premium_forward.udl +0 -604
- package/examples/reconciled_payout/README.md +0 -3
- package/examples/reconciled_payout/reconciled_payout.hsx +0 -13
- package/examples/reconciled_payout/reconciled_payout.udl +0 -312
- package/examples/rotating_pool/README.md +0 -3
- package/examples/rotating_pool/rotating_pool.hsx +0 -18
- package/examples/rotating_pool/rotating_pool.udl +0 -4370
- package/examples/scheduled/README.md +0 -3
- package/examples/scheduled/scheduled.hsx +0 -12
- package/examples/scheduled/scheduled.udl +0 -355
- package/examples/security_deposit/README.md +0 -3
- package/examples/security_deposit/security_deposit.hsx +0 -21
- package/examples/security_deposit/security_deposit.udl +0 -320
- package/examples/settlement_batch/README.md +0 -3
- package/examples/settlement_batch/settlement_batch.hsx +0 -19
- package/examples/settlement_batch/settlement_batch.udl +0 -757
- package/examples/swap/README.md +0 -3
- package/examples/swap/swap.hsx +0 -19
- package/examples/swap/swap.udl +0 -892
- package/examples/threshold_pool/README.md +0 -3
- package/examples/threshold_pool/threshold_pool.hsx +0 -16
- package/examples/threshold_pool/threshold_pool.udl +0 -680
- package/examples/weighted_distribution/README.md +0 -3
- package/examples/weighted_distribution/weighted_distribution.hsx +0 -20
- package/examples/weighted_distribution/weighted_distribution.udl +0 -348
- package/skills/hsx/SKILL.md +0 -449
- package/src/diagnostics.ts +0 -620
- package/src/emit.ts +0 -282
- package/src/entry-overrides.ts +0 -428
- package/src/ir.ts +0 -113
- package/src/limits.ts +0 -22
- package/src/lsp/server.ts +0 -460
- package/src/modules.ts +0 -452
- package/src/typecheck.ts +0 -5515
- package/std/SEMANTICS.md +0 -44
- package/std/money_flows/advance.hsx +0 -235
- package/std/money_flows/cancellable_booking.hsx +0 -402
- package/std/money_flows/captured_payment.hsx +0 -220
- package/std/money_flows/conditional_disbursement.hsx +0 -226
- package/std/money_flows/credit_facility.hsx +0 -214
- package/std/money_flows/held_payment.hsx +0 -812
- package/std/money_flows/index.hsx +0 -4
- package/std/money_flows/instant_transfer.hsx +0 -231
- package/std/money_flows/metered.hsx +0 -104
- package/std/money_flows/pooled_split.hsx +0 -109
- package/std/money_flows/premium_forward.hsx +0 -307
- package/std/money_flows/reconciled_payout.hsx +0 -119
- package/std/money_flows/rotating_pool.hsx +0 -305
- package/std/money_flows/scheduled.hsx +0 -599
- package/std/money_flows/security_deposit.hsx +0 -248
- package/std/money_flows/settlement_batch.hsx +0 -173
- package/std/money_flows/swap.hsx +0 -1192
- package/std/money_flows/threshold_pool.hsx +0 -307
- package/std/money_flows/weighted_distribution.hsx +0 -237
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
module std.money_flows.premium_forward
|
|
2
|
-
|
|
3
|
-
// Insurance premium escrow holding customer funds until policy binding, then partitioning net carrier premium and commission.
|
|
4
|
-
//
|
|
5
|
-
// ### Purpose
|
|
6
|
-
// `premium_forward` manages insurance premium collection, broker commission retention, and carrier remittance.
|
|
7
|
-
// A policyholder funds the premium into dedicated escrow. The funds remain held until the policy binds via the `bind` port.
|
|
8
|
-
// Upon binding, the gross premium is automatically partitioned: the platform fee/commission is retained, and the net
|
|
9
|
-
// balance forwards to the carrier. It also supports policy endorsements and renewal schedules.
|
|
10
|
-
//
|
|
11
|
-
// ### Selection guidance
|
|
12
|
-
// - vs `held_payment`: `premium_forward` is tailored for insurance lifecycles, featuring automatic commission splits
|
|
13
|
-
// upon binding and policy endorsement tracking. `held_payment` is general commercial escrow without insurance
|
|
14
|
-
// underwriting binding semantics or gross-to-net fee partitioning.
|
|
15
|
-
// - vs `conditional_disbursement`: `premium_forward` collects and forwards inbound policy premiums to carriers.
|
|
16
|
-
// `conditional_disbursement` pays outbound claim settlements to claimants against stored evidence.
|
|
17
|
-
//
|
|
18
|
-
// ### Parameters
|
|
19
|
-
// - `payer`: The policyholder paying the insurance premium.
|
|
20
|
-
// - `carrier`: The insurance carrier underwriting the policy.
|
|
21
|
-
// - `amount`: Total gross premium in minor units of currency `C`.
|
|
22
|
-
// - `bind`: Condition port triggering policy binding and premium forwarding.
|
|
23
|
-
// - `commission`: Platform commission percentage retained from the gross premium.
|
|
24
|
-
// - `policy_ref`: Optional policy identifier string.
|
|
25
|
-
// - `renewal_due`: Optional date anchor when the policy is due for renewal.
|
|
26
|
-
// - `endorsement`: Optional condition port for recording policy endorsements.
|
|
27
|
-
//
|
|
28
|
-
// ### Decision ports
|
|
29
|
-
// - `bind`: Port authorizing policy binding, triggering carrier payout and commission retention.
|
|
30
|
-
// - `endorsement`: Port allowing carrier endorsement evidence to be recorded.
|
|
31
|
-
//
|
|
32
|
-
// ### Example
|
|
33
|
-
// ```hsx
|
|
34
|
-
// program premium_forward_example "Premium forward example"
|
|
35
|
-
// import { premium_forward } from "std/money_flows"
|
|
36
|
-
// party policyholder: person
|
|
37
|
-
// party carrier: business
|
|
38
|
-
// settlement premium = premium_forward {
|
|
39
|
-
// payer: policyholder
|
|
40
|
-
// carrier: carrier
|
|
41
|
-
// amount: premiumAmount: money(SAR)
|
|
42
|
-
// commission: 2%
|
|
43
|
-
// bind: port bind_policy
|
|
44
|
-
// policy_ref: policyReference
|
|
45
|
-
// renewal_due: renewalDueAt
|
|
46
|
-
// endorsement: port record_endorsement
|
|
47
|
-
// }
|
|
48
|
-
// port bind_policy { allowed: [policyholder, carrier] }
|
|
49
|
-
// port record_endorsement {
|
|
50
|
-
// allowed: [carrier]
|
|
51
|
-
// shape: { evidenceReference: text }
|
|
52
|
-
// }
|
|
53
|
-
// ```
|
|
54
|
-
export instrument premium_forward<C>(
|
|
55
|
-
payer: party,
|
|
56
|
-
carrier: party,
|
|
57
|
-
amount: money<C>,
|
|
58
|
-
bind: condition,
|
|
59
|
-
commission: percent,
|
|
60
|
-
policy_ref: optional<text>,
|
|
61
|
-
renewal_due: optional<date>,
|
|
62
|
-
endorsement: optional<condition>,
|
|
63
|
-
) {
|
|
64
|
-
let(instrument_words): words(instrument);
|
|
65
|
-
let(bind_name): concat(bind);
|
|
66
|
-
let(payer_field): camel(concat(payer, "_account_id"));
|
|
67
|
-
let(carrier_field): camel(concat(carrier, "_account_id"));
|
|
68
|
-
let(amount_field): concat(amount);
|
|
69
|
-
let(net_bps): sub(10000, commission);
|
|
70
|
-
let(fee_bps): add(commission, 0);
|
|
71
|
-
let(net_percent): percent_text(net_bps);
|
|
72
|
-
let(fee_percent): percent_text(fee_bps);
|
|
73
|
-
let(owner_id_key): "owner.id";
|
|
74
|
-
let(owner_type_key): "owner.type";
|
|
75
|
-
let(metadata_instrument_key): "metadata.instrumentId";
|
|
76
|
-
let(metadata_instance_key): "metadata.instrumentInstanceId";
|
|
77
|
-
let(metadata_phase_key): "metadata.phase";
|
|
78
|
-
let(bind_capture_key): camel(concat(bind, "_transfer_transfer_id"));
|
|
79
|
-
let(fee_port_key): "x-hyperscale-fee-collection-port";
|
|
80
|
-
let(reference_filter_key): "x-hyperscale-reference-filter";
|
|
81
|
-
|
|
82
|
-
title: sentence(instrument);
|
|
83
|
-
agent_description: "Reach for {instrument_words} when the {payer} pays an insurance premium ahead of cover and the {carrier} must not be paid until the policy binds. The {amount_field} sits in this settlement's own escrow until {bind_name} fires. Binding then forwards {net_percent} to the {carrier} and {fee_percent} to the platform.";
|
|
84
|
-
summary: "Premium held for the {carrier} until the policy binds";
|
|
85
|
-
description: "Premium forward: the {payer} funds the {amount_field} into this settlement's own escrow; binding through {bind_name} forwards it to the {carrier} exactly once, minus the platform commission";
|
|
86
|
-
partitions: { total_field: amount_field; piece_fields: [piece1Amount, piece2Amount]; };
|
|
87
|
-
|
|
88
|
-
fields {
|
|
89
|
-
platform_account_id: {
|
|
90
|
-
type: account;
|
|
91
|
-
description: "The product fee collection account";
|
|
92
|
-
[fee_port_key]: true;
|
|
93
|
-
[reference_filter_key]: { column: role; values: [customer_balance, product_revenue]; };
|
|
94
|
-
}
|
|
95
|
-
amount: {
|
|
96
|
-
type: money<C>;
|
|
97
|
-
description: "The gross held amount in {C} minor units; the piece fields below partition it exactly";
|
|
98
|
-
}
|
|
99
|
-
piece1_amount: {
|
|
100
|
-
type: money<C>;
|
|
101
|
-
description: "{net_percent} of {amount_field} (carries the integer-division remainder): released to the {carrier}. Computed as floor({amount_field} * {net_bps} / 10000) in {C} minor units";
|
|
102
|
-
}
|
|
103
|
-
piece2_amount: {
|
|
104
|
-
type: money<C>;
|
|
105
|
-
description: "{fee_percent} of {amount_field}: released to the platform. Computed as floor({amount_field} * {fee_bps} / 10000) in {C} minor units";
|
|
106
|
-
}
|
|
107
|
-
when(policy_ref) {
|
|
108
|
-
policy_ref: {
|
|
109
|
-
type: text;
|
|
110
|
-
description: "Immutable external policy reference recorded with this forward";
|
|
111
|
-
max_length: 180;
|
|
112
|
-
min_length: 1;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
when(renewal_due) {
|
|
116
|
-
renewal_due: {
|
|
117
|
-
type: date;
|
|
118
|
-
description: "Stored renewal due condition for the forwarded policy";
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
parties { payer: payer; beneficiary: carrier; }
|
|
124
|
-
|
|
125
|
-
lifecycle {
|
|
126
|
-
states created funding_1 funded releasing_1 released abandoned;
|
|
127
|
-
when(endorsement) { states endorsed lapsed; }
|
|
128
|
-
initial created;
|
|
129
|
-
on fund_piece_1: created -> funding_1;
|
|
130
|
-
on fund_piece_2: funding_1 -> funded;
|
|
131
|
-
on [bind]: funded -> releasing_1;
|
|
132
|
-
on forward_piece_2: releasing_1 -> released;
|
|
133
|
-
on unfund_piece_1: funding_1 -> abandoned;
|
|
134
|
-
on abandon: created -> abandoned;
|
|
135
|
-
when(endorsement) {
|
|
136
|
-
on [endorsement]: released -> endorsed;
|
|
137
|
-
on lapse: released|endorsed -> lapsed;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
action create {
|
|
142
|
-
agent_description: "Open the {instrument_words} and provision the escrow account that holds the funds. This is the first call on the settlement, and funding refuses until it lands. It moves no money.";
|
|
143
|
-
summary: "Create a {instrument_words} settlement";
|
|
144
|
-
steps: [{
|
|
145
|
-
operation: "account.escrow.provision";
|
|
146
|
-
bind: {
|
|
147
|
-
currency: { from: instance; path: fields.currency; };
|
|
148
|
-
[owner_id_key]: { from: instance; path: productId; };
|
|
149
|
-
[owner_type_key]: { from: const; value: product; };
|
|
150
|
-
product_id: { from: instance; path: productId; };
|
|
151
|
-
role: { from: const; value: product_escrow; };
|
|
152
|
-
};
|
|
153
|
-
capture: { escrow_account_id: accountId; };
|
|
154
|
-
}];
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
action fund_piece_1 {
|
|
158
|
-
agent_description: "Move the {carrier}'s share of the premium from the {payer} into escrow. The settlement must exist and be unfunded. It debits the {payer} for real, and piece 2 still has to fund before the policy can bind.";
|
|
159
|
-
summary: "Fund piece 1 of the held amount into escrow";
|
|
160
|
-
moves: [{
|
|
161
|
-
key: transfer; operation: "internal_transfer.create";
|
|
162
|
-
bind: {
|
|
163
|
-
amount: { from: instance; path: fields.piece1Amount; };
|
|
164
|
-
currency: { from: instance; path: fields.currency; };
|
|
165
|
-
destination_account_id: { from: instance; path: refs.escrowAccountId; };
|
|
166
|
-
source_account_id: { from: instance; path: concat("fields.", payer_field); };
|
|
167
|
-
[metadata_instrument_key]: { from: const; value: instrument; };
|
|
168
|
-
[metadata_instance_key]: { from: instance; path: instrumentInstanceId; };
|
|
169
|
-
[metadata_phase_key]: { from: const; value: fund_piece_1; };
|
|
170
|
-
product_id: { from: instance; path: productId; };
|
|
171
|
-
};
|
|
172
|
-
capture: { fund_piece_1_transfer_transfer_id: transferId; };
|
|
173
|
-
}];
|
|
174
|
-
sandbox_failure_point: funding;
|
|
175
|
-
steps: [];
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
action fund_piece_2 {
|
|
179
|
-
agent_description: "Move the platform commission piece from the {payer} into escrow, which completes funding. Piece 1 must be in escrow first. It debits the {payer} for real, and the premium is then held whole.";
|
|
180
|
-
summary: "Fund piece 2 of the held amount into escrow";
|
|
181
|
-
moves: [{
|
|
182
|
-
key: transfer; operation: "internal_transfer.create";
|
|
183
|
-
bind: {
|
|
184
|
-
amount: { from: instance; path: fields.piece2Amount; };
|
|
185
|
-
currency: { from: instance; path: fields.currency; };
|
|
186
|
-
destination_account_id: { from: instance; path: refs.escrowAccountId; };
|
|
187
|
-
source_account_id: { from: instance; path: concat("fields.", payer_field); };
|
|
188
|
-
[metadata_instrument_key]: { from: const; value: instrument; };
|
|
189
|
-
[metadata_instance_key]: { from: instance; path: instrumentInstanceId; };
|
|
190
|
-
[metadata_phase_key]: { from: const; value: fund_piece_2; };
|
|
191
|
-
product_id: { from: instance; path: productId; };
|
|
192
|
-
};
|
|
193
|
-
capture: { fund_piece_2_transfer_transfer_id: transferId; };
|
|
194
|
-
}];
|
|
195
|
-
sandbox_failure_point: funding;
|
|
196
|
-
steps: [];
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
action [bind] {
|
|
200
|
-
agent_description: "Bind the policy through {bind_name} and forward the {carrier}'s share out of escrow. The premium must be fully funded first, and the call carries the decision reference the product asks for. Money leaves escrow here and does not come back.";
|
|
201
|
-
summary: "Confirm through {bind_name} and start the forward payout";
|
|
202
|
-
input: {
|
|
203
|
-
additional_properties: false;
|
|
204
|
-
properties: {
|
|
205
|
-
for item in keys(bind_fields) {
|
|
206
|
-
[item]: get(bind_fields, item);
|
|
207
|
-
}
|
|
208
|
-
};
|
|
209
|
-
required: keys(bind_fields);
|
|
210
|
-
type: object;
|
|
211
|
-
};
|
|
212
|
-
port: { allowed_parties: bind_allowed; };
|
|
213
|
-
moves: [{
|
|
214
|
-
key: transfer; operation: "internal_transfer.create";
|
|
215
|
-
bind: {
|
|
216
|
-
amount: { from: instance; path: fields.piece1Amount; };
|
|
217
|
-
currency: { from: instance; path: fields.currency; };
|
|
218
|
-
destination_account_id: { from: instance; path: concat("fields.", carrier_field); };
|
|
219
|
-
source_account_id: { from: instance; path: refs.escrowAccountId; };
|
|
220
|
-
[metadata_instrument_key]: { from: const; value: instrument; };
|
|
221
|
-
[metadata_instance_key]: { from: instance; path: instrumentInstanceId; };
|
|
222
|
-
[metadata_phase_key]: { from: const; value: bind; };
|
|
223
|
-
product_id: { from: instance; path: productId; };
|
|
224
|
-
};
|
|
225
|
-
capture: { [bind_capture_key]: transferId; };
|
|
226
|
-
}];
|
|
227
|
-
sandbox_failure_point: "release";
|
|
228
|
-
steps: [];
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
action forward_piece_2 {
|
|
232
|
-
agent_description: "Pay the platform commission out of escrow to the fee collection account, which closes the forward. {bind_name} must have run first. Money leaves escrow here and does not come back.";
|
|
233
|
-
summary: "Forward piece 2 of the held amount";
|
|
234
|
-
moves: [{
|
|
235
|
-
key: transfer; operation: "internal_transfer.create";
|
|
236
|
-
bind: {
|
|
237
|
-
amount: { from: instance; path: fields.piece2Amount; };
|
|
238
|
-
currency: { from: instance; path: fields.currency; };
|
|
239
|
-
destination_account_id: { from: instance; path: fields.platformAccountId; };
|
|
240
|
-
source_account_id: { from: instance; path: refs.escrowAccountId; };
|
|
241
|
-
[metadata_instrument_key]: { from: const; value: instrument; };
|
|
242
|
-
[metadata_instance_key]: { from: instance; path: instrumentInstanceId; };
|
|
243
|
-
[metadata_phase_key]: { from: const; value: forward_piece_2; };
|
|
244
|
-
product_id: { from: instance; path: productId; };
|
|
245
|
-
};
|
|
246
|
-
capture: { forward_piece_2_transfer_transfer_id: transferId; };
|
|
247
|
-
}];
|
|
248
|
-
steps: [];
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
action unfund_piece_1 {
|
|
252
|
-
agent_description: "Return the {carrier}'s share from escrow to the {payer} and abandon the forward. It runs only while funding stopped after piece 1, before the policy binds. The settlement ends abandoned.";
|
|
253
|
-
summary: "Return piece 1 to the {payer} on abandonment";
|
|
254
|
-
moves: [{
|
|
255
|
-
key: transfer; operation: "internal_transfer.create";
|
|
256
|
-
bind: {
|
|
257
|
-
amount: { from: instance; path: fields.piece1Amount; };
|
|
258
|
-
currency: { from: instance; path: fields.currency; };
|
|
259
|
-
destination_account_id: { from: instance; path: concat("fields.", payer_field); };
|
|
260
|
-
source_account_id: { from: instance; path: refs.escrowAccountId; };
|
|
261
|
-
[metadata_instrument_key]: { from: const; value: instrument; };
|
|
262
|
-
[metadata_instance_key]: { from: instance; path: instrumentInstanceId; };
|
|
263
|
-
[metadata_phase_key]: { from: const; value: unfund_piece_1; };
|
|
264
|
-
product_id: { from: instance; path: productId; };
|
|
265
|
-
};
|
|
266
|
-
capture: { unfund_piece_1_transfer_transfer_id: transferId; };
|
|
267
|
-
}];
|
|
268
|
-
steps: [];
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
action abandon {
|
|
272
|
-
agent_description: "Close a {instrument_words} that was never funded. The escrow account must be empty, so this refuses once any piece is in it. It moves no money and the settlement ends here.";
|
|
273
|
-
summary: "Abandon the settlement before any money is held";
|
|
274
|
-
requires drained: { path: refs.escrowAccountId; };
|
|
275
|
-
steps: [];
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
when(endorsement) {
|
|
279
|
-
action [endorsement] {
|
|
280
|
-
agent_description: "Record one endorsement against a policy that already forwarded, from evidence the caller supplies. The forward must be released first, and only the {carrier} may call it. It moves no money and it does not change the premium.";
|
|
281
|
-
summary: "Record one non-money endorsement from external evidence";
|
|
282
|
-
when(endorsement_fields) {
|
|
283
|
-
input: {
|
|
284
|
-
additional_properties: false;
|
|
285
|
-
properties: {
|
|
286
|
-
for item in keys(endorsement_fields) {
|
|
287
|
-
[item]: get(endorsement_fields, item);
|
|
288
|
-
}
|
|
289
|
-
};
|
|
290
|
-
required: keys(endorsement_fields);
|
|
291
|
-
type: object;
|
|
292
|
-
};
|
|
293
|
-
capture_input: {
|
|
294
|
-
for item in keys(endorsement_fields) { [item]: item; }
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
port { allowed_parties: endorsement_allowed; };
|
|
298
|
-
steps: [];
|
|
299
|
-
}
|
|
300
|
-
action lapse {
|
|
301
|
-
summary: "Mark the forwarded policy lapsed at its stored renewal due condition";
|
|
302
|
-
due: { field: renewal_due; };
|
|
303
|
-
requires drained: { path: refs.escrowAccountId; };
|
|
304
|
-
steps: [];
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
module std.money_flows.reconciled_payout
|
|
2
|
-
|
|
3
|
-
// Outbound bank payout instruction with end-to-end reconciliation against external bank statement feeds.
|
|
4
|
-
//
|
|
5
|
-
// ### Purpose
|
|
6
|
-
// `reconciled_payout` manages high-assurance payouts to external suppliers, partners, or customers where payment
|
|
7
|
-
// is not complete until confirmed by bank statement data. An instruction is dispatched to the beneficiary and an expectation
|
|
8
|
-
// record is opened. Incoming statement debit lines match against the expectation within configurable tolerance thresholds
|
|
9
|
-
// (`matched_within`, `matched_ceiling`). If the statement debit does not match before `settle_by`, a formal break row is raised.
|
|
10
|
-
//
|
|
11
|
-
// ### Selection guidance
|
|
12
|
-
// - vs `settlement_batch`: `reconciled_payout` executes and reconciles an individual bank payout instruction.
|
|
13
|
-
// `settlement_batch` aggregates periodic captures, fees, and signed adjustments to calculate a net payable batch.
|
|
14
|
-
// - vs `instant_transfer`: `instant_transfer` executes an immediate internal ledger transfer between platform accounts.
|
|
15
|
-
// `reconciled_payout` dispatches funds across external banking rails with reconciliation tolerances and break tracking.
|
|
16
|
-
//
|
|
17
|
-
// ### Parameters
|
|
18
|
-
// - `payer`: The funding party providing the payout.
|
|
19
|
-
// - `beneficiary`: The beneficiary party receiving the external payout.
|
|
20
|
-
// - `amount`: Instructed payout amount in minor units of currency `C`.
|
|
21
|
-
// - `beneficiary_ref`: Registered external beneficiary ID for bank routing.
|
|
22
|
-
// - `settle_by`: Cut-off date when unmatched expectation amounts become formal break records.
|
|
23
|
-
// - `matched_within`: Match tolerance window in basis points or minor units.
|
|
24
|
-
// - `matched_ceiling`: Maximum acceptable tolerance ceiling between instructed amount and settled debit.
|
|
25
|
-
//
|
|
26
|
-
// ### Decision ports
|
|
27
|
-
// None. Payout dispatch and settlement matching follow the declared schedule, bank statement lines, and tolerance rules.
|
|
28
|
-
//
|
|
29
|
-
// ### Example
|
|
30
|
-
// ```hsx
|
|
31
|
-
// program reconciled_payout_example "Reconciled payout example"
|
|
32
|
-
// import { reconciled_payout } from "std/money_flows"
|
|
33
|
-
// party treasury: business
|
|
34
|
-
// party supplier: business
|
|
35
|
-
// settlement supplier_payout = reconciled_payout {
|
|
36
|
-
// payer: treasury
|
|
37
|
-
// beneficiary: supplier
|
|
38
|
-
// amount: netPayable: money(SAR)
|
|
39
|
-
// beneficiary_ref: supplierBeneficiaryId
|
|
40
|
-
// settle_by: settleBy
|
|
41
|
-
// matched_within: 100
|
|
42
|
-
// matched_ceiling: 500
|
|
43
|
-
// }
|
|
44
|
-
// ```
|
|
45
|
-
export instrument reconciled_payout<C>(
|
|
46
|
-
payer: party,
|
|
47
|
-
beneficiary: party,
|
|
48
|
-
amount: money<C>,
|
|
49
|
-
beneficiary_ref: text,
|
|
50
|
-
settle_by: date,
|
|
51
|
-
matched_within: integer,
|
|
52
|
-
matched_ceiling: integer,
|
|
53
|
-
) {
|
|
54
|
-
let(payer_account_field): camel(concat(payer, "_account_id"));
|
|
55
|
-
let(beneficiary_account_field): camel(concat(beneficiary, "_account_id"));
|
|
56
|
-
let(reference_filter_key): "x-hyperscale-reference-filter";
|
|
57
|
-
fields {
|
|
58
|
-
amount { type: money<C>; description: concat("Amount instructed to the ", words(beneficiary), " in minor units"); }
|
|
59
|
-
currency { type: text; description: "ISO 4217 currency code"; minLength: 3; maxLength: 3; pattern: "^[A-Z]{3}$"; }
|
|
60
|
-
settle_by { type: date; description: "Instant the expectation stops waiting and the unmatched amount becomes a break"; }
|
|
61
|
-
beneficiary_ref { type: text; description: "Beneficiary ID for the payout instruction"; pattern: "^ben_(sandbox|live)_[a-z0-9]{8,64}$"; }
|
|
62
|
-
[beneficiary_account_field] { type: account<C>; description: concat("The ", words(beneficiary), " account"); [reference_filter_key]: { column: role; values: [customer_balance]; }; }
|
|
63
|
-
[payer_account_field] { type: account<C>; description: concat("The ", words(payer), " account the payout leaves"); [reference_filter_key]: { column: role; values: [customer_balance]; }; }
|
|
64
|
-
}
|
|
65
|
-
lifecycle {
|
|
66
|
-
states created instructed settled;
|
|
67
|
-
initial created;
|
|
68
|
-
on instruct: created -> instructed;
|
|
69
|
-
on settle: instructed -> settled;
|
|
70
|
-
}
|
|
71
|
-
parties { beneficiary: beneficiary_account_field; payer: payer_account_field; }
|
|
72
|
-
required: [amount, beneficiary_account_field, beneficiary_ref, currency, payer_account_field, settle_by];
|
|
73
|
-
title: sentence(instrument);
|
|
74
|
-
agent_description: concat("Reach for reconciled payout when a payment to the ", words(beneficiary), " is not finished until the bank confirms the debit. The instruction goes out, the expectation waits for a matching statement line, and anything still unmatched at the settle date becomes a break row instead of disappearing. Pick instant transfer when no bank confirmation is involved.");
|
|
75
|
-
id_prefix: prefix(instrument);
|
|
76
|
-
summary: concat("Payout from ", words(payer), " to ", words(beneficiary), " that is not done until the bank agrees");
|
|
77
|
-
description: "A payout the instrument owns end to end: one instruction, one expectation about the debit it will produce, and one break when the debit never matches";
|
|
78
|
-
dials: [{ key: settlement_tolerance; kind: reconcile_tolerance; maxMinorUnits: matched_ceiling; summary: "Largest difference between the instructed amount and the settled debit that still counts as matched."; title: "Settlement tolerance"; }];
|
|
79
|
-
action create { summary: concat("Create a ", words(instrument)); agent_description: concat("Open the payout row with the ", words(payer), " and ", words(beneficiary), " accounts, the amount, the beneficiary reference, and the settle date. No money moves and no instruction goes out yet. Call instruct next."); moves: []; steps: []; }
|
|
80
|
-
action instruct {
|
|
81
|
-
agent_description: concat("Send the payout instruction and start the expectation clock. This commits the amount to the ", words(beneficiary), " and the payout is not reversible from here. The bank debit is matched later by settle, which runs on its own at the settle date.");
|
|
82
|
-
summary: concat("Instruct the payout to the ", words(beneficiary));
|
|
83
|
-
payout { amount: concat("fields.", amount); beneficiaryField: beneficiary_ref; beneficiaryPartyField: beneficiary_account_field; capture: payoutId; currencyField: currency; sourceAccountField: payer_account_field; speed: standard; }
|
|
84
|
-
moves: []; steps: [];
|
|
85
|
-
}
|
|
86
|
-
action settle {
|
|
87
|
-
summary: "Match the bank's debit against what the instruction promised";
|
|
88
|
-
due { field: settle_by; }
|
|
89
|
-
reconcile {
|
|
90
|
-
amount: concat("fields.", amount); capture: settlementEvidenceId; counterpartyRef: payoutId;
|
|
91
|
-
currencyField: currency; direction: debit; evidence: statement_line;
|
|
92
|
-
exception { amountField: unmatchedAmount; childInstrumentId: concat(instrument, "_break"); maxOpen: 1; reasonField: breakReason; refField: concat(camel(instrument), "Id"); }
|
|
93
|
-
match { law: tolerance; dial: settlement_tolerance; minorUnits: matched_within; }
|
|
94
|
-
within { field: settle_by; }
|
|
95
|
-
}
|
|
96
|
-
moves: []; steps: [];
|
|
97
|
-
}
|
|
98
|
-
instruments {
|
|
99
|
-
instrument {
|
|
100
|
-
let(parent_name): instrument;
|
|
101
|
-
id: concat(parent_name, "_break");
|
|
102
|
-
id_prefix: concat(prefix(parent_name), "bk");
|
|
103
|
-
fields {
|
|
104
|
-
unmatchedAmount { type: money<C>; description: "Difference between the instructed amount and the evidence, in minor units"; }
|
|
105
|
-
currency { type: text; description: "ISO 4217 currency code"; minLength: 3; maxLength: 3; pattern: "^[A-Z]{3}$"; }
|
|
106
|
-
breakReason { type: text; description: "Why the expectation went unmatched"; minLength: 1; maxLength: 180; }
|
|
107
|
-
[parent_name]Id { type: ref<parent_name>; description: "Payout whose expectation broke"; pattern: concat("^", prefix(parent_name), "_(sandbox|live)_[a-z0-9]{8,64}$"); }
|
|
108
|
-
}
|
|
109
|
-
lifecycle { states created carried; initial created; on carry: created -> carried; }
|
|
110
|
-
required: [breakReason, currency, unmatchedAmount, concat(camel(parent_name), "Id")];
|
|
111
|
-
title: concat(sentence(parent_name), " Break");
|
|
112
|
-
agent_description: concat("Reach for this child row when a ", words(parent_name), " expectation reached its window with no matching bank debit. The break carries the unmatched amount and the reason so the difference is owned by someone rather than silently dropped.");
|
|
113
|
-
summary: "Unmatched settlement expectation carried as its own row";
|
|
114
|
-
description: "One break raised when a payout expectation reached its window with no matching debit; it is carried, never silently dropped";
|
|
115
|
-
action create { summary: "Raise a break against an instructed payout"; agent_description: "Raise a break against an instructed payout, recording the unmatched amount and why the expectation went unmatched. No money moves. The payout must still be instructed, and only one open break exists per payout."; requires refs { field: concat(camel(parent_name), "Id"); statuses: [instructed]; match: { "fields.currency": "fields.currency"; }; } moves: []; steps: []; }
|
|
116
|
-
action carry { summary: "Carry the break to whoever owns it"; agent_description: "Hand the break to whoever owns resolving it. No money moves. The payout must still be instructed. This is the only exit from a raised break, so a break is never closed by dropping it."; requires refs { field: concat(camel(parent_name), "Id"); statuses: [instructed]; match: { "fields.currency": "fields.currency"; }; } moves: []; steps: []; }
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|