@hyperscale0/hsx 3.0.0 → 3.1.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 +8 -0
- package/LICENSE.md +356 -0
- package/NOTICE.md +8 -0
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +2 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/std-bundle.js +1 -1
- package/dist/src/std-bundle.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/docs/README.md +10 -10
- package/package.json +6 -7
- package/src/cli.ts +2 -1
- package/src/std-bundle.ts +1 -1
- package/src/version.ts +1 -1
- package/std/financing.hsx +15 -15
- package/LICENSE +0 -661
- package/LICENSING.md +0 -52
- package/TRADEMARKS.md +0 -35
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
# HSX 3.1.0
|
|
2
|
+
|
|
3
|
+
Licensed under the Hyperscale Intellectual Property and Copyright License 1.0 (`LicenseRef-Hyperscale-IPCL-1.0`), Tier 2 (Source Available). The AGPL-3.0-only grant ends with this release; earlier versions keep it. `LICENSE.md` and `NOTICE.md` replace the previous license, licensing and trademark files; trademark and conformance rules now live in the license. No grammar change.
|
|
4
|
+
|
|
5
|
+
# HSX 3.0.1
|
|
6
|
+
|
|
7
|
+
std financing: `payment.pay` collects slice by slice in position order (profit before principal under `fines_profit_principal`, principal first under `principal_profit`) and selects pending and due slices only, so paid slices stay paid. The CLI reports the package version from `version.ts`.
|
|
8
|
+
|
|
1
9
|
# HSX 3.0.0
|
|
2
10
|
|
|
3
11
|
Version 3 replaces the previous grammar. Recreate development estates. There is no migration reader.
|
package/LICENSE.md
ADDED
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# Hyperscale Intellectual Property and Copyright License
|
|
2
|
+
|
|
3
|
+
Version 1.0, effective 18 September 2026. This text is under review by
|
|
4
|
+
Hyperscale LLC's counsel. Until a revised version replaces it, it states the
|
|
5
|
+
terms on which Hyperscale makes the Software available.
|
|
6
|
+
|
|
7
|
+
SPDX identifier: `LicenseRef-Hyperscale-IPCL-1.0`
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2026 Hyperscale LLC. All rights reserved.
|
|
10
|
+
|
|
11
|
+
This is not an open source license. The Software is proprietary. Hyperscale
|
|
12
|
+
publishes some of it so that you can read it, learn it, build on the Hyperscale
|
|
13
|
+
platform with it, and verify what Hyperscale runs. Publishing is not a gift of
|
|
14
|
+
rights. Every right not written in this License stays with Hyperscale.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 1. Acceptance
|
|
19
|
+
|
|
20
|
+
By accessing, viewing, downloading, cloning, installing, copying, compiling,
|
|
21
|
+
running, or otherwise using any part of the Software, you accept this License.
|
|
22
|
+
If you do not accept it, do none of those things. If you act for an
|
|
23
|
+
organisation, you confirm you have authority to bind it, and "you" means that
|
|
24
|
+
organisation and every person acting for it.
|
|
25
|
+
|
|
26
|
+
## 2. Definitions
|
|
27
|
+
|
|
28
|
+
"Hyperscale" means Hyperscale LLC, a limited liability company organised under
|
|
29
|
+
the laws of the Kingdom of Saudi Arabia, and its successors and assigns.
|
|
30
|
+
|
|
31
|
+
"Software" means every work Hyperscale distributes under this License, in any
|
|
32
|
+
form: source code, compiled or bundled code, schemas, grammars, standard
|
|
33
|
+
libraries, headers, example programs, fixtures, conformance cases, generated
|
|
34
|
+
artifacts, documentation, designs, images, and data files, and every update,
|
|
35
|
+
version, or part of any of them.
|
|
36
|
+
|
|
37
|
+
"Specification" means the parts of the Software that Hyperscale designates as a
|
|
38
|
+
Specification in the applicable Notice: a schema, grammar, wire format,
|
|
39
|
+
manifest format, vocabulary, or interface description, together with its
|
|
40
|
+
documentation and published example inputs and outputs.
|
|
41
|
+
|
|
42
|
+
"Hyperscale Platform" means the products and services Hyperscale offers or
|
|
43
|
+
operates, in any form and under any name, including Hyperscale Arc, Architect,
|
|
44
|
+
Composer, the Hyperscale engine, portals, registries, hosted compilers, hosted
|
|
45
|
+
MCP servers, generated SDKs, and every successor product.
|
|
46
|
+
|
|
47
|
+
"Notice" means the file named `NOTICE` or `NOTICE.md`, or the license
|
|
48
|
+
statement in a package manifest, that accompanies a copy of the Software and
|
|
49
|
+
states which Tier under section 4 applies to it.
|
|
50
|
+
|
|
51
|
+
"Tier" means one of the three permission levels in section 4.
|
|
52
|
+
|
|
53
|
+
"Derivative Work" means any work that is based on, incorporates, translates,
|
|
54
|
+
adapts, ports, reimplements, transforms, or is derived from the Software or any
|
|
55
|
+
part of it, in any language or form, including a work produced by studying the
|
|
56
|
+
Software and then writing new code that performs the same function.
|
|
57
|
+
|
|
58
|
+
"Competing Product" means any product, service, library, platform, or tool,
|
|
59
|
+
whether or not sold, that performs or is offered as performing substantially the
|
|
60
|
+
same function as the Hyperscale Platform or any part of it, including: a
|
|
61
|
+
language, compiler, or checker for financial programs; an engine, runtime, or
|
|
62
|
+
ledger that executes financial product definitions; a framework for declaring,
|
|
63
|
+
conforming, or operating bank or payment provider adapters; a service that
|
|
64
|
+
generates APIs, SDKs, or agent tools from a financial product definition; or a
|
|
65
|
+
hosted or embedded version of any of those. A product you build on the
|
|
66
|
+
Hyperscale Platform for your own customers is not a Competing Product.
|
|
67
|
+
|
|
68
|
+
"Hosted Use" means making the functionality of the Software available to any
|
|
69
|
+
third party over a network, whether as a service, an API, an agent tool, an
|
|
70
|
+
embedded feature, or otherwise.
|
|
71
|
+
|
|
72
|
+
"Contribution" means any work of authorship you intentionally submit to
|
|
73
|
+
Hyperscale for inclusion in the Software, by any means, unless you clearly mark
|
|
74
|
+
it "not a contribution".
|
|
75
|
+
|
|
76
|
+
"Marks" means the names, logos, and trade dress of Hyperscale and its products,
|
|
77
|
+
including "Hyperscale", "Hyperscale Arc", "HSX", "UDL", "ADL", "Architect",
|
|
78
|
+
"Composer", the `hyperscale0` GitHub organisation, the `@hyperscale0` npm
|
|
79
|
+
scope, and every confusingly similar name or sign.
|
|
80
|
+
|
|
81
|
+
"Confidential Material" means Software distributed under Tier 3, and any part
|
|
82
|
+
of the Software that Hyperscale has not made publicly available.
|
|
83
|
+
|
|
84
|
+
## 3. Ownership
|
|
85
|
+
|
|
86
|
+
Hyperscale owns all right, title, and interest in the Software, the
|
|
87
|
+
Specifications, the Marks, and every Derivative Work Hyperscale creates,
|
|
88
|
+
including all copyright, patent, trade secret, design, database, and moral
|
|
89
|
+
rights, worldwide. The Software is licensed, not sold. This License transfers
|
|
90
|
+
no ownership of anything to you. Your possession of a copy, in any form, gives
|
|
91
|
+
you no right in it beyond what this License states.
|
|
92
|
+
|
|
93
|
+
The Specifications describe how the Hyperscale Platform works. The design
|
|
94
|
+
choices they record, the vocabulary they fix, the structure of the financial
|
|
95
|
+
programs, products, ledgers, and adapters they define, and the standard library
|
|
96
|
+
of financial instruments Hyperscale publishes are Hyperscale's intellectual
|
|
97
|
+
property. Publication does not place any of it in the public domain.
|
|
98
|
+
|
|
99
|
+
## 4. Tiers of permission
|
|
100
|
+
|
|
101
|
+
Every copy of the Software carries a Notice naming its Tier. If a copy carries
|
|
102
|
+
no Notice, Tier 3 applies. A permission granted at a higher-numbered Tier is
|
|
103
|
+
never implied at a lower-numbered one.
|
|
104
|
+
|
|
105
|
+
### Tier 1: Open Specification
|
|
106
|
+
|
|
107
|
+
For Software designated as a Specification, Hyperscale grants you a worldwide,
|
|
108
|
+
non-exclusive, non-transferable, royalty-free, revocable license to:
|
|
109
|
+
|
|
110
|
+
1. read, copy, and redistribute the Specification, unmodified and with all
|
|
111
|
+
notices intact;
|
|
112
|
+
2. write programs, documents, and data that conform to the Specification, and
|
|
113
|
+
use them in any way, including commercially;
|
|
114
|
+
3. write and distribute software that reads, writes, validates, or displays
|
|
115
|
+
data conforming to the Specification, solely for the purpose of using or
|
|
116
|
+
interoperating with the Hyperscale Platform or with products built on it;
|
|
117
|
+
4. quote reasonable portions of the Specification in documentation, teaching,
|
|
118
|
+
and commentary, with attribution to Hyperscale.
|
|
119
|
+
|
|
120
|
+
Tier 1 does not permit you to build a Competing Product, to publish a modified
|
|
121
|
+
Specification under any name that includes or resembles a Mark, or to claim
|
|
122
|
+
conformance or compatibility except as section 8 allows.
|
|
123
|
+
|
|
124
|
+
### Tier 2: Source Available
|
|
125
|
+
|
|
126
|
+
For Software designated as Source Available, Hyperscale grants you a worldwide,
|
|
127
|
+
non-exclusive, non-transferable, non-sublicensable, royalty-free, revocable
|
|
128
|
+
license to:
|
|
129
|
+
|
|
130
|
+
1. view, download, and study the source;
|
|
131
|
+
2. install, compile, and run the Software, unmodified or modified, on systems
|
|
132
|
+
you control, for the purpose of building, testing, operating, and
|
|
133
|
+
maintaining your own products on the Hyperscale Platform;
|
|
134
|
+
3. modify the Software for that purpose and keep the modification for your own
|
|
135
|
+
internal use;
|
|
136
|
+
4. submit modifications to Hyperscale as Contributions;
|
|
137
|
+
5. redistribute unmodified copies of the Software, in the form Hyperscale
|
|
138
|
+
published them, with all notices and this License intact, for example by
|
|
139
|
+
mirroring a package or vendoring a dependency.
|
|
140
|
+
|
|
141
|
+
Tier 2 does not permit Hosted Use, distribution of modified copies,
|
|
142
|
+
distribution of compiled or bundled forms other than those Hyperscale
|
|
143
|
+
published, or any use in or toward a Competing Product.
|
|
144
|
+
|
|
145
|
+
### Tier 3: Confidential
|
|
146
|
+
|
|
147
|
+
For Software designated as Confidential, or carrying no Notice, Hyperscale
|
|
148
|
+
grants you only the license written in the agreement under which you received
|
|
149
|
+
it. If there is no such agreement, you have no license, and you must not use,
|
|
150
|
+
copy, disclose, or retain the Software. Confidential Material includes generated
|
|
151
|
+
SDKs, downloadable product artifacts, private repositories, and anything you
|
|
152
|
+
obtain through a portal, a registry, or a signed-in session. You may use
|
|
153
|
+
Confidential Material only for your own organisation's Hyperscale integration,
|
|
154
|
+
must not publish it to any public repository or package registry, must not
|
|
155
|
+
disclose it beyond personnel and contractors who need it and are bound by
|
|
156
|
+
confidentiality at least as protective as this License, and must destroy it on
|
|
157
|
+
request or when your access ends.
|
|
158
|
+
|
|
159
|
+
## 5. Restrictions
|
|
160
|
+
|
|
161
|
+
Whatever the Tier, you must not, and must not help or allow anyone else to:
|
|
162
|
+
|
|
163
|
+
1. build, contribute to, market, sell, or operate a Competing Product using
|
|
164
|
+
the Software, a Derivative Work, or knowledge gained from the Software;
|
|
165
|
+
2. create a Derivative Work except as Tier 2 permits for internal use;
|
|
166
|
+
3. reimplement, port, translate, or clone the Software or any part of it, in
|
|
167
|
+
any programming language, whether by copying or by studying it and
|
|
168
|
+
rewriting it;
|
|
169
|
+
4. offer the Software or a Derivative Work for Hosted Use;
|
|
170
|
+
5. sublicense, sell, rent, lease, lend, or assign the Software or any right in
|
|
171
|
+
it;
|
|
172
|
+
6. remove, hide, or alter any copyright, trademark, license, or attribution
|
|
173
|
+
notice, or misstate the origin of the Software;
|
|
174
|
+
7. reverse engineer, decompile, disassemble, or unminify any compiled, bundled,
|
|
175
|
+
or generated form of the Software, except where a law forbids this
|
|
176
|
+
restriction and only to the extent it does;
|
|
177
|
+
8. circumvent, disable, or evade any license check, access control, rate limit,
|
|
178
|
+
key, or technical protection in the Software or the Hyperscale Platform;
|
|
179
|
+
9. use the Software, the Specifications, or any output of the Hyperscale
|
|
180
|
+
Platform as training, fine-tuning, evaluation, or retrieval data for any
|
|
181
|
+
machine-learning model, or to generate a Competing Product with such a
|
|
182
|
+
model, without Hyperscale's prior written consent;
|
|
183
|
+
10. use the Software to benchmark or compare the Hyperscale Platform in any
|
|
184
|
+
publication without Hyperscale's prior written consent;
|
|
185
|
+
11. register, apply for, or claim any patent, trademark, design, or domain
|
|
186
|
+
name that covers or resembles the Software, the Specifications, or the
|
|
187
|
+
Marks;
|
|
188
|
+
12. use the Software in violation of any law, sanction, or export control;
|
|
189
|
+
13. use the Software for any purpose this License does not expressly permit.
|
|
190
|
+
|
|
191
|
+
## 6. Contributions
|
|
192
|
+
|
|
193
|
+
You are not required to contribute. If you do, then on submission you grant
|
|
194
|
+
Hyperscale, and everyone who receives the Software from Hyperscale, a
|
|
195
|
+
perpetual, worldwide, non-exclusive, irrevocable, royalty-free license to use,
|
|
196
|
+
reproduce, modify, distribute, sublicense, and relicense your Contribution
|
|
197
|
+
under any terms, including this License and any commercial license, and you
|
|
198
|
+
grant Hyperscale a patent license of the same scope covering the claims your
|
|
199
|
+
Contribution alone or in combination with the Software would infringe. You
|
|
200
|
+
confirm you have the right to make these grants and that the Contribution is
|
|
201
|
+
your own work or that you have permission to submit it. Hyperscale may require
|
|
202
|
+
a signed contributor agreement before merging any Contribution and may decline
|
|
203
|
+
any Contribution for any reason. Feedback, suggestions, and ideas you send
|
|
204
|
+
about the Software are not confidential and Hyperscale may use them freely.
|
|
205
|
+
|
|
206
|
+
## 7. Marks
|
|
207
|
+
|
|
208
|
+
This License grants no right to any Mark. You may refer to the Software and to
|
|
209
|
+
the Hyperscale Platform by name to describe truthfully that your product uses
|
|
210
|
+
or integrates with them. You must not use any Mark as or in the name of your
|
|
211
|
+
product, company, package, domain, or repository, in a logo, or in any way that
|
|
212
|
+
suggests Hyperscale made, sponsors, certifies, or endorses your work.
|
|
213
|
+
|
|
214
|
+
## 8. Conformance and compatibility claims
|
|
215
|
+
|
|
216
|
+
You may state that your product "conforms to" or "is compatible with" a named
|
|
217
|
+
Specification version only if, at the time of the claim, your product
|
|
218
|
+
validates against the Specification exactly as Hyperscale published it, using
|
|
219
|
+
Hyperscale's published example inputs unmodified, and you built the product
|
|
220
|
+
under Tier 1 for the purpose of interoperating with the Hyperscale Platform.
|
|
221
|
+
The claim is a statement about your product and never an endorsement by
|
|
222
|
+
Hyperscale. Hyperscale may require you to withdraw a claim it considers false.
|
|
223
|
+
No claim of conformance permits a Competing Product.
|
|
224
|
+
|
|
225
|
+
## 9. Commercial license
|
|
226
|
+
|
|
227
|
+
Hyperscale offers a commercial license to organisations whose use falls
|
|
228
|
+
outside this License, including Hosted Use, distribution of modified copies,
|
|
229
|
+
embedding in a proprietary product, or any use a procurement policy cannot
|
|
230
|
+
accept under these terms. Ask through <https://hyperscale0.ai>. Nothing in this
|
|
231
|
+
section grants any right until a commercial agreement is signed.
|
|
232
|
+
|
|
233
|
+
## 10. Prior releases
|
|
234
|
+
|
|
235
|
+
Any version of the Software that Hyperscale released under a different license
|
|
236
|
+
remains available under that license for that version only. This License
|
|
237
|
+
applies to every version that carries it and to every later version unless
|
|
238
|
+
that version states otherwise. Nothing in this License narrows a right you
|
|
239
|
+
already hold in a prior version under its own license.
|
|
240
|
+
|
|
241
|
+
## 11. Term and termination
|
|
242
|
+
|
|
243
|
+
This License takes effect when you accept it and lasts until terminated. It
|
|
244
|
+
terminates automatically, with no notice, the moment you breach section 5 or
|
|
245
|
+
section 7. For any other breach, it terminates thirty days after Hyperscale
|
|
246
|
+
notifies you, unless you cure the breach within that period and it is the
|
|
247
|
+
first notice you have received. Hyperscale may also terminate this License for
|
|
248
|
+
convenience for any Tier 3 material, on notice. On termination you must stop
|
|
249
|
+
all use, destroy every copy in your possession or control, including
|
|
250
|
+
Derivative Works, and confirm destruction in writing if asked. Sections 3, 5,
|
|
251
|
+
6, 7, 11, 12, 13, 14, 15, and 16 survive termination.
|
|
252
|
+
|
|
253
|
+
## 12. Disclaimer of warranty
|
|
254
|
+
|
|
255
|
+
The Software is provided "as is" and "as available". Hyperscale makes no
|
|
256
|
+
warranty of any kind, express, implied, or statutory, including any warranty
|
|
257
|
+
of merchantability, fitness for a particular purpose, title, non-infringement,
|
|
258
|
+
accuracy, or that the Software will be error-free or uninterrupted. Hyperscale
|
|
259
|
+
is not a bank, does not hold money, and gives no assurance that any financial
|
|
260
|
+
program, product, or adapter written with the Software is lawful, licensed,
|
|
261
|
+
or fit for any real-world financial use in any jurisdiction.
|
|
262
|
+
|
|
263
|
+
## 13. Limitation of liability
|
|
264
|
+
|
|
265
|
+
To the fullest extent the law allows, Hyperscale is not liable to you or any
|
|
266
|
+
third party for any indirect, incidental, special, consequential, exemplary, or
|
|
267
|
+
punitive damages, or for any loss of profit, revenue, data, goodwill, or
|
|
268
|
+
business opportunity, arising from or related to the Software or this
|
|
269
|
+
License, however caused and under any theory of liability, even if advised of
|
|
270
|
+
the possibility. Hyperscale's total liability under this License is limited to
|
|
271
|
+
one thousand Saudi riyals (SAR 1,000) or the amount you paid Hyperscale for the
|
|
272
|
+
Software in the twelve months before the claim, whichever is greater.
|
|
273
|
+
|
|
274
|
+
## 14. Indemnity
|
|
275
|
+
|
|
276
|
+
You will defend, indemnify, and hold harmless Hyperscale, its owners,
|
|
277
|
+
officers, employees, and agents from every claim, loss, damage, liability,
|
|
278
|
+
cost, and expense, including reasonable legal fees, arising from your use of
|
|
279
|
+
the Software, your Derivative Works, your products, or your breach of this
|
|
280
|
+
License.
|
|
281
|
+
|
|
282
|
+
## 15. Remedies and enforcement
|
|
283
|
+
|
|
284
|
+
You acknowledge that the Software embodies valuable trade secrets and
|
|
285
|
+
intellectual property of Hyperscale, that a breach of section 3, 4, 5, or 7
|
|
286
|
+
would cause Hyperscale irreparable harm that money alone cannot repair, and
|
|
287
|
+
that Hyperscale is entitled to injunctive and other equitable relief in any
|
|
288
|
+
court of competent jurisdiction to stop or prevent a breach, without posting a
|
|
289
|
+
bond and in addition to every other remedy. You will pay Hyperscale's
|
|
290
|
+
reasonable legal fees and costs in any action in which Hyperscale enforces
|
|
291
|
+
this License and prevails on any claim. Hyperscale may bring an action in the
|
|
292
|
+
courts named in section 16 or in any jurisdiction where the Software is used,
|
|
293
|
+
a Derivative Work is made, or a Competing Product is offered, and you consent
|
|
294
|
+
to the jurisdiction of those courts.
|
|
295
|
+
|
|
296
|
+
## 16. Governing law and venue
|
|
297
|
+
|
|
298
|
+
This License is governed by the laws of the Kingdom of Saudi Arabia, including
|
|
299
|
+
the Copyright Law issued by Royal Decree M/41 and its implementing
|
|
300
|
+
regulations, without regard to conflict-of-law rules. The competent courts of
|
|
301
|
+
Riyadh have exclusive jurisdiction over any dispute arising from this License,
|
|
302
|
+
subject to Hyperscale's right under section 15 to enforce elsewhere. The
|
|
303
|
+
Berne Convention and the TRIPS Agreement apply to the protection of the
|
|
304
|
+
Software in every member state. Where a law of another jurisdiction gives you
|
|
305
|
+
a right this License cannot exclude, that right is preserved to the minimum
|
|
306
|
+
extent that law requires and no further.
|
|
307
|
+
|
|
308
|
+
## 17. General
|
|
309
|
+
|
|
310
|
+
1. This License is the entire agreement between you and Hyperscale about the
|
|
311
|
+
Software under its Tier, and replaces every earlier or contemporaneous
|
|
312
|
+
understanding, except a signed commercial agreement, which prevails where
|
|
313
|
+
the two conflict.
|
|
314
|
+
2. If any provision is held unenforceable, it is limited to the minimum
|
|
315
|
+
extent necessary and the rest stays in force.
|
|
316
|
+
3. Hyperscale's failure or delay in enforcing any provision is not a waiver.
|
|
317
|
+
A waiver is effective only in writing signed by Hyperscale.
|
|
318
|
+
4. You may not assign or transfer this License or any right under it, by
|
|
319
|
+
operation of law or otherwise, and any attempt is void. Hyperscale may
|
|
320
|
+
assign it freely.
|
|
321
|
+
5. Hyperscale may publish new versions of this License. Each version of the
|
|
322
|
+
Software carries the License version it was released under, and a new
|
|
323
|
+
License version applies only to Software that carries it.
|
|
324
|
+
6. This License is written in English. Hyperscale may publish an Arabic
|
|
325
|
+
translation. Where a court requires an Arabic text, the certified Arabic
|
|
326
|
+
translation Hyperscale provides is the text of record; in every other case
|
|
327
|
+
the English text governs.
|
|
328
|
+
7. Nothing in this License creates a partnership, joint venture, agency, or
|
|
329
|
+
employment relationship between you and Hyperscale.
|
|
330
|
+
8. Notices to Hyperscale go to the address published at
|
|
331
|
+
<https://hyperscale0.ai/legal>.
|
|
332
|
+
|
|
333
|
+
---
|
|
334
|
+
|
|
335
|
+
## Applying this License
|
|
336
|
+
|
|
337
|
+
A copy of the Software must carry this file as `LICENSE.md` and a `NOTICE.md`
|
|
338
|
+
that states the Tier. The form is:
|
|
339
|
+
|
|
340
|
+
```
|
|
341
|
+
This work is licensed under the Hyperscale Intellectual Property and
|
|
342
|
+
Copyright License, version 1.0 (LicenseRef-Hyperscale-IPCL-1.0).
|
|
343
|
+
Copyright (c) 2026 Hyperscale LLC. All rights reserved.
|
|
344
|
+
|
|
345
|
+
Tier: 2 (Source Available)
|
|
346
|
+
Specifications under Tier 1 in this repository: spec/, docs/grammar.md
|
|
347
|
+
|
|
348
|
+
Not open source. See LICENSE.md.
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
A package manifest states `"license": "SEE LICENSE IN LICENSE.md"`. A source
|
|
352
|
+
file may carry the one-line header:
|
|
353
|
+
|
|
354
|
+
```
|
|
355
|
+
// Copyright (c) 2026 Hyperscale LLC. Licensed under LicenseRef-Hyperscale-IPCL-1.0. Not open source.
|
|
356
|
+
```
|
package/NOTICE.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
This work is licensed under the Hyperscale Intellectual Property and
|
|
2
|
+
Copyright License, version 1.0 (`LicenseRef-Hyperscale-IPCL-1.0`).
|
|
3
|
+
Copyright (c) 2026 Hyperscale LLC. All rights reserved.
|
|
4
|
+
|
|
5
|
+
Tier: 2 (Source Available)
|
|
6
|
+
Specifications under Tier 1 (Open Specification) in this repository: docs/, examples/, editors/vscode/syntaxes/, editors/vscode/language-configuration.json
|
|
7
|
+
|
|
8
|
+
Not open source. See [LICENSE.md](LICENSE.md).
|
package/dist/src/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,EAAE;IACjB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;CAChC;AACD,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAiE7E"}
|
package/dist/src/cli.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { headerManifest } from "./headers.js";
|
|
4
|
+
import { HSX_VERSION } from "./version.js";
|
|
4
5
|
import { compile } from "./compile.js";
|
|
5
6
|
import { format } from "./format.js";
|
|
6
7
|
import { serializeUdl } from "@hyperscale0/udl";
|
|
@@ -29,7 +30,7 @@ export async function runCli(argv, io) {
|
|
|
29
30
|
return 0;
|
|
30
31
|
}
|
|
31
32
|
if (command === "--version") {
|
|
32
|
-
io.out(
|
|
33
|
+
io.out(`${HSX_VERSION} (UDL 3)`);
|
|
33
34
|
return 0;
|
|
34
35
|
}
|
|
35
36
|
if (!command ||
|
package/dist/src/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,MAAM,eAAe,GAAG;IACtB,MAAM,EAAE,CAAC,MAAc,EAAE,EAAE;QACzB,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,MAAM,MAAM,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9D,IAAI,UAAU,CAAC,IAAI,CAAC;gBAAE,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF,CAAC;AAUF,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAuB,EAAE,EAAM;IAC1D,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,IAAI,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACxC,EAAE,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;YACpC,OAAO,CAAC,CAAC;QACX,CAAC;QACD,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACjE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;QACrD,EAAE,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QAC1D,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAC5B,EAAE,CAAC,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,MAAM,eAAe,GAAG;IACtB,MAAM,EAAE,CAAC,MAAc,EAAE,EAAE;QACzB,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,MAAM,MAAM,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9D,IAAI,UAAU,CAAC,IAAI,CAAC;gBAAE,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;CACF,CAAC;AAUF,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAuB,EAAE,EAAM;IAC1D,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC;IACzC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,IAAI,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YACxC,EAAE,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;YACpC,OAAO,CAAC,CAAC;QACX,CAAC;QACD,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,eAAe,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACjE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,CAAC;QACrD,EAAE,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QAC1D,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;QAC5B,EAAE,CAAC,GAAG,CAAC,GAAG,WAAW,UAAU,CAAC,CAAC;QACjC,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IACE,CAAC,OAAO;QACR,CAAC,IAAI;QACL,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EACvD,CAAC;QACD,EAAE,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;QACjE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,IAAI,MAA0B,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,IAAI,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM,KAAK,SAAS;YAClE,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;aACnB,IAAI,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,EAAE,CAAC;YACvD,EAAE,CAAC,GAAG,CAAC,kBAAkB,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACvC,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,IAAY,CAAC;QACjB,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;YACzB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBACf,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBACnE,OAAO,CAAC,CAAC;YACX,CAAC;YACD,IAAI,GAAG,MAAM,CAAC,SAAS,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,eAAe,EAAE,CAAC,CAAC;YACpD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,WAAW;gBAChC,EAAE,CAAC,GAAG,CACJ,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,GAAG,EAAE,CAClE,CAAC;YACJ,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO,KAAK,OAAO;gBAAE,OAAO,CAAC,CAAC;YAC9D,IAAI,OAAO,KAAK,OAAO;gBAAE,OAAO,CAAC,CAAC;YAClC,IAAI;gBACF,OAAO,KAAK,MAAM;oBAChB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI;oBAC/D,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,MAAM;YAAE,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;;YACxC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5B,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,EAAE,CAAC,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/D,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC;AAED,IAAI,OAAO,IAAI,CAAC,IAAI;IAClB,OAAO,CAAC,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;QACrD,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QAChD,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,GAAG,IAAI,CAAC;QAChD,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAC1C,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC;KACzD,CAAC,CAAC"}
|
package/dist/src/std-bundle.js
CHANGED
|
@@ -4,7 +4,7 @@ export const BUNDLED_STD_FILES = new Map([
|
|
|
4
4
|
["cards.hsx", "header cards\n\ninstrument cardholder(holder: party) {\n fields { holder: account of holder }\n lifecycle { states: [pending, active, suspended, closed], initial: pending }\n action create {}\n action activate { from: pending, to: active }\n action suspend { from: active, to: suspended }\n action resume { from: suspended, to: active }\n action close { from: [active, suspended], to: closed }\n}\n\ninstrument card(holder: ref<cards.cardholder>, spend_limit: money) {\n fields { holder: ref<holder>, spendLimit: money = spend_limit }\n lifecycle { states: [issued, active, frozen, cancelled], initial: issued }\n action create { requires self.holder in [active] }\n action activate { from: issued, to: active, requires self.holder in [active] }\n action freeze { from: active, to: frozen }\n action unfreeze { from: frozen, to: active, requires self.holder in [active] }\n action cancel { from: [issued, active, frozen], to: cancelled }\n}\n\ninstrument authorization(card: ref<cards.card>, merchant: party, approval: approval) {\n fields { card: ref<card>, merchant: account of merchant, amount: money, expiresAt: date, reservation: text? }\n lifecycle { states: [pending, approved, captured, declined, reversed, expired], initial: pending }\n action create {\n requires self.card in [active]\n requires self.amount <= self.card.spendLimit\n }\n action approve {\n from: pending, to: approved, deadline: { at: self.expiresAt }\n requires approval by approval; requires self.card in [active]\n moves reserve self.amount from self.card.holder.holder to merchant capture \"reservation\"\n }\n action capture { from: approved, to: captured, deadline: { at: self.expiresAt }, moves post self.reservation }\n action reverse { from: approved, to: reversed, moves void self.reservation }\n action decline { from: pending, to: declined, requires approval by approval for \"approve\" is \"declined\" }\n action expire { from: approved, to: expired, actor: clock, due: { at: self.expiresAt }, moves void self.reservation }\n action abandon { from: pending, to: expired, actor: clock, due: { at: self.expiresAt } }\n}\n\ninstrument transaction(authorization: ref<cards.authorization>) {\n fields { authorization: ref<authorization>, amount: money = self.authorization.amount }\n lifecycle { states: [posted, refunded], initial: posted }\n action create { requires self.authorization in [captured]; requires unique \"captured_authorization\" on [self.authorization] }\n action refund {\n from: posted, to: refunded, input { reason: text }\n moves self.amount from self.authorization.merchant to self.authorization.card.holder.holder\n }\n}\n\ninstrument dispute(transaction: ref<cards.transaction>, approved_by: approval, within: duration = 90d) {\n fields { transaction: ref<transaction>, evidence: text, expiresAt: date = after(self.createdAt, within) }\n lifecycle { states: [filed, reviewing, won, lost], initial: filed }\n action create { requires self.transaction in [posted]; requires unique \"disputed_transaction\" on [self.transaction] }\n action review { from: filed, to: reviewing }\n action win {\n from: reviewing, to: won, deadline: { at: self.expiresAt }\n requires approval by approved_by\n invoke: [{ reference: self.transaction, action: refund, input: { reason: { field: self.evidence } } }]\n }\n action lose { from: [filed, reviewing], to: lost, actor: clock, due: { at: self.expiresAt } }\n}\n"],
|
|
5
5
|
["collections.hsx", "header collections\n\ninstrument case(on: ref<financing.installments>[], agency: approval, overdue: duration = 3d, fee: percent = 20%) {\n summary: \"Refer an overdue installment without creating another debt.\"\n fields { plan: ref<on>, slice: ref<on.slice>, payment: ref<on.payment>, eligibleAt: date = after(self.slice.dueAt, overdue), agencyFee: money = rate(self.payment.amount, fee) }\n lifecycle { states: [opened, assigned, recovered, recalled, returned_uncollected], initial: opened }\n action create {\n due: { at: self.eligibleAt }\n requires self.plan == self.slice.plan\n requires self.slice.principalReceivable.balance > \"0\"\n requires unique \"overdue_referral\" on [self.slice]\n }\n action assign { from: opened, to: assigned, requires approval by agency }\n action recover { from: assigned, to: recovered, actor: { party: agency }, requires self.payment.plan == self.plan, invoke: [{ reference: self.payment, action: pay, input: {} }, { reference: self.id, action: pay_fee, input: {} }] }\n action pay_fee { from: recovered, to: recovered, actor: { parent: current() }, moves self.agencyFee from self.plan.capital to agency }\n action recall { from: [opened, assigned], to: recalled }\n action return_uncollected { from: assigned, to: returned_uncollected, actor: { party: agency } }\n}\n\ninstrument contact(case: ref<collections.case>[], agency: party, max_contacts: integer = 10, window: duration = 30d, contact_from: integer(0, 23) = 8, contact_until: integer(1, 23) = 20, timezone: text = \"Asia/Riyadh\") {\n constraints { contact_from: less_than(contact_until) }\n summary: \"An agency contact admitted against the locked rolling count and local hours.\"\n fields { case: ref<case>, attemptedAt: date?, evidence: text, maximum: integer = max_contacts }\n lifecycle { states: [recorded], initial: recorded }\n invariants count of { instrument: current(), reference: \"case\", anchor: self.case, states: [recorded], limit: 366, window: { field: attemptedAt, milliseconds: window } } <= self.maximum\n action create {\n actor: { party: agency }\n set: { attemptedAt: { field: self.now } }\n requires self.case in [assigned]; requires hours self.now between contact_from and contact_until timezone timezone\n }\n}\n"],
|
|
6
6
|
["escrow.hsx", "header escrow\n\ninstrument hold(payer: party, payee: party, for: ref<marketplace.order>, accept_within: duration = 48h, fee: fee = { seller: 0%, tax: 0% }, dispute: policy = { refund_after: return_verified }) {\n summary: \"Hold an order's price through delivery, acceptance and verified return.\"\n fields { payer: account of payer, payee: account of payee, order: ref<for>, price: money, held: account of self, deliveredAt: date? }\n lifecycle { states: [pending, funded, delivered, disputed, return_verified, released, refunded, cancelled], initial: pending }\n action create {\n requires self.payer == self.order.buyer; requires self.payee == self.order.listing.seller; requires self.price == self.order.price\n }\n action fund {\n from: pending, to: funded, actor: { party: payer }\n requires self.order in [placed]\n moves self.price from payer to self.held\n }\n action confirm {\n from: pending, to: funded\n requires self.held.balance == self.price\n }\n action deliver {\n from: funded, to: delivered, actor: { party: payee }\n set: { deliveredAt: { field: self.now } }\n }\n action accept {\n from: delivered, to: released, actor: { party: payer }\n input { acceptanceReference: text, titleReference: text, coverReference: text }\n deadline: { at: self.deliveredAt, offset: accept_within }\n moves self.price from self.held to payee fee fee\n }\n action expire_acceptance {\n from: delivered, to: disputed, actor: clock\n due: { at: self.deliveredAt, offset: accept_within }\n }\n action dispute {\n from: delivered, to: disputed, actor: { party: payer }\n deadline: { at: self.deliveredAt, offset: accept_within }\n }\n action verify_return { from: disputed, to: return_verified, input { returnReference: text } }\n action refund {\n from: dispute.refund_after, to: refunded\n moves self.price from self.held to payer\n }\n action cancel { from: pending, to: cancelled }\n}\n"],
|
|
7
|
-
["financing.hsx", "header financing\n\ninstrument installments(months: integer(1, 366), profit: percent, disburse_to: enum(funds, borrower) = funds, profit_earned: enum(on_payment, by_schedule, at_disbursement) = on_payment, apply: enum(fines_profit_principal, principal_profit, pro_rata) = fines_profit_principal, payoff_rebate: percent = 100%, down_payment: percent = 0%, funds: ref, approval: approval, borrower: party = party(person), capital: party = programOperator, profit_to: party = programOperator, limits: ref<financing.limits> = object(financing.limits)) {\n summary: \"Funding, profit recognition and payment order chosen by the program.\"\n fields {\n funds: ref<funds>, borrower: account of borrower, settlementIdentity: text, borrowerLimit: ref<limits>, portfolioLimit: ref<limits.portfolio>\n months: integer = months, dates: list(date, months)\n capital: account(capital, cash, \"capital\"), profitIncome: account(profit_to, cash, \"profitIncome\"), loss: account(capital, claim, \"loss\")\n principalReturned: money?, profitReturned: money?, lossRecorded: money?\n price: money = self.funds.price\n downPayment: money = rate(self.price, down_payment)\n principal: money = subtract(self.price, self.downPayment)\n profit: money = rate(self.principal, profit)\n total: money = sum(self.principal, self.profit)\n }\n lifecycle { states: [quoted, signed, active, paid, written_off, cancelled], initial: quoted }\n invariants count of { instrument: all(financing.installments), reference: \"borrowerLimit\", anchor: self.borrowerLimit, states: [active], limit: 366 } <= self.borrowerLimit.activePlans\n invariants sum \"principalReceivable.balance\" of { instrument: all(financing.installments.slice), reference: \"borrowerLimit\", anchor: self.borrowerLimit, states: [pending, due, paid], limit: 366 } <= self.borrowerLimit.limit\n invariants sum \"principalReceivable.balance\" of { instrument: all(financing.installments.slice), reference: \"portfolioLimit\", anchor: self.portfolioLimit, states: [pending, due, paid], limit: 366 } <= self.portfolioLimit.limit\n action create { requires self.borrower == self.funds.payer; requires self.borrowerLimit.borrower == self.funds.payer }\n action sign {\n from: quoted, to: signed, input { signedOffer: text, affordabilityReference: text }\n requires count of { instrument: slice, reference: \"plan\", anchor: self.id, states: [draft], limit: 366 } == self.months\n }\n action disburse {\n from: signed, to: active\n requires approval by approval\n requires self.borrowerLimit in [approved]\n requires self.portfolioLimit in [approved]\n when disburse_to is funds {\n requires self.funds in [pending]\n moves self.downPayment from self.funds.payer to self.funds.held\n moves self.principal from self.capital to self.funds.held\n }\n when disburse_to is borrower { moves self.principal from self.capital to self.borrower }\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [draft], limit: 366, order: [position] }, action: activate, input: {} }]\n when disburse_to is funds { invoke: [{ reference: self.funds, action: confirm, input: {} }] }\n }\n action complete {\n from: active, to: paid\n requires count of { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366 } == 0\n }\n action restore { from: [active, paid], to: active, actor: { parent: payment } }\n action payoff {\n from: active, to: paid\n calculate: [\n { target: \"principalReturned\", op: \"aggregate\", selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366 }, measure: { sum: \"principalReceivable.balance\" } }\n ]\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366, order: [position] }, action: payoff, input: { identity: { field: self.settlementIdentity } } }, { reference: self.id, action: record_payoff, input: {} }]\n }\n action record_payoff {\n from: paid, to: paid, actor: { parent: current() }\n calculate: [{ target: profitReturned, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [paid], limit: 366, where: { payoffIdentity: { field: self.settlementIdentity } } }, measure: { sum: \"payoffProfit\" } }]\n invoke: [{ instrument: settlement, action: create, input: { plan: { field: self.id }, identity: { field: self.settlementIdentity }, principal: { field: self.principalReturned }, profit: { field: self.profitReturned }, loss: { literal: \"0\" }, kind: { literal: \"cash\" } } }]\n }\n action write_off {\n from: active, to: written_off\n input { overdueSlice: ref<slice> }\n calculate: [{ target: \"lossRecorded\", op: \"aggregate\", selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366 }, measure: { sum: \"principalReceivable.balance\" } }]\n due: { at: input.overdueSlice.lossEligibleAt }\n requires approval by approval; requires input.overdueSlice.plan == self.id; requires input.overdueSlice.principalReceivable.balance > \"0\"\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366, order: [position] }, action: write_off, input: {} }, { instrument: settlement, action: create, input: { plan: { field: self.id }, identity: { field: self.settlementIdentity }, principal: { literal: \"0\" }, profit: { literal: \"0\" }, loss: { field: self.lossRecorded }, kind: { literal: \"loss\" } } }]\n }\n action record_payment {\n from: active, to: active, actor: { parent: payment }\n input { identity: text, principal: money, profit: money }\n invoke: [{ instrument: settlement, action: create, input: { plan: { field: self.id }, identity: { field: input.identity }, principal: { field: input.principal }, profit: { field: input.profit }, loss: { literal: \"0\" }, kind: { literal: \"cash\" } } }]\n }\n action cancel { from: quoted, to: cancelled }\n records {\n settlement: {\n fields { plan: ref<parent>, identity: text, principal: money, profit: money, loss: money, kind: enum(cash, loss)\n capital: account(capital, cash, \"capital\"), profitIncome: account(profit_to, cash, \"profitIncome\"), lossAccount: account(capital, claim, \"loss\") }\n lifecycle { states: [recorded], initial: recorded }\n action create {\n actor: { parent: parent }\n input { plan: ref<parent>, identity: text, principal: money, profit: money, loss: money, kind: enum(cash, loss) }\n requires unique \"settlement_identity\" on [self.plan, self.identity]\n }\n }\n slice: {\n fields {\n plan: ref<parent>, borrowerLimit: ref<limits>, portfolioLimit: ref<limits.portfolio>, position: integer(1, months)\n dueAt: date = at(self.plan.dates, self.position), lossEligibleAt: date = after(self.dueAt, 90d)\n principalBase: money = divide(self.plan.principal, months)\n principalAllocated: money = multiply(self.principalBase, months)\n principalRemainder: money = subtract(self.plan.principal, self.principalAllocated)\n profitBase: money = divide(self.plan.profit, months)\n profitAllocated: money = multiply(self.profitBase, months)\n profitRemainder: money = subtract(self.plan.profit, self.profitAllocated)\n first: integer = divide(1, self.position)\n principalAdjustment: money = multiply(self.principalRemainder, self.first)\n profitAdjustment: money = multiply(self.profitRemainder, self.first)\n principal: money = sum(self.principalBase, self.principalAdjustment)\n profit: money = sum(self.profitBase, self.profitAdjustment)\n principalReceivable: account(self, claim), profitReceivable: account(self, claim), profitEarned: account(self, claim)\n payoffIdentity: text?, payoffRebate: money?, payoffProfitTotal: money?, payoffProfit: money?\n paymentBudget: money?, principalPayment: money?, principalBasePayment: money?, principalRatio: money?, profitPayment: money?, profitBudget: money?, collectibleProfit: money?, collectibleTotal: money?, ratioDenominator: integer = sum(10000, profit)\n debt: account(borrower, claim, contra, \"debt\"), loss: account(capital, claim, \"loss\")\n }\n lifecycle { states: [draft, pending, due, paid, written_off], initial: draft }\n action create {\n requires self.plan in [quoted]; requires unique \"signed_position\" on [self.plan, self.position]; requires self.borrowerLimit == self.plan.borrowerLimit; requires self.portfolioLimit == self.plan.portfolioLimit\n }\n action activate {\n from: draft, to: pending, actor: { parent: parent }\n moves self.principal from self.debt to self.principalReceivable\n moves self.profit from self.debt to self.profitReceivable\n when profit_earned is at_disbursement { moves self.profit from self.profitReceivable to self.profitEarned }\n when profit_earned is by_schedule { invoke: [{ instrument: recognition, action: create, input: { slice: { field: self.id } } }] }\n }\n action mature {\n from: pending, to: due, actor: clock, due: { at: self.dueAt }\n }\n action collect_principal {\n from: [pending, due, paid], to: due, actor: { parent: payment }\n input { payment: ref<payment> }\n requires input.payment.plan == self.plan\n invoke: [{ instrument: principal_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.principalReceivable.balance } } }]\n }\n action collect_profit {\n from: [pending, due, paid], to: due, actor: { parent: payment }\n input { payment: ref<payment> }\n requires input.payment.plan == self.plan\n when profit_earned is on_payment { invoke: [{ instrument: profit_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.profitReceivable.balance } } }] }\n when profit_earned is by_schedule { invoke: [{ instrument: profit_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.profitEarned.balance } } }] }\n when profit_earned is at_disbursement { invoke: [{ instrument: profit_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.profitEarned.balance } } }] }\n }\n action collect_pro_rata {\n from: [pending, due, paid], to: due, actor: { parent: payment }, input { payment: ref<payment> }\n requires input.payment.plan == self.plan\n when profit_earned is on_payment { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.profitReceivable.balance }] }] }\n when profit_earned is by_schedule { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.profitEarned.balance }] }] }\n when profit_earned is at_disbursement { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.profitEarned.balance }] }] }\n calculate: [\n { target: collectibleTotal, op: sum, values: [{ field: self.principalReceivable.balance }, { field: self.collectibleProfit }] }\n { target: paymentBudget, op: minimum, values: [{ field: input.payment.held.balance }, { field: self.collectibleTotal }] }\n { target: principalRatio, op: ratio, amount: { field: self.paymentBudget }, numerator: { literal: 10000 }, denominator: { field: self.ratioDenominator }, rounding: floor }\n { target: principalBasePayment, op: minimum, values: [{ field: self.principalRatio }, { field: self.principalReceivable.balance }] }\n { target: profitBudget, op: subtract, base: { field: self.paymentBudget }, subtract: [{ field: self.principalBasePayment }] }\n { target: profitPayment, op: minimum, values: [{ field: self.profitBudget }, { field: self.collectibleProfit }] }\n { target: principalPayment, op: subtract, base: { field: self.paymentBudget }, subtract: [{ field: self.profitPayment }] }\n ]\n invoke: [{ instrument: principal_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.principalPayment } } }, { instrument: profit_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.profitPayment } } }]\n }\n action complete {\n from: [pending, due], to: paid\n requires self.principalReceivable.balance == \"0\"; requires self.profitReceivable.balance == \"0\"; requires self.profitEarned.balance == \"0\"\n }\n action restore { from: [pending, due, paid], to: due, actor: { parent: payment } }\n action payoff {\n from: [pending, due], to: paid, actor: { parent: parent }, input { identity: text }\n set: { payoffIdentity: { field: input.identity } }\n calculate: [{ target: payoffRebate, op: rate, base: { field: self.profitReceivable.balance }, bps: { literal: payoff_rebate }, rounding: floor }, { target: payoffProfitTotal, op: sum, values: [{ field: self.profitReceivable.balance }, { field: self.profitEarned.balance }] }, { target: payoffProfit, op: subtract, base: { field: self.payoffProfitTotal }, subtract: [{ field: self.payoffRebate }] }]\n moves self.principalReceivable.balance from self.plan.borrower to self.plan.capital\n moves self.payoffProfit from self.plan.borrower to self.plan.profitIncome\n moves self.principalReceivable.balance from self.principalReceivable to self.debt\n moves self.profitReceivable.balance from self.profitReceivable to self.debt\n moves self.profitEarned.balance from self.profitEarned to self.debt\n }\n action write_off {\n from: [pending, due], to: written_off, actor: { parent: parent }\n moves self.principalReceivable.balance from self.principalReceivable to self.loss; moves self.profitReceivable.balance from self.profitReceivable to self.debt; moves self.profitEarned.balance from self.profitEarned to self.loss\n }\n }\n recognition: {\n fields { slice: ref<slice>, dueAt: date = after(self.slice.dueAt, 0) }\n lifecycle { states: [pending, recognised], initial: pending }\n action create { actor: { parent: slice }, input { slice: ref<slice> }, requires unique \"profit_recognition\" on [self.slice] }\n action mature { from: pending, to: recognised, actor: clock, due: { at: self.dueAt }, moves self.slice.profitReceivable.balance from self.slice.profitReceivable to self.slice.profitEarned }\n }\n payment: {\n fields { plan: ref<parent>, amount: money, paymentIdentity: text, held: account of self\n capital: account(capital, cash, \"capital\"), profitIncome: account(profit_to, cash, \"profitIncome\"), loss: account(capital, claim, \"loss\")\n outstandingPrincipal: money?, outstandingProfit: money?, outstandingFines: money?, outstandingCosts: money?, outstandingTotal: money?, principalReturned: money?, profitReturned: money?, lossRecorded: money? }\n\n lifecycle { states: [pending, paid, refunded], initial: pending }\n action create { input { plan: ref<parent>, amount: money, paymentIdentity: text } requires self.plan in [active]; requires unique \"payment_identity\" on [self.plan, self.paymentIdentity] }\n action pay {\n from: pending, to: paid\n calculate: [{ target: outstandingPrincipal, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, measure: { sum: \"principalReceivable.balance\" } }]\n when profit_earned is on_payment { calculate: [{ target: outstandingProfit, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, measure: { sum: \"profitReceivable.balance\" } }] }\n when profit_earned is by_schedule { calculate: [{ target: outstandingProfit, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, measure: { sum: \"profitEarned.balance\" } }] }\n when profit_earned is at_disbursement { calculate: [{ target: outstandingProfit, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, measure: { sum: \"profitEarned.balance\" } }] }\n when apply is fines_profit_principal {\n calculate: [{ target: outstandingFines, op: aggregate, selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366, order: [overdueAt] }, measure: { sum: \"receivable.balance\" } }, { target: outstandingCosts, op: aggregate, selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366, order: [overdueAt] }, measure: { sum: \"receivable.balance\" } }, { target: outstandingTotal, op: sum, values: [{ field: self.outstandingPrincipal }, { field: self.outstandingProfit }, { field: self.outstandingFines }, { field: self.outstandingCosts }] }]\n }\n when apply is principal_profit { calculate: [{ target: outstandingTotal, op: sum, values: [{ field: self.outstandingPrincipal }, { field: self.outstandingProfit }] }] }\n when apply is pro_rata { calculate: [{ target: outstandingTotal, op: sum, values: [{ field: self.outstandingPrincipal }, { field: self.outstandingProfit }] }] }\n requires self.plan in [active]; requires self.amount <= self.outstandingTotal\n moves self.amount from self.plan.borrower to self.held\n when apply is principal_profit {\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, action: collect_principal, input: { payment: { field: self.id } } }, { selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, action: collect_profit, input: { payment: { field: self.id } } }]\n }\n when apply is fines_profit_principal {\n invoke: [{ selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366, order: [overdueAt] }, action: collect, input: { payment: { field: self.id } } }, { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366, order: [overdueAt] }, action: collect, input: { payment: { field: self.id } } }]\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, action: collect_profit, input: { payment: { field: self.id } } }, { selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, action: collect_principal, input: { payment: { field: self.id } } }]\n }\n when apply is pro_rata {\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, action: collect_pro_rata, input: { payment: { field: self.id } } }]\n }\n invoke: [{ reference: self.id, action: record, input: {} }]\n }\n action record {\n from: paid, to: paid, actor: { parent: current() }\n requires self.held.balance == \"0\"\n calculate: [{ target: principalReturned, op: aggregate, selection: { instrument: principal_piece, reference: \"payment\", anchor: self.id, states: [paid], limit: 366 }, measure: { sum: \"amount\" } }, { target: profitReturned, op: aggregate, selection: { instrument: profit_piece, reference: \"payment\", anchor: self.id, states: [paid], limit: 366 }, measure: { sum: \"amount\" } }]\n invoke: [{ reference: self.plan, action: record_payment, input: { identity: { field: self.paymentIdentity }, principal: { field: self.principalReturned }, profit: { field: self.profitReturned } } }]\n }\n action refund {\n from: paid, to: refunded\n requires unique \"settlement_consumption\" on [self.plan, self.paymentIdentity]; requires self.plan in [active, paid]\n when apply is fines_profit_principal {\n invoke: [{ selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366, order: [overdueAt] }, action: refund, input: { payment: { field: self.id } } }, { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366, order: [overdueAt] }, action: refund, input: { payment: { field: self.id } } }]\n }\n invoke: [{ reference: self.plan, action: restore, input: {} }, { selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366 }, action: restore, input: {} }, { selection: { instrument: principal_piece, reference: \"payment\", anchor: self.id, states: [paid], limit: 366 }, action: refund, input: {} }, { selection: { instrument: profit_piece, reference: \"payment\", anchor: self.id, states: [paid], limit: 366 }, action: refund, input: {} }]\n }\n }\n principal_piece: {\n fields { slice: ref<slice>, payment: ref<payment>, limit: money, amount: money = minimum(self.payment.held.balance, self.slice.principalReceivable.balance, self.limit) }\n lifecycle { states: [paid, refunded], initial: paid }\n action create {\n actor: { parent: slice }\n input { slice: ref<slice>, payment: ref<payment>, limit: money }\n requires unique \"principal_receipt\" on [self.slice, self.payment]\n moves self.amount from self.payment.held to self.slice.plan.capital; moves self.amount from self.slice.principalReceivable to self.slice.debt\n }\n action refund {\n from: paid, to: refunded, actor: { parent: payment }\n moves self.amount from self.slice.plan.capital to self.slice.plan.funds.payer; moves self.amount from self.slice.debt to self.slice.principalReceivable\n }\n }\n profit_piece: {\n fields { slice: ref<slice>, payment: ref<payment>, limit: money, amount: money = minimum(self.payment.held.balance, self.limit) }\n lifecycle { states: [paid, refunded], initial: paid }\n action create {\n actor: { parent: slice }\n input { slice: ref<slice>, payment: ref<payment>, limit: money }\n requires unique \"profit_receipt\" on [self.slice, self.payment]\n moves self.amount from self.payment.held to self.slice.plan.profitIncome\n when profit_earned is on_payment { moves self.amount from self.slice.profitReceivable to self.slice.debt }\n when profit_earned is by_schedule { moves self.amount from self.slice.profitEarned to self.slice.debt }\n when profit_earned is at_disbursement { moves self.amount from self.slice.profitEarned to self.slice.debt }\n }\n action refund {\n from: paid, to: refunded, actor: { parent: payment }\n moves self.amount from self.slice.plan.profitIncome to self.slice.plan.borrower\n when profit_earned is on_payment { moves self.amount from self.slice.debt to self.slice.profitReceivable }\n when profit_earned is by_schedule { moves self.amount from self.slice.debt to self.slice.profitEarned }\n when profit_earned is at_disbursement { moves self.amount from self.slice.debt to self.slice.profitEarned }\n }\n }\n }\n}\n\ninstrument late_charge(on: ref<financing.installments>[], grace: duration = 3d, fine: money = 50 SAR, cap: money = 25 SAR, fines_to: party = programOperator, costs_to: party = programOperator, approval: approval = programOperator, borrower: party = party(person)) {\n summary: \"Separate approved fine and evidenced recovery claims on an overdue installment.\"\n fields {\n plan: ref<on>, slice: ref<on.slice>, borrower: account of borrower, fine: money = fine, overdueAt: date = after(self.slice.dueAt, grace)\n receivable: account(self, claim), debt: account(borrower, claim, contra, \"debt\")\n }\n lifecycle { states: [proposed, assessed, collected, waived, refunded], initial: proposed }\n action create { requires unique \"late_assessment\" on [self.slice]; requires self.borrower == self.slice.plan.borrower; requires self.plan == self.slice.plan }\n action assess {\n from: proposed, to: assessed, due: { at: self.overdueAt }\n requires self.slice.principalReceivable.balance > \"0\"; requires approval by approval\n moves self.fine from self.debt to self.receivable\n }\n action collect {\n from: [assessed, collected], to: assessed, input { payment: ref<on.payment> }\n requires input.payment in [paid]\n requires input.payment.plan == self.plan\n invoke: [{ instrument: receipt, action: create, input: { assessment: { field: self.id }, payment: { field: input.payment } } }, { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, receivable.balance: { literal: \"0\" } } }, action: finish, input: {} }]\n }\n action finish { from: assessed, to: collected, actor: { parent: current() }, requires self.receivable.balance == \"0\" }\n action cancel { from: proposed, to: waived }\n action waive { from: assessed, to: waived, moves self.receivable.balance from self.receivable to self.debt }\n action refund {\n from: [assessed, collected], to: assessed, input { payment: ref<on.payment> }\n requires input.payment in [paid, refunded]\n requires input.payment.plan == self.plan\n invoke: [{ selection: { instrument: receipt, reference: \"payment\", anchor: input.payment, states: [paid], limit: 1, where: { assessment: { field: self.id } } }, action: refund, input: {} }, { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, receivable.balance: { literal: \"0\" } } }, action: finish, input: {} }]\n }\n records {\n receipt: {\n fields { assessment: ref<parent>, payment: ref<on.payment>, amount: money = minimum(self.payment.held.balance, self.assessment.receivable.balance) }\n lifecycle { states: [paid, refunded], initial: paid }\n action create { actor: { parent: parent }, input { assessment: ref<parent>, payment: ref<on.payment> }, requires input.payment.plan == self.assessment.plan; requires unique \"fine_receipt\" on [self.assessment, self.payment]; moves self.amount from self.payment.held to fines_to; moves self.amount from self.assessment.receivable to self.assessment.debt }\n action refund { from: paid, to: refunded, actor: { parent: parent }, moves self.amount from fines_to to self.payment.plan.borrower; moves self.amount from self.assessment.debt to self.assessment.receivable }\n }\n\n cost: {\n fields {\n plan: ref<on>, assessment: ref<parent>, overdueAt: date = after(self.assessment.slice.dueAt, grace), evidence: text, evidencedCost: money, amount: money = minimum(self.evidencedCost, cap)\n receivable: account(self, claim), debt: account(borrower, claim, contra, \"debt\")\n }\n lifecycle { states: [proposed, assessed, collected, waived, refunded], initial: proposed }\n action create { requires unique \"recovery_assessment\" on [self.assessment]; requires self.plan == self.assessment.plan }\n action assess {\n from: proposed, to: assessed, due: { at: self.assessment.overdueAt }\n requires self.assessment.slice.principalReceivable.balance > \"0\"; requires approval by approval\n moves self.amount from self.debt to self.receivable\n }\n action collect {\n from: [assessed, collected], to: assessed, input { payment: ref<on.payment> }\n requires input.payment in [paid]\n requires input.payment.plan == self.plan\n invoke: [{ instrument: receipt, action: create, input: { assessment: { field: self.id }, payment: { field: input.payment } } }, { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, receivable.balance: { literal: \"0\" } } }, action: finish, input: {} }]\n }\n action finish { from: assessed, to: collected, actor: { parent: current() }, requires self.receivable.balance == \"0\" }\n action cancel { from: proposed, to: waived }\n action waive { from: assessed, to: waived, moves self.receivable.balance from self.receivable to self.debt }\n action refund {\n from: [assessed, collected], to: assessed, input { payment: ref<on.payment> }\n requires input.payment in [paid, refunded]\n requires input.payment.plan == self.plan\n invoke: [{ selection: { instrument: receipt, reference: \"payment\", anchor: input.payment, states: [paid], limit: 1, where: { assessment: { field: self.id } } }, action: refund, input: {} }, { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, receivable.balance: { literal: \"0\" } } }, action: finish, input: {} }]\n }\n records {\n receipt: {\n fields { assessment: ref<parent>, payment: ref<on.payment>, amount: money = minimum(self.payment.held.balance, self.assessment.receivable.balance) }\n lifecycle { states: [paid, refunded], initial: paid }\n action create { actor: { parent: parent }, input { assessment: ref<parent>, payment: ref<on.payment> }, requires input.payment.plan == self.assessment.plan; requires unique \"cost_receipt\" on [self.assessment, self.payment]; moves self.amount from self.payment.held to costs_to; moves self.amount from self.assessment.receivable to self.assessment.debt }\n action refund { from: paid, to: refunded, actor: { parent: parent }, moves self.amount from costs_to to self.payment.plan.borrower; moves self.amount from self.assessment.debt to self.assessment.receivable }\n }\n }\n }\n }\n}\n\ninstrument limits(per_borrower: money, portfolio: money, borrower: party = party(person), active_plans: integer = 1) {\n summary: \"One borrower ceiling and one shared portfolio ceiling.\"\n fields { borrower: account of borrower, limit: money = per_borrower, activePlans: integer = active_plans }\n lifecycle { states: [pending, approved], initial: pending }\n action create { requires unique \"borrower_limit\" on [self.borrower] }\n action approve { from: pending, to: approved }\n records {\n portfolio: {\n fields { key: text = \"portfolio\", limit: money = portfolio }\n lifecycle { states: [pending, approved], initial: pending }\n action create { requires unique \"portfolio_limit\" on [self.key] }\n action approve { from: pending, to: approved }\n }\n }\n}\n\ninstrument credit_line(borrower: party, lender: party, limit: money, expires: date) {\n summary: \"A revolving facility; each draw is a separate immutable advance.\"\n fields { borrower: account of borrower, lender: account of lender, debt: account(borrower, claim, contra, \"debt\"), limit: money = limit, expiresAt: date = expires }\n lifecycle { states: [pending, active, suspended, closed], initial: pending }\n action create {}\n action activate { from: pending, to: active, actor: { party: lender } }\n action suspend { from: active, to: suspended, actor: { party: lender } }\n action resume { from: suspended, to: active, actor: { party: lender } }\n action close { from: [active, suspended], to: closed, due: { at: self.expiresAt }, requires count of { instrument: all(financing.advance), reference: \"line\", anchor: self.id, states: [drawn], limit: 366 } == 0 }\n}\n\ninstrument advance(line: ref<financing.credit_line>, amount: money = runtime) {\n summary: \"A single facility draw with an immutable principal and full repayment.\"\n fields { line: ref<line>, amount: money = amount, principalReceivable: account(self, claim) }\n lifecycle { states: [pending, drawn, repaid, cancelled], initial: pending }\n action create { requires self.amount <= self.line.limit }\n invariants sum \"principalReceivable.balance\" of { instrument: all(financing.advance), reference: \"line\", anchor: self.line, states: [drawn], limit: 366 } <= self.line.limit\n action draw {\n from: pending, to: drawn\n requires self.line in [active]\n deadline: { at: self.line.expiresAt }\n moves self.amount from self.line.lender to self.line.borrower; moves self.amount from self.line.debt to self.principalReceivable\n }\n action repay { from: drawn, to: repaid, moves self.amount from self.line.borrower to self.line.lender; moves self.amount from self.principalReceivable to self.line.debt }\n action cancel { from: pending, to: cancelled }\n}\n"],
|
|
7
|
+
["financing.hsx", "header financing\n\ninstrument installments(months: integer(1, 366), profit: percent, disburse_to: enum(funds, borrower) = funds, profit_earned: enum(on_payment, by_schedule, at_disbursement) = on_payment, apply: enum(fines_profit_principal, principal_profit, pro_rata) = fines_profit_principal, payoff_rebate: percent = 100%, down_payment: percent = 0%, funds: ref, approval: approval, borrower: party = party(person), capital: party = programOperator, profit_to: party = programOperator, limits: ref<financing.limits> = object(financing.limits)) {\n summary: \"Funding, profit recognition and payment order chosen by the program.\"\n fields {\n funds: ref<funds>, borrower: account of borrower, settlementIdentity: text, borrowerLimit: ref<limits>, portfolioLimit: ref<limits.portfolio>\n months: integer = months, dates: list(date, months)\n capital: account(capital, cash, \"capital\"), profitIncome: account(profit_to, cash, \"profitIncome\"), loss: account(capital, claim, \"loss\")\n principalReturned: money?, profitReturned: money?, lossRecorded: money?\n price: money = self.funds.price\n downPayment: money = rate(self.price, down_payment)\n principal: money = subtract(self.price, self.downPayment)\n profit: money = rate(self.principal, profit)\n total: money = sum(self.principal, self.profit)\n }\n lifecycle { states: [quoted, signed, active, paid, written_off, cancelled], initial: quoted }\n invariants count of { instrument: all(financing.installments), reference: \"borrowerLimit\", anchor: self.borrowerLimit, states: [active], limit: 366 } <= self.borrowerLimit.activePlans\n invariants sum \"principalReceivable.balance\" of { instrument: all(financing.installments.slice), reference: \"borrowerLimit\", anchor: self.borrowerLimit, states: [pending, due, paid], limit: 366 } <= self.borrowerLimit.limit\n invariants sum \"principalReceivable.balance\" of { instrument: all(financing.installments.slice), reference: \"portfolioLimit\", anchor: self.portfolioLimit, states: [pending, due, paid], limit: 366 } <= self.portfolioLimit.limit\n action create { requires self.borrower == self.funds.payer; requires self.borrowerLimit.borrower == self.funds.payer }\n action sign {\n from: quoted, to: signed, input { signedOffer: text, affordabilityReference: text }\n requires count of { instrument: slice, reference: \"plan\", anchor: self.id, states: [draft], limit: 366 } == self.months\n }\n action disburse {\n from: signed, to: active\n requires approval by approval\n requires self.borrowerLimit in [approved]\n requires self.portfolioLimit in [approved]\n when disburse_to is funds {\n requires self.funds in [pending]\n moves self.downPayment from self.funds.payer to self.funds.held\n moves self.principal from self.capital to self.funds.held\n }\n when disburse_to is borrower { moves self.principal from self.capital to self.borrower }\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [draft], limit: 366, order: [position] }, action: activate, input: {} }]\n when disburse_to is funds { invoke: [{ reference: self.funds, action: confirm, input: {} }] }\n }\n action complete {\n from: active, to: paid\n requires count of { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366 } == 0\n }\n action restore { from: [active, paid], to: active, actor: { parent: payment } }\n action payoff {\n from: active, to: paid\n calculate: [\n { target: \"principalReturned\", op: \"aggregate\", selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366 }, measure: { sum: \"principalReceivable.balance\" } }\n ]\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366, order: [position] }, action: payoff, input: { identity: { field: self.settlementIdentity } } }, { reference: self.id, action: record_payoff, input: {} }]\n }\n action record_payoff {\n from: paid, to: paid, actor: { parent: current() }\n calculate: [{ target: profitReturned, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [paid], limit: 366, where: { payoffIdentity: { field: self.settlementIdentity } } }, measure: { sum: \"payoffProfit\" } }]\n invoke: [{ instrument: settlement, action: create, input: { plan: { field: self.id }, identity: { field: self.settlementIdentity }, principal: { field: self.principalReturned }, profit: { field: self.profitReturned }, loss: { literal: \"0\" }, kind: { literal: \"cash\" } } }]\n }\n action write_off {\n from: active, to: written_off\n input { overdueSlice: ref<slice> }\n calculate: [{ target: \"lossRecorded\", op: \"aggregate\", selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366 }, measure: { sum: \"principalReceivable.balance\" } }]\n due: { at: input.overdueSlice.lossEligibleAt }\n requires approval by approval; requires input.overdueSlice.plan == self.id; requires input.overdueSlice.principalReceivable.balance > \"0\"\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366, order: [position] }, action: write_off, input: {} }, { instrument: settlement, action: create, input: { plan: { field: self.id }, identity: { field: self.settlementIdentity }, principal: { literal: \"0\" }, profit: { literal: \"0\" }, loss: { field: self.lossRecorded }, kind: { literal: \"loss\" } } }]\n }\n action record_payment {\n from: active, to: active, actor: { parent: payment }\n input { identity: text, principal: money, profit: money }\n invoke: [{ instrument: settlement, action: create, input: { plan: { field: self.id }, identity: { field: input.identity }, principal: { field: input.principal }, profit: { field: input.profit }, loss: { literal: \"0\" }, kind: { literal: \"cash\" } } }]\n }\n action cancel { from: quoted, to: cancelled }\n records {\n settlement: {\n fields { plan: ref<parent>, identity: text, principal: money, profit: money, loss: money, kind: enum(cash, loss)\n capital: account(capital, cash, \"capital\"), profitIncome: account(profit_to, cash, \"profitIncome\"), lossAccount: account(capital, claim, \"loss\") }\n lifecycle { states: [recorded], initial: recorded }\n action create {\n actor: { parent: parent }\n input { plan: ref<parent>, identity: text, principal: money, profit: money, loss: money, kind: enum(cash, loss) }\n requires unique \"settlement_identity\" on [self.plan, self.identity]\n }\n }\n slice: {\n fields {\n plan: ref<parent>, borrowerLimit: ref<limits>, portfolioLimit: ref<limits.portfolio>, position: integer(1, months)\n dueAt: date = at(self.plan.dates, self.position), lossEligibleAt: date = after(self.dueAt, 90d)\n principalBase: money = divide(self.plan.principal, months)\n principalAllocated: money = multiply(self.principalBase, months)\n principalRemainder: money = subtract(self.plan.principal, self.principalAllocated)\n profitBase: money = divide(self.plan.profit, months)\n profitAllocated: money = multiply(self.profitBase, months)\n profitRemainder: money = subtract(self.plan.profit, self.profitAllocated)\n first: integer = divide(1, self.position)\n principalAdjustment: money = multiply(self.principalRemainder, self.first)\n profitAdjustment: money = multiply(self.profitRemainder, self.first)\n principal: money = sum(self.principalBase, self.principalAdjustment)\n profit: money = sum(self.profitBase, self.profitAdjustment)\n principalReceivable: account(self, claim), profitReceivable: account(self, claim), profitEarned: account(self, claim)\n payoffIdentity: text?, payoffRebate: money?, payoffProfitTotal: money?, payoffProfit: money?\n paymentBudget: money?, principalPayment: money?, principalBasePayment: money?, principalRatio: money?, profitPayment: money?, profitBudget: money?, collectibleProfit: money?, collectibleTotal: money?, ratioDenominator: integer = sum(10000, profit)\n debt: account(borrower, claim, contra, \"debt\"), loss: account(capital, claim, \"loss\")\n }\n lifecycle { states: [draft, pending, due, paid, written_off], initial: draft }\n action create {\n requires self.plan in [quoted]; requires unique \"signed_position\" on [self.plan, self.position]; requires self.borrowerLimit == self.plan.borrowerLimit; requires self.portfolioLimit == self.plan.portfolioLimit\n }\n action activate {\n from: draft, to: pending, actor: { parent: parent }\n moves self.principal from self.debt to self.principalReceivable\n moves self.profit from self.debt to self.profitReceivable\n when profit_earned is at_disbursement { moves self.profit from self.profitReceivable to self.profitEarned }\n when profit_earned is by_schedule { invoke: [{ instrument: recognition, action: create, input: { slice: { field: self.id } } }] }\n }\n action mature {\n from: pending, to: due, actor: clock, due: { at: self.dueAt }\n }\n action collect {\n from: [pending, due], to: due, actor: { parent: payment }\n input { payment: ref<payment> }\n requires input.payment.plan == self.plan\n when profit_earned is on_payment { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.profitReceivable.balance }] }] }\n when profit_earned is by_schedule { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.profitEarned.balance }] }] }\n when profit_earned is at_disbursement { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.profitEarned.balance }] }] }\n when apply is fines_profit_principal {\n invoke: [{ instrument: profit_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.collectibleProfit } } }, { instrument: principal_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.principalReceivable.balance } } }]\n }\n when apply is principal_profit {\n invoke: [{ instrument: principal_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.principalReceivable.balance } } }, { instrument: profit_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.collectibleProfit } } }]\n }\n }\n action collect_pro_rata {\n from: [pending, due], to: due, actor: { parent: payment }, input { payment: ref<payment> }\n requires input.payment.plan == self.plan\n when profit_earned is on_payment { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.profitReceivable.balance }] }] }\n when profit_earned is by_schedule { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.profitEarned.balance }] }] }\n when profit_earned is at_disbursement { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.profitEarned.balance }] }] }\n calculate: [\n { target: collectibleTotal, op: sum, values: [{ field: self.principalReceivable.balance }, { field: self.collectibleProfit }] }\n { target: paymentBudget, op: minimum, values: [{ field: input.payment.held.balance }, { field: self.collectibleTotal }] }\n { target: principalRatio, op: ratio, amount: { field: self.paymentBudget }, numerator: { literal: 10000 }, denominator: { field: self.ratioDenominator }, rounding: floor }\n { target: principalBasePayment, op: minimum, values: [{ field: self.principalRatio }, { field: self.principalReceivable.balance }] }\n { target: profitBudget, op: subtract, base: { field: self.paymentBudget }, subtract: [{ field: self.principalBasePayment }] }\n { target: profitPayment, op: minimum, values: [{ field: self.profitBudget }, { field: self.collectibleProfit }] }\n { target: principalPayment, op: subtract, base: { field: self.paymentBudget }, subtract: [{ field: self.profitPayment }] }\n ]\n invoke: [{ instrument: principal_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.principalPayment } } }, { instrument: profit_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.profitPayment } } }]\n }\n action complete {\n from: [pending, due], to: paid\n requires self.principalReceivable.balance == \"0\"; requires self.profitReceivable.balance == \"0\"; requires self.profitEarned.balance == \"0\"\n }\n action restore { from: [pending, due, paid], to: due, actor: { parent: payment } }\n action payoff {\n from: [pending, due], to: paid, actor: { parent: parent }, input { identity: text }\n set: { payoffIdentity: { field: input.identity } }\n calculate: [{ target: payoffRebate, op: rate, base: { field: self.profitReceivable.balance }, bps: { literal: payoff_rebate }, rounding: floor }, { target: payoffProfitTotal, op: sum, values: [{ field: self.profitReceivable.balance }, { field: self.profitEarned.balance }] }, { target: payoffProfit, op: subtract, base: { field: self.payoffProfitTotal }, subtract: [{ field: self.payoffRebate }] }]\n moves self.principalReceivable.balance from self.plan.borrower to self.plan.capital\n moves self.payoffProfit from self.plan.borrower to self.plan.profitIncome\n moves self.principalReceivable.balance from self.principalReceivable to self.debt\n moves self.profitReceivable.balance from self.profitReceivable to self.debt\n moves self.profitEarned.balance from self.profitEarned to self.debt\n }\n action write_off {\n from: [pending, due], to: written_off, actor: { parent: parent }\n moves self.principalReceivable.balance from self.principalReceivable to self.loss; moves self.profitReceivable.balance from self.profitReceivable to self.debt; moves self.profitEarned.balance from self.profitEarned to self.loss\n }\n }\n recognition: {\n fields { slice: ref<slice>, dueAt: date = after(self.slice.dueAt, 0) }\n lifecycle { states: [pending, recognised], initial: pending }\n action create { actor: { parent: slice }, input { slice: ref<slice> }, requires unique \"profit_recognition\" on [self.slice] }\n action mature { from: pending, to: recognised, actor: clock, due: { at: self.dueAt }, moves self.slice.profitReceivable.balance from self.slice.profitReceivable to self.slice.profitEarned }\n }\n payment: {\n fields { plan: ref<parent>, amount: money, paymentIdentity: text, held: account of self\n capital: account(capital, cash, \"capital\"), profitIncome: account(profit_to, cash, \"profitIncome\"), loss: account(capital, claim, \"loss\")\n outstandingPrincipal: money?, outstandingProfit: money?, outstandingFines: money?, outstandingCosts: money?, outstandingTotal: money?, principalReturned: money?, profitReturned: money?, lossRecorded: money? }\n\n lifecycle { states: [pending, paid, refunded], initial: pending }\n action create { input { plan: ref<parent>, amount: money, paymentIdentity: text } requires self.plan in [active]; requires unique \"payment_identity\" on [self.plan, self.paymentIdentity] }\n action pay {\n from: pending, to: paid\n calculate: [{ target: outstandingPrincipal, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, measure: { sum: \"principalReceivable.balance\" } }]\n when profit_earned is on_payment { calculate: [{ target: outstandingProfit, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, measure: { sum: \"profitReceivable.balance\" } }] }\n when profit_earned is by_schedule { calculate: [{ target: outstandingProfit, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, measure: { sum: \"profitEarned.balance\" } }] }\n when profit_earned is at_disbursement { calculate: [{ target: outstandingProfit, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366, order: [position] }, measure: { sum: \"profitEarned.balance\" } }] }\n when apply is fines_profit_principal {\n calculate: [{ target: outstandingFines, op: aggregate, selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366, order: [overdueAt] }, measure: { sum: \"receivable.balance\" } }, { target: outstandingCosts, op: aggregate, selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366, order: [overdueAt] }, measure: { sum: \"receivable.balance\" } }, { target: outstandingTotal, op: sum, values: [{ field: self.outstandingPrincipal }, { field: self.outstandingProfit }, { field: self.outstandingFines }, { field: self.outstandingCosts }] }]\n }\n when apply is principal_profit { calculate: [{ target: outstandingTotal, op: sum, values: [{ field: self.outstandingPrincipal }, { field: self.outstandingProfit }] }] }\n when apply is pro_rata { calculate: [{ target: outstandingTotal, op: sum, values: [{ field: self.outstandingPrincipal }, { field: self.outstandingProfit }] }] }\n requires self.plan in [active]; requires self.amount <= self.outstandingTotal\n moves self.amount from self.plan.borrower to self.held\n when apply is principal_profit {\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due], limit: 366, order: [position] }, action: collect, input: { payment: { field: self.id } } }]\n }\n when apply is fines_profit_principal {\n invoke: [{ selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366, order: [overdueAt] }, action: collect, input: { payment: { field: self.id } } }, { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366, order: [overdueAt] }, action: collect, input: { payment: { field: self.id } } }]\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due], limit: 366, order: [position] }, action: collect, input: { payment: { field: self.id } } }]\n }\n when apply is pro_rata {\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due], limit: 366, order: [position] }, action: collect_pro_rata, input: { payment: { field: self.id } } }]\n }\n invoke: [{ reference: self.id, action: record, input: {} }]\n }\n action record {\n from: paid, to: paid, actor: { parent: current() }\n requires self.held.balance == \"0\"\n calculate: [{ target: principalReturned, op: aggregate, selection: { instrument: principal_piece, reference: \"payment\", anchor: self.id, states: [paid], limit: 366 }, measure: { sum: \"amount\" } }, { target: profitReturned, op: aggregate, selection: { instrument: profit_piece, reference: \"payment\", anchor: self.id, states: [paid], limit: 366 }, measure: { sum: \"amount\" } }]\n invoke: [{ reference: self.plan, action: record_payment, input: { identity: { field: self.paymentIdentity }, principal: { field: self.principalReturned }, profit: { field: self.profitReturned } } }]\n }\n action refund {\n from: paid, to: refunded\n requires unique \"settlement_consumption\" on [self.plan, self.paymentIdentity]; requires self.plan in [active, paid]\n when apply is fines_profit_principal {\n invoke: [{ selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366, order: [overdueAt] }, action: refund, input: { payment: { field: self.id } } }, { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366, order: [overdueAt] }, action: refund, input: { payment: { field: self.id } } }]\n }\n invoke: [{ reference: self.plan, action: restore, input: {} }, { selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366 }, action: restore, input: {} }, { selection: { instrument: principal_piece, reference: \"payment\", anchor: self.id, states: [paid], limit: 366 }, action: refund, input: {} }, { selection: { instrument: profit_piece, reference: \"payment\", anchor: self.id, states: [paid], limit: 366 }, action: refund, input: {} }]\n }\n }\n principal_piece: {\n fields { slice: ref<slice>, payment: ref<payment>, limit: money, amount: money = minimum(self.payment.held.balance, self.slice.principalReceivable.balance, self.limit) }\n lifecycle { states: [paid, refunded], initial: paid }\n action create {\n actor: { parent: slice }\n input { slice: ref<slice>, payment: ref<payment>, limit: money }\n requires unique \"principal_receipt\" on [self.slice, self.payment]\n moves self.amount from self.payment.held to self.slice.plan.capital; moves self.amount from self.slice.principalReceivable to self.slice.debt\n }\n action refund {\n from: paid, to: refunded, actor: { parent: payment }\n moves self.amount from self.slice.plan.capital to self.slice.plan.funds.payer; moves self.amount from self.slice.debt to self.slice.principalReceivable\n }\n }\n profit_piece: {\n fields { slice: ref<slice>, payment: ref<payment>, limit: money, amount: money = minimum(self.payment.held.balance, self.limit) }\n lifecycle { states: [paid, refunded], initial: paid }\n action create {\n actor: { parent: slice }\n input { slice: ref<slice>, payment: ref<payment>, limit: money }\n requires unique \"profit_receipt\" on [self.slice, self.payment]\n moves self.amount from self.payment.held to self.slice.plan.profitIncome\n when profit_earned is on_payment { moves self.amount from self.slice.profitReceivable to self.slice.debt }\n when profit_earned is by_schedule { moves self.amount from self.slice.profitEarned to self.slice.debt }\n when profit_earned is at_disbursement { moves self.amount from self.slice.profitEarned to self.slice.debt }\n }\n action refund {\n from: paid, to: refunded, actor: { parent: payment }\n moves self.amount from self.slice.plan.profitIncome to self.slice.plan.borrower\n when profit_earned is on_payment { moves self.amount from self.slice.debt to self.slice.profitReceivable }\n when profit_earned is by_schedule { moves self.amount from self.slice.debt to self.slice.profitEarned }\n when profit_earned is at_disbursement { moves self.amount from self.slice.debt to self.slice.profitEarned }\n }\n }\n }\n}\n\ninstrument late_charge(on: ref<financing.installments>[], grace: duration = 3d, fine: money = 50 SAR, cap: money = 25 SAR, fines_to: party = programOperator, costs_to: party = programOperator, approval: approval = programOperator, borrower: party = party(person)) {\n summary: \"Separate approved fine and evidenced recovery claims on an overdue installment.\"\n fields {\n plan: ref<on>, slice: ref<on.slice>, borrower: account of borrower, fine: money = fine, overdueAt: date = after(self.slice.dueAt, grace)\n receivable: account(self, claim), debt: account(borrower, claim, contra, \"debt\")\n }\n lifecycle { states: [proposed, assessed, collected, waived, refunded], initial: proposed }\n action create { requires unique \"late_assessment\" on [self.slice]; requires self.borrower == self.slice.plan.borrower; requires self.plan == self.slice.plan }\n action assess {\n from: proposed, to: assessed, due: { at: self.overdueAt }\n requires self.slice.principalReceivable.balance > \"0\"; requires approval by approval\n moves self.fine from self.debt to self.receivable\n }\n action collect {\n from: [assessed, collected], to: assessed, input { payment: ref<on.payment> }\n requires input.payment in [paid]\n requires input.payment.plan == self.plan\n invoke: [{ instrument: receipt, action: create, input: { assessment: { field: self.id }, payment: { field: input.payment } } }, { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, receivable.balance: { literal: \"0\" } } }, action: finish, input: {} }]\n }\n action finish { from: assessed, to: collected, actor: { parent: current() }, requires self.receivable.balance == \"0\" }\n action cancel { from: proposed, to: waived }\n action waive { from: assessed, to: waived, moves self.receivable.balance from self.receivable to self.debt }\n action refund {\n from: [assessed, collected], to: assessed, input { payment: ref<on.payment> }\n requires input.payment in [paid, refunded]\n requires input.payment.plan == self.plan\n invoke: [{ selection: { instrument: receipt, reference: \"payment\", anchor: input.payment, states: [paid], limit: 1, where: { assessment: { field: self.id } } }, action: refund, input: {} }, { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, receivable.balance: { literal: \"0\" } } }, action: finish, input: {} }]\n }\n records {\n receipt: {\n fields { assessment: ref<parent>, payment: ref<on.payment>, amount: money = minimum(self.payment.held.balance, self.assessment.receivable.balance) }\n lifecycle { states: [paid, refunded], initial: paid }\n action create { actor: { parent: parent }, input { assessment: ref<parent>, payment: ref<on.payment> }, requires input.payment.plan == self.assessment.plan; requires unique \"fine_receipt\" on [self.assessment, self.payment]; moves self.amount from self.payment.held to fines_to; moves self.amount from self.assessment.receivable to self.assessment.debt }\n action refund { from: paid, to: refunded, actor: { parent: parent }, moves self.amount from fines_to to self.payment.plan.borrower; moves self.amount from self.assessment.debt to self.assessment.receivable }\n }\n\n cost: {\n fields {\n plan: ref<on>, assessment: ref<parent>, overdueAt: date = after(self.assessment.slice.dueAt, grace), evidence: text, evidencedCost: money, amount: money = minimum(self.evidencedCost, cap)\n receivable: account(self, claim), debt: account(borrower, claim, contra, \"debt\")\n }\n lifecycle { states: [proposed, assessed, collected, waived, refunded], initial: proposed }\n action create { requires unique \"recovery_assessment\" on [self.assessment]; requires self.plan == self.assessment.plan }\n action assess {\n from: proposed, to: assessed, due: { at: self.assessment.overdueAt }\n requires self.assessment.slice.principalReceivable.balance > \"0\"; requires approval by approval\n moves self.amount from self.debt to self.receivable\n }\n action collect {\n from: [assessed, collected], to: assessed, input { payment: ref<on.payment> }\n requires input.payment in [paid]\n requires input.payment.plan == self.plan\n invoke: [{ instrument: receipt, action: create, input: { assessment: { field: self.id }, payment: { field: input.payment } } }, { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, receivable.balance: { literal: \"0\" } } }, action: finish, input: {} }]\n }\n action finish { from: assessed, to: collected, actor: { parent: current() }, requires self.receivable.balance == \"0\" }\n action cancel { from: proposed, to: waived }\n action waive { from: assessed, to: waived, moves self.receivable.balance from self.receivable to self.debt }\n action refund {\n from: [assessed, collected], to: assessed, input { payment: ref<on.payment> }\n requires input.payment in [paid, refunded]\n requires input.payment.plan == self.plan\n invoke: [{ selection: { instrument: receipt, reference: \"payment\", anchor: input.payment, states: [paid], limit: 1, where: { assessment: { field: self.id } } }, action: refund, input: {} }, { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, receivable.balance: { literal: \"0\" } } }, action: finish, input: {} }]\n }\n records {\n receipt: {\n fields { assessment: ref<parent>, payment: ref<on.payment>, amount: money = minimum(self.payment.held.balance, self.assessment.receivable.balance) }\n lifecycle { states: [paid, refunded], initial: paid }\n action create { actor: { parent: parent }, input { assessment: ref<parent>, payment: ref<on.payment> }, requires input.payment.plan == self.assessment.plan; requires unique \"cost_receipt\" on [self.assessment, self.payment]; moves self.amount from self.payment.held to costs_to; moves self.amount from self.assessment.receivable to self.assessment.debt }\n action refund { from: paid, to: refunded, actor: { parent: parent }, moves self.amount from costs_to to self.payment.plan.borrower; moves self.amount from self.assessment.debt to self.assessment.receivable }\n }\n }\n }\n }\n}\n\ninstrument limits(per_borrower: money, portfolio: money, borrower: party = party(person), active_plans: integer = 1) {\n summary: \"One borrower ceiling and one shared portfolio ceiling.\"\n fields { borrower: account of borrower, limit: money = per_borrower, activePlans: integer = active_plans }\n lifecycle { states: [pending, approved], initial: pending }\n action create { requires unique \"borrower_limit\" on [self.borrower] }\n action approve { from: pending, to: approved }\n records {\n portfolio: {\n fields { key: text = \"portfolio\", limit: money = portfolio }\n lifecycle { states: [pending, approved], initial: pending }\n action create { requires unique \"portfolio_limit\" on [self.key] }\n action approve { from: pending, to: approved }\n }\n }\n}\n\ninstrument credit_line(borrower: party, lender: party, limit: money, expires: date) {\n summary: \"A revolving facility; each draw is a separate immutable advance.\"\n fields { borrower: account of borrower, lender: account of lender, debt: account(borrower, claim, contra, \"debt\"), limit: money = limit, expiresAt: date = expires }\n lifecycle { states: [pending, active, suspended, closed], initial: pending }\n action create {}\n action activate { from: pending, to: active, actor: { party: lender } }\n action suspend { from: active, to: suspended, actor: { party: lender } }\n action resume { from: suspended, to: active, actor: { party: lender } }\n action close { from: [active, suspended], to: closed, due: { at: self.expiresAt }, requires count of { instrument: all(financing.advance), reference: \"line\", anchor: self.id, states: [drawn], limit: 366 } == 0 }\n}\n\ninstrument advance(line: ref<financing.credit_line>, amount: money = runtime) {\n summary: \"A single facility draw with an immutable principal and full repayment.\"\n fields { line: ref<line>, amount: money = amount, principalReceivable: account(self, claim) }\n lifecycle { states: [pending, drawn, repaid, cancelled], initial: pending }\n action create { requires self.amount <= self.line.limit }\n invariants sum \"principalReceivable.balance\" of { instrument: all(financing.advance), reference: \"line\", anchor: self.line, states: [drawn], limit: 366 } <= self.line.limit\n action draw {\n from: pending, to: drawn\n requires self.line in [active]\n deadline: { at: self.line.expiresAt }\n moves self.amount from self.line.lender to self.line.borrower; moves self.amount from self.line.debt to self.principalReceivable\n }\n action repay { from: drawn, to: repaid, moves self.amount from self.line.borrower to self.line.lender; moves self.amount from self.principalReceivable to self.line.debt }\n action cancel { from: pending, to: cancelled }\n}\n"],
|
|
8
8
|
["insurance.hsx", "header insurance\n\ninstrument cover(holder: party, insurer: party, commission: percent = 0%, covers: ref, premium: money = runtime) {\n summary: \"Recurring cover with separate premium slices and commission clawback.\"\n fields { covers: ref<covers>, holder: account of holder, insurer: account of insurer, expiresAt: date }\n lifecycle { states: [pending, active, cancelled, expired], initial: pending }\n action create {}\n action activate { from: pending, to: active, actor: { party: insurer } }\n action cancel {\n from: active, to: cancelled\n invoke: [{ selection: { instrument: slice, reference: \"cover\", anchor: self.id, states: [paid], limit: 366 }, action: refund, input: {} }]\n }\n action expire { from: active, to: expired, actor: clock, due: { at: self.expiresAt } }\n records {\n slice: {\n summary: \"A whole premium period, collected once and refundable only before it starts.\"\n fields {\n cover: ref<parent>, covers: ref<covers>, premium: money = premium, startsAt: date, endsAt: date\n commission: money = rate(self.premium, commission)\n carrierNet: money = subtract(self.premium, self.commission)\n }\n lifecycle { states: [pending, paid, active, expired, refunded], initial: pending }\n action create {\n requires self.covers == self.cover.covers\n requires self.startsAt < self.endsAt\n requires unique \"premium_period\" on [self.cover, self.startsAt, self.endsAt]\n }\n action collect {\n from: pending, to: paid\n requires self.cover in [active]\n moves self.premium from holder to insurer\n moves self.commission from insurer to programOperator\n }\n action start { from: paid, to: active, actor: clock, due: { at: self.startsAt } }\n action expire { from: active, to: expired, actor: clock, due: { at: self.endsAt } }\n action refund {\n from: paid, to: refunded, deadline: { at: self.startsAt }\n moves self.commission from programOperator to insurer\n moves self.premium from insurer to holder\n }\n }\n }\n}\n\ninstrument claim(cover: ref<insurance.cover>, approved_by: approval) {\n summary: \"A carrier decision reserves one claim payment before settlement.\"\n fields { cover: ref<cover>, amount: money, expiresAt: date, evidence: text, reservation: text? }\n lifecycle { states: [submitted, approved, paid, denied, expired], initial: submitted }\n action create { requires self.cover in [active] }\n action approve {\n from: submitted, to: approved, actor: { party: approved_by }\n requires approval by approved_by\n deadline: { at: self.expiresAt }\n moves reserve self.amount from self.cover.insurer to self.cover.holder capture \"reservation\"\n }\n action pay { from: approved, to: paid, deadline: { at: self.expiresAt }, moves post self.reservation }\n action deny { from: submitted, to: denied, requires approval by approved_by for approve is \"declined\" }\n action expire { from: approved, to: expired, actor: clock, due: { at: self.expiresAt }, moves void self.reservation }\n}\n"],
|
|
9
9
|
["lending.hsx", "header lending\n\ninstrument round(borrower: party, capital: party, plan: ref<financing.installments> = object(financing.installments), months: integer(1, 366) = 3, profit: percent = 3%, minimum_ticket: money = 100 SAR, investor_cap: percent = 20%, commitments: ref<lending.commitment> = object(lending.commitment)) {\n summary: \"A threshold funding round; failed rounds return each original wallet contribution.\"\n fields {\n borrower: account of borrower, capital: account(capital, cash, \"capital\"), plan: ref<plan>, price: money, closesAt: date\n months: integer = months, profit: money = rate(self.price, profit)\n minimumTicket: money = minimum_ticket, maximumTicket: money = rate(self.price, investor_cap)\n held: account of self\n }\n lifecycle { states: [open, funded, failed], initial: open }\n action create { requires unique \"funding_plan\" on [self.plan]; requires self.months == self.plan.months; requires self.profit == self.plan.profit; requires self.price == self.plan.principal; requires self.borrower == self.plan.funds.payer }\n action close {\n from: open, to: funded\n requires sum \"amount\" of { instrument: commitments, reference: \"round\", anchor: self.id, states: [committed], limit: 366 } == self.price\n requires self.held.balance == self.price\n moves self.price from self.held to self.plan.capital\n invoke: [{ selection: { instrument: commitments, reference: \"round\", anchor: self.id, states: [committed], limit: 366 }, action: fund, input: {} }]\n }\n action fail {\n from: open, to: failed, actor: clock, due: { at: self.closesAt }\n requires self.held.balance < self.price\n invoke: [{ selection: { instrument: commitments, reference: \"round\", anchor: self.id, states: [committed], limit: 366 }, action: refund, input: {} }]\n }\n}\n\ninstrument commitment(round: ref<lending.round>, wallet: ref<wallet.balance>, investor: party = party(person)) {\n summary: \"One investor's original-wallet contribution, capped cumulatively within the round.\"\n fields { round: ref<round>, wallet: ref<wallet>, amount: money, loss: account(investor, claim, \"loss\") }\n lifecycle { states: [committed, funded, withdrawn, refunded], initial: committed }\n invariants sum \"amount\" of { instrument: all(lending.commitment), reference: \"round\", anchor: self.round, states: [committed, funded], limit: 366, where: { wallet: { field: self.wallet } } } <= self.round.maximumTicket\n invariants sum \"amount\" of { instrument: all(lending.commitment), reference: \"round\", anchor: self.round, states: [committed, funded], limit: 366 } <= self.round.price\n action create {\n requires self.round in [open]\n requires self.wallet in [active]\n requires self.amount >= self.round.minimumTicket\n deadline: { at: self.round.closesAt }\n moves self.amount from self.wallet.held to self.round.held\n }\n action fund { from: committed, to: funded, actor: { parent: round } }\n action withdraw {\n from: committed, to: withdrawn\n requires self.round in [open]\n deadline: { at: self.round.closesAt }\n moves self.amount from self.round.held to self.wallet.held\n }\n action refund {\n from: committed, to: refunded, actor: { parent: round }\n moves self.amount from self.round.held to self.wallet.held\n }\n}\n\ninstrument distribution(round: ref<lending.round>, receipt: ref, commitments: ref<lending.commitment> = object(lending.commitment), mode: enum(cash, loss) = cash, residual_to: party = programOperator, fee: percent = 1%, tax: percent = 15%) {\n summary: \"Frozen weighted shares, floored once, with residual assigned to the chosen party.\"\n fields {\n round: ref<round>, source: ref<receipt>, mode: enum(cash, loss) = mode\n principal: money?, profit: money?, grossTotal: money?, charge: money?, vat: money?, net: money?\n held: account of self, losses: account(self, claim), residualLoss: account(residual_to, claim, \"loss\")\n }\n lifecycle { states: [pending, cash_ready, loss_ready, distributed], initial: pending }\n action create { requires self.round in [funded]; requires self.source.plan == self.round.plan; requires unique \"settlement_consumption\" on [self.source.plan, self.source.identity] }\n action prepare_cash {\n from: pending, to: cash_ready\n requires self.mode == \"cash\"; requires self.source.kind == \"cash\"\n calculate: [\n { target: \"principal\", op: \"sum\", values: [{ field: self.source.principal }] }\n { target: \"profit\", op: \"sum\", values: [{ field: self.source.profit }] }\n { target: \"charge\", op: \"rate\", base: { field: self.profit }, bps: { literal: fee }, rounding: \"floor\" }\n { target: \"vat\", op: \"rate\", base: { field: self.charge }, bps: { literal: tax }, rounding: \"floor\" }\n { target: \"grossTotal\", op: \"sum\", values: [{ field: self.principal }, { field: self.profit }] }\n { target: \"net\", op: \"subtract\", base: { field: self.grossTotal }, subtract: [{ field: self.charge }, { field: self.vat }] }\n ]\n }\n action prepare_loss {\n from: pending, to: loss_ready\n requires self.mode == \"loss\"; requires self.source.kind == \"loss\"\n calculate: [{ target: \"net\", op: \"sum\", values: [{ field: self.source.loss }] }]\n }\n action distribute_cash {\n from: cash_ready, to: distributed\n requires sum \"weight\" of { instrument: share, reference: \"distribution\", anchor: self.id, states: [pending], limit: 366 } == self.round.price\n moves self.principal from self.source.capital to self.held; moves self.profit from self.source.profitIncome to self.held; moves self.charge from self.held to programOperator; moves self.vat from self.held to programTax\n invoke: [{ selection: { instrument: share, reference: \"distribution\", anchor: self.id, states: [pending], limit: 366 }, action: cash, input: {} }, { reference: self.id, action: residual_cash, input: {} }]\n }\n action residual_cash {\n from: distributed, to: distributed, actor: { parent: current() }\n moves self.held.balance from self.held to residual_to\n }\n action distribute_loss {\n from: loss_ready, to: distributed\n requires sum \"weight\" of { instrument: share, reference: \"distribution\", anchor: self.id, states: [pending], limit: 366 } == self.round.price\n moves self.net from self.source.lossAccount to self.losses\n invoke: [{ selection: { instrument: share, reference: \"distribution\", anchor: self.id, states: [pending], limit: 366 }, action: loss, input: {} }, { reference: self.id, action: residual_loss, input: {} }]\n }\n action residual_loss {\n from: distributed, to: distributed, actor: { parent: current() }\n moves self.losses.balance from self.losses to self.residualLoss\n }\n records {\n share: {\n fields {\n distribution: ref<parent>, commitment: ref<commitments>\n weight: money = self.commitment.amount\n gross: money = ratio(self.distribution.net, self.weight, self.distribution.round.price)\n }\n lifecycle { states: [pending, paid], initial: pending }\n action create { requires self.distribution in [cash_ready, loss_ready]; requires self.commitment in [funded]; requires unique \"distribution_weight\" on [self.distribution, self.commitment]; requires self.commitment.round == self.distribution.round }\n action cash {\n from: pending, to: paid, actor: { parent: parent }\n moves self.gross from self.distribution.held to self.commitment.wallet.held\n }\n action loss { from: pending, to: paid, actor: { parent: parent }, moves self.gross from self.distribution.losses to self.commitment.loss }\n }\n }\n}\n"],
|
|
10
10
|
["marketplace.hsx", "header marketplace\n\ninstrument listing(seller: party) {\n summary: \"A seller's offer and its asking price.\"\n fields { seller: account of seller, title: text, price: money }\n lifecycle { states: [draft, active, withdrawn, sold], initial: draft }\n action create { actor: { party: seller } }\n action publish { from: draft, to: active, actor: { party: seller } }\n action withdraw { from: active, to: withdrawn, actor: { party: seller } }\n action sell { from: active, to: sold, actor: { party: seller } }\n}\n\ninstrument order(listing: ref<marketplace.listing>, buyer: party) {\n summary: \"A buyer's order for one listing at its declared price.\"\n fields { listing: ref<listing>, buyer: account of buyer, price: money }\n lifecycle { states: [placed, fulfilled, cancelled], initial: placed }\n action create {\n actor: { party: buyer }\n requires self.listing in [active]\n requires self.price == self.listing.price\n }\n action fulfill { from: placed, to: fulfilled }\n action cancel { from: placed, to: cancelled, actor: { party: buyer } }\n}\n"],
|