@hyperscale0/hsx 5.4.0 → 5.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +45 -62
  3. package/dist/src/examples-bundle.d.ts.map +1 -1
  4. package/dist/src/examples-bundle.js +16 -15
  5. package/dist/src/examples-bundle.js.map +1 -1
  6. package/dist/src/std-bundle.js +12 -12
  7. package/dist/src/std-bundle.js.map +1 -1
  8. package/dist/src/version.d.ts +1 -1
  9. package/dist/src/version.js +1 -1
  10. package/docs/README.md +136 -30
  11. package/docs/examples.md +1 -0
  12. package/examples/cards.hsx +4 -0
  13. package/examples/collections.hsx +5 -2
  14. package/examples/escrow.hsx +2 -0
  15. package/examples/financing.hsx +3 -0
  16. package/examples/insurance.hsx +3 -0
  17. package/examples/lending.hsx +5 -0
  18. package/examples/library.hsx +3 -3
  19. package/examples/marketplace.hsx +6 -0
  20. package/examples/money.hsx +1 -0
  21. package/examples/rental-deposit.hsx +60 -0
  22. package/examples/repair-approval.hsx +1 -0
  23. package/examples/reporting.hsx +4 -1
  24. package/examples/savings.hsx +2 -0
  25. package/examples/serviced.hsx +5 -4
  26. package/examples/travel.hsx +3 -0
  27. package/examples/wallet.hsx +2 -0
  28. package/package.json +3 -3
  29. package/src/examples-bundle.ts +16 -15
  30. package/src/std-bundle.ts +12 -12
  31. package/src/version.ts +1 -1
  32. package/std/cards.hsx +4 -0
  33. package/std/collections.hsx +4 -0
  34. package/std/escrow.hsx +4 -0
  35. package/std/financing.hsx +4 -0
  36. package/std/insurance.hsx +4 -0
  37. package/std/lending.hsx +4 -0
  38. package/std/marketplace.hsx +4 -0
  39. package/std/money.hsx +4 -0
  40. package/std/reporting.hsx +4 -0
  41. package/std/savings.hsx +4 -0
  42. package/std/travel.hsx +5 -0
  43. package/std/wallet.hsx +4 -0
@@ -1 +1 @@
1
- {"version":3,"file":"std-bundle.js","sourceRoot":"","sources":["../../src/std-bundle.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,MAAM,CAAC,MAAM,iBAAiB,GAAgC,IAAI,GAAG,CAAiB;IACpF,CAAC,WAAW,EAAE,k6JAAk6J,CAAC;IACj7J,CAAC,iBAAiB,EAAE,s8LAAs8L,CAAC;IAC39L,CAAC,YAAY,EAAE,00FAA00F,CAAC;IAC11F,CAAC,eAAe,EAAE,2z0DAA2z0D,CAAC;IAC900D,CAAC,eAAe,EAAE,0+IAA0+I,CAAC;IAC7/I,CAAC,aAAa,EAAE,oyRAAoyR,CAAC;IACrzR,CAAC,iBAAiB,EAAE,y1RAAy1R,CAAC;IAC92R,CAAC,WAAW,EAAE,0yTAA0yT,CAAC;IACzzT,CAAC,eAAe,EAAE,uq9CAAuq9C,CAAC;IAC1r9C,CAAC,aAAa,EAAE,o+IAAo+I,CAAC;IACr/I,CAAC,YAAY,EAAE,s6OAAs6O,CAAC;IACt7O,CAAC,YAAY,EAAE,qjFAAqjF,CAAC;CACtkF,CAAC,CAAC"}
1
+ {"version":3,"file":"std-bundle.js","sourceRoot":"","sources":["../../src/std-bundle.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,MAAM,CAAC,MAAM,iBAAiB,GAAgC,IAAI,GAAG,CAAiB;IACpF,CAAC,WAAW,EAAE,2oKAA2oK,CAAC;IAC1pK,CAAC,iBAAiB,EAAE,+rMAA+rM,CAAC;IACptM,CAAC,YAAY,EAAE,6jGAA6jG,CAAC;IAC7kG,CAAC,eAAe,EAAE,0j1DAA0j1D,CAAC;IAC7k1D,CAAC,eAAe,EAAE,ouJAAouJ,CAAC;IACvvJ,CAAC,aAAa,EAAE,4hSAA4hS,CAAC;IAC7iS,CAAC,iBAAiB,EAAE,ilSAAilS,CAAC;IACtmS,CAAC,WAAW,EAAE,kjUAAkjU,CAAC;IACjkU,CAAC,eAAe,EAAE,649CAA649C,CAAC;IACh69C,CAAC,aAAa,EAAE,mtJAAmtJ,CAAC;IACpuJ,CAAC,YAAY,EAAE,ssPAAssP,CAAC;IACttP,CAAC,YAAY,EAAE,kxFAAkxF,CAAC;CACnyF,CAAC,CAAC"}
@@ -1,2 +1,2 @@
1
- export declare const HSX_VERSION = "5.4.0";
1
+ export declare const HSX_VERSION = "5.4.2";
2
2
  //# sourceMappingURL=version.d.ts.map
@@ -1,2 +1,2 @@
1
- export const HSX_VERSION = "5.4.0";
1
+ export const HSX_VERSION = "5.4.2";
2
2
  //# sourceMappingURL=version.js.map
package/docs/README.md CHANGED
@@ -1,18 +1,107 @@
1
1
  # HSX
2
2
 
3
- A program declares business objects and financial instruments. Objects contain
4
- optional metadata. Attachments expose named actions against an object.
3
+ HSX composes a company's objects, agreements and actions into a typed program.
4
+ A repair approval can change state without moving money. A rental can collect a
5
+ deposit and refund it under declared rules. Headers supply reusable instruments;
6
+ you can also write an instrument with its own fields, lifecycle and actions.
7
+ The compiler emits UDL, the Universal Domain Language contract an executor reads.
8
+ It does not run the business or move money. This release supports SAR only.
9
+
10
+ ## First program
11
+
12
+ The package supplies the `hsx` executable. Save this as `lesson.hsx`:
5
13
 
6
14
  ```hsx
7
- program cars "Cars"
8
- use escrow
9
- object car "Cars" {
10
- fields { make: text, model: text, year: integer }
11
- columns: [make, model, year]
12
- attach sale = escrow.hold { payer: actor, payee: owner, expose fund as sell }
15
+ program tutoring "Tutoring studio"
16
+ use money
17
+ object lesson "Lesson" {
18
+ fields { student: text }
19
+ columns: [student]
20
+ attach payment = money.transfer {
21
+ payer: owner, payee: operator, amount: 150 SAR
22
+ expose create as book_lesson
23
+ expose pay as pay_for_lesson
24
+ expose cancel as cancel_lesson
25
+ }
13
26
  }
14
27
  ```
15
28
 
29
+ An object is the business record. An instrument holds an agreement's state and
30
+ money rules. An attachment connects the instrument to an object kind. A tunable
31
+ is a header parameter, such as `amount`, fixed by this program. An exposed action
32
+ is a public name for an instrument action. Exposing it does not grant permission.
33
+
34
+ ```sh
35
+ hsx check lesson.hsx
36
+ hsx build lesson.hsx --out lesson.udl.json
37
+ hsx cost lesson.hsx
38
+ ```
39
+
40
+ `check` exits zero without output on success. `build` writes canonical UDL;
41
+ without `--out` it prints to stdout. `cost` prints instruction counts, described
42
+ below. `format` prints formatted source or writes it with `--out`. `headers --json`
43
+ prints the header manifest. These commands have no `--strict` or `--catalog` option.
44
+ Exit 1 means invalid source; exit 2 means a command or file error. Diagnostics name
45
+ the source, line, column, code, problem and suggested fix. UDL validation keeps
46
+ its UDL diagnostic codes; binding errors can have names such as
47
+ `subject_party_unbound`. Read the message and fix, not just the code.
48
+
49
+ At runtime, create a lesson object first, then call `book_lesson` to create its
50
+ agreement. Call `pay_for_lesson` on that agreement to move 150 SAR from its bound
51
+ owner to the operator. Object creation alone creates no agreement. Object
52
+ metadata such as `student` is optional until an action requires it. Account IDs
53
+ and party IDs are not metadata supplied by the caller.
54
+
55
+ ## A rental deposit in one hour
56
+
57
+ Open [rental-deposit.hsx](../examples/rental-deposit.hsx). It is a complete source
58
+ file for a business renting equipment from the program operator. Copy it to
59
+ `rental.hsx` and run the same check, build and cost commands against that file.
60
+ No header import is needed because it declares its own instrument.
61
+
62
+ The terms are a 1,000 SAR deposit and a one-time 50 SAR late fee. The supplied
63
+ `dueAt` timestamp is the cutoff: a return before it gets the whole deposit back;
64
+ a return at or after it gets 950 SAR back. The operator receives the other 50 SAR.
65
+ The late fee is not a daily charge and is not `financing.late_charge`, which
66
+ requires a financing plan and an overdue installment.
67
+
68
+ | Step | Public action | Actor and required values | Money effect |
69
+ | ---------------------------- | ----------------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------- |
70
+ | Create the object | Host object creation | Optional `equipment` metadata | None |
71
+ | Agree terms | `agree_rental` | Bound renter; `dueAt`, for example `2027-01-10T12:00:00+03:00`, must be in the future | Creates the agreement's held account |
72
+ | Fund before the cutoff | `pay_deposit` | Bound renter with 1,000 SAR available | Renter pays 1,000 SAR into held |
73
+ | Record an on-time return | `return_equipment` | Operator; `returnReference` metadata | Held pays 1,000 SAR to renter |
74
+ | Or record a late return | `return_equipment_late` | Operator; `returnReference` metadata | Held pays 50 SAR to operator and 950 SAR to renter |
75
+ | Cancel an unfunded agreement | `cancel_rental` | Bound renter, while pending | None |
76
+
77
+ Choose one return action. Both finish the agreement, so the fee and refund cannot
78
+ repeat. The late action calculates the refund from the held balance before either
79
+ move runs. Both paths empty the held account. `returnReference` records the
80
+ operator's return evidence; it does not verify the physical return. Time means
81
+ the executor's current time when the action runs, not a caller-supplied return date.
82
+ A late `due` permits the operator action; it does not schedule that action.
83
+
84
+ This sample binds a declared business named `renter` in Product configuration.
85
+ It uses fixed parties because this compiler rejects parameterized instruments
86
+ inside a program. Changing the renter binding is a Build configuration decision,
87
+ not a different party ID on each request. Use header party parameters bound to
88
+ `owner` or `actor` for per-object participants. Reusable custom headers require a
89
+ host-supplied `StandardLibrary`; `use` cannot load a local file through this CLI.
90
+
91
+ Inspect `objects` in the compiled UDL for the attachment and public names, then
92
+ its instrument for fields, transitions, actors, requirements and ordered moves.
93
+ The `hide deposit.*` lines remove public names from the unattached declaration;
94
+ the attachment exposes its own copy. `money.hold` and `escrow.hold` both refund
95
+ whole amounts, so neither implements this partial-refund policy by itself.
96
+
97
+ A local compile gives you a contract. Executing it needs a host with authenticated
98
+ parties, object actions, funded accounts and a saved Product Build. A Build is the
99
+ frozen contract and configuration used by its agreements. Existing agreements
100
+ keep that Build when the program changes. The package includes no local money
101
+ executor. Compilation cannot establish balances, permissions or provider readiness.
102
+
103
+ ## Objects, metadata and parties
104
+
16
105
  Every attached party parameter binds to `owner`, `actor`, `operator`, a declared
17
106
  business, or a declared staff party with a supported role. Configure declared
18
107
  business participants per Build. Declared person parties cannot bind attachments.
@@ -42,6 +131,8 @@ Creation accepts `{}`. Every normalized field, including adapter requirements,
42
131
  is optional at creation. Only a named action requires its subject metadata.
43
132
  Use `attach` inside the object block to configure its financial instruments.
44
133
 
134
+ ## Headers and tunables
135
+
45
136
  The header defines the available policies. The company chooses percentages, amounts, durations,
46
137
  parties and typed references. `funds: sale` links the stored records through the
47
138
  library's declared reference type. References can name a child, such as
@@ -51,9 +142,14 @@ policy. Its references can point into either plan; selections can span both.
51
142
  A plain `ref<T>` accepts one object only.
52
143
  Tunable constructors are `enum(choices)` and `integer(minimum, maximum)`.
53
144
  Other constructors, including `party(business)` and bounded `money(...)`, are
54
- rejected at the header declaration. Their arguments do not restrict bindings.
145
+ rejected as tunable types. A default selector such as `payer: party = party(person)`
146
+ is different: its type is plain `party`, and the call chooses a default binding.
147
+ Use explicit `payer: owner` or `payer: actor` bindings when the participant comes
148
+ from the object or session.
55
149
  Imports are `use header`; there are no file imports, macros or executable strings.
56
150
 
151
+ ## Values and money
152
+
57
153
  Amounts use `750 SAR`; percentages use `2.5%`; durations use `48h`, `3d`, or `1w`.
58
154
  Dates use `2026-11-28` or a timestamp with an explicit offset. Money has at most two
59
155
  decimal places and percentages at most two. The compiler uses integer minor units
@@ -81,11 +177,6 @@ same book and key within the Product. Providers remain outside parties.
81
177
  A missing binding refuses before money moves. Reference paths such as
82
178
  `self.cover.insurer` use the referenced agreement's account.
83
179
 
84
- Insurance collection pays the premium net of commission to the insurer account
85
- and pays commission separately to the bound broker, which defaults to the operator.
86
- Refunds return those two portions directly from insurer and broker to holder.
87
- Claims reserve from the cover's insurer account. These moves record ledger money;
88
- external confirmation still needs the boundary protocol.
89
180
  `account(buyer, claim, contra, "debt")` declares the borrower's claim contra account.
90
181
  Provider confirmation belongs on a reserved move with `boundary adapter`,
91
182
  followed by instruction-bound evidence and a post or void. External account
@@ -115,6 +206,14 @@ The four transfer instructions are create, reserve, post and void under
115
206
  reversed or voided status. Voided means a released reservation. Settled means
116
207
  provider confirmation, not an internal account balance change.
117
208
 
209
+ ## Authored instruments and actions
210
+
211
+ An action is the business instruction: its actor, state, requirements and effects
212
+ define when it is valid. The executor still checks those conditions on each call.
213
+ The four transfer instructions below that action are its money effects. There is
214
+ no general-purpose `instruction` declaration; `instruction` in an evidence clause
215
+ binds external evidence to a captured boundary instruction.
216
+
118
217
  For a new record type, declare `instrument name { fields { ... } lifecycle { ... }
119
218
  action create { ... } }`. Fields are `money`, `account of buyer`, `ref<order>`,
120
219
  `date`, `duration`, `text`, `integer`, `percent`, `boolean`, `enum(a, b)` or
@@ -146,7 +245,7 @@ maxAge 1d` requires a recent completed provider check.
146
245
  `capture`, `key` and `boundary` modifiers describe a move. `boundary` applies
147
246
  only to reservations. Fees settle with create moves, never reservations. Repeated clauses keep
148
247
  their declaration order. The JSON-like clause form remains accepted and lowers
149
- to the same [UDL clauses](../../udl/spec/README.md).
248
+ to the same [UDL clauses](https://github.com/hyperscale0/hyperscale-udl/blob/main/spec/README.md).
150
249
  They cannot add kernel instructions. `at(list, position)` reads a dated list;
151
250
  `aggregate(selection, "amount")` sums selected money; `ratio(amount, weight, total)`
152
251
  floors a weighted share. `records` declares child types. `invoke` can create a child
@@ -241,25 +340,26 @@ unsupported percentage semantics and repair. They do not change the tunable type
241
340
  UDL refusals retain their UDL codes. A terminal-money refusal includes the owned
242
341
  account and the prover's action path in related diagnostic information.
243
342
 
244
- Build with `hsx build company.hsx --out company.udl.json`; check with
245
- `hsx check company.hsx`; print instruction counts with `hsx cost company.hsx`.
246
- Print the compiler-owned object manifest with `hsx headers --json`.
247
- The compiler API is `compile(source)`. A valid result contains `artifacts.document`,
248
- `costManifest` and source origins. Instruction counts are not bank tariffs or a
249
- promise of provider execution cost.
343
+ ## Instruction cost
250
344
 
251
- The [header inventory](headers.md) is generated from the declarations. The
252
- [object example](../examples/library.hsx) shows authenticated role bindings.
253
- The [playground](../playground/index.html) compiles locally in the browser.
345
+ `hsx cost company.hsx` reports `transfers`, `accounts` and `invocations` per
346
+ instrument action after lowering. Transfers count declared move instructions,
347
+ including reserve, post and void. Accounts count self-owned accounts created by
348
+ `create`, not every party account. Bounded invocations include child costs up to
349
+ the selection limit, so a count is an upper bound rather than observed usage.
350
+ Zero-valued moves can cost fewer actual transfers than their static count.
254
351
 
255
- ## Financing attachments
352
+ The rental attachment's create declares one owned account, fund declares one
353
+ transfer, on-time return one, and late return two. These are counts, not SAR
354
+ prices. The executor's tariff supplies commercial prices and actual usage.
256
355
 
257
- Financing retains its authored borrower and portfolio limits. Bind every party
258
- parameter to a subject role, declared business or staff party with a supported
259
- role, and link the existing escrow and limits attachments.
260
- No limit is inferred from object metadata.
356
+ The compiler API is `compile(source)`. On success, `result.verdict` is `valid`
357
+ and `result.artifacts` contains `document`, `costManifest` and `originMap`.
358
+ On refusal, inspect `result.diagnostics`; no artifact is returned.
261
359
 
262
- See the complete [financing object example](../examples/library.hsx).
360
+ The [header inventory](headers.md) is generated from the declarations. The
361
+ [object example](../examples/library.hsx) shows authenticated role bindings.
362
+ The [playground](../playground/index.html) compiles locally in the browser.
263
363
 
264
364
  ## Standard-library behavior
265
365
 
@@ -281,6 +381,12 @@ adapters are bound, participants have funds, or the flow can finish.
281
381
  | `financing.late_charge` | `fine` is a fixed money amount, not a percentage of overdue principal. |
282
382
  | `cards.card` | `spend_limit` is a per-authorization ceiling, not a monthly aggregate. |
283
383
 
384
+ The financing, collections and reporting samples compose loan agreements; they
385
+ do not supply a complete public repayment path. Insurance and travel also need
386
+ premium-slice records and actions. Savings needs dated contribution records.
387
+ Create aliases in these samples cover the root attachments, not every child
388
+ record. Read each header's creation and lifecycle requirements before execution.
389
+
284
390
  The [lending sample](../examples/lending.hsx) exposes limit approvals, funding and
285
391
  commitment creation, and cash prepare/distribute actions. Its repayment and share
286
392
  child actions still lack a public execution path. It is a composition example,
package/docs/examples.md CHANGED
@@ -13,6 +13,7 @@ Each file is an authored program. Object creation enters no agreement; an attach
13
13
  | [Financed car sales](../examples/library.hsx) | escrow, financing | A minimal financed car sale connects escrow to a three-instalment plan and lending limits. |
14
14
  | [Freelance marketplace](../examples/marketplace.hsx) | marketplace, escrow | Freelancers publish offers and clients place orders with funds held until work is accepted. |
15
15
  | [Tutoring studio](../examples/money.hsx) | money | A tutoring studio collects a fixed fee for each lesson and can cancel unpaid bookings. |
16
+ | [Equipment rental](../examples/rental-deposit.hsx) | | A business rents equipment with a 1000 SAR deposit and a single 50 SAR late fee. On-time return refunds 1000 SAR; late return pays the operator 50 SAR and refunds 950 SAR. |
16
17
  | [Repair approvals](../examples/repair-approval.hsx) | | A repair shop records inspection and approval evidence before it can complete a job. |
17
18
  | [Equipment loan reports](../examples/reporting.hsx) | reporting, financing | An equipment lender keeps an ageing report over its financed purchases and recorded repayments. |
18
19
  | [Savings circle](../examples/savings.hsx) | savings | Six members contribute to a shared pot and receive it in their agreed calendar order. |
@@ -7,23 +7,27 @@ object employee "Employee card" {
7
7
  fields { employeeName: text, department: text }
8
8
  columns: [employeeName, department]
9
9
  attach holder = cards.cardholder {
10
+ expose create as create_holder
10
11
  holder: owner
11
12
  expose activate as activate_employee
12
13
  expose suspend as suspend_employee
13
14
  }
14
15
  attach card = cards.card {
16
+ expose create as create_card
15
17
  holder: holder, spend_limit: 5000 SAR
16
18
  expose activate as activate_card
17
19
  expose freeze as freeze_card
18
20
  expose unfreeze as unfreeze_card
19
21
  }
20
22
  attach payment = cards.authorization {
23
+ expose create as create_payment
21
24
  card: card, merchant: supplier
22
25
  expose approve as approve_payment
23
26
  expose capture as capture_payment
24
27
  expose reverse as reverse_payment
25
28
  }
26
29
  attach receipt = cards.transaction {
30
+ expose create as create_receipt
27
31
  authorization: payment
28
32
  expose refund as refund_payment
29
33
  }
@@ -7,9 +7,10 @@ party agency: business
7
7
  object facility "Business loan" {
8
8
  fields { businessName: text, purpose: text, price: money }
9
9
  columns: [businessName, purpose, price]
10
- attach allowance = financing.limits { borrower: owner, per_borrower: 100000 SAR }
11
- attach budget = financing.portfolio_limit { limit: 2000000 SAR }
10
+ attach allowance = financing.limits { expose create as create_allowance, borrower: owner, per_borrower: 100000 SAR }
11
+ attach budget = financing.portfolio_limit { expose create as create_budget, limit: 2000000 SAR }
12
12
  attach loan = financing.installments {
13
+ expose create as create_loan
13
14
  borrower: owner, capital: operator
14
15
  months: 12, profit: 6%, disburse_to: borrower
15
16
  limits: allowance, portfolio: budget
@@ -17,12 +18,14 @@ object facility "Business loan" {
17
18
  expose disburse as release_loan
18
19
  }
19
20
  attach recovery = collections.case {
21
+ expose create as create_recovery
20
22
  on: loan, agency: agency
21
23
  expose assign as assign_case
22
24
  expose recover as recover_payment
23
25
  expose recall as recall_case
24
26
  }
25
27
  attach contact = collections.contact {
28
+ expose create as create_contact
26
29
  case: recovery, agency: agency
27
30
  }
28
31
  }
@@ -11,6 +11,7 @@ object device "Device" {
11
11
  }
12
12
  columns: [model, condition, price]
13
13
  attach sale = escrow.hold {
14
+ expose create as create_sale
14
15
  payer: actor, payee: owner
15
16
  expose fund as pay_for_device
16
17
  expose deliver as confirm_delivery
@@ -18,5 +19,6 @@ object device "Device" {
18
19
  expose dispute as report_problem
19
20
  expose verify_return as verify_return
20
21
  expose refund as refund_buyer
22
+ expose cancel as cancel_sale
21
23
  }
22
24
  }
@@ -6,14 +6,17 @@ object enrolment "Enrolment" {
6
6
  fields { student: text, course: text, price: money }
7
7
  columns: [student, course, price]
8
8
  attach allowance = financing.limits {
9
+ expose create as create_allowance
9
10
  borrower: owner, per_borrower: 12000 SAR
10
11
  expose approve as approve_student
11
12
  }
12
13
  attach budget = financing.portfolio_limit {
14
+ expose create as create_budget
13
15
  limit: 500000 SAR
14
16
  expose approve as approve_budget
15
17
  }
16
18
  attach tuition = financing.installments {
19
+ expose create as create_tuition
17
20
  borrower: owner, capital: operator
18
21
  months: 3, profit: 0%, disburse_to: borrower
19
22
  limits: allowance, portfolio: budget
@@ -8,16 +8,19 @@ object device "Insured device" {
8
8
  fields { model: text, serialNumber: text, purchaseDate: date }
9
9
  columns: [model, serialNumber, purchaseDate]
10
10
  attach purchase = money.transfer {
11
+ expose create as create_purchase
11
12
  payer: owner, payee: operator
12
13
  expose pay as pay_for_device
13
14
  }
14
15
  // Bind device_insurer to an ADL adapter before creating cover. Premiums net of commission go to its account.
15
16
  attach protection = insurance.cover {
17
+ expose create as create_protection
16
18
  holder: owner, adapter: "device_insurer", commission: 10%, covers: purchase
17
19
  expose activate as activate_cover
18
20
  expose cancel as cancel_cover
19
21
  }
20
22
  attach claim = insurance.claim {
23
+ expose create as create_claim
21
24
  cover: protection, inspector: inspector
22
25
  expose approve as approve_claim
23
26
  expose deny as deny_claim
@@ -9,14 +9,17 @@ object business "Business funding" {
9
9
  fields { businessName: text, purpose: text, price: money }
10
10
  columns: [businessName, purpose, price]
11
11
  attach allowance = financing.limits {
12
+ expose create as create_allowance
12
13
  borrower: owner, per_borrower: 100000 SAR
13
14
  expose approve as approve_borrower
14
15
  }
15
16
  attach budget = financing.portfolio_limit {
17
+ expose create as create_budget
16
18
  limit: 2000000 SAR
17
19
  expose approve as approve_budget
18
20
  }
19
21
  attach loan = financing.installments {
22
+ expose create as create_loan
20
23
  borrower: owner, capital: operator
21
24
  months: 12, profit: 6%, disburse_to: borrower
22
25
  limits: allowance, portfolio: budget
@@ -24,6 +27,7 @@ object business "Business funding" {
24
27
  expose disburse as release_loan
25
28
  }
26
29
  attach investor_balance = wallet.balance {
30
+ expose create as create_investor_balance
27
31
  holder: actor
28
32
  expose activate as open_wallet
29
33
  expose topup as add_funds
@@ -39,6 +43,7 @@ object business "Business funding" {
39
43
  expose withdraw as withdraw_investment
40
44
  }
41
45
  attach returns = lending.distribution {
46
+ expose create as create_returns
42
47
  round: funding, receipt: loan.settlement
43
48
  expose prepare_cash as prepare_returns
44
49
  expose distribute_cash as distribute_returns
@@ -4,9 +4,9 @@ use escrow
4
4
  use financing
5
5
  object car "Cars" {
6
6
  fields { make: text, model: text, year: integer }
7
- attach sale = escrow.hold { payer: actor, payee: owner, expose fund as sell }
8
- attach limits = financing.limits { borrower: actor, per_borrower: 60000 SAR }
9
- attach ceiling = financing.portfolio_limit { limit: 1500000 SAR }
7
+ attach sale = escrow.hold { expose create as create_sale, payer: actor, payee: owner, expose fund as sell }
8
+ attach limits = financing.limits { expose create as create_limits, borrower: actor, per_borrower: 60000 SAR }
9
+ attach ceiling = financing.portfolio_limit { expose create as create_ceiling, limit: 1500000 SAR }
10
10
  attach plan = financing.installments {
11
11
  borrower: actor, capital: operator, share: 25%
12
12
  months: 3, profit: 2.5%, funds: sale, limits: limits, portfolio: ceiling
@@ -7,20 +7,26 @@ object project "Project" {
7
7
  fields { brief: text, deliverable: text, price: money }
8
8
  columns: [brief, deliverable, price]
9
9
  attach offer = marketplace.listing {
10
+ expose create as create_offer
10
11
  seller: owner
11
12
  expose publish as publish_offer
12
13
  expose withdraw as withdraw_offer
13
14
  }
14
15
  attach order = marketplace.order {
16
+ expose create as create_order
15
17
  listing: offer, buyer: actor
16
18
  expose commit as place_order
17
19
  expose fulfill as finish_order
18
20
  }
19
21
  attach payment = escrow.hold {
22
+ expose create as create_payment
20
23
  payer: actor, payee: owner
21
24
  expose fund as fund_project
22
25
  expose deliver as submit_work
23
26
  expose accept as accept_work
24
27
  expose dispute as dispute_work
28
+ expose verify_return as verify_return
29
+ expose refund as refund_client
30
+ expose cancel as cancel_payment
25
31
  }
26
32
  }
@@ -10,6 +10,7 @@ object lesson "Lesson" {
10
10
  }
11
11
  columns: [student, tutor, startsAt]
12
12
  attach payment = money.transfer {
13
+ expose create as create_payment
13
14
  payer: actor, payee: operator, amount: 150 SAR
14
15
  expose pay as pay_for_lesson
15
16
  expose cancel as cancel_payment
@@ -0,0 +1,60 @@
1
+ // A business rents equipment with a 1000 SAR deposit and a single 50 SAR late fee.
2
+ // On-time return refunds 1000 SAR; late return pays the operator 50 SAR and refunds 950 SAR.
3
+ program equipment_rental "Equipment rental"
4
+ party renter: business
5
+
6
+ // Program-local instruments have fixed terms and parties, not tunable parameters.
7
+ instrument deposit {
8
+ summary: "Hold a rental deposit, then return it less any fixed late fee."
9
+ fields {
10
+ renter: account of renter
11
+ held: account of self
12
+ amount: money = 1000 SAR
13
+ lateFee: money = 50 SAR
14
+ dueAt: date
15
+ refund: money?
16
+ }
17
+ lifecycle { states: [pending, funded, returned, cancelled], initial: pending }
18
+ action create {
19
+ actor: { party: renter }
20
+ requires self.dueAt > self.now
21
+ }
22
+ action fund {
23
+ from: pending, to: funded, actor: { party: renter }
24
+ deadline: { at: self.dueAt }
25
+ moves self.amount from self.renter to self.held
26
+ }
27
+ action return_on_time {
28
+ from: funded, to: returned, actor: { party: programOperator }
29
+ deadline: { at: self.dueAt }
30
+ subject { returnReference: text }
31
+ moves self.held.balance from self.held to self.renter
32
+ }
33
+ action return_late {
34
+ from: funded, to: returned, actor: { party: programOperator }
35
+ due: { at: self.dueAt }
36
+ subject { returnReference: text }
37
+ calculate: [{ target: refund, op: subtract, base: { field: self.held.balance }, subtract: [{ field: self.lateFee }] }]
38
+ moves self.lateFee from self.held to programOperator
39
+ moves self.refund from self.held to self.renter
40
+ }
41
+ action cancel { from: pending, to: cancelled, actor: { party: renter } }
42
+ }
43
+
44
+ object rental "Equipment rental" {
45
+ fields { equipment: text }
46
+ columns: [equipment, dueAt]
47
+ attach security = deposit {
48
+ expose create as agree_rental
49
+ expose fund as pay_deposit
50
+ expose return_on_time as return_equipment
51
+ expose return_late as return_equipment_late
52
+ expose cancel as cancel_rental
53
+ }
54
+ }
55
+
56
+ hide deposit.create
57
+ hide deposit.fund
58
+ hide deposit.return_on_time
59
+ hide deposit.return_late
60
+ hide deposit.cancel
@@ -29,6 +29,7 @@ object repair "Repair" {
29
29
  fields { item: text, problem: text }
30
30
  columns: [item, problem]
31
31
  attach review = assessment {
32
+ expose create as create_review
32
33
  expose inspect as inspect_repair
33
34
  expose approve as approve_repair
34
35
  expose reject as reject_repair
@@ -7,19 +7,22 @@ object purchase "Equipment loan" {
7
7
  fields { businessName: text, equipment: text, price: money }
8
8
  columns: [businessName, equipment, price]
9
9
  attach allowance = financing.limits {
10
+ expose create as create_allowance
10
11
  borrower: owner, per_borrower: 200000 SAR
11
12
  expose approve as approve_business
12
13
  }
13
14
  attach budget = financing.portfolio_limit {
15
+ expose create as create_budget
14
16
  limit: 5000000 SAR
15
17
  expose approve as approve_budget
16
18
  }
17
19
  attach loan = financing.installments {
20
+ expose create as create_loan
18
21
  borrower: owner, capital: operator
19
22
  months: 12, profit: 6%, disburse_to: borrower
20
23
  limits: allowance, portfolio: budget
21
24
  expose sign as sign_purchase_loan
22
25
  expose disburse as fund_purchase
23
26
  }
24
- attach reports = reporting.portfolio { on: loan }
27
+ attach reports = reporting.portfolio { expose create as create_reports, on: loan }
25
28
  }
@@ -6,11 +6,13 @@ object group "Savings group" {
6
6
  fields { groupName: text, purpose: text }
7
7
  columns: [groupName, purpose]
8
8
  attach circle = savings.circle {
9
+ expose create as create_circle
9
10
  contribution: 500 SAR, members: 6, starts: 2027-01-01
10
11
  expose disband as disband_circle
11
12
  expose close as close_circle
12
13
  }
13
14
  attach membership = savings.membership {
15
+ expose create as create_membership
14
16
  circle: circle, member: actor
15
17
  expose activate as confirm_membership
16
18
  expose withdraw as leave_circle
@@ -6,9 +6,9 @@ use collections
6
6
  object car "Car" {
7
7
  fields { make: text, model: text, year: integer, vin: text, price: money }
8
8
  columns: [make, model, year, vin, price]
9
- attach sale = escrow.hold { payer: actor, payee: operator, expose fund as purchase }
10
- attach limits = financing.limits { borrower: actor, per_borrower: 250000 SAR }
11
- attach ceiling = financing.portfolio_limit { limit: 10000000 SAR }
9
+ attach sale = escrow.hold { expose create as create_sale, payer: actor, payee: operator, expose fund as purchase }
10
+ attach limits = financing.limits { expose create as create_limits, borrower: actor, per_borrower: 250000 SAR }
11
+ attach ceiling = financing.portfolio_limit { expose create as create_ceiling, limit: 10000000 SAR }
12
12
  attach plan = financing.installments {
13
13
  borrower: actor, capital: operator
14
14
  months: 36, profit: 8.5%, down_payment: 10%
@@ -17,8 +17,9 @@ object car "Car" {
17
17
  expose create as finance, expose sign as sign_contract, expose payoff as payoff
18
18
  }
19
19
  attach late = financing.late_charge {
20
+ expose create as create_late
20
21
  on: plan, grace: 3d, fine: 50 SAR, cap: 25 SAR
21
22
  fines_to: operator, costs_to: operator, borrower: actor
22
23
  }
23
- attach reminders = collections.reminder { on: plan, operator: operator, before_days: 3, overdue_days: 1 }
24
+ attach reminders = collections.reminder { expose create as create_reminders, on: plan, operator: operator, before_days: 3, overdue_days: 1 }
24
25
  }
@@ -8,15 +8,18 @@ object holiday "Holiday booking" {
8
8
  fields { destination: text, leadTraveller: text }
9
9
  columns: [destination, leadTraveller]
10
10
  attach trip = travel.package {
11
+ expose create as create_trip
11
12
  price: 5000 SAR, supplier_cost: 3500 SAR, departure: 2027-07-01
12
13
  expose publish as publish_trip
13
14
  }
14
15
  // Bind travel_insurer to an ADL adapter before creating cover. Premiums net of commission go to its account.
15
16
  attach protection = insurance.cover {
17
+ expose create as create_protection
16
18
  holder: actor, adapter: "travel_insurer", commission: 10%, covers: reservation
17
19
  expose activate as activate_cover
18
20
  }
19
21
  attach reservation = travel.booking {
22
+ expose create as create_reservation
20
23
  package: trip, buyer: actor, supplier: hotel, cover: protection
21
24
  expose deposit as pay_deposit
22
25
  expose balance as pay_balance
@@ -6,6 +6,7 @@ object membership "Membership" {
6
6
  fields { memberName: text, membershipNumber: text }
7
7
  columns: [memberName, membershipNumber]
8
8
  attach balance = wallet.balance {
9
+ expose create as create_balance
9
10
  holder: owner
10
11
  expose activate as open_balance
11
12
  expose topup as add_credit
@@ -13,6 +14,7 @@ object membership "Membership" {
13
14
  expose close as close_balance
14
15
  }
15
16
  attach visit = wallet.spend {
17
+ expose create as create_visit
16
18
  wallet: balance, payee: operator
17
19
  expose reserve as reserve_visit
18
20
  expose pay as charge_visit
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperscale0/hsx",
3
- "version": "5.4.0",
3
+ "version": "5.4.2",
4
4
  "description": "The strictly typed HSX language: compile total financial programs into canonical UDL.",
5
5
  "keywords": [
6
6
  "hsx",
@@ -86,7 +86,7 @@
86
86
  },
87
87
  "dependencies": {
88
88
  "@hyperscale0/adl": "1.0.0-beta.8",
89
- "@hyperscale0/udl": "4.5.0",
89
+ "@hyperscale0/udl": "4.6.0",
90
90
  "fast-sha256": "1.3.0"
91
91
  },
92
92
  "devDependencies": {
@@ -98,5 +98,5 @@
98
98
  "Amir Ayub",
99
99
  "Sara AlBakaawi"
100
100
  ],
101
- "gitHead": "4141f2296d9427b30d04933c735be4af1ba88dec"
101
+ "gitHead": "bb10d3ee33343ddd5a4328401f25177cd46be9f6"
102
102
  }