@hyperscale0/hsx 5.4.2 → 5.6.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/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const HSX_VERSION = "5.4.2";
1
+ export const HSX_VERSION = "5.6.0";
@@ -1,5 +1,8 @@
1
1
  header collections
2
2
 
3
+ // Economics: Company capital pays agencies as participant payouts; outside capital passes through.
4
+ // A company agency earns outside capital fees; its own capital fee is internal.
5
+
3
6
  // Expose case.create, assign and recover as separate steps. Creation needs overdue
4
7
  // outstanding principal and a matching slice/plan. Assignment belongs to capital;
5
8
  // recovery belongs to agency and pays the linked payment before the agency fee.
@@ -28,7 +31,7 @@ instrument case(on: ref<financing.installments>[], agency: party, capital: party
28
31
  }
29
32
  action assign { from: opened, to: assigned, actor: { party: capital } }
30
33
  action recover { expansionLimit: 8192, 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: {} }] }
31
- action pay_fee { allowZero: true, from: recovered, to: recovered, actor: { parent: current() }, moves self.agencyFee from self.plan.capital to agency }
34
+ action pay_fee { allowZero: true, from: recovered, to: recovered, actor: { parent: current() }, moves self.agencyFee from self.plan.capital to agency economics { recipient: agency, company: { recipient: capital, company: { purpose: internal, sourceParty: capital }, participant: { purpose: earning, sourceParty: capital } }, participant: { recipient: capital, company: { purpose: participant_payout, sourceParty: capital }, participant: { purpose: pass_through, sourceParty: capital } } } }
32
35
  action recall { from: [opened, assigned], to: recalled, actor: { party: capital } }
33
36
  action return_uncollected { from: assigned, to: returned_uncollected, actor: { party: agency } }
34
37
  }
package/std/escrow.hsx CHANGED
@@ -1,5 +1,8 @@
1
1
  header escrow
2
2
 
3
+ // Economics: Funding and unspent returns are principal. Acceptance realizes earnings for
4
+ // the company or a payout to a bound outside seller; tax is pass-through.
5
+
3
6
  // Expose create, fund, deliver and accept for the purchase path. Create captures
4
7
  // subject.price; acceptance pays payee less the configured fee, not payer.
5
8
  // Expose dispute, verify_return and refund separately for the return path.
@@ -31,7 +34,7 @@ instrument hold(payer: party = party(person), payee: party = programOperator, ac
31
34
  action fund {
32
35
  from: pending, to: funded, actor: { party: payer }
33
36
  subject { price: money }
34
- moves self.price from payer to self.held
37
+ moves self.price from payer to self.held economics { purpose: principal, sourceParty: payer }
35
38
  }
36
39
  action confirm {
37
40
  from: pending, to: funded
@@ -45,7 +48,7 @@ instrument hold(payer: party = party(person), payee: party = programOperator, ac
45
48
  from: delivered, to: released, actor: { party: payer }
46
49
  input { acceptanceReference: text }
47
50
  deadline: { at: self.deliveredAt, offset: accept_within }
48
- moves self.price from self.held to payee fee fee
51
+ moves self.price from self.held to payee fee fee economics { payee: { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: participant_payout, sourceParty: programOperator } }, fee: { purpose: earning, sourceParty: payer }, tax: { purpose: pass_through, sourceParty: programOperator } }
49
52
  }
50
53
  action expire_acceptance {
51
54
  from: delivered, to: disputed, actor: clock
@@ -61,10 +64,10 @@ instrument hold(payer: party = party(person), payee: party = programOperator, ac
61
64
  }
62
65
  action refund {
63
66
  from: dispute.refund_after, to: refunded, actor: { party: payee }
64
- moves self.price from self.held to payer
67
+ moves self.price from self.held to payer economics { purpose: principal, sourceParty: programOperator }
65
68
  }
66
69
  action cancel { allowZero: true,
67
70
  from: pending, to: cancelled, actor: { party: payer }
68
- moves self.held.balance from self.held to payer
71
+ moves self.held.balance from self.held to payer economics { purpose: principal, sourceParty: programOperator }
69
72
  }
70
73
  }
package/std/financing.hsx CHANGED
@@ -1,5 +1,10 @@
1
1
  header financing
2
2
 
3
+ // Economics: Principal advances and repayments are excluded from earnings. Claims, waivers,
4
+ // write-offs and allocations are internal. Paid profit and company charges are
5
+ // earnings; receipt refunds reverse captured cash. Outside recovery recipients
6
+ // receive payouts from held company cash, or pass-through direct customer cash.
7
+
3
8
  // Expose create and sign on installments, then collect_down_payment as checkout
4
9
  // for disburse_to: funds. Checkout requires a signed plan and pending escrow;
5
10
  // it tops up only the missing down payment, without advancing lender principal.
@@ -68,7 +73,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
68
73
  when disburse_to is funds {
69
74
  requires self.funds in [pending]
70
75
  calculate: [{ target: downPaymentCredit, op: minimum, values: [{ field: self.funds.held.balance }, { field: self.downPayment }] }, { target: downPaymentRemaining, op: subtract, base: { field: self.downPayment }, subtract: [{ field: self.downPaymentCredit }] }]
71
- moves self.downPaymentRemaining from self.borrower to self.funds.held
76
+ moves self.downPaymentRemaining from self.borrower to self.funds.held economics { purpose: principal, sourceParty: borrower }
72
77
  }
73
78
  }
74
79
  action disburse { allowZero: true,
@@ -79,7 +84,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
79
84
  requires self.funds in [pending]
80
85
  invoke: [{ reference: self.id, action: fund_down_payment, input: {} }]
81
86
  }
82
- when disburse_to is borrower { moves self.principal from self.capital to self.borrower }
87
+ when disburse_to is borrower { moves self.principal from self.capital to self.borrower economics { purpose: principal, sourceParty: capital } }
83
88
  invoke: [{ selection: { instrument: slice, reference: "plan", anchor: self.id, states: [draft], limit: 366, order: [position] }, action: activate, input: {} }]
84
89
  when disburse_to is funds { invoke: [{ reference: self.funds, action: confirm, input: {} }] }
85
90
  }
@@ -87,8 +92,8 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
87
92
  from: active, to: active, actor: { parent: current() }
88
93
  when disburse_to is funds {
89
94
  calculate: [{ target: downPaymentCredit, op: minimum, values: [{ field: self.funds.held.balance }, { field: self.downPayment }] }, { target: downPaymentRemaining, op: subtract, base: { field: self.downPayment }, subtract: [{ field: self.downPaymentCredit }] }]
90
- moves self.downPaymentRemaining from self.funds.payer to self.funds.held
91
- moves self.principal from self.capital to self.funds.held
95
+ moves self.downPaymentRemaining from self.funds.payer to self.funds.held economics { purpose: principal, sourceParty: borrower }
96
+ moves self.principal from self.capital to self.funds.held economics { purpose: principal, sourceParty: capital }
92
97
  }
93
98
  }
94
99
  action complete {
@@ -233,11 +238,11 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
233
238
  input { plan: ref<parent>, identity: text, principal: money, profit: money, loss: money, kind: enum(cash, loss) }
234
239
  requires unique "settlement_identity" on [self.plan, self.identity]
235
240
  calculate: [{ target: "share", op: "rate", base: { field: self.profit }, bps: { literal: share }, rounding: "floor" }, { target: retainedProfit, op: "subtract", base: { field: self.profit }, subtract: [{ field: self.share }] }]
236
- moves self.share from self.profitIncome to self.allocatedPayable
241
+ moves self.share from self.profitIncome to self.allocatedPayable economics { purpose: internal, sourceParty: capital }
237
242
  }
238
243
  action refund { allowZero: true,
239
244
  from: recorded, to: refunded, actor: { parent: payment }
240
- moves self.share from self.allocatedPayable to self.profitIncome
245
+ moves self.share from self.allocatedPayable to self.profitIncome economics { purpose: internal, sourceParty: capital }
241
246
  }
242
247
  }
243
248
  slice: {
@@ -303,9 +308,9 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
303
308
  }
304
309
  action activate { allowZero: true,
305
310
  from: draft, to: pending, actor: { parent: parent }
306
- moves self.principal from self.debt to self.principalReceivable
307
- moves self.profit from self.debt to self.profitReceivable
308
- when profit_earned is at_disbursement { moves self.profit from self.profitReceivable to self.profitEarned }
311
+ moves self.principal from self.debt to self.principalReceivable economics { purpose: internal, sourceParty: borrower }
312
+ moves self.profit from self.debt to self.profitReceivable economics { purpose: internal, sourceParty: borrower }
313
+ when profit_earned is at_disbursement { moves self.profit from self.profitReceivable to self.profitEarned economics { purpose: internal, sourceParty: programOperator } }
309
314
  when profit_earned is by_schedule { invoke: [{ instrument: recognition, action: create, input: { slice: { field: self.id } } }] }
310
315
  }
311
316
  action mature {
@@ -370,15 +375,15 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
370
375
  from: [pending, due], to: paid, actor: { parent: parent }, input { identity: text }
371
376
  set: { payoffIdentity: { field: input.identity } }
372
377
  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 }] }]
373
- moves self.principalReceivable.balance from self.plan.borrower to self.plan.capital
374
- moves self.payoffProfit from self.plan.borrower to self.plan.profitIncome
375
- moves self.principalReceivable.balance from self.principalReceivable to self.debt
376
- moves self.profitReceivable.balance from self.profitReceivable to self.debt
377
- moves self.profitEarned.balance from self.profitEarned to self.debt
378
+ moves self.principalReceivable.balance from self.plan.borrower to self.plan.capital economics { purpose: principal, sourceParty: borrower }
379
+ moves self.payoffProfit from self.plan.borrower to self.plan.profitIncome economics { recipient: capital, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: borrower } }
380
+ moves self.principalReceivable.balance from self.principalReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }
381
+ moves self.profitReceivable.balance from self.profitReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }
382
+ moves self.profitEarned.balance from self.profitEarned to self.debt economics { purpose: internal, sourceParty: programOperator }
378
383
  }
379
384
  action write_off { allowZero: true,
380
385
  from: [pending, due], to: written_off, actor: { parent: parent }
381
- 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
386
+ moves self.principalReceivable.balance from self.principalReceivable to self.loss economics { purpose: internal, sourceParty: programOperator }; moves self.profitReceivable.balance from self.profitReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }; moves self.profitEarned.balance from self.profitEarned to self.loss economics { purpose: internal, sourceParty: programOperator }
382
387
  }
383
388
  }
384
389
  recognition: {
@@ -386,7 +391,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
386
391
  lifecycle { states: [pending, recognised], initial: pending }
387
392
  action create { actor: { parent: slice }, input { slice: ref<slice> }, requires unique "profit_recognition" on [self.slice] }
388
393
  action reschedule { from: pending, to: pending, actor: { parent: slice }, calculate: [{ target: dueAt, op: shift, date: { field: self.slice.dueAt }, milliseconds: { literal: 0 }, direction: after }] }
389
- action mature { allowZero: true, from: pending, to: recognised, actor: clock, due: { at: self.dueAt }, moves self.slice.profitReceivable.balance from self.slice.profitReceivable to self.slice.profitEarned }
394
+ action mature { allowZero: true, from: pending, to: recognised, actor: clock, due: { at: self.dueAt }, moves self.slice.profitReceivable.balance from self.slice.profitReceivable to self.slice.profitEarned economics { purpose: internal, sourceParty: programOperator } }
390
395
  }
391
396
  payment: {
392
397
  revisioned: true
@@ -408,7 +413,7 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
408
413
  when apply is principal_profit { calculate: [{ target: outstandingTotal, op: sum, values: [{ field: self.outstandingPrincipal }, { field: self.outstandingProfit }] }] }
409
414
  when apply is pro_rata { calculate: [{ target: outstandingTotal, op: sum, values: [{ field: self.outstandingPrincipal }, { field: self.outstandingProfit }] }] }
410
415
  requires self.plan in [active]; requires self.amount <= self.outstandingTotal
411
- moves self.amount from self.plan.borrower to self.held
416
+ moves self.amount from self.plan.borrower to self.held economics { purpose: principal, sourceParty: borrower }
412
417
  when apply is principal_profit {
413
418
  invoke: [{ selection: { instrument: slice, reference: "plan", anchor: self.plan, states: [pending, due], limit: 366, order: [position] }, action: collect, guard: { kind: compare, left: { field: self.held.balance }, operator: ">", right: { literal: "0" } }, input: { payment: { field: self.id } } }]
414
419
  }
@@ -445,32 +450,32 @@ instrument installments(months: integer(1, 366), charge_limit: integer(1, 3) = 3
445
450
  actor: { parent: slice }
446
451
  input { slice: ref<slice>, payment: ref<payment>, limit: money }
447
452
  requires unique "principal_receipt" on [self.slice, self.payment]
448
- moves self.amount from self.payment.held to self.slice.plan.capital; moves self.amount from self.slice.principalReceivable to self.slice.debt
453
+ moves self.amount from self.payment.held to self.slice.plan.capital economics { purpose: principal, sourceParty: programOperator }; moves self.amount from self.slice.principalReceivable to self.slice.debt economics { purpose: internal, sourceParty: programOperator }
449
454
  }
450
455
  action refund { allowZero: true,
451
456
  from: paid, to: refunded, actor: { parent: payment }
452
- moves self.amount from self.slice.plan.capital to self.slice.plan.borrower; moves self.amount from self.slice.debt to self.slice.principalReceivable
457
+ moves self.amount from self.slice.plan.capital to self.slice.plan.borrower economics { purpose: principal, sourceParty: capital }; moves self.amount from self.slice.debt to self.slice.principalReceivable economics { purpose: internal, sourceParty: borrower }
453
458
  }
454
459
  }
455
460
  profit_piece: {
456
- fields { slice: ref<slice>, payment: ref<payment>, limit: money, amount: money? }
461
+ fields { cashReceipt: text?, slice: ref<slice>, payment: ref<payment>, limit: money, amount: money? }
457
462
  lifecycle { states: [paid, refunded], initial: paid }
458
463
  action create { allowZero: true,
459
464
  calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.limit }] }]
460
465
  actor: { parent: slice }
461
466
  input { slice: ref<slice>, payment: ref<payment>, limit: money }
462
467
  requires unique "profit_receipt" on [self.slice, self.payment]
463
- moves self.amount from self.payment.held to self.slice.plan.profitIncome
464
- when profit_earned is on_payment { moves self.amount from self.slice.profitReceivable to self.slice.debt }
465
- when profit_earned is by_schedule { moves self.amount from self.slice.profitEarned to self.slice.debt }
466
- when profit_earned is at_disbursement { moves self.amount from self.slice.profitEarned to self.slice.debt }
468
+ moves self.amount from self.payment.held to self.slice.plan.profitIncome capture "cashReceipt" economics { recipient: capital, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: participant_payout, sourceParty: programOperator } }
469
+ when profit_earned is on_payment { moves self.amount from self.slice.profitReceivable to self.slice.debt economics { purpose: internal, sourceParty: programOperator } }
470
+ when profit_earned is by_schedule { moves self.amount from self.slice.profitEarned to self.slice.debt economics { purpose: internal, sourceParty: programOperator } }
471
+ when profit_earned is at_disbursement { moves self.amount from self.slice.profitEarned to self.slice.debt economics { purpose: internal, sourceParty: programOperator } }
467
472
  }
468
473
  action refund { allowZero: true,
469
474
  from: paid, to: refunded, actor: { parent: payment }
470
- moves self.amount from self.slice.plan.profitIncome to self.slice.plan.borrower
471
- when profit_earned is on_payment { moves self.amount from self.slice.debt to self.slice.profitReceivable }
472
- when profit_earned is by_schedule { moves self.amount from self.slice.debt to self.slice.profitEarned }
473
- when profit_earned is at_disbursement { moves self.amount from self.slice.debt to self.slice.profitEarned }
475
+ moves self.amount from self.slice.plan.profitIncome to self.slice.plan.borrower economics { recipient: capital, company: { purpose: earning, sourceParty: capital, reversalOf: self.cashReceipt }, participant: unclassified }
476
+ when profit_earned is on_payment { moves self.amount from self.slice.debt to self.slice.profitReceivable economics { purpose: internal, sourceParty: borrower } }
477
+ when profit_earned is by_schedule { moves self.amount from self.slice.debt to self.slice.profitEarned economics { purpose: internal, sourceParty: borrower } }
478
+ when profit_earned is at_disbursement { moves self.amount from self.slice.debt to self.slice.profitEarned economics { purpose: internal, sourceParty: borrower } }
474
479
  }
475
480
  }
476
481
  }
@@ -496,7 +501,7 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
496
501
  action assess { allowZero: true,
497
502
  from: proposed, to: assessed, actor: clock, due: { at: self.overdueAt }
498
503
  requires self.slice.principalReceivable.balance > "0"
499
- moves self.fine from self.debt to self.receivable
504
+ moves self.fine from self.debt to self.receivable economics { purpose: internal, sourceParty: borrower }
500
505
  }
501
506
  action collect {
502
507
  from: [assessed, collected], to: assessed, actor: { parent: child(on, slice) }, input { payment: ref<on.payment> }
@@ -507,8 +512,8 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
507
512
  action payoff { allowZero: true,
508
513
  from: [assessed, collected], to: collected, actor: { parent: on }
509
514
  requires self.plan in [paid]
510
- moves self.receivable.balance from self.plan.borrower to fines_to
511
- moves self.receivable.balance from self.receivable to self.debt
515
+ moves self.receivable.balance from self.plan.borrower to fines_to economics { recipient: fines_to, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: borrower } }
516
+ moves self.receivable.balance from self.receivable to self.debt economics { purpose: internal, sourceParty: programOperator }
512
517
  }
513
518
  action finish { from: assessed, to: collected, actor: { parent: current() }, requires self.receivable.balance == "0" }
514
519
  action cancel { from: proposed, to: waived }
@@ -517,7 +522,7 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
517
522
  requires input.amendment.plan == self.plan; requires input.amendment in [applied]
518
523
  invoke: [{ instrument: waiver, action: create, input: { assessment: { field: self.id }, amendment: { field: input.amendment } } }]
519
524
  }
520
- action waive { allowZero: true, from: [assessed, collected], to: waived, actor: { parent: waiver_request }, input { reason: text, evidence: text }, moves self.receivable.balance from self.receivable to self.debt }
525
+ action waive { allowZero: true, from: [assessed, collected], to: waived, actor: { parent: waiver_request }, input { reason: text, evidence: text }, moves self.receivable.balance from self.receivable to self.debt economics { purpose: internal, sourceParty: programOperator } }
521
526
  action refund {
522
527
  from: [assessed, collected], to: assessed, actor: { party: fines_to }, input { payment: ref<on.payment> }
523
528
  requires input.payment in [paid, refunded]
@@ -542,14 +547,14 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
542
547
  actor: { parent: parent }, input { assessment: ref<parent>, amendment: ref<on.amendment> }
543
548
  calculate: [{ target: amount, op: rate, base: { field: self.assessment.receivable.balance }, bps: { field: self.amendment.waiverPercent }, rounding: floor }]
544
549
  requires unique "amendment_waiver" on [self.assessment, self.amendment]
545
- moves self.amount from self.assessment.receivable to self.assessment.debt
550
+ moves self.amount from self.assessment.receivable to self.assessment.debt economics { purpose: internal, sourceParty: programOperator }
546
551
  }
547
552
  }
548
553
  receipt: {
549
- fields { assessment: ref<parent>, payment: ref<on.payment>, amount: money? }
554
+ fields { cashReceipt: text?, assessment: ref<parent>, payment: ref<on.payment>, amount: money? }
550
555
  lifecycle { states: [paid, refunded], initial: paid }
551
- action create { allowZero: true, calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.assessment.receivable.balance }] }], 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 }
552
- action refund { allowZero: true, 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 }
556
+ action create { allowZero: true, calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.assessment.receivable.balance }] }], 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 capture "cashReceipt" economics { recipient: fines_to, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: participant_payout, sourceParty: programOperator } }; moves self.amount from self.assessment.receivable to self.assessment.debt economics { purpose: internal, sourceParty: programOperator } }
557
+ action refund { allowZero: true, from: paid, to: refunded, actor: { parent: parent }, moves self.amount from fines_to to self.payment.plan.borrower economics { recipient: fines_to, company: { purpose: earning, sourceParty: fines_to, reversalOf: self.cashReceipt }, participant: unclassified }; moves self.amount from self.assessment.debt to self.assessment.receivable economics { purpose: internal, sourceParty: borrower } }
553
558
  }
554
559
 
555
560
  cost: {
@@ -563,7 +568,7 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
563
568
  action assess { allowZero: true,
564
569
  from: proposed, to: assessed, actor: clock, due: { at: self.assessment.overdueAt }
565
570
  requires self.assessment.slice.principalReceivable.balance > "0"
566
- moves self.amount from self.debt to self.receivable
571
+ moves self.amount from self.debt to self.receivable economics { purpose: internal, sourceParty: borrower }
567
572
  }
568
573
  action collect {
569
574
  from: [assessed, collected], to: assessed, actor: { parent: child(on, slice) }, input { payment: ref<on.payment> }
@@ -574,8 +579,8 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
574
579
  action payoff { allowZero: true,
575
580
  from: [assessed, collected], to: collected, actor: { parent: on }
576
581
  requires self.plan in [paid]
577
- moves self.receivable.balance from self.plan.borrower to costs_to
578
- moves self.receivable.balance from self.receivable to self.debt
582
+ moves self.receivable.balance from self.plan.borrower to costs_to economics { recipient: costs_to, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: borrower } }
583
+ moves self.receivable.balance from self.receivable to self.debt economics { purpose: internal, sourceParty: programOperator }
579
584
  }
580
585
  action finish { from: assessed, to: collected, actor: { parent: current() }, requires self.receivable.balance == "0" }
581
586
  action cancel { from: proposed, to: waived }
@@ -584,7 +589,7 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
584
589
  requires input.amendment.plan == self.plan; requires input.amendment in [applied]
585
590
  invoke: [{ instrument: waiver, action: create, input: { assessment: { field: self.id }, amendment: { field: input.amendment } } }]
586
591
  }
587
- action waive { allowZero: true, from: [assessed, collected], to: waived, actor: { parent: waiver_request }, input { reason: text, evidence: text }, moves self.receivable.balance from self.receivable to self.debt }
592
+ action waive { allowZero: true, from: [assessed, collected], to: waived, actor: { parent: waiver_request }, input { reason: text, evidence: text }, moves self.receivable.balance from self.receivable to self.debt economics { purpose: internal, sourceParty: programOperator } }
588
593
  action refund {
589
594
  from: [assessed, collected], to: assessed, actor: { party: costs_to }, input { payment: ref<on.payment> }
590
595
  requires input.payment in [paid, refunded]
@@ -609,14 +614,14 @@ instrument late_charge(on: ref<financing.installments>[], grace: duration = 3d,
609
614
  actor: { parent: parent }, input { assessment: ref<parent>, amendment: ref<on.amendment> }
610
615
  calculate: [{ target: amount, op: rate, base: { field: self.assessment.receivable.balance }, bps: { field: self.amendment.waiverPercent }, rounding: floor }]
611
616
  requires unique "amendment_waiver" on [self.assessment, self.amendment]
612
- moves self.amount from self.assessment.receivable to self.assessment.debt
617
+ moves self.amount from self.assessment.receivable to self.assessment.debt economics { purpose: internal, sourceParty: programOperator }
613
618
  }
614
619
  }
615
620
  receipt: {
616
- fields { assessment: ref<parent>, payment: ref<on.payment>, amount: money? }
621
+ fields { cashReceipt: text?, assessment: ref<parent>, payment: ref<on.payment>, amount: money? }
617
622
  lifecycle { states: [paid, refunded], initial: paid }
618
- action create { allowZero: true, calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.assessment.receivable.balance }] }], 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 }
619
- action refund { allowZero: true, 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 }
623
+ action create { allowZero: true, calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.assessment.receivable.balance }] }], 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 capture "cashReceipt" economics { recipient: costs_to, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: participant_payout, sourceParty: programOperator } }; moves self.amount from self.assessment.receivable to self.assessment.debt economics { purpose: internal, sourceParty: programOperator } }
624
+ action refund { allowZero: true, from: paid, to: refunded, actor: { parent: parent }, moves self.amount from costs_to to self.payment.plan.borrower economics { recipient: costs_to, company: { purpose: earning, sourceParty: costs_to, reversalOf: self.cashReceipt }, participant: unclassified }; moves self.amount from self.assessment.debt to self.assessment.receivable economics { purpose: internal, sourceParty: borrower } }
620
625
  }
621
626
  }
622
627
  }
package/std/insurance.hsx CHANGED
@@ -1,5 +1,9 @@
1
1
  header insurance
2
2
 
3
+ // Economics: Company commission is earning; refunds reverse its captured transfer.
4
+ // Outside broker commissions are pass-through. Adapter-owned premium and claim
5
+ // accounts lack an authored source party, so their moves remain unclassified.
6
+
3
7
  // Expose cover.create, activate and cancel separately. Activation binds adapter;
4
8
  // each slice needs a separately created unique period and an active cover to collect.
5
9
  // Collection debits holder for insurerPremium to the insurer and commission to
@@ -39,7 +43,7 @@ instrument cover(holder: party, adapter: text, commission: percent = 0%, broker:
39
43
  fields {
40
44
  cover: ref<parent>, covers: ref<covers>, premium: money = premium, startsAt: date, endsAt: date
41
45
  commission: money = rate(self.premium, commission)
42
- insurerPremium: money = subtract(self.premium, self.commission)
46
+ insurerPremium: money = subtract(self.premium, self.commission), commissionReceipt: text?
43
47
  }
44
48
  lifecycle { states: [pending, paid, active, expired, refunded], initial: pending }
45
49
  action create {
@@ -53,7 +57,7 @@ instrument cover(holder: party, adapter: text, commission: percent = 0%, broker:
53
57
  from: pending, to: paid, actor: { party: holder }
54
58
  requires self.cover in [active]
55
59
  moves self.insurerPremium from holder to self.cover.insurer
56
- moves self.commission from holder to broker
60
+ moves self.commission from holder to broker capture "commissionReceipt" economics { recipient: broker, company: { purpose: earning, sourceParty: holder }, participant: { purpose: pass_through, sourceParty: holder } }
57
61
  }
58
62
  action start { from: paid, to: active, actor: clock, due: { at: self.startsAt } }
59
63
  action expire { from: active, to: expired, actor: clock, due: { at: self.endsAt } }
@@ -62,7 +66,7 @@ instrument cover(holder: party, adapter: text, commission: percent = 0%, broker:
62
66
  requires self.premium > "0"
63
67
  from: paid, to: refunded, actor: { parent: parent }, deadline: { at: self.startsAt }
64
68
  moves self.insurerPremium from self.cover.insurer to holder
65
- moves self.commission from broker to holder
69
+ moves self.commission from broker to holder economics { recipient: broker, company: { purpose: earning, sourceParty: broker, reversalOf: self.commissionReceipt }, participant: { purpose: pass_through, sourceParty: broker } }
66
70
  }
67
71
  }
68
72
  }
package/std/lending.hsx CHANGED
@@ -1,5 +1,9 @@
1
1
  header lending
2
2
 
3
+ // Economics: Funding and commitment returns are principal. Distribution tax is
4
+ // pass-through; own-account fee and claim allocations are internal. Mixed
5
+ // principal/profit distributions and unbound source owners remain unclassified.
6
+
3
7
  // Round target is plan.principal from runtime subject.price, not its credit limit.
4
8
  // Expose round.create and close plus commitment.create and withdraw. A commitment
5
9
  // debits the bound investor's original active wallet before closesAt. Investor cap
@@ -31,7 +35,7 @@ instrument round(borrower: party, plan: ref<financing.installments> = object(fin
31
35
  from: open, to: funded, actor: { party: operator }
32
36
  requires sum "amount" of { instrument: commitments, reference: "round", anchor: self.id, states: [committed], limit: 366 } == self.price
33
37
  requires self.held.balance == self.price
34
- moves self.price from self.held to self.plan.capital
38
+ moves self.price from self.held to self.plan.capital economics { purpose: principal, sourceParty: programOperator }
35
39
  invoke: [{ selection: { instrument: commitments, reference: "round", anchor: self.id, states: [committed], limit: 366 }, action: fund, input: {} }]
36
40
  }
37
41
  action fail {
@@ -54,18 +58,18 @@ instrument commitment(round: ref<lending.round>, wallet: ref<wallet.balance>, in
54
58
  requires self.wallet.holder == self.investor
55
59
  requires self.amount >= self.round.minimumTicket
56
60
  deadline: { at: self.round.closesAt }
57
- moves self.amount from self.wallet.held to self.round.held
61
+ moves self.amount from self.wallet.held to self.round.held economics { purpose: principal, sourceParty: programOperator }
58
62
  }
59
63
  action fund { from: committed, to: funded, actor: { parent: round } }
60
64
  action withdraw {
61
65
  from: committed, to: withdrawn, actor: { party: investor }
62
66
  requires self.round in [open]
63
67
  deadline: { at: self.round.closesAt }
64
- moves self.amount from self.round.held to self.wallet.held
68
+ moves self.amount from self.round.held to self.wallet.held economics { purpose: principal, sourceParty: programOperator }
65
69
  }
66
70
  action refund {
67
71
  from: committed, to: refunded, actor: { parent: round }
68
- moves self.amount from self.round.held to self.wallet.held
72
+ moves self.amount from self.round.held to self.wallet.held economics { purpose: principal, sourceParty: programOperator }
69
73
  }
70
74
  }
71
75
 
@@ -98,7 +102,7 @@ instrument distribution(round: ref<lending.round>, receipt: ref, commitments: re
98
102
  action distribute_cash { allowZero: true,
99
103
  from: cash_ready, to: distributed, actor: { party: operator }
100
104
  requires sum "weight" of { instrument: share, reference: "distribution", anchor: self.id, states: [pending], limit: 366 } == self.round.price
101
- 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
105
+ 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 economics { purpose: internal, sourceParty: programOperator }; moves self.vat from self.held to programTax economics { purpose: pass_through, sourceParty: programOperator }
102
106
  invoke: [{ selection: { instrument: share, reference: "distribution", anchor: self.id, states: [pending], limit: 366 }, action: cash, input: {} }, { reference: self.id, action: residual_cash, input: {} }]
103
107
  }
104
108
  action residual_cash { allowZero: true,
@@ -113,7 +117,7 @@ instrument distribution(round: ref<lending.round>, receipt: ref, commitments: re
113
117
  }
114
118
  action residual_loss { allowZero: true,
115
119
  from: distributed, to: distributed, actor: { parent: current() }
116
- moves self.losses.balance from self.losses to self.residualLoss
120
+ moves self.losses.balance from self.losses to self.residualLoss economics { purpose: internal, sourceParty: programOperator }
117
121
  }
118
122
  records {
119
123
  share: {
@@ -128,7 +132,7 @@ instrument distribution(round: ref<lending.round>, receipt: ref, commitments: re
128
132
  from: pending, to: paid, actor: { parent: parent }
129
133
  moves self.gross from self.distribution.held to self.commitment.wallet.held
130
134
  }
131
- action loss { allowZero: true, from: pending, to: paid, actor: { parent: parent }, moves self.gross from self.distribution.losses to self.commitment.loss }
135
+ action loss { allowZero: true, from: pending, to: paid, actor: { parent: parent }, moves self.gross from self.distribution.losses to self.commitment.loss economics { purpose: internal, sourceParty: programOperator } }
132
136
  }
133
137
  }
134
138
  }
@@ -1,5 +1,8 @@
1
1
  header marketplace
2
2
 
3
+ // Economics: Deposit funding, escrow credit and returns are principal. Retention is
4
+ // earning for the company or a payout to a bound outside recipient.
5
+
3
6
  // Listing, order and reservation are separate agreements. Expose their create
4
7
  // and decision actions individually. Order fulfillment does not move escrow cash.
5
8
  // Pair an order with escrow.hold and expose its fund, deliver, accept, dispute,
@@ -77,7 +80,7 @@ instrument reservation(listing: ref<marketplace.listing>, funds: ref<escrow.hold
77
80
  calculate: [{ target: expiresAt, op: shift, date: { field: self.now }, milliseconds: { literal: expires_after }, direction: after }]
78
81
  requires self.listing in [active]; requires self.price == self.listing.price
79
82
  requires count of { instrument: all(marketplace.order), reference: "listing", anchor: self.listing, states: [placed, fulfilled], limit: 366 } == 0
80
- moves self.deposit from self.buyer to self.held
83
+ moves self.deposit from self.buyer to self.held economics { purpose: principal, sourceParty: buyer }
81
84
  }
82
85
  action convert_financed {
83
86
  from: active, to: active, actor: { party: buyer }, deadline: { at: self.expiresAt }
@@ -96,31 +99,31 @@ instrument reservation(listing: ref<marketplace.listing>, funds: ref<escrow.hold
96
99
  requires input.contribution <= self.price
97
100
  calculate: [{ target: credit, op: minimum, values: [{ field: self.held.balance }, { field: input.contribution }] }, { target: refund, op: subtract, base: { field: self.held.balance }, subtract: [{ field: self.credit }] }]
98
101
  set: { dispositionAt: { field: self.now } }
99
- moves self.credit from self.held to input.funds.held
100
- moves self.refund from self.held to self.buyer
102
+ moves self.credit from self.held to input.funds.held economics { purpose: principal, sourceParty: programOperator }
103
+ moves self.refund from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }
101
104
  }
102
105
  action cancel { allowZero: true,
103
106
  from: active, to: cancelled, actor: { party: buyer }, input { reason: text }
104
107
  calculate: [{ target: refund, op: rate, base: { field: self.held.balance }, bps: { literal: cancellation_refund }, rounding: floor }, { target: retained, op: subtract, base: { field: self.held.balance }, subtract: [{ field: self.refund }] }]
105
108
  set: { reason: { field: input.reason }, dispositionAt: { field: self.now } }
106
- moves self.refund from self.held to self.buyer; moves self.retained from self.held to retained_to
109
+ moves self.refund from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }; moves self.retained from self.held to retained_to economics { recipient: retained_to, company: { purpose: earning, sourceParty: buyer }, participant: { purpose: participant_payout, sourceParty: programOperator } }
107
110
  }
108
111
  action seller_cancel {
109
112
  from: active, to: cancelled, actor: { party: seller }, input { reason: text }
110
113
  set: { reason: { field: input.reason }, dispositionAt: { field: self.now } }
111
- moves self.held.balance from self.held to self.buyer
114
+ moves self.held.balance from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }
112
115
  }
113
116
  action operator_cancel {
114
117
  from: active, to: cancelled, actor: { party: operator }, input { reason: text }
115
118
  set: { reason: { field: input.reason }, dispositionAt: { field: self.now } }
116
- moves self.held.balance from self.held to self.buyer
119
+ moves self.held.balance from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }
117
120
  }
118
121
  action withdraw { from: proposed, to: cancelled, actor: { party: buyer } }
119
122
  action expire { allowZero: true,
120
123
  from: active, to: expired, actor: clock, due: { at: self.expiresAt }
121
124
  calculate: [{ target: refund, op: rate, base: { field: self.held.balance }, bps: { literal: expiry_refund }, rounding: floor }, { target: retained, op: subtract, base: { field: self.held.balance }, subtract: [{ field: self.refund }] }]
122
125
  set: { dispositionAt: { field: self.now } }
123
- moves self.refund from self.held to self.buyer; moves self.retained from self.held to retained_to
126
+ moves self.refund from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }; moves self.retained from self.held to retained_to economics { recipient: retained_to, company: { purpose: earning, sourceParty: buyer }, participant: { purpose: participant_payout, sourceParty: programOperator } }
124
127
  }
125
128
  action expire_proposal { from: proposed, to: expired, actor: clock, due: { at: self.proposalExpiresAt } }
126
129
  }
package/std/money.hsx CHANGED
@@ -1,5 +1,9 @@
1
1
  header money
2
2
 
3
+ // Economics: Held funding and returns are principal. Release to the company realizes
4
+ // earnings; release to another participant is a payout. Generic transfers, splits,
5
+ // schedules, swaps, boundary payouts and metered fees retain no assumed purpose.
6
+
3
7
  // Expose each attachment's create and caller actions explicitly. A transfer or
4
8
  // split pays once; a hold exposes fund, release and refund separately. Release
5
9
  // pays payee and refund returns payer. A hold has no dispute or damage decision.
@@ -36,7 +40,7 @@ instrument hold(payer: party, payee: party, amount: money = runtime) {
36
40
  action create { }
37
41
  action fund {
38
42
  from: pending, to: funded, actor: { party: payer }
39
- moves self.amount from payer to self.held
43
+ moves self.amount from payer to self.held economics { purpose: principal, sourceParty: payer }
40
44
  }
41
45
  action confirm {
42
46
  from: pending, to: funded
@@ -44,11 +48,11 @@ instrument hold(payer: party, payee: party, amount: money = runtime) {
44
48
  }
45
49
  action release {
46
50
  from: funded, to: released, actor: { party: payer }
47
- moves self.amount from self.held to payee
51
+ moves self.amount from self.held to payee economics { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: participant_payout, sourceParty: programOperator } }
48
52
  }
49
53
  action refund {
50
54
  from: funded, to: refunded, actor: { party: payee }
51
- moves self.amount from self.held to payer
55
+ moves self.amount from self.held to payer economics { purpose: principal, sourceParty: programOperator }
52
56
  }
53
57
  action cancel { from: pending, to: cancelled }
54
58
  }
@@ -103,7 +107,7 @@ instrument pool(payer: party, payee: party, target: money, closes: date) {
103
107
  action pay {
104
108
  from: open, to: paid, actor: { party: payee }
105
109
  requires self.held.balance == self.target
106
- moves self.target from self.held to payee
110
+ moves self.target from self.held to payee economics { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: participant_payout, sourceParty: programOperator } }
107
111
  }
108
112
  action fail {
109
113
  from: open, to: failed, actor: clock, due: { at: self.closesAt }
@@ -116,8 +120,8 @@ instrument pool(payer: party, payee: party, target: money, closes: date) {
116
120
  lifecycle { states: [pending, paid, refunded], initial: pending }
117
121
  invariants count of { instrument: current(), reference: "pool", anchor: self.pool, states: [paid], limit: 366 } <= 366
118
122
  action create { requires self.pool in [open] }
119
- action pay { from: pending, to: paid, actor: { party: payer }, deadline: { at: self.pool.closesAt }, requires self.pool in [open], calculate: [{ target: remaining, op: subtract, base: { field: self.pool.target }, subtract: [{ field: self.pool.held.balance }] }], requires self.amount <= self.remaining, moves self.amount from self.payer to self.pool.held }
120
- action refund { from: paid, to: refunded, actor: { parent: parent }, moves self.amount from self.pool.held to self.payer }
123
+ action pay { from: pending, to: paid, actor: { party: payer }, deadline: { at: self.pool.closesAt }, requires self.pool in [open], calculate: [{ target: remaining, op: subtract, base: { field: self.pool.target }, subtract: [{ field: self.pool.held.balance }] }], requires self.amount <= self.remaining, moves self.amount from self.payer to self.pool.held economics { purpose: principal, sourceParty: payer } }
124
+ action refund { from: paid, to: refunded, actor: { parent: parent }, moves self.amount from self.pool.held to self.payer economics { purpose: principal, sourceParty: programOperator } }
121
125
  }
122
126
  }
123
127
  }
package/std/savings.hsx CHANGED
@@ -1,5 +1,7 @@
1
1
  header savings
2
2
 
3
+ // Economics: Contributions and returned pots are principal, not company earnings.
4
+
3
5
  // Expose circle.create and membership.create; create one pending contribution
4
6
  // record per member per circle date before membership.activate. Circle activation
5
7
  // is clock-owned and needs exactly members joined memberships at or after startsAt.
@@ -52,7 +54,7 @@ instrument membership(circle: ref<savings.circle>, member: party) {
52
54
  from: active, to: received, actor: clock, due: { at: self.receivesAt }
53
55
  requires self.circle in [active]
54
56
  requires count of { instrument: all(savings.membership), reference: "circle", anchor: self.circle, states: [received], limit: 60 } == self.preceding
55
- moves self.total from self.circle.held to self.member
57
+ moves self.total from self.circle.held to self.member economics { purpose: principal, sourceParty: programOperator }
56
58
  }
57
59
  action withdraw { from: joined, to: withdrawn, requires self.circle in [disbanded] }
58
60
  records {
@@ -60,7 +62,7 @@ instrument membership(circle: ref<savings.circle>, member: party) {
60
62
  fields { membership: ref<parent>, period: integer(1, 60), dueAt: date = at(self.membership.circle.circleDates, self.period), amount: money = self.membership.contribution }
61
63
  lifecycle { states: [pending, paid], initial: pending }
62
64
  action create { requires self.period <= self.membership.circle.members; requires self.membership in [joined]; requires unique "seat_period" on [self.membership, self.period] }
63
- action pay { from: pending, to: paid, actor: clock, due: { at: self.dueAt }, requires self.membership in [active, received]; requires self.membership.circle in [active], moves self.amount from self.membership.member to self.membership.circle.held }
65
+ action pay { from: pending, to: paid, actor: clock, due: { at: self.dueAt }, requires self.membership in [active, received]; requires self.membership.circle in [active], moves self.amount from self.membership.member to self.membership.circle.held economics { purpose: principal, sourceParty: member } }
64
66
  }
65
67
  }
66
68
  }