@hyperscale0/hsx 1.0.338 → 1.0.340

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/dist/src/ast.d.ts +1 -0
  2. package/dist/src/ast.d.ts.map +1 -1
  3. package/dist/src/ast.js.map +1 -1
  4. package/dist/src/attachment-economics.d.ts +19 -0
  5. package/dist/src/attachment-economics.d.ts.map +1 -1
  6. package/dist/src/attachment-economics.js +101 -3
  7. package/dist/src/attachment-economics.js.map +1 -1
  8. package/dist/src/binding-contract.d.ts.map +1 -1
  9. package/dist/src/binding-contract.js +10 -4
  10. package/dist/src/binding-contract.js.map +1 -1
  11. package/dist/src/compile.d.ts.map +1 -1
  12. package/dist/src/compile.js +36 -8
  13. package/dist/src/compile.js.map +1 -1
  14. package/dist/src/examples-bundle.js +1 -1
  15. package/dist/src/examples-bundle.js.map +1 -1
  16. package/dist/src/headers.d.ts.map +1 -1
  17. package/dist/src/headers.js +3 -1
  18. package/dist/src/headers.js.map +1 -1
  19. package/dist/src/parse.js +13 -1
  20. package/dist/src/parse.js.map +1 -1
  21. package/dist/src/std-bundle.js +6 -6
  22. package/dist/src/std-bundle.js.map +1 -1
  23. package/dist/src/template-guide.d.ts.map +1 -1
  24. package/dist/src/template-guide.js +2 -1
  25. package/dist/src/template-guide.js.map +1 -1
  26. package/docs/README.md +5 -2
  27. package/examples/camera-rental.hsx +4 -2
  28. package/package.json +4 -4
  29. package/src/ast.ts +7 -1
  30. package/src/attachment-economics.ts +127 -2
  31. package/src/binding-contract.ts +13 -6
  32. package/src/compile.ts +63 -9
  33. package/src/examples-bundle.ts +1 -1
  34. package/src/headers.ts +6 -1
  35. package/src/parse.ts +16 -1
  36. package/src/std-bundle.ts +6 -6
  37. package/src/template-guide.ts +2 -1
  38. package/std/collections.hsx +4 -4
  39. package/std/financing.hsx +461 -266
  40. package/std/insurance.hsx +21 -5
  41. package/std/lending.hsx +13 -9
  42. package/std/money.hsx +88 -32
  43. package/std/reporting.hsx +6 -6
package/src/std-bundle.ts CHANGED
@@ -3,16 +3,16 @@
3
3
  export const BUNDLED_STD_FILES: ReadonlyMap<string, string> = new Map<string, string>([
4
4
  ["booking.hsx", "header booking\n\n// Economics: Deposit and balance payments and every refund are principal. Completion\n// and any forfeit are earnings for the company, or pass the customer's cash through\n// to a bound outside operator.\n\n// Expose create, pay_deposit and pay_balance for the booking path, and\n// cancel_early, cancel_middle and cancel_late for the customer. Create captures\n// subject departure, price, deposit and balance, and refuses a deposit and balance\n// that do not add up to the price. Both installments must be positive. Creation\n// and deposit payment close at the balance cutoff. The balance is payable only after the deposit\n// and before balance_due ahead of departure, so a cancelled booking never offers\n// it. cancel_early runs until early_until before departure and returns everything\n// held. cancel_middle runs from then until late_from; cancel_late runs from then\n// until departure, even when the clock's complete runs late. They keep\n// middle_forfeit or late_forfeit of the held money and return the rest. Both\n// forfeits default to 0%, so nothing is kept unless the author sets them. At\n// departure the clock completes a paid booking and pays operator, and lapses an\n// unpaid one on cancel_late's terms, so nothing stays held after departure.\n\n// Cost: create declares one owned account. Each payment declares one transfer;\n// cancellation and completion move the held balance. Run hsx cost for the\n// composed counts.\n\ninstrument reservation(customer: party = party(person), operator: party = programOperator, early_until: duration = 30d, late_from: duration = 15d, balance_due: duration = 15d, middle_forfeit: percent = 0%, late_forfeit: percent = 0%) {\n constraints { late_from: less_than(early_until) }\n revisioned: true\n summary: \"Take a deposit and a balance for a dated booking, with cancellation windows before departure.\"\n fields {\n customer: account of customer, operator: account of operator, held: account of self\n departure: date, price: money = subject.price\n deposit: money = subject.deposit, balance: money = subject.balance\n split: money = sum(self.deposit, self.balance)\n balanceAt: date = before(self.departure, balance_due)\n earlyAt: date = before(self.departure, early_until)\n lateAt: date = before(self.departure, late_from)\n refund: money?, forfeit: money?\n }\n lifecycle { states: [reserved, deposit_paid, paid, completed, cancelled], initial: reserved }\n action create {\n subject { departure: date, price: money, deposit: money, balance: money }\n actor: { party: customer }\n requires self.balanceAt > self.now\n requires self.departure > self.balanceAt\n requires self.deposit > \"0\"\n requires self.balance > \"0\"\n requires self.split == self.price\n }\n action pay_deposit {\n from: reserved, to: deposit_paid, actor: { party: customer }, deadline: { at: self.balanceAt }\n moves self.deposit from customer to self.held economics { purpose: principal, sourceParty: customer }\n }\n action pay_balance {\n from: deposit_paid, to: paid, actor: { party: customer }, deadline: { at: self.balanceAt }\n moves self.balance from customer to self.held economics { purpose: principal, sourceParty: customer }\n }\n action complete {\n from: paid, to: completed, actor: clock, due: { at: self.departure }\n moves self.held.balance from self.held to operator economics { recipient: operator, company: { purpose: earning, sourceParty: customer }, participant: { purpose: pass_through, sourceParty: programOperator } }\n }\n action cancel_early { allowZero: true,\n from: [reserved, deposit_paid, paid], to: cancelled, actor: { party: customer }, deadline: { at: self.earlyAt }\n moves self.held.balance from self.held to customer economics { purpose: principal, sourceParty: programOperator }\n }\n action cancel_middle { allowZero: true,\n from: [reserved, deposit_paid, paid], to: cancelled, actor: { party: customer }, due: { at: self.earlyAt }, deadline: { at: self.lateAt }\n calculate: [{ target: forfeit, op: rate, base: { field: self.held.balance }, bps: { literal: middle_forfeit }, rounding: floor }, { target: refund, op: subtract, base: { field: self.held.balance }, subtract: [{ field: self.forfeit }] }]\n moves self.refund from self.held to customer economics { purpose: principal, sourceParty: programOperator }; moves self.forfeit from self.held to operator economics { recipient: operator, company: { purpose: earning, sourceParty: customer }, participant: { purpose: pass_through, sourceParty: programOperator } }\n }\n action cancel_late { allowZero: true,\n from: [reserved, deposit_paid, paid], to: cancelled, actor: { party: customer }, due: { at: self.lateAt }, deadline: { at: self.departure }\n calculate: [{ target: forfeit, op: rate, base: { field: self.held.balance }, bps: { literal: late_forfeit }, rounding: floor }, { target: refund, op: subtract, base: { field: self.held.balance }, subtract: [{ field: self.forfeit }] }]\n moves self.refund from self.held to customer economics { purpose: principal, sourceParty: programOperator }; moves self.forfeit from self.held to operator economics { recipient: operator, company: { purpose: earning, sourceParty: customer }, participant: { purpose: pass_through, sourceParty: programOperator } }\n }\n action lapse { allowZero: true,\n from: [reserved, deposit_paid], to: cancelled, actor: clock, due: { at: self.departure }\n calculate: [{ target: forfeit, op: rate, base: { field: self.held.balance }, bps: { literal: late_forfeit }, rounding: floor }, { target: refund, op: subtract, base: { field: self.held.balance }, subtract: [{ field: self.forfeit }] }]\n moves self.refund from self.held to customer economics { purpose: principal, sourceParty: programOperator }; moves self.forfeit from self.held to operator economics { recipient: operator, company: { purpose: earning, sourceParty: customer }, participant: { purpose: pass_through, sourceParty: programOperator } }\n }\n}\n"],
5
5
  ["cards.hsx", "header cards\n\n// Activate holder and card before creating and approving an authorization.\n// Only the Product operator activates, suspends or resumes a cardholder; the\n// cardholder or the Product operator closes it. The card's person, bound to the\n// cardholder's holder, freezes, unfreezes and cancels their own card. The issuer\n// freezes it with issuer_freeze into blocked, which only issuer_unfreeze lifts,\n// and cancels it with issuer_cancel.\n// Expose authorization.create, approve and capture; expose decline and reverse\n// separately if callers need those paths. Issuer declines only from pending;\n// merchant captures or reverses an approved reservation. Expiry voids approved\n// reservations or abandons pending ones; it does not delay a captured refund.\n// Create one transaction for the captured authorization and expose its refund.\n// Refund is available immediately from posted, even before authorization.expiresAt,\n// and moves the whole captured amount from merchant to holder under programOperator.\n// No partial capture, repeated capture or partial transaction refund is provided.\n// Disputes need a posted transaction, issuer review and win before their deadline;\n// win invokes the same refund. The alias never changes the declared action actor.\n\n// Cost: authorization approve, capture and reverse each declare one transfer\n// instruction. Transaction refund declares one transfer; a successful dispute\n// invokes that refund. Card state changes alone declare no transfers.\n\ninstrument cardholder(holder: party) {\n summary: \"An account holder whose card access can be activated, suspended or closed.\"\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, actor: { party: programOperator } }\n action suspend { from: active, to: suspended, actor: { party: programOperator } }\n action resume { from: suspended, to: active, actor: { party: programOperator } }\n action close { from: [active, suspended], to: closed, actor: { party: holder } }\n action operator_close { from: [active, suspended], to: closed, actor: { party: programOperator } }\n}\n\ninstrument card(holder: ref<cards.cardholder>, spend_limit: money, issuer: party = programOperator, person: party = party(person)) {\n summary: \"A card with a per-spend ceiling that can be activated, frozen or cancelled.\"\n fields { holder: ref<holder>, person: account of person, spendLimit: money = spend_limit }\n lifecycle { states: [issued, active, frozen, blocked, cancelled], initial: issued }\n action create { requires self.holder in [active]; requires self.holder.holder == self.person }\n action activate { from: issued, to: active, requires self.holder in [active] }\n action freeze { from: active, to: frozen, actor: { party: person } }\n action unfreeze { from: frozen, to: active, actor: { party: person }, requires self.holder in [active] }\n action issuer_freeze { from: [active, frozen], to: blocked, actor: { party: issuer } }\n action issuer_unfreeze { from: [frozen, blocked], to: active, actor: { party: issuer }, requires self.holder in [active] }\n action cancel { from: [issued, active, frozen, blocked], to: cancelled, actor: { party: person } }\n action issuer_cancel { from: [issued, active, frozen, blocked], to: cancelled, actor: { party: issuer } }\n}\n\ninstrument authorization(card: ref<cards.card>, merchant: party, issuer: party = programOperator) {\n summary: \"Reserve a card payment for the merchant, then capture it or release the reservation.\"\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.card.holder in [active]\n requires self.amount <= self.card.spendLimit\n }\n action approve {\n from: pending, to: approved, actor: { party: issuer }, deadline: { at: self.expiresAt }\n requires self.card in [active]\n requires self.card.holder in [active]\n moves reserve self.amount from self.card.holder.holder to merchant capture \"reservation\"\n }\n action capture { from: approved, to: captured, actor: { party: merchant }, deadline: { at: self.expiresAt }, moves post self.reservation }\n action reverse { from: approved, to: reversed, actor: { party: merchant }, moves void self.reservation }\n action decline { from: pending, to: declined, actor: { party: issuer } }\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 summary: \"Record a captured card payment and return its amount when refunded.\"\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, actor: { party: programOperator }, 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>, issuer: party = programOperator, within: duration = 90d) {\n summary: \"Review a disputed card payment before its deadline and refund it when the dispute is won.\"\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, actor: { party: issuer } }\n action win {\n from: reviewing, to: won, actor: { party: issuer }, deadline: { at: self.expiresAt }\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"],
6
- ["collections.hsx", "header collections\n\n// Economics: Company capital pays agencies as participant payouts; outside capital passes through.\n// A company agency earns outside capital fees; its own capital fee is internal.\n\n// Expose case.create, assign and recover as separate steps. Creation needs overdue\n// outstanding principal and a matching slice/plan. Assignment belongs to capital;\n// recovery belongs to agency and pays the linked payment before the agency fee.\n// Payment must belong to the same plan. Recovered means that payment was processed,\n// not that the entire debt was repaid. Fee debits plan.capital, not the borrower.\n// Expose recall for capital and return_uncollected for agency when needed.\n// Contacts need an assigned case, matching agency, local hours and rolling count.\n// Contact outcomes are separate records. Reminder dispatch is operator-owned;\n// before_due/overdue are clock-owned and require active debt. Scheduled admission\n// does not prove delivery or retry. No collector can infer authority from an alias.\n\n// Cost: case recovery invokes the linked payment and then charges its agency\n// fee. Its count includes those child effects. Contact and reminder delivery costs\n// are not provider prices in hsx cost; the executor supplies commercial tariffs.\n\ninstrument case(on: ref<financing.installments>[], agency: party, capital: party = programOperator, overdue: duration = 3d, fee: percent = 20%) {\n revisioned: true\n summary: \"Refer an overdue installment without creating another debt.\"\n fields { assignedAgency: account of agency, 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, actor: { party: capital } }\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 { 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 } } } }\n action recall { from: [opened, assigned], to: recalled, actor: { party: capital } }\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 { agency: account of agency, 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.agency == self.case.assignedAgency; requires self.case in [assigned]; requires hours self.now between contact_from and contact_until timezone timezone\n }\n records {\n outcome: {\n fields { contact: ref<parent>, agency: account of agency, outcome: enum(reached, no_answer, promise_to_pay, disputed, wrong_contact, refused), evidence: text, recordedAt: date? }\n lifecycle { states: [recorded], initial: recorded }\n action create {\n actor: { party: agency }\n requires self.agency == self.contact.case.assignedAgency\n set: { recordedAt: { field: self.now } }\n }\n }\n }\n}\n\n\ninstrument reminder(on: ref<financing.installments>[], operator: party = programOperator, before_days: integer(0, 366) = 3, overdue_days: integer(1, 366) = 1, max_per_day: integer(1, 10) = 1, send_from: integer(0, 23) = 8, send_until: integer(1, 24) = 20, timezone: text = \"Asia/Riyadh\") {\n constraints { send_from: less_than(send_until) }\n summary: \"Send an email to the installment borrower's stored contact address.\"\n fields { slice: ref<on.slice> }\n lifecycle { states: [ready], initial: ready }\n action create { requires unique \"installment_reminder\" on [self.slice] }\n action dispatch {\n from: ready, to: ready, actor: { party: operator }\n invoke: [{ reference: self.id, action: send, input: {} }]\n }\n action before_due {\n from: ready, to: ready, actor: clock\n due: { at: self.slice.dueAt, localDay: { days: before_days, direction: \"before\", hour: send_from, timezone: timezone } }\n invoke: [{ selection: { instrument: current(), reference: \"slice\", anchor: self.slice, states: [ready], limit: 1, where: { slice.plan.status: { literal: \"active\" } } }, action: send, guard: { kind: compare, left: { field: self.slice.principalReceivable.balance }, operator: \">\", right: { literal: \"0\" } }, input: {} }]\n }\n action overdue {\n from: ready, to: ready, actor: clock\n due: { at: self.slice.dueAt, localDay: { days: overdue_days, direction: \"after\", hour: send_from, timezone: timezone } }\n invoke: [{ selection: { instrument: current(), reference: \"slice\", anchor: self.slice, states: [ready], limit: 1, where: { slice.plan.status: { literal: \"active\" } } }, action: send, guard: { kind: compare, left: { field: self.slice.principalReceivable.balance }, operator: \">\", right: { literal: \"0\" } }, input: {} }]\n }\n action send {\n from: ready, to: ready, actor: { parent: current() }\n requires self.slice.plan in [active]\n requires self.slice.principalReceivable.balance > \"0\"\n reminder: { installment: self.slice, recipient: self.slice.plan.borrower, dueAt: self.slice.dueAt, channel: \"email\", template: \"payment_reminder\", beforeDays: before_days, overdueDays: overdue_days, maxPerDay: max_per_day, startHour: send_from, endHour: send_until, timezone: timezone }\n }\n}\n"],
6
+ ["collections.hsx", "header collections\n\n// Economics: Company capital pays agencies as participant payouts; outside capital passes through.\n// A company agency earns outside capital fees; its own capital fee is internal.\n\n// Expose case.create, assign and recover as separate steps. Creation needs overdue\n// outstanding principal and a matching slice/plan. Assignment belongs to capital;\n// recovery belongs to agency and pays the linked payment before the agency fee.\n// Payment must belong to the same plan. Recovered means that payment was processed,\n// not that the entire debt was repaid. Fee debits plan.capital, not the borrower.\n// Expose recall for capital and return_uncollected for agency when needed.\n// Contacts need an assigned case, matching agency, local hours and rolling count.\n// Contact outcomes are separate records. Reminder dispatch is operator-owned;\n// before_due/overdue are clock-owned and require active debt. Scheduled admission\n// does not prove delivery or retry. No collector can infer authority from an alias.\n\n// Cost: case recovery invokes the linked payment and then charges its agency\n// fee. Its count includes those child effects. Contact and reminder delivery costs\n// are not provider prices in hsx cost; the executor supplies commercial tariffs.\n\ninstrument case(on: ref<financing.installments>[], agency: party, capital: party = programOperator, overdue: duration = 3d, fee: percent = 20%) {\n revisioned: true\n summary: \"Refer an overdue installment without creating another debt.\"\n fields { assignedAgency: account of agency, 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.openPrincipal > \"0\"\n requires unique \"overdue_referral\" on [self.slice]\n }\n action assign { from: opened, to: assigned, actor: { party: capital } }\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 { 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 } } } }\n action recall { from: [opened, assigned], to: recalled, actor: { party: capital } }\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 { agency: account of agency, 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.agency == self.case.assignedAgency; requires self.case in [assigned]; requires hours self.now between contact_from and contact_until timezone timezone\n }\n records {\n outcome: {\n fields { contact: ref<parent>, agency: account of agency, outcome: enum(reached, no_answer, promise_to_pay, disputed, wrong_contact, refused), evidence: text, recordedAt: date? }\n lifecycle { states: [recorded], initial: recorded }\n action create {\n actor: { party: agency }\n requires self.agency == self.contact.case.assignedAgency\n set: { recordedAt: { field: self.now } }\n }\n }\n }\n}\n\n\ninstrument reminder(on: ref<financing.installments>[], operator: party = programOperator, before_days: integer(0, 366) = 3, overdue_days: integer(1, 366) = 1, max_per_day: integer(1, 10) = 1, send_from: integer(0, 23) = 8, send_until: integer(1, 24) = 20, timezone: text = \"Asia/Riyadh\") {\n constraints { send_from: less_than(send_until) }\n summary: \"Send an email to the installment borrower's stored contact address.\"\n fields { slice: ref<on.slice> }\n lifecycle { states: [ready], initial: ready }\n action create { requires unique \"installment_reminder\" on [self.slice] }\n action dispatch {\n from: ready, to: ready, actor: { party: operator }\n invoke: [{ reference: self.id, action: send, input: {} }]\n }\n action before_due {\n from: ready, to: ready, actor: clock\n due: { at: self.slice.dueAt, localDay: { days: before_days, direction: \"before\", hour: send_from, timezone: timezone } }\n invoke: [{ selection: { instrument: current(), reference: \"slice\", anchor: self.slice, states: [ready], limit: 1, where: { slice.plan.status: { literal: \"active\" } } }, action: send, guard: { kind: compare, left: { field: self.slice.openPrincipal }, operator: \">\", right: { literal: \"0\" } }, input: {} }]\n }\n action overdue {\n from: ready, to: ready, actor: clock\n due: { at: self.slice.dueAt, localDay: { days: overdue_days, direction: \"after\", hour: send_from, timezone: timezone } }\n invoke: [{ selection: { instrument: current(), reference: \"slice\", anchor: self.slice, states: [ready], limit: 1, where: { slice.plan.status: { literal: \"active\" } } }, action: send, guard: { kind: compare, left: { field: self.slice.openPrincipal }, operator: \">\", right: { literal: \"0\" } }, input: {} }]\n }\n action send {\n from: ready, to: ready, actor: { parent: current() }\n requires self.slice.plan in [active]\n requires self.slice.openPrincipal > \"0\"\n reminder: { installment: self.slice, recipient: self.slice.plan.borrower, dueAt: self.slice.dueAt, channel: \"email\", template: \"payment_reminder\", beforeDays: before_days, overdueDays: overdue_days, maxPerDay: max_per_day, startHour: send_from, endHour: send_until, timezone: timezone }\n }\n}\n"],
7
7
  ["escrow.hsx", "header escrow\n\n// Economics: Funding and unspent returns are principal. Acceptance realizes earnings for\n// the company; the payer's cash passes through to a bound outside seller, less the\n// fee the company earns. Tax is pass-through.\n\n// Expose create, fund, deliver and accept for the purchase path. Create captures\n// subject.price; acceptance pays payee less the configured fee, not payer.\n// Expose dispute, verify_return and refund separately for the return path.\n// Payer disputes delivered goods; payee verifies return evidence from disputed.\n// Refunds return the held balance to the payer. A composition can supply funding\n// controllers and the states in which they block direct refunds. Only those\n// controllers may confirm outside funding or finish its coordinated refund.\n// Expose refund_undelivered to let the payer take the whole held price back once\n// deliver_within has passed since funding without delivery. It is a payer action\n// that becomes available at that time; nothing runs it automatically.\n// The Product operator settles any disputed hold: settle_release pays the payee\n// as acceptance would, and settle_return moves it to return_verified. Without a\n// active funding controller, settle_return also runs settle_refund to return\n// the whole balance to the payer. Otherwise the controller coordinates the\n// return before the operator's settle_refund returns the rest.\n// Acceptance expiry enters disputed, never released. Neither verify_return nor\n// refund becomes public merely because dispute is exposed. Clock actions remain\n// internal. Expose cancel for a pending hold, including a checkout-funded hold;\n// it returns its credited balance to payer before cancelling. Confirm requires\n// the whole captured price in held. This flow has no partial release or refund.\n\n// Cost: create declares one owned account. Fund and refund each declare one\n// transfer; accept expands the configured fee and tax into moves. Run hsx cost\n// on the composed program for instruction counts. The executor supplies prices.\n\ninstrument hold(payer: party = party(person), payee: party = programOperator, accept_within: duration = 48h, deliver_within: duration = 14d, fee: fee = { seller: 0%, tax: 0% }, dispute: policy = { refund_after: return_verified }, funding: policy = { controllers: [], reference: \"funds\", blocking_states: [active] }) {\n revisioned: true\n summary: \"Hold the subject price through delivery, acceptance and verified return.\"\n fields {\n payer: account of payer, payee: account of payee\n held: account of self, fundedAt: date?, deliverBy: date?, deliveredAt: date?, blockingFunding: integer?\n price: money = subject.price\n }\n lifecycle { states: [pending, funded, delivered, disputed, return_verified, released, refunded, cancelled], initial: pending }\n action create {\n subject { price: money }\n actor: { party: payer }\n }\n action fund {\n from: pending, to: funded, actor: { party: payer }\n set: { fundedAt: { field: self.now } }\n moves self.price from payer to self.held economics { purpose: principal, sourceParty: payer }\n }\n action confirm {\n from: pending, to: funded, actor: { parent: funding.controllers }\n requires self.held.balance == self.price\n calculate: [{ target: deliverBy, op: shift, date: { field: self.now }, milliseconds: { literal: deliver_within }, direction: after }]\n }\n action deliver {\n from: funded, to: delivered, actor: { party: payee }\n set: { deliveredAt: { field: self.now } }\n }\n action accept { allowZero: true, requires self.price > \"0\";\n from: delivered, to: released, actor: { party: payer }\n input { acceptanceReference: text }\n deadline: { at: self.deliveredAt, offset: accept_within }\n moves self.price from self.held to payee fee fee economics { payee: { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: pass_through, sourceParty: programOperator } }, fee: { purpose: earning, sourceParty: payer }, tax: { purpose: pass_through, sourceParty: programOperator } }\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 {\n from: disputed, to: return_verified, actor: { party: payee }\n input { returnEvidence: text }\n }\n action settle_release { allowZero: true, requires self.price > \"0\";\n from: disputed, to: released, actor: { party: programOperator }\n input { ruling: text }\n moves self.price from self.held to payee fee fee economics { payee: { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: pass_through, sourceParty: programOperator } }, fee: { purpose: earning, sourceParty: payer }, tax: { purpose: pass_through, sourceParty: programOperator } }\n }\n action settle_return {\n from: disputed, to: return_verified, actor: { party: programOperator }\n input { ruling: text }\n calculate: [{ target: blockingFunding, op: aggregate, selection: { instrument: funding.controllers, reference: funding.reference, anchor: self.id, states: funding.blocking_states, limit: 1 }, measure: count }]\n invoke: [{ reference: self.id, action: settle_refund, guard: { kind: compare, left: { field: self.blockingFunding }, operator: \"==\", right: { literal: 0 } }, input: {} }]\n }\n action settle_refund { allowZero: true,\n from: return_verified, to: refunded, actor: { party: programOperator }\n requires count of { instrument: funding.controllers, reference: funding.reference, anchor: self.id, states: funding.blocking_states, limit: 1 } == 0\n moves self.held.balance from self.held to payer economics { purpose: principal, sourceParty: programOperator }\n }\n action refund {\n from: [funded, dispute.refund_after], to: refunded, actor: { party: payee }\n requires count of { instrument: funding.controllers, reference: funding.reference, anchor: self.id, states: funding.blocking_states, limit: 1 } == 0\n moves self.held.balance from self.held to payer economics { purpose: principal, sourceParty: programOperator }\n }\n action refund_undelivered {\n from: funded, to: refunded, actor: { party: payer }\n due: { at: self.fundedAt, offset: deliver_within }\n requires count of { instrument: funding.controllers, reference: funding.reference, anchor: self.id, states: funding.blocking_states, limit: 1 } == 0\n moves self.price from self.held to payer economics { purpose: principal, sourceParty: programOperator }\n }\n action finish_refund { allowZero: true,\n from: [funded, return_verified], to: refunded, actor: { parent: funding.controllers }\n moves self.held.balance from self.held to payer economics { purpose: principal, sourceParty: programOperator }\n }\n action cancel { allowZero: true,\n from: pending, to: cancelled, actor: { party: payer }\n moves self.held.balance from self.held to payer economics { purpose: principal, sourceParty: programOperator }\n }\n}\n"],
8
- ["financing.hsx", "header financing\n\n// Economics: Principal advances and repayments are excluded from earnings. Claims, waivers,\n// write-offs and allocations are internal. Paid profit and company charges are\n// earnings; receipt refunds reverse captured cash. Borrower cash paid to outside\n// capital or recovery recipients passes through, whether held first or paid direct.\n\n// Pricing is required. amortizing reads profit_rate as an annual rate on the\n// declining balance: equal monthly instalments, the last absorbing rounding.\n// flat_total reads it as one charge on principal for the whole term (murabaha,\n// fixed-fee pay-later). 12,000 at 18% over 12 months costs 13,201.95 amortizing\n// and 14,160 flat_total.\n// Expose create and sign on installments. A funding composition owns checkout,\n// destination funding and returns when disburse_to is funds. The repayment plan\n// owns principal, profit, limits and debt cancellation.\n// disburse_to: seller pays principal to the seller party at activation (pay later\n// with the merchant paid on day one). Capital may refund any paid payment to\n// the borrower. Payments stay refundable while the plan is active. The\n// payment that clears the last slice completes the plan when no late charge or\n// recovery cost is outstanding; otherwise expose complete to close it once they\n// are settled or waived. When\n// the plan leaves active (paid, written off or cancelled) it sets refundUntil to\n// refund_within (default 30d) later, and payment, late charge and recovery cost\n// refunds stop at that time. A refund that reopens the plan clears refundUntil, which is set\n// from the calculated refundWindow so a restore can clear it. Once it passes,\n// nothing can move the plan's payments or late charges, so they stop counting as\n// open records. On a return, capital runs unwind: it takes the outstanding\n// principal back to capital and cancels open slices with their claims. Seller\n// mode debits the seller, who also returns the principal the borrower repaid;\n// funds mode needs the hold in return_verified and debits the hold, after which\n// the payee's escrow refund returns the down payment and the repaid principal.\n// Before delivery, the Product\n// operator runs unwind_undelivered on a funds-mode plan whose hold is still\n// funded: principal goes back to capital and the hold's unwind_financed returns\n// the down payment to the payer and closes the hold as refunded, all in one\n// operation, so deliver is refused afterwards. It also cancels proposed and\n// assessed late charges and recovery costs: goods that never arrived earn no\n// fines. Escrow refund refuses while any plan that is\n// not cancelled funds the hold, written off included, so the borrower never\n// receives lender principal. A funds-mode plan writes off only once its hold\n// has released principal to the seller: principal still held is not a loss, and\n// unwind or unwind_undelivered returns it. unwind_undelivered needs no paid\n// payments and no collected late charges; refund them first. unwind needs no\n// assessed late charges; waive them first. When goods never arrive on a paid plan, the\n// Product operator runs unwind_paid once the hold's deliverBy has passed, so an\n// early payoff never cuts the seller's delivery window short. It refunds every\n// payment, share, profit piece, fine and cost receipt and reverses the payoff's\n// profit, fines and costs, cancels the plan, and returns the hold's whole price\n// to the borrower; capital keeps the principal the borrower repaid. A settlement\n// a lending.distribution has paid out keeps its profit and share, since investors\n// hold that profit; only the other settlements' profit is refunded. unwind_paid\n// selects at most max_history (default and most 366) of each record kind, so\n// a payment refuses when it would leave more paid payments than max_history\n// less one, keeping a settlement for the payoff, or more paid profit pieces,\n// fine receipts or cost receipts than max_history; a fine or a recovery cost\n// refuses past max_history unwaived fines or costs on the plan, counted across\n// every late charge attachment, so a waived fine's cost keeps its own slot. A company lowers it to keep unwinds smaller. If any\n// source account is short, the whole action refuses and nothing moves; a\n// company that wants a partial refund writes that rule in its own program.\n// returned_goods decides the split on returned goods, before or after payoff.\n// keep_profit, the default, keeps the profit and fines paid so far with the\n// company: unwind runs with payments still paid, and on a paid plan the Product\n// operator runs return_hold after the refund window to return a return_verified\n// hold's whole balance. refund_all makes unwind wait until capital has refunded\n// every payment and collected charge, removes return_hold, and lets unwind_paid\n// settle returned goods too.\n// Borrower- and seller-directed disbursement exclude collect_down_payment. A down_payment\n// there reduces principal but does not collect cash. Price is subject metadata,\n// not the borrower limit. The funding composition checks its payer and price.\n// Cancelling a plan cancels its debt agreement. Its funding composition owns\n// returning any cash collected before activation.\n// Approve borrower and portfolio limits before disbursement. Create builds the\n// dated slice records from future, strictly increasing dates; disbursement\n// refuses once a slice is due. Payments need a separate payment record and pay action.\n// Expose parent payoff separately and create a current, unexpired payoff_quote.\n// Expose late_charge.create as propose_assessment before the clock can assess;\n// provide matching plan, slice and borrower. Fine is fixed money, not a percentage.\n// Collection uses the minimum of payment cash and outstanding fine; a partial\n// payment does not settle the remaining fine. Recovery cost needs its own record,\n// which only the Product operator creates; only it cancels a proposed fine or cost.\n// Profit share credits capital's allocatedProfitPayable, not an outside agency.\n// Credit lines need adapter binding at activation; draws are ledger advances,\n// not evidence of outside funding. Only the line's borrower, the Product operator\n// by default, opens and closes the line and creates, draws, repays or cancels an\n// advance on it. Only the Product operator creates the portfolio limit and\n// approves borrower and portfolio limits. No clock declaration proves retries.\n\n// Cost: installments include cash and claim moves, child-account creation and\n// bounded invocations across slices and assessments. Month and charge limits affect\n// the bound. Run hsx cost on the selected policies; profit is not a platform tariff.\n\ninstrument installments(months: integer(1, 366), max_history: integer(2, 366) = 366, pricing: enum(amortizing, flat_total), profit_rate: percent, charge_limit: integer(1, 3) = 3, disburse_to: enum(funds, borrower, seller) = funds, seller: party?, 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%, write_off_after: duration = 90d, max_extension: duration = 90d, max_amendments: integer(0, 366) = 2, waiver_limit: percent = 100%, amendment_expiry: duration = 7d, payoff_quote_expiry: duration = 1h, refund_within: duration = 30d, returned_goods: enum(keep_profit, refund_all) = keep_profit, allow_overdue: enum(allowed, blocked) = allowed, assessed_fines: enum(carry, require_waiver) = carry, down_payment: percent = 0%, funds: ref?, borrower: party = party(person), capital: party = programOperator, share: percent = 0%, limits: ref<financing.limits> = object(financing.limits), portfolio: ref<financing.portfolio_limit> = object(financing.portfolio_limit)) {\n dependencies {\n funds {\n selector: disburse_to, is: funds\n message: \"Attachment `{attachment}` disburses into a hold, but `funds` is not bound.\"\n fix: \"Bind `funds: checkout` to a funding composition. Choose `disburse_to: seller` to pay a seller on activation, or `disburse_to: borrower` only if the borrower should receive the money directly.\"\n }\n seller {\n selector: disburse_to, is: seller\n message: \"Attachment `{attachment}` pays a seller, but `seller` is not bound.\"\n fix: \"Bind `seller: merchant` to the declared business that receives the principal.\"\n }\n }\n revisioned: true\n familyRevision: 1\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<portfolio>\n months: integer = months, dates: list(date, months), historyLimit: integer = max_history, paymentLimit: integer = subtract(max_history, 1)\n allocatedPayable: account(capital, cash, \"allocatedProfitPayable\"), capital: account(capital, cash, \"capital\"), profitIncome: account(capital, cash, \"profitIncome\"), loss: account(capital, claim, \"loss\")\n principalOutstanding: money?, principalRepaid: money?, principalReturned: money?, profitReturned: money?, lossRecorded: money?, refundWindow: date?, refundUntil: date?\n openSlices: integer?, openCharges: money?, openCosts: money?, payoffRefunds: integer?\n price: money = subject.price\n downPayment: money = rate(self.price, down_payment)\n principal: money = subtract(self.price, self.downPayment)\n flatProfit: money?\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 {\n subject { price: money }\n actor: { party: borrower }\n requires self.borrowerLimit.borrower == self.borrower\n when pricing is flat_total { calculate: [{ target: flatProfit, op: rate, base: { field: self.principal }, bps: { literal: profit_rate }, rounding: floor }] }\n when disburse_to is funds { invoke: [{ reference: self.funds, action: check, input: { plan: { field: self.id } } }] }\n invoke: [{ range: { count: { literal: months }, maximum: months, bind: position }, instrument: slice, action: create, input: { plan: { field: self.id }, borrowerLimit: { field: self.borrowerLimit }, portfolioLimit: { field: self.portfolioLimit }, position: { field: position } } }, { selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [draft], limit: months, where: { first: { literal: 0 } } }, action: check_order, input: {} }]\n }\n action sign {\n from: quoted, to: signed, actor: { party: borrower }, 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 collect_down_payment { allowZero: true,\n from: signed, to: signed, actor: { party: borrower }\n when disburse_to is borrower { requires true == false }\n when disburse_to is seller { requires true == false }\n when disburse_to is funds { invoke: [{ reference: self.funds, action: collect, input: { plan: { field: self.id } } }] }\n }\n action disburse { allowZero: true,\n from: signed, to: active, actor: { party: capital }\n requires self.borrowerLimit in [approved]\n requires self.portfolioLimit in [approved]\n when disburse_to is funds { invoke: [{ reference: self.funds, action: disburse, input: { plan: { field: self.id } } }] }\n when disburse_to is borrower { moves self.principal from self.capital to self.borrower economics { purpose: principal, sourceParty: capital } }\n when disburse_to is seller { moves self.principal from self.capital to seller economics { purpose: principal, sourceParty: capital } }\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [draft], limit: 366, order: [position] }, action: activate, input: {} }]\n }\n action complete {\n from: active, to: paid\n calculate: [{ target: refundWindow, op: shift, date: { field: self.now }, milliseconds: { literal: refund_within }, direction: after }]\n set: { refundUntil: { field: self.refundWindow } }\n requires count of { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366 } == 0\n requires sum \"receivable.balance\" of { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [assessed, collected], limit: 366 } == \"0\"\n requires sum \"receivable.balance\" of { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [assessed, collected], limit: 366 } == \"0\"\n }\n action restore { from: [active, paid], to: active, actor: { parent: payment }, input { refundUntil: date? }, set: { refundUntil: { field: input.refundUntil } } }\n action payoff {\n from: active, to: paid, actor: { party: borrower }\n input { quote: ref<payoff_quote> }\n requires input.quote.plan == self.id; requires input.quote.revision == self.productRevision\n deadline: { at: input.quote.expiresAt }\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 { target: refundWindow, op: shift, date: { field: self.now }, milliseconds: { literal: refund_within }, direction: after }\n ]\n set: { refundUntil: { field: self.refundWindow } }\n invoke: [{ selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [assessed, collected], limit: 366, order: [overdueAt] }, action: payoff, input: {} }, { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [assessed, collected], limit: 366, order: [overdueAt] }, action: payoff, input: {} }]\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, actor: { parent: write_off_request }\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\" } }, { target: refundWindow, op: shift, date: { field: self.now }, milliseconds: { literal: refund_within }, direction: after }]\n set: { refundUntil: { field: self.refundWindow } }\n due: { at: input.overdueSlice.lossEligibleAt }\n requires input.overdueSlice.plan == self.id; requires input.overdueSlice.principalReceivable.balance > \"0\"\n when disburse_to is funds { invoke: [{ reference: self.funds, action: write_off, input: { plan: { field: self.id } } }] }\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 calculate: [\n { target: openSlices, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366 }, measure: count }\n { target: openCharges, op: aggregate, selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [assessed, collected], limit: 366 }, measure: { sum: \"receivable.balance\" } }\n { target: openCosts, op: aggregate, selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [assessed, collected], limit: 366 }, measure: { sum: \"receivable.balance\" } }\n ]\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 invoke: [{ selection: { instrument: current(), reference: \"borrowerLimit\", anchor: self.borrowerLimit, states: [active], limit: 1, where: { id: { field: self.id }, openSlices: { literal: 0 }, openCharges: { literal: \"0\" }, openCosts: { literal: \"0\" } } }, action: complete, input: {} }]\n }\n action cancel { from: quoted, to: cancelled }\n action void { from: signed, to: cancelled, actor: { party: borrower } }\n action unwind { allowZero: true,\n from: active, to: cancelled, actor: { party: capital }\n calculate: [\n { target: refundWindow, op: shift, date: { field: self.now }, milliseconds: { literal: refund_within }, direction: after }\n { target: principalOutstanding, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366 }, measure: { sum: \"principalReceivable.balance\" } }\n { target: principalRepaid, op: subtract, base: { field: self.principal }, subtract: [{ field: self.principalOutstanding }] }\n ]\n set: { refundUntil: { field: self.refundWindow } }\n when disburse_to is borrower { requires true == false }\n when returned_goods is refund_all {\n requires count of { instrument: payment, reference: \"plan\", anchor: self.id, states: [paid], limit: 366 } == 0\n requires count of { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [collected], limit: 366 } == 0\n requires count of { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [collected], limit: 366 } == 0\n }\n requires count of { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [assessed], limit: 366 } == 0\n requires count of { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [assessed], limit: 366 } == 0\n when disburse_to is funds { invoke: [{ reference: self.funds, action: refund, input: { plan: { field: self.id }, principal: { field: self.principalOutstanding } } }] }\n when disburse_to is seller {\n moves self.principalOutstanding from seller to self.capital economics { purpose: principal, sourceParty: seller }\n moves self.principalRepaid from seller to self.borrower economics { purpose: principal, sourceParty: seller }\n }\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366, order: [position] }, action: cancel, input: {} }]\n }\n action unwind_undelivered { allowZero: true,\n from: active, to: cancelled, actor: { party: programOperator }\n calculate: [{ target: refundWindow, op: shift, date: { field: self.now }, milliseconds: { literal: refund_within }, direction: after }]\n set: { refundUntil: { field: self.refundWindow } }\n when disburse_to is borrower { requires true == false }\n when disburse_to is seller { requires true == false }\n requires count of { instrument: payment, reference: \"plan\", anchor: self.id, states: [paid], limit: 366 } == 0\n requires count of { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [collected], limit: 366 } == 0\n requires count of { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [collected], limit: 366 } == 0\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: 366, order: [position] }, action: cancel, input: {} }]\n invoke: [{ selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [proposed, assessed], limit: 366 }, action: cancel_undelivered, input: {} }, { selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [proposed, assessed], limit: 366 }, action: cancel_undelivered, input: {} }]\n when disburse_to is funds { invoke: [{ reference: self.funds, action: cancel_undelivered, input: { plan: { field: self.id } } }] }\n }\n action return_hold {\n from: paid, to: paid, actor: { party: programOperator }\n requires self.refundUntil < self.now\n when disburse_to is borrower { requires true == false }\n when disburse_to is seller { requires true == false }\n when returned_goods is refund_all { requires true == false }\n when disburse_to is funds {\n invoke: [{ reference: self.funds, action: return_paid, input: { plan: { field: self.id } } }]\n }\n }\n action unwind_paid {\n from: paid, to: cancelled, actor: { party: programOperator }\n when disburse_to is borrower { requires true == false }\n when disburse_to is seller { requires true == false }\n invoke: [{ selection: { instrument: settlement, reference: \"plan\", anchor: self.id, states: [recorded], limit: max_history }, action: unwind, input: {} }, { selection: { instrument: profit_piece, reference: \"plan\", anchor: self.id, states: [paid], limit: max_history, where: { payment.status: { literal: \"refunded\" } } }, action: refund, input: {} }, { selection: { instrument: payment, reference: \"plan\", anchor: self.id, states: [paid], limit: max_history }, action: unwind, input: {} }, { reference: self.id, action: unwind_payoff_profit, input: {} }]\n invoke: [{ selection: { instrument: all(financing.late_charge.receipt), reference: \"plan\", anchor: self.id, states: [paid], limit: max_history }, action: refund, input: {} }, { selection: { instrument: all(financing.late_charge.cost.receipt), reference: \"plan\", anchor: self.id, states: [paid], limit: max_history }, action: refund, input: {} }, { selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [collected], limit: max_history }, action: unwind_payoff, input: {} }, { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [collected], limit: max_history }, action: unwind_payoff, input: {} }]\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due, paid], limit: 366, order: [position] }, action: cancel, input: {} }]\n invoke: [{ selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [proposed, assessed, collected], limit: max_history }, action: cancel_undelivered, input: {} }, { selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [proposed, assessed, collected], limit: max_history }, action: cancel_undelivered, input: {} }]\n when disburse_to is funds {\n when returned_goods is keep_profit { invoke: [{ reference: self.funds, action: unwind_paid_undelivered, input: { plan: { field: self.id } } }] }\n when returned_goods is refund_all { invoke: [{ reference: self.funds, action: unwind_paid, input: { plan: { field: self.id } } }] }\n }\n }\n action unwind_payoff_profit {\n from: cancelled, to: cancelled, actor: { parent: current() }\n calculate: [{ target: payoffRefunds, op: aggregate, selection: { instrument: settlement, reference: \"plan\", anchor: self.id, states: [refunded], limit: 1, where: { identity: { field: self.settlementIdentity } } }, measure: count }]\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [paid], limit: 366, where: { payoffIdentity: { field: self.settlementIdentity } } }, action: unwind_payoff, guard: { kind: compare, left: { field: self.payoffRefunds }, operator: \"==\", right: { literal: 1 } }, input: {} }]\n }\n records {\n write_off_request: {\n fields { plan: ref<parent>, overdueSlice: ref<slice> }\n lifecycle { states: [requested, applied, cancelled], initial: requested }\n action create { requires self.overdueSlice.plan == self.plan; requires self.plan in [active] }\n action apply {\n from: requested, to: applied, actor: { party: capital }\n invoke: [{ reference: self.plan, action: write_off, input: { overdueSlice: { field: self.overdueSlice } } }]\n }\n action cancel { from: requested, to: cancelled }\n }\n payoff_quote: {\n fields {\n plan: ref<parent>, revision: text?, effectiveAt: date?, expiresAt: date = after(self.createdAt, payoff_quote_expiry)\n principal: money?, earnedProfit: money?, unearnedProfit: money?, rebate: money?, fines: money?, costs: money?, gross: money?, amount: money?\n }\n lifecycle { states: [quoted], initial: quoted }\n action create {\n requires self.plan in [active]\n set: { revision: { field: self.productRevision }, effectiveAt: { field: self.now } }\n invoke: [\n { selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending], limit: 366 }, action: quote_pending, input: { quote: { field: self.id } } }\n { selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [due], limit: 366 }, action: quote_due, input: { quote: { field: self.id } } }\n { reference: self.id, action: record, input: {} }\n ]\n }\n action record {\n from: quoted, to: quoted, actor: { parent: current() }\n calculate: [\n { target: principal, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366 }, measure: { sum: \"principalReceivable.balance\" } }\n { target: earnedProfit, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366 }, measure: { sum: \"profitEarned.balance\" } }\n { target: unearnedProfit, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366 }, measure: { sum: \"profitReceivable.balance\" } }\n { target: rebate, op: aggregate, selection: { instrument: quote_piece, reference: \"quote\", anchor: self.id, states: [recorded], limit: 366 }, measure: { sum: \"rebate\" } }\n { target: fines, op: aggregate, selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366 }, measure: { sum: \"receivable.balance\" } }\n { target: costs, op: aggregate, selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366 }, measure: { sum: \"receivable.balance\" } }\n { target: gross, op: sum, values: [{ field: self.principal }, { field: self.earnedProfit }, { field: self.unearnedProfit }, { field: self.fines }, { field: self.costs }] }\n { target: amount, op: subtract, base: { field: self.gross }, subtract: [{ field: self.rebate }] }\n ]\n }\n }\n quote_piece: {\n fields { quote: ref<payoff_quote>, slice: ref<slice>, rebate: money = rate(self.slice.profitReceivable.balance, payoff_rebate) }\n lifecycle { states: [recorded], initial: recorded }\n action create { actor: { parent: slice }, input { quote: ref<payoff_quote>, slice: ref<slice> }, requires unique \"payoff_slice_quote\" on [self.quote, self.slice] }\n }\n amendment: {\n fields {\n plan: ref<parent>, dates: list(date, months), agreement: text, waiverPercent: percent, waiverEvidence: text, maximumWaiver: percent = waiver_limit\n revision: text?, acceptedAt: date?, staleReason: text?, expiresAt: date = after(self.createdAt, amendment_expiry)\n fineDisposition: enum(carry, require_waiver) = assessed_fines, addedProfit: money = 0 SAR\n principalSnapshot: money?, earnedProfitSnapshot: money?, unearnedProfitSnapshot: money?, finesSnapshot: money?, costsSnapshot: money?\n extension: duration = max_extension, maximum: integer = max_amendments\n }\n lifecycle { states: [proposed, applied, declined, withdrawn, expired, superseded], initial: proposed }\n action create {\n actor: { party: capital }\n requires self.plan in [active]; requires self.waiverPercent <= self.maximumWaiver\n set: { revision: { field: self.productRevision } }\n calculate: [\n { target: principalSnapshot, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366 }, measure: { sum: \"principalReceivable.balance\" } }\n { target: earnedProfitSnapshot, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366 }, measure: { sum: \"profitEarned.balance\" } }\n { target: unearnedProfitSnapshot, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due, paid], limit: 366 }, measure: { sum: \"profitReceivable.balance\" } }\n { target: finesSnapshot, op: aggregate, selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366 }, measure: { sum: \"receivable.balance\" } }\n { target: costsSnapshot, op: aggregate, selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366 }, measure: { sum: \"receivable.balance\" } }\n ]\n requires count of { instrument: current(), reference: \"plan\", anchor: self.plan, states: [applied], limit: 366 } < self.maximum\n invoke: [{ range: { count: { literal: months }, maximum: months, bind: position }, instrument: proposed_date, action: create, input: { amendment: { field: self.id }, position: { field: position } } }, { selection: { instrument: proposed_date, reference: \"amendment\", anchor: self.id, states: [recorded], limit: 366, where: { first: { literal: 0 } } }, action: check_order, input: {} }]\n }\n action accept {\n from: proposed, to: applied, actor: { party: borrower }, deadline: { at: self.expiresAt }\n requires self.plan in [active]; requires self.revision == self.productRevision\n requires count of { instrument: current(), reference: \"plan\", anchor: self.plan, states: [applied], limit: 366 } < self.maximum\n set: { acceptedAt: { field: self.now } }\n when assessed_fines is require_waiver { requires self.waiverPercent == 10000 }\n invoke: [{ selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366 }, action: waive_for_amendment, input: { amendment: { field: self.id } } }, { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366 }, action: waive_for_amendment, input: { amendment: { field: self.id } } }]\n invoke: [{ selection: { instrument: all(collections.case), reference: \"plan\", anchor: self.plan, states: [opened, assigned], limit: 366 }, action: recall, input: {} }, { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [proposed], limit: 366 }, action: cancel_for_amendment, input: {} }, { selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [proposed], limit: 366 }, action: cancel_for_amendment, input: {} }]\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due], limit: 366, order: [position] }, action: amend, input: { amendment: { field: self.id } } }]\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [paid], limit: 366 }, action: verify_fixed_date, input: { amendment: { field: self.id } } }]\n }\n action withdraw { from: proposed, to: withdrawn, actor: { party: capital } }\n action decline { from: proposed, to: declined, actor: { party: borrower } }\n action expire { from: proposed, to: expired, actor: clock, due: { at: self.expiresAt } }\n action supersede { from: proposed, to: superseded, requires self.revision != self.productRevision, set: { staleReason: { literal: \"economic_revision_changed\" } } }\n }\n proposed_date: {\n fields { amendment: ref<amendment>, position: integer(1, months), date: date = at(self.amendment.dates, self.position), first: integer = divide(1, self.position), prior: integer = subtract(self.position, 1), previousPosition: integer = sum(self.prior, self.first), previous: date = at(self.amendment.dates, self.previousPosition) }\n lifecycle { states: [recorded], initial: recorded }\n action create { actor: { parent: amendment }, input { amendment: ref<amendment>, position: integer(1, months) }, requires self.date >= self.previous }\n action check_order { from: recorded, to: recorded, actor: { parent: amendment }, requires self.date > self.previous }\n }\n date_change: {\n fields { amendment: ref<amendment>, slice: ref<slice>, oldDate: date, newDate: date }\n lifecycle { states: [recorded], initial: recorded }\n action create { actor: { parent: slice }, input { amendment: ref<amendment>, slice: ref<slice>, oldDate: date, newDate: date }, requires unique \"amended_slice\" on [self.amendment, self.slice] }\n }\n settlement: {\n fields { plan: ref<parent>, identity: text, principal: money, profit: money, loss: money, kind: enum(cash, loss), share: money?, retainedProfit: money?\n allocatedPayable: account(capital, cash, \"allocatedProfitPayable\"), capital: account(capital, cash, \"capital\"), profitIncome: account(capital, cash, \"profitIncome\"), lossAccount: account(capital, claim, \"loss\") }\n lifecycle { states: [recorded, distributed, refunded], initial: recorded }\n action create { allowZero: true,\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 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 }] }]\n moves self.share from self.profitIncome to self.allocatedPayable economics { purpose: internal, sourceParty: capital }\n }\n action refund { allowZero: true,\n from: recorded, to: refunded, actor: { parent: payment }\n moves self.share from self.allocatedPayable to self.profitIncome economics { purpose: internal, sourceParty: capital }\n }\n action distribute { from: recorded, to: distributed, actor: { parent: all(lending.distribution) } }\n // profitIncome is one account per capital party, so refunding profit a\n // distribution already paid out would spend other plans' profit. unwind_paid\n // unwinds only settlements still recorded; each marks its payment refunded,\n // and the plan refunds the profit pieces and payoff profit behind them.\n action unwind { allowZero: true,\n from: recorded, to: refunded, actor: { parent: parent }\n moves self.share from self.allocatedPayable to self.profitIncome economics { purpose: internal, sourceParty: capital }\n invoke: [{ selection: { instrument: payment, reference: \"plan\", anchor: self.plan, states: [paid], limit: 1, where: { paymentIdentity: { field: self.identity } } }, action: unwind, input: {} }]\n }\n }\n slice: {\n revisioned: true\n fields {\n plan: ref<parent>, borrowerLimit: ref<limits>, portfolioLimit: ref<portfolio>, position: integer(1, months)\n originalDueAt: date = at(self.plan.dates, self.position), dueAt: date?, nextDueAt: date?, previousDueAt: date?, prior: integer = subtract(self.position, 1), previousPosition: integer = sum(self.prior, self.first), previousDate: date = at(self.plan.dates, self.previousPosition), extensionLimit: date = after(self.originalDueAt, max_extension), lossEligibleAt: date?\n first: integer = divide(1, self.position)\n principalBase: money?, principalAllocated: money?, principalRemainder: money?, principalAdjustment: money?\n profitBase: money?, profitAllocated: money?, profitRemainder: money?, profitAdjustment: money?\n principal: money, profit: money, instalment: money\n principalReceivable: account(self, claim), profitReceivable: account(self, claim), profitEarned: account(self, claim)\n payoffIdentity: text?, payoffRebate: money?, payoffProfitTotal: money?, payoffProfit: money?, payoffReceipt: text?\n paymentBudget: money?, principalPayment: money?, principalBasePayment: money?, principalRatio: money?, profitPayment: money?, profitBudget: money?, collectibleProfit: money?, collectibleTotal: money?, ratioDenominator: integer = sum(10000, profit_rate)\n debt: account(borrower, claim, contra, \"debt\"), loss: account(capital, claim, \"loss\")\n }\n lifecycle { states: [draft, pending, due, paid, written_off, cancelled], initial: draft }\n action create {\n actor: { parent: parent }\n input { plan: ref<parent>, borrowerLimit: ref<limits>, portfolioLimit: ref<portfolio>, position: integer(1, months) }\n set: { dueAt: { field: self.originalDueAt } }\n when pricing is flat_total {\n calculate: [\n { target: principalBase, op: divide, amount: { field: self.plan.principal }, divisor: { literal: months }, rounding: floor }\n { target: principalAllocated, op: multiply, amount: { field: self.principalBase }, units: { literal: months } }\n { target: principalRemainder, op: subtract, base: { field: self.plan.principal }, subtract: [{ field: self.principalAllocated }] }\n { target: principalAdjustment, op: multiply, amount: { field: self.principalRemainder }, units: { field: self.first } }\n { target: principal, op: sum, values: [{ field: self.principalBase }, { field: self.principalAdjustment }] }\n { target: profitBase, op: divide, amount: { field: self.plan.flatProfit }, divisor: { literal: months }, rounding: floor }\n { target: profitAllocated, op: multiply, amount: { field: self.profitBase }, units: { literal: months } }\n { target: profitRemainder, op: subtract, base: { field: self.plan.flatProfit }, subtract: [{ field: self.profitAllocated }] }\n { target: profitAdjustment, op: multiply, amount: { field: self.profitRemainder }, units: { field: self.first } }\n { target: profit, op: sum, values: [{ field: self.profitBase }, { field: self.profitAdjustment }] }\n { target: instalment, op: sum, values: [{ field: self.principal }, { field: self.profit }] }\n ]\n }\n when pricing is amortizing {\n calculate: [\n { target: principal, op: annuity, amount: { field: self.plan.principal }, rate: { literal: profit_rate }, periods: { literal: months }, position: { field: self.position }, part: principal }\n { target: profit, op: annuity, amount: { field: self.plan.principal }, rate: { literal: profit_rate }, periods: { literal: months }, position: { field: self.position }, part: interest }\n { target: instalment, op: sum, values: [{ field: self.principal }, { field: self.profit }] }\n ]\n }\n invoke: [{ reference: self.id, action: refresh_loss_date, input: {} }]\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 requires self.originalDueAt > self.now; requires self.originalDueAt >= self.previousDate\n }\n action check_order { from: draft, to: draft, actor: { parent: parent }, requires self.originalDueAt > self.previousDate }\n action quote_pending {\n from: pending, to: pending, actor: { parent: payoff_quote }, input { quote: ref<payoff_quote> }\n requires input.quote.plan == self.plan\n invoke: [{ instrument: quote_piece, action: create, input: { quote: { field: input.quote }, slice: { field: self.id } } }]\n }\n action quote_due {\n from: due, to: due, actor: { parent: payoff_quote }, input { quote: ref<payoff_quote> }\n requires input.quote.plan == self.plan\n invoke: [{ instrument: quote_piece, action: create, input: { quote: { field: input.quote }, slice: { field: self.id } } }]\n }\n action refresh_loss_date {\n from: [draft, pending, due], to: draft, actor: { parent: current() }\n calculate: [{ target: lossEligibleAt, op: shift, date: { field: self.dueAt }, milliseconds: { literal: write_off_after }, direction: after }]\n }\n action amend {\n from: [pending, due], to: pending, actor: { parent: amendment }, input { amendment: ref<amendment> }\n requires input.amendment.plan == self.plan\n when allow_overdue is blocked { requires self.dueAt > self.now }\n calculate: [\n { target: nextDueAt, op: at, list: input.amendment.dates, position: { field: self.position } }\n { target: lossEligibleAt, op: shift, date: { field: self.nextDueAt }, milliseconds: { literal: write_off_after }, direction: after }\n ]\n requires self.nextDueAt > self.now; requires self.nextDueAt >= self.dueAt; requires self.nextDueAt <= self.extensionLimit\n set: { previousDueAt: { field: self.dueAt }, dueAt: { field: self.nextDueAt } }\n invoke: [{ instrument: date_change, action: create, input: { amendment: { field: input.amendment }, slice: { field: self.id }, oldDate: { field: self.previousDueAt }, newDate: { field: self.nextDueAt } } }]\n when profit_earned is by_schedule { invoke: [{ selection: { instrument: recognition, reference: \"slice\", anchor: self.id, states: [pending], limit: 1 }, action: reschedule, input: {} }] }\n }\n action verify_fixed_date {\n from: paid, to: paid, actor: { parent: amendment }, input { amendment: ref<amendment> }\n calculate: [{ target: nextDueAt, op: at, list: input.amendment.dates, position: { field: self.position } }]\n requires self.nextDueAt == self.dueAt\n }\n action activate { allowZero: true,\n from: draft, to: pending, actor: { parent: parent }\n requires self.dueAt > self.now\n moves self.principal from self.debt to self.principalReceivable economics { purpose: internal, sourceParty: borrower }\n moves self.profit from self.debt to self.profitReceivable economics { purpose: internal, sourceParty: borrower }\n when profit_earned is at_disbursement { moves self.profit from self.profitReceivable to self.profitEarned economics { purpose: internal, sourceParty: programOperator } }\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: preserve, 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 principal_profit {\n invoke: [\n { instrument: principal_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.principalReceivable.balance } } }\n { instrument: profit_piece, action: create, input: { plan: { field: self.plan }, slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.collectibleProfit } } }\n { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [pending, due], limit: 1, where: { id: { field: self.id }, principalReceivable.balance: { literal: \"0\" }, profitReceivable.balance: { literal: \"0\" }, profitEarned.balance: { literal: \"0\" } } }, action: complete, input: {} }\n ]\n }\n }\n action collect_waterfall {\n from: [pending, due], to: preserve, 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 invoke: [\n { selection: { instrument: all(financing.late_charge), reference: \"slice\", anchor: self.id, states: [assessed], limit: charge_limit, order: [overdueAt] }, action: collect, input: { payment: { field: input.payment } } }\n { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [assessed], limit: charge_limit, order: [overdueAt], where: { assessment.slice: { field: self.id } } }, action: collect, input: { payment: { field: input.payment } } }\n { instrument: profit_piece, action: create, input: { plan: { field: self.plan }, slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.collectibleProfit } } }\n { instrument: principal_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.principalReceivable.balance } } }\n { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [pending, due], limit: 1, where: { id: { field: self.id }, principalReceivable.balance: { literal: \"0\" }, profitReceivable.balance: { literal: \"0\" }, profitEarned.balance: { literal: \"0\" } } }, action: complete, input: {} }\n ]\n }\n action collect_pro_rata {\n from: [pending, due], to: preserve, 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 ]\n when pricing is flat_total { calculate: [{ target: principalRatio, op: ratio, amount: { field: self.paymentBudget }, numerator: { literal: 10000 }, denominator: { field: self.ratioDenominator }, rounding: floor }] }\n when pricing is amortizing { calculate: [{ target: principalRatio, op: ratio, amount: { field: self.paymentBudget }, numerator: { field: self.principal }, denominator: { field: self.instalment }, rounding: floor }] }\n calculate: [\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: [\n { instrument: principal_piece, action: create, input: { slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.principalPayment } } }\n { instrument: profit_piece, action: create, input: { plan: { field: self.plan }, slice: { field: self.id }, payment: { field: input.payment }, limit: { field: self.profitPayment } } }\n { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [pending, due], limit: 1, where: { id: { field: self.id }, principalReceivable.balance: { literal: \"0\" }, profitReceivable.balance: { literal: \"0\" }, profitEarned.balance: { literal: \"0\" } } }, action: complete, input: {} }\n ]\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: pending, actor: { parent: payment } }\n action payoff { allowZero: true,\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 economics { purpose: principal, sourceParty: borrower }\n moves self.payoffProfit from self.plan.borrower to self.plan.profitIncome capture \"payoffReceipt\" economics { recipient: capital, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: borrower } }\n moves self.principalReceivable.balance from self.principalReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.profitReceivable.balance from self.profitReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.profitEarned.balance from self.profitEarned to self.debt economics { purpose: internal, sourceParty: programOperator }\n }\n action unwind_payoff { allowZero: true,\n from: paid, to: paid, actor: { parent: parent }\n moves self.payoffProfit from self.plan.profitIncome to self.plan.borrower economics { recipient: capital, company: { purpose: earning, sourceParty: capital, reversalOf: self.payoffReceipt }, participant: unclassified }\n }\n action write_off { allowZero: true,\n from: [pending, due], to: written_off, actor: { parent: parent }\n 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 }\n }\n action cancel { allowZero: true,\n from: [pending, due, paid], to: cancelled, actor: { parent: parent }\n moves self.principalReceivable.balance from self.principalReceivable to self.debt 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.debt economics { purpose: internal, sourceParty: programOperator }\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 reschedule { from: pending, to: pending, actor: { parent: slice }, calculate: [{ target: dueAt, op: shift, date: { field: self.slice.dueAt }, milliseconds: { literal: 0 }, direction: after }] }\n 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 } }\n }\n payment: {\n revisioned: true\n fields { plan: ref<parent>, amount: money, paymentIdentity: text, held: account of self\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, actor: { party: borrower }\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 economics { purpose: principal, sourceParty: borrower }\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, guard: { kind: compare, left: { field: self.held.balance }, operator: \">\", right: { literal: \"0\" } }, input: { payment: { field: self.id } } }]\n }\n when apply is fines_profit_principal {\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due], limit: 366, order: [position] }, action: collect_waterfall, guard: { kind: compare, left: { field: self.held.balance }, operator: \">\", right: { literal: \"0\" } }, 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, guard: { kind: compare, left: { field: self.held.balance }, operator: \">\", right: { literal: \"0\" } }, 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 requires count of { instrument: current(), reference: \"plan\", anchor: self.plan, states: [paid], limit: 366 } <= self.plan.paymentLimit\n requires count of { instrument: profit_piece, reference: \"plan\", anchor: self.plan, states: [paid], limit: 366 } <= self.plan.historyLimit\n requires count of { instrument: all(financing.late_charge.receipt), reference: \"plan\", anchor: self.plan, states: [paid], limit: 366 } <= self.plan.historyLimit\n requires count of { instrument: all(financing.late_charge.cost.receipt), reference: \"plan\", anchor: self.plan, states: [paid], limit: 366 } <= self.plan.historyLimit\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 unwind { from: paid, to: refunded, actor: { parent: [parent, settlement] } }\n action refund {\n from: paid, to: refunded, actor: { party: capital }, deadline: { at: self.plan.refundUntil }\n requires unique \"settlement_consumption\" on [self.plan, self.paymentIdentity]; requires self.plan in [active, paid]\n requires count of { instrument: settlement, reference: \"plan\", anchor: self.plan, states: [recorded], limit: 366, where: { identity: { field: self.paymentIdentity } } } == 1\n invoke: [{ selection: { instrument: settlement, reference: \"plan\", anchor: self.plan, states: [recorded], limit: 366, where: { identity: { field: self.paymentIdentity } } }, action: refund, input: {} }]\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? }\n lifecycle { states: [paid, refunded], initial: paid }\n action create { allowZero: true,\n calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.slice.principalReceivable.balance }, { field: self.limit }] }]\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 economics { purpose: principal, sourceParty: programOperator }; moves self.amount from self.slice.principalReceivable to self.slice.debt economics { purpose: internal, sourceParty: programOperator }\n }\n action refund { allowZero: true,\n from: paid, to: refunded, actor: { parent: payment }\n 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 }\n }\n }\n profit_piece: {\n fields { cashReceipt: text?, plan: ref<parent>, slice: ref<slice>, payment: ref<payment>, limit: money, amount: money? }\n lifecycle { states: [paid, refunded], initial: paid }\n action create { allowZero: true,\n calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.limit }] }]\n actor: { parent: slice }\n input { plan: ref<parent>, 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 capture \"cashReceipt\" economics { recipient: capital, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: programOperator } }\n when profit_earned is on_payment { moves self.amount from self.slice.profitReceivable to self.slice.debt economics { purpose: internal, sourceParty: programOperator } }\n when profit_earned is by_schedule { moves self.amount from self.slice.profitEarned to self.slice.debt economics { purpose: internal, sourceParty: programOperator } }\n when profit_earned is at_disbursement { moves self.amount from self.slice.profitEarned to self.slice.debt economics { purpose: internal, sourceParty: programOperator } }\n }\n action refund { allowZero: true,\n from: paid, to: refunded, actor: { parent: [payment, parent] }\n 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 }\n when profit_earned is on_payment { moves self.amount from self.slice.debt to self.slice.profitReceivable economics { purpose: internal, sourceParty: borrower } }\n when profit_earned is by_schedule { moves self.amount from self.slice.debt to self.slice.profitEarned economics { purpose: internal, sourceParty: borrower } }\n when profit_earned is at_disbursement { moves self.amount from self.slice.debt to self.slice.profitEarned economics { purpose: internal, sourceParty: borrower } }\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, borrower: party = party(person)) {\n parameterDiagnostics {\n fine {\n accepts: \"a fixed amount\"\n percentage: \"a percentage of overdue debt\"\n fix: \"Use a fixed amount only if that is the intended policy. A percentage charge needs an authored rate calculation; do not approximate it with a cash amount.\"\n }\n }\n revisioned: true\n familyRevision: 1\n summary: \"Separate 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?, payoffAmount: money?, payoffReceipt: text?\n receivable: account(self, claim), debt: account(borrower, claim, contra, \"debt\")\n }\n lifecycle { states: [proposed, assessed, collected, waived], initial: proposed }\n action create { input { slice: ref<on.slice>? }, calculate: [{ target: overdueAt, op: shift, date: { field: self.slice.dueAt }, milliseconds: { literal: grace }, direction: after }, { target: payoffAmount, op: sum, values: [{ literal: \"0\" }] }], requires unique \"late_assessment\" on [self.slice, self.overdueAt]; requires self.borrower == self.slice.plan.borrower; requires self.plan == self.slice.plan; requires count of { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [proposed, assessed, collected], limit: 366 } < self.plan.historyLimit }\n action assess { allowZero: true,\n from: proposed, to: assessed, actor: clock, due: { at: self.overdueAt }\n requires self.slice.principalReceivable.balance > \"0\"\n moves self.fine from self.debt to self.receivable economics { purpose: internal, sourceParty: borrower }\n }\n action collect {\n from: [assessed, collected], to: assessed, actor: { parent: child(on, slice) }, 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: { plan: { field: self.plan }, 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 payoff { allowZero: true,\n from: [assessed, collected], to: collected, actor: { parent: on }\n requires self.plan in [paid]\n calculate: [{ target: payoffAmount, op: sum, values: [{ field: self.receivable.balance }] }]\n moves self.payoffAmount from self.plan.borrower to fines_to capture \"payoffReceipt\" economics { recipient: fines_to, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: borrower } }\n moves self.payoffAmount from self.receivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n }\n action unwind_payoff { allowZero: true,\n from: collected, to: collected, actor: { parent: on }\n moves self.payoffAmount from fines_to to self.plan.borrower economics { recipient: fines_to, company: { purpose: earning, sourceParty: fines_to, reversalOf: self.payoffReceipt }, participant: unclassified }\n }\n action finish { from: assessed, to: collected, actor: { parent: current() }, requires self.receivable.balance == \"0\" }\n action cancel { from: proposed, to: waived, actor: { party: programOperator } }\n action cancel_for_amendment { from: proposed, to: waived, actor: { parent: child(on, amendment) } }\n action cancel_undelivered { allowZero: true, from: [proposed, assessed, collected], to: waived, actor: { parent: on }, moves self.receivable.balance from self.receivable to self.debt economics { purpose: internal, sourceParty: programOperator } }\n action waive_for_amendment {\n from: [assessed, collected], to: assessed, actor: { parent: child(on, amendment) }, input { amendment: ref<on.amendment> }\n requires input.amendment.plan == self.plan; requires input.amendment in [applied]\n invoke: [{ instrument: waiver, action: create, input: { assessment: { field: self.id }, amendment: { field: input.amendment } } }]\n }\n 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 } }\n action refund {\n from: [assessed, collected], to: assessed, actor: { party: fines_to }, input { payment: ref<on.payment> }, deadline: { at: self.plan.refundUntil }\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 waiver_request: {\n fields { assessment: ref<parent>, reason: text, evidence: text }\n lifecycle { states: [requested, applied, cancelled], initial: requested }\n action create { requires self.assessment in [assessed, collected] }\n action apply {\n from: requested, to: applied, actor: { party: fines_to }, input { reason: text, evidence: text }\n invoke: [{ reference: self.assessment, action: waive, input: { reason: { field: input.reason }, evidence: { field: input.evidence } } }]\n }\n action cancel { from: requested, to: cancelled }\n }\n waiver: {\n fields { assessment: ref<parent>, amendment: ref<on.amendment>, amount: money? }\n lifecycle { states: [recorded], initial: recorded }\n action create { allowZero: true,\n actor: { parent: parent }, input { assessment: ref<parent>, amendment: ref<on.amendment> }\n calculate: [{ target: amount, op: rate, base: { field: self.assessment.receivable.balance }, bps: { field: self.amendment.waiverPercent }, rounding: floor }]\n requires unique \"amendment_waiver\" on [self.assessment, self.amendment]\n moves self.amount from self.assessment.receivable to self.assessment.debt economics { purpose: internal, sourceParty: programOperator }\n }\n }\n receipt: {\n fields { cashReceipt: text?, plan: ref<on>, assessment: ref<parent>, payment: ref<on.payment>, amount: money? }\n lifecycle { states: [paid, refunded], initial: paid }\n action create { allowZero: true, calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.assessment.receivable.balance }] }], actor: { parent: parent }, input { plan: ref<on>, 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: pass_through, sourceParty: programOperator } }; moves self.amount from self.assessment.receivable to self.assessment.debt economics { purpose: internal, sourceParty: programOperator } }\n action refund { allowZero: true, from: paid, to: refunded, actor: { parent: [parent, on] }, 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 } }\n }\n\n cost: {\n revisioned: true\n fields {\n plan: ref<on>, assessment: ref<parent>, overdueAt: date?, evidence: text, evidencedCost: money, amount: money = minimum(self.evidencedCost, cap), payoffAmount: money?, payoffReceipt: text?\n receivable: account(self, claim), debt: account(borrower, claim, contra, \"debt\")\n }\n lifecycle { states: [proposed, assessed, collected, waived], initial: proposed }\n action create { actor: { party: programOperator }, calculate: [{ target: overdueAt, op: shift, date: { field: self.assessment.overdueAt }, milliseconds: { literal: 0 }, direction: after }, { target: payoffAmount, op: sum, values: [{ literal: \"0\" }] }], requires unique \"recovery_assessment\" on [self.assessment]; requires self.plan == self.assessment.plan; requires count of { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [proposed, assessed, collected], limit: 366 } < self.plan.historyLimit }\n action assess { allowZero: true,\n from: proposed, to: assessed, actor: clock, due: { at: self.assessment.overdueAt }\n requires self.assessment.slice.principalReceivable.balance > \"0\"\n moves self.amount from self.debt to self.receivable economics { purpose: internal, sourceParty: borrower }\n }\n action collect {\n from: [assessed, collected], to: assessed, actor: { parent: child(on, slice) }, 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: { plan: { field: self.plan }, 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 payoff { allowZero: true,\n from: [assessed, collected], to: collected, actor: { parent: on }\n requires self.plan in [paid]\n calculate: [{ target: payoffAmount, op: sum, values: [{ field: self.receivable.balance }] }]\n moves self.payoffAmount from self.plan.borrower to costs_to capture \"payoffReceipt\" economics { recipient: costs_to, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: borrower } }\n moves self.payoffAmount from self.receivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n }\n action unwind_payoff { allowZero: true,\n from: collected, to: collected, actor: { parent: on }\n moves self.payoffAmount from costs_to to self.plan.borrower economics { recipient: costs_to, company: { purpose: earning, sourceParty: costs_to, reversalOf: self.payoffReceipt }, participant: unclassified }\n }\n action finish { from: assessed, to: collected, actor: { parent: current() }, requires self.receivable.balance == \"0\" }\n action cancel { from: proposed, to: waived, actor: { party: programOperator } }\n action cancel_for_amendment { from: proposed, to: waived, actor: { parent: child(on, amendment) } }\n action cancel_undelivered { allowZero: true, from: [proposed, assessed, collected], to: waived, actor: { parent: on }, moves self.receivable.balance from self.receivable to self.debt economics { purpose: internal, sourceParty: programOperator } }\n action waive_for_amendment {\n from: [assessed, collected], to: assessed, actor: { parent: child(on, amendment) }, input { amendment: ref<on.amendment> }\n requires input.amendment.plan == self.plan; requires input.amendment in [applied]\n invoke: [{ instrument: waiver, action: create, input: { assessment: { field: self.id }, amendment: { field: input.amendment } } }]\n }\n 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 } }\n action refund {\n from: [assessed, collected], to: assessed, actor: { party: costs_to }, input { payment: ref<on.payment> }, deadline: { at: self.plan.refundUntil }\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 waiver_request: {\n fields { assessment: ref<parent>, reason: text, evidence: text }\n lifecycle { states: [requested, applied, cancelled], initial: requested }\n action create { requires self.assessment in [assessed, collected] }\n action apply {\n from: requested, to: applied, actor: { party: costs_to }, input { reason: text, evidence: text }\n invoke: [{ reference: self.assessment, action: waive, input: { reason: { field: input.reason }, evidence: { field: input.evidence } } }]\n }\n action cancel { from: requested, to: cancelled }\n }\n waiver: {\n fields { assessment: ref<parent>, amendment: ref<on.amendment>, amount: money? }\n lifecycle { states: [recorded], initial: recorded }\n action create { allowZero: true,\n actor: { parent: parent }, input { assessment: ref<parent>, amendment: ref<on.amendment> }\n calculate: [{ target: amount, op: rate, base: { field: self.assessment.receivable.balance }, bps: { field: self.amendment.waiverPercent }, rounding: floor }]\n requires unique \"amendment_waiver\" on [self.assessment, self.amendment]\n moves self.amount from self.assessment.receivable to self.assessment.debt economics { purpose: internal, sourceParty: programOperator }\n }\n }\n receipt: {\n fields { cashReceipt: text?, plan: ref<on>, assessment: ref<parent>, payment: ref<on.payment>, amount: money? }\n lifecycle { states: [paid, refunded], initial: paid }\n action create { allowZero: true, calculate: [{ target: amount, op: minimum, values: [{ field: self.payment.held.balance }, { field: self.assessment.receivable.balance }] }], actor: { parent: parent }, input { plan: ref<on>, 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: pass_through, sourceParty: programOperator } }; moves self.amount from self.assessment.receivable to self.assessment.debt economics { purpose: internal, sourceParty: programOperator } }\n action refund { allowZero: true, from: paid, to: refunded, actor: { parent: [parent, on] }, 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 } }\n }\n }\n }\n }\n}\n\ninstrument limits(per_borrower: money, borrower: party = party(person), active_plans: integer = 1) {\n familyRevision: 1\n scope: product\n summary: \"One outstanding balance ceiling per borrower.\"\n fields { borrower: account of borrower, limit: money = per_borrower, activePlans: integer = active_plans }\n lifecycle { states: [pending, approved], initial: pending }\n action create { actor: { party: borrower }, requires unique \"borrower_limit\" on [self.borrower] }\n action approve { from: pending, to: approved, actor: { party: programOperator } }\n}\n\ninstrument portfolio_limit(limit: money) {\n familyRevision: 1\n scope: product\n summary: \"One shared ceiling on the principal the product may hold.\"\n fields { key: text = \"portfolio\", limit: money = limit }\n lifecycle { states: [pending, approved], initial: pending }\n action create { actor: { party: programOperator }, requires unique \"portfolio_limit\" on [self.key] }\n action approve { from: pending, to: approved, actor: { party: programOperator } }\n}\n\ninstrument credit_line(borrower: party = programOperator, adapter: text, limit: money, expires: date) {\n familyRevision: 1\n summary: \"A revolving facility from an outside lender; each draw is a separate immutable advance.\"\n fields { borrower: account of borrower, facility: account(borrower, cash, \"facility\"), debt: account(borrower, claim, contra, \"debt\"), limit: money = limit, expiresAt: date = expires }\n lifecycle { states: [pending, active, suspended, closed], initial: pending }\n action create { actor: { party: borrower } }\n action activate {\n from: pending, to: active, actor: { party: borrower }\n subject { adapter: adapter }\n }\n action suspend { from: active, to: suspended, actor: { party: borrower } }\n action resume { from: suspended, to: active, actor: { party: borrower } }\n action close { from: [active, suspended], to: closed, actor: { party: borrower }, 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, borrower: party = programOperator) {\n familyRevision: 1\n summary: \"A single facility draw with an immutable principal and full repayment.\"\n fields { line: ref<line>, borrower: account of borrower, amount: money = amount, principalReceivable: account(self, claim) }\n lifecycle { states: [pending, drawn, repaid, cancelled], initial: pending }\n action create { actor: { party: borrower }, requires self.borrower == self.line.borrower; 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, actor: { party: borrower }\n requires self.line in [active]\n deadline: { at: self.line.expiresAt }\n moves self.amount from self.line.facility to self.line.borrower; moves self.amount from self.line.debt to self.principalReceivable\n }\n action repay { from: drawn, to: repaid, actor: { party: borrower }, moves self.amount from self.line.borrower to self.line.facility; moves self.amount from self.principalReceivable to self.line.debt }\n action cancel { from: pending, to: cancelled, actor: { party: borrower } }\n}\n"],
9
- ["insurance.hsx", "header insurance\n\n// Economics: Company commission is earning; refunds reverse its captured transfer.\n// Outside broker commissions and insurer premiums are pass-through.\n// Claim moves remain unclassified until their money purpose is declared.\n\n// Expose cover.create, activate and cancel separately. The adapter names a\n// registered boundary adapter (conformance_boundary in sandbox). covers is an\n// optional link to a sibling attachment; the attached object is already the\n// insured thing. claim_limit is the sum insured: approved and paid claims on one\n// cover, across every claim attachment, never total more. Activation binds adapter;\n// each slice needs a separately created unique period and an active cover to collect.\n// Collection debits holder for insurerPremium to the insurer and commission to\n// broker as two moves. Broker defaults to programOperator; bind a declared business\n// for a distinct agency. The two amounts sum to premium. Zero portions are allowed.\n// Cover.cancel invokes refund only on paid slices, before each startsAt. It returns\n// insurerPremium from insurer and commission from broker to holder. Active or\n// expired periods are excluded; insufficient recipient funds refuse the reversal.\n// Slice refund is parent-owned, not a public alias. Expose cover.cancel instead.\n// Claims require active cover. Expose claim.create, approve, deny and pay as needed.\n// Inspector approves OR denies from submitted. After approval only pay or clock\n// expiry can consume the reservation; deny is never available after approval.\n// Inspector is a bound party, not necessarily staff. These are ledger transfers;\n// outside settlement needs the boundary protocol, not a claim of provider success.\n\n// Cost: each slice collection or refund declares two transfers. Claim approval\n// reserves once; pay posts once and expiry voids once. Cover cancellation adds\n// bounded slice invocations. Run hsx cost for composed counts, not provider prices.\n\ninstrument cover(holder: party, adapter: text, commission: percent = 0%, broker: party = programOperator, covers: ref?, premium: money = runtime, claim_limit: money = runtime) {\n summary: \"Recurring cover bound to an outside insurer across an ADL boundary.\"\n fields { covers: ref<covers>?, holder: account of holder, insurer: account(adapter(adapter), cash, \"premium\"), expiresAt: date, claimLimit: money = claim_limit }\n lifecycle { states: [pending, active, cancelled, expired], initial: pending }\n action create { actor: { party: holder } }\n action activate {\n from: pending, to: active, actor: { party: programOperator }\n subject { adapter: adapter }\n }\n action cancel {\n from: active, to: cancelled, actor: { party: holder }\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>, premium: money = premium, startsAt: date, endsAt: date\n commission: money = rate(self.premium, commission)\n insurerPremium: money = subtract(self.premium, self.commission), commissionReceipt: text?\n }\n lifecycle { states: [pending, paid, active, expired, refunded], initial: pending }\n action create {\n requires self.startsAt < self.endsAt\n requires unique \"premium_period\" on [self.cover, self.startsAt, self.endsAt]\n }\n action collect {\n allowZero: true\n requires self.premium > \"0\"\n from: pending, to: paid, actor: { party: holder }\n requires self.cover in [active]\n moves self.insurerPremium from holder to self.cover.insurer economics { purpose: pass_through, sourceParty: holder }\n moves self.commission from holder to broker capture \"commissionReceipt\" economics { recipient: broker, company: { purpose: earning, sourceParty: holder }, participant: { purpose: pass_through, sourceParty: holder } }\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 allowZero: true\n requires self.premium > \"0\"\n from: paid, to: refunded, actor: { parent: parent }, deadline: { at: self.startsAt }\n moves self.insurerPremium from self.cover.insurer to holder economics { purpose: pass_through, sourceParty: programOperator }\n moves self.commission from broker to holder economics { recipient: broker, company: { purpose: earning, sourceParty: broker, reversalOf: self.commissionReceipt }, participant: { purpose: pass_through, sourceParty: broker } }\n }\n }\n }\n}\n\ninstrument claim(cover: ref<insurance.cover>, inspector: party) {\n summary: \"A claim 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 invariants sum \"amount\" of { instrument: all(insurance.claim), reference: \"cover\", anchor: self.cover, states: [approved, paid], limit: 366 } <= self.cover.claimLimit\n action create { requires self.cover in [active] }\n action approve {\n from: submitted, to: approved\n actor: { party: inspector }\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, actor: { party: inspector }, deadline: { at: self.expiresAt }, moves post self.reservation }\n action deny { from: submitted, to: denied, actor: { party: inspector } }\n action expire { from: approved, to: expired, actor: clock, due: { at: self.expiresAt }, moves void self.reservation }\n}\n"],
10
- ["lending.hsx", "header lending\n\n// Economics: Funding and commitment returns are principal. Distribution tax is\n// pass-through; own-account fee and claim allocations are internal. Mixed\n// principal/profit distributions and unbound source owners remain unclassified.\n\n// Round target is plan.principal from runtime subject.price, not its credit limit.\n// The operator opens the round and closes it before closesAt. Expose\n// round.create and close plus commitment.create and withdraw. A commitment\n// debits the bound investor's original active wallet before closesAt. Investor cap\n// aggregates by investor across wallets. A round still open at closesAt fails,\n// even when fully committed, and refunds those original wallets.\n// Closing needs the exact target; it funds plan.capital and does not disburse the\n// loan. Expose plan.disburse separately after signing and limit approval.\n// Distribution.create needs a recorded settlement matching the plan. Only the\n// payout consumes it: distribute_cash or distribute_loss claims the settlement\n// and marks it distributed, so the plan's unwind_paid keeps that profit, while an\n// abandoned distribution leaves the settlement refundable.\n// Prepare cash or loss first, then create shares against funded commitments of\n// that round. Distribution needs pending share weights equal to the round target.\n// Cash fee is a percentage of retained profit, VAT a percentage of that fee.\n// Principal plus retained profit less fee and VAT goes to weighted wallets;\n// floored residual goes to residual_to. Loss mode moves claim balances, not cash.\n// Child share execution is parent-owned. No report or clock proves outside payout.\n\n// Cost: round.create declares one owned account. Close transfers its balance\n// and invokes commitments; failure invokes their refunds. Distribution adds moves\n// and bounded share invocations. Run hsx cost for counts after policy selection.\n\ninstrument round(borrower: party, plan: ref<financing.installments> = object(financing.installments), operator: party = programOperator, 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, plan: ref<plan>, price: money = self.plan.principal, closesAt: date\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 { actor: { party: operator }, requires unique \"funding_plan\" on [self.plan]; requires self.borrower == self.plan.borrower }\n action close {\n from: open, to: funded, actor: { party: operator }\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 economics { purpose: principal, sourceParty: programOperator }\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 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>, investor: account of investor, 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: { investor: { field: self.investor } } } <= 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 actor: { party: investor }\n requires self.round in [open]\n requires self.wallet in [active]\n requires self.wallet.holder == self.investor\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 economics { purpose: principal, sourceParty: programOperator }\n }\n action fund { from: committed, to: funded, actor: { parent: round } }\n action withdraw {\n from: committed, to: withdrawn, actor: { party: investor }\n requires self.round in [open]\n deadline: { at: self.round.closesAt }\n moves self.amount from self.round.held to self.wallet.held economics { purpose: principal, sourceParty: programOperator }\n }\n action refund {\n from: committed, to: refunded, actor: { parent: round }\n moves self.amount from self.round.held to self.wallet.held economics { purpose: principal, sourceParty: programOperator }\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, operator: 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 {\n requires self.round in [funded]; requires self.source in [recorded]; requires self.source.plan == self.round.plan\n }\n action prepare_cash {\n from: pending, to: cash_ready\n requires self.mode == \"cash\"; requires self.source.kind == \"cash\"; requires self.source in [recorded]\n calculate: [\n { target: \"principal\", op: \"sum\", values: [{ field: self.source.principal }] }\n { target: \"profit\", op: \"sum\", values: [{ field: self.source.retainedProfit }] }\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\"; requires self.source in [recorded]\n calculate: [{ target: \"net\", op: \"sum\", values: [{ field: self.source.loss }] }]\n }\n action distribute_cash { allowZero: true,\n from: cash_ready, to: distributed, actor: { party: operator }\n requires self.source in [recorded]; requires unique \"settlement_consumption\" on [self.source.plan, self.source.identity]\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 economics { purpose: internal, sourceParty: programOperator }; moves self.vat from self.held to programTax economics { purpose: pass_through, sourceParty: programOperator }\n invoke: [{ reference: self.source, action: distribute, input: {} }, { 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 { allowZero: true,\n from: distributed, to: distributed, actor: { parent: current() }\n moves self.held.balance from self.held to residual_to\n }\n action distribute_loss { allowZero: true,\n from: loss_ready, to: distributed, actor: { party: operator }\n requires self.source in [recorded]; requires unique \"settlement_consumption\" on [self.source.plan, self.source.identity]\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: [{ reference: self.source, action: distribute, input: {} }, { 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 { allowZero: true,\n from: distributed, to: distributed, actor: { parent: current() }\n moves self.losses.balance from self.losses to self.residualLoss economics { purpose: internal, sourceParty: programOperator }\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 { allowZero: true,\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 { 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 } }\n }\n }\n}\n"],
8
+ ["financing.hsx", "header financing\n\n// Economics: Principal advances and repayments are excluded from earnings. Claims, waivers,\n// write-offs and allocations are internal. Paid profit and company charges are\n// earnings; receipt refunds reverse captured cash. Borrower cash paid to outside\n// capital or recovery recipients passes through, whether held first or paid direct.\n\n// Terms: loan_kind names the product and caps the term. max_term defaults to\n// the longest term the library allows for that kind, and a company may lower it\n// but never raise it:\n// mortgage 360 monthly instalments\n// auto 84\n// personal 84 (the default kind)\n// short_term 12 (pay later and other short consumer credit)\n// months is the instalment count of one plan. Set it in the program to fix the\n// term, or leave it runtime and supply it at create; create refuses a plan\n// longer than max_term.\n\n// Pricing is required. amortizing reads profit_rate as an annual rate on the\n// declining balance: equal monthly instalments, the last absorbing rounding.\n// flat_total reads it as one charge on principal for the whole term (murabaha,\n// fixed-fee pay-later). 12,000 at 18% over 12 months costs 13,201.95 amortizing\n// and 14,160 flat_total.\n// Expose create and sign on installments. A funding composition owns checkout,\n// destination funding and returns when disburse_to is funds. The repayment plan\n// owns principal, profit, limits and debt cancellation.\n// disburse_to: seller pays principal to the seller party at activation (pay later\n// with the merchant paid on day one). Capital may refund any paid payment to\n// the borrower. Payments stay refundable while the plan is active. The\n// payment that clears the last slice completes the plan when no late charge or\n// recovery cost is outstanding; otherwise expose complete to close it once they\n// are settled or waived. When\n// the plan leaves active (paid, written off or cancelled) it sets refundUntil to\n// refund_within (default 30d) later, and payment, late charge and recovery cost\n// refunds stop at that time. A refund that reopens the plan clears refundUntil, which is set\n// from the calculated refundWindow so a restore can clear it. Once it passes,\n// nothing can move the plan's payments or late charges, so they stop counting as\n// open records. On a return, capital runs unwind: it takes the outstanding\n// principal back to capital and cancels open slices with their claims. Seller\n// mode debits the seller, who also returns the principal the borrower repaid;\n// funds mode needs the hold in return_verified and debits the hold, after which\n// the payee's escrow refund returns the down payment and the repaid principal.\n// Before delivery, the Product\n// operator runs unwind_undelivered on a funds-mode plan whose hold is still\n// funded: principal goes back to capital and the hold's unwind_financed returns\n// the down payment to the payer and closes the hold as refunded, all in one\n// operation, so deliver is refused afterwards. It also cancels proposed and\n// assessed late charges and recovery costs: goods that never arrived earn no\n// fines. Escrow refund refuses while any plan that is\n// not cancelled funds the hold, written off included, so the borrower never\n// receives lender principal. A funds-mode plan writes off only once its hold\n// has released principal to the seller: principal still held is not a loss, and\n// unwind or unwind_undelivered returns it. unwind_undelivered needs no paid\n// payments and no collected late charges; refund them first. unwind needs no\n// assessed late charges; waive them first. When goods never arrive on a paid plan, the\n// Product operator runs unwind_paid once the hold's deliverBy has passed, so an\n// early payoff never cuts the seller's delivery window short. It refunds the\n// profit of every payment, every share, fine and cost receipt, reverses the\n// payoff's profit, fines and costs, cancels the plan, and returns the hold's\n// whole price to the borrower; capital keeps the principal the borrower repaid.\n// A settlement a lending.distribution has paid out keeps its profit and share,\n// since investors hold that profit; only the other settlements' profit is\n// refunded. Each refund is its own transfer, so unwind_paid moves the plan to\n// unwinding and refunds 64 payments and 16 fine and 16 cost receipts per\n// operation; the plan's unwind_step clock runs the next batch a second later\n// until none remain, then the plan cancels and the hold refunds. max_history\n// (default and most 366) caps the late charges and recovery costs on one plan,\n// counted across every late charge attachment. A company lowers it to keep\n// payoffs and amendments smaller. If any source account is short, the whole\n// action refuses and nothing moves; a company that wants a partial refund\n// writes that rule in its own program.\n// returned_goods decides the split on returned goods, before or after payoff.\n// keep_profit, the default, keeps the profit and fines paid so far with the\n// company: unwind runs with payments still paid, and on a paid plan the Product\n// operator runs return_hold after the refund window to return a return_verified\n// hold's whole balance. refund_all makes unwind wait until capital has refunded\n// every payment and collected charge, removes return_hold, and lets unwind_paid\n// settle returned goods too.\n// Borrower- and seller-directed disbursement exclude collect_down_payment. A down_payment\n// there reduces principal but does not collect cash. Price is subject metadata,\n// not the borrower limit. The funding composition checks its payer and price.\n// Cancelling a plan cancels its debt agreement. Its funding composition owns\n// returning any cash collected before activation.\n// Approve borrower and portfolio limits before disbursement. Create builds the\n// dated slice records from future, strictly increasing dates; disbursement\n// refuses once a slice is due. Payments need a separate payment record and pay action.\n// Expose parent payoff separately and create a current, unexpired payoff_quote.\n// Expose late_charge.create as propose_assessment before the clock can assess;\n// provide matching plan, slice and borrower. Fine is fixed money, not a percentage.\n// A payment under fines_profit_principal first takes assessed fines and then\n// recovery costs, oldest first and at most charge_limit (default 12) of each,\n// then profit and principal slice by slice in due order. A payment that would\n// leave cash unapplied refuses, so a plan with more open charges than\n// charge_limit takes several payments. Collection uses the minimum of payment\n// cash and outstanding fine; a partial payment does not settle the remaining\n// fine. Recovery cost needs its own record,\n// which only the Product operator creates; only it cancels a proposed fine or cost.\n// Profit share credits capital's allocatedProfitPayable, not an outside agency.\n// Credit lines need adapter binding at activation; draws are ledger advances,\n// not evidence of outside funding. Only the line's borrower, the Product operator\n// by default, opens and closes the line and creates, draws, repays or cancels an\n// advance on it. Only the Product operator creates the portfolio limit and\n// approves borrower and portfolio limits. No clock declaration proves retries.\n\n// Cost: the plan holds one principal, unearned profit, earned profit, fine and\n// cost claim, so disbursement, payoff, write-off, cancellation and refunds post\n// one transfer per party and purpose, whatever the term. Slices, pieces and\n// charges are state. Only receipts carry their own transfers: a payment posts at\n// most 2 per collected charge, so charge_limit bounds it, and unwind_paid\n// batches its refunds. Run hsx cost on the selected policies; every action of a\n// 360-month plan stays under one 253-transfer batch. Profit is not a platform\n// tariff.\n\ninstrument installments(loan_kind: enum(mortgage, auto, personal, short_term) = personal, max_term: integer(1, 360) = 360, months: integer(1, 360) = runtime, max_history: integer(2, 366) = 366, pricing: enum(amortizing, flat_total), profit_rate: percent, charge_limit: integer(1, 24) = 12, disburse_to: enum(funds, borrower, seller) = funds, seller: party?, 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%, write_off_after: duration = 90d, max_extension: duration = 90d, max_amendments: integer(0, 366) = 2, waiver_limit: percent = 100%, amendment_expiry: duration = 7d, payoff_quote_expiry: duration = 1h, refund_within: duration = 30d, returned_goods: enum(keep_profit, refund_all) = keep_profit, allow_overdue: enum(allowed, blocked) = allowed, assessed_fines: enum(carry, require_waiver) = carry, down_payment: percent = 0%, funds: ref?, borrower: party = party(person), capital: party = programOperator, share: percent = 0%, limits: ref<financing.limits> = object(financing.limits), portfolio: ref<financing.portfolio_limit> = object(financing.portfolio_limit)) {\n dependencies {\n funds {\n selector: disburse_to, is: funds\n message: \"Attachment `{attachment}` disburses into a hold, but `funds` is not bound.\"\n fix: \"Bind `funds: checkout` to a funding composition. Choose `disburse_to: seller` to pay a seller on activation, or `disburse_to: borrower` only if the borrower should receive the money directly.\"\n }\n seller {\n selector: disburse_to, is: seller\n message: \"Attachment `{attachment}` pays a seller, but `seller` is not bound.\"\n fix: \"Bind `seller: merchant` to the declared business that receives the principal.\"\n }\n }\n ceilings { max_term { by: loan_kind, mortgage: 360, auto: 84, personal: 84, short_term: 12 } }\n constraints { months: at_most(max_term) }\n revisioned: true\n familyRevision: 1\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<portfolio>\n months: integer = months, maxTerm: integer = max_term, dates: list(date, max_term), historyLimit: integer = max_history\n allocatedPayable: account(capital, cash, \"allocatedProfitPayable\"), capital: account(capital, cash, \"capital\"), profitIncome: account(capital, cash, \"profitIncome\"), loss: account(capital, claim, \"loss\")\n principalReceivable: account(self, claim), profitReceivable: account(self, claim), profitEarned: account(self, claim), fineReceivable: account(self, claim), costReceivable: account(self, claim), debt: account(borrower, claim, contra, \"debt\")\n principalOutstanding: money?, principalRepaid: money?, principalReturned: money?, profitReturned: money?, lossRecorded: money?, refundWindow: date?, refundUntil: date?\n scheduledPrincipal: money?, scheduledProfit: money?, payoffRebate: money?, payoffProfitTotal: money?, payoffProfit: money?, payoffReceipt: text?\n unwindAt: date?, paymentsLeft: integer?, finesLeft: integer?, costsLeft: integer?\n openSlices: integer?, openCharges: money?, openCosts: money?, payoffRefunds: integer?\n price: money = subject.price\n downPayment: money = rate(self.price, down_payment)\n principal: money = subtract(self.price, self.downPayment)\n flatProfit: money?\n }\n lifecycle { states: [quoted, signed, active, paid, unwinding, 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), reference: \"borrowerLimit\", anchor: self.borrowerLimit, states: [active], limit: 366 } <= self.borrowerLimit.limit\n invariants sum \"principalReceivable.balance\" of { instrument: all(financing.installments), reference: \"portfolioLimit\", anchor: self.portfolioLimit, states: [active], limit: 366 } <= self.portfolioLimit.limit\n action create {\n subject { price: money }\n actor: { party: borrower }\n requires self.borrowerLimit.borrower == self.borrower\n requires self.months <= self.maxTerm\n when pricing is flat_total { calculate: [{ target: flatProfit, op: rate, base: { field: self.principal }, bps: { literal: profit_rate }, rounding: floor }] }\n when disburse_to is funds { invoke: [{ reference: self.funds, action: check, input: { plan: { field: self.id } } }] }\n invoke: [{ range: { count: { field: self.months }, maximum: max_term, bind: position }, instrument: slice, action: create, input: { plan: { field: self.id }, borrowerLimit: { field: self.borrowerLimit }, portfolioLimit: { field: self.portfolioLimit }, position: { field: position } } }, { selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [draft], limit: max_term, where: { first: { literal: 0 } } }, action: check_order, input: {} }]\n }\n action sign {\n from: quoted, to: signed, actor: { party: borrower }, input { signedOffer: text, affordabilityReference: text }\n requires count of { instrument: slice, reference: \"plan\", anchor: self.id, states: [draft], limit: max_term } == self.months\n }\n action collect_down_payment { allowZero: true,\n from: signed, to: signed, actor: { party: borrower }\n when disburse_to is borrower { requires true == false }\n when disburse_to is seller { requires true == false }\n when disburse_to is funds { invoke: [{ reference: self.funds, action: collect, input: { plan: { field: self.id } } }] }\n }\n action disburse { allowZero: true,\n from: signed, to: active, actor: { party: capital }\n requires self.borrowerLimit in [approved]\n requires self.portfolioLimit in [approved]\n calculate: [\n { target: scheduledPrincipal, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [draft], limit: max_term }, measure: { sum: \"principal\" } }\n { target: scheduledProfit, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [draft], limit: max_term }, measure: { sum: \"profit\" } }\n ]\n when disburse_to is funds { invoke: [{ reference: self.funds, action: disburse, input: { plan: { field: self.id } } }] }\n when disburse_to is borrower { moves self.principal from self.capital to self.borrower economics { purpose: principal, sourceParty: capital } }\n when disburse_to is seller { moves self.principal from self.capital to seller economics { purpose: principal, sourceParty: capital } }\n moves self.scheduledPrincipal from self.debt to self.principalReceivable economics { purpose: internal, sourceParty: borrower }\n moves self.scheduledProfit from self.debt to self.profitReceivable economics { purpose: internal, sourceParty: borrower }\n when profit_earned is at_disbursement { moves self.scheduledProfit from self.profitReceivable to self.profitEarned economics { purpose: internal, sourceParty: programOperator } }\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [draft], limit: max_term, order: [position] }, action: activate, input: {} }]\n }\n action complete {\n from: active, to: paid\n calculate: [{ target: refundWindow, op: shift, date: { field: self.now }, milliseconds: { literal: refund_within }, direction: after }]\n set: { refundUntil: { field: self.refundWindow } }\n requires count of { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: max_term } == 0\n requires self.fineReceivable.balance == \"0\"\n requires self.costReceivable.balance == \"0\"\n }\n action restore { from: [active, paid], to: active, actor: { parent: payment }, input { refundUntil: date? }, set: { refundUntil: { field: input.refundUntil } } }\n action payoff { allowZero: true,\n from: active, to: paid, actor: { party: borrower }\n input { quote: ref<payoff_quote> }\n requires input.quote.plan == self.id; requires input.quote.revision == self.productRevision\n deadline: { at: input.quote.expiresAt }\n calculate: [\n { target: principalReturned, op: sum, values: [{ field: self.principalReceivable.balance }] }\n { target: payoffRebate, op: rate, base: { field: self.profitReceivable.balance }, bps: { literal: payoff_rebate }, rounding: floor }\n { target: payoffProfitTotal, op: sum, values: [{ field: self.profitReceivable.balance }, { field: self.profitEarned.balance }] }\n { target: payoffProfit, op: subtract, base: { field: self.payoffProfitTotal }, subtract: [{ field: self.payoffRebate }] }\n { target: refundWindow, op: shift, date: { field: self.now }, milliseconds: { literal: refund_within }, direction: after }\n ]\n set: { refundUntil: { field: self.refundWindow } }\n moves self.principalReturned from self.borrower to self.capital economics { purpose: principal, sourceParty: borrower }\n moves self.payoffProfit from self.borrower to self.profitIncome capture \"payoffReceipt\" economics { recipient: capital, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: borrower } }\n moves self.principalReturned from self.principalReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.profitReceivable.balance from self.profitReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.profitEarned.balance from self.profitEarned to self.debt economics { purpose: internal, sourceParty: programOperator }\n // Each attachment's oldest open charge settles that attachment's charges in\n // one cash transfer; four attachments per kind are enough for any program\n // and settle_payoff refuses if a charge is still open.\n invoke: [\n { selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [assessed], limit: 1, batch: true, order: [overdueAt] }, action: payoff, input: {} }\n { selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [assessed], limit: 1, batch: true, order: [overdueAt] }, action: payoff, input: {} }\n { selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [assessed], limit: 1, batch: true, order: [overdueAt] }, action: payoff, input: {} }\n { selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [assessed], limit: 1, batch: true, order: [overdueAt] }, action: payoff, input: {} }\n { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [assessed], limit: 1, batch: true, order: [overdueAt] }, action: payoff, input: {} }\n { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [assessed], limit: 1, batch: true, order: [overdueAt] }, action: payoff, input: {} }\n { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [assessed], limit: 1, batch: true, order: [overdueAt] }, action: payoff, input: {} }\n { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [assessed], limit: 1, batch: true, order: [overdueAt] }, action: payoff, input: {} }\n ]\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: max_term, order: [position] }, action: payoff, input: { identity: { field: self.settlementIdentity } } }, { reference: self.id, action: settle_payoff, input: {} }]\n }\n action settle_payoff {\n from: paid, to: paid, actor: { parent: current() }\n requires self.fineReceivable.balance == \"0\"\n requires self.costReceivable.balance == \"0\"\n invoke: [{ instrument: settlement, action: create, input: { plan: { field: self.id }, identity: { field: self.settlementIdentity }, principal: { field: self.principalReturned }, profit: { field: self.payoffProfit }, loss: { literal: \"0\" }, kind: { literal: \"cash\" } } }]\n }\n action write_off { allowZero: true,\n from: active, to: written_off, actor: { parent: write_off_request }\n input { overdueSlice: ref<slice> }\n calculate: [{ target: lossRecorded, op: sum, values: [{ field: self.principalReceivable.balance }] }, { target: refundWindow, op: shift, date: { field: self.now }, milliseconds: { literal: refund_within }, direction: after }]\n set: { refundUntil: { field: self.refundWindow } }\n due: { at: input.overdueSlice.lossEligibleAt }\n requires input.overdueSlice.plan == self.id; requires input.overdueSlice.openPrincipal > \"0\"\n moves self.lossRecorded from self.principalReceivable to self.loss economics { purpose: internal, sourceParty: programOperator }\n moves self.profitReceivable.balance from self.profitReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.profitEarned.balance from self.profitEarned to self.loss economics { purpose: internal, sourceParty: programOperator }\n when disburse_to is funds { invoke: [{ reference: self.funds, action: write_off, input: { plan: { field: self.id } } }] }\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: max_term, 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 calculate: [\n { target: openSlices, op: aggregate, selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: max_term }, measure: count }\n { target: openCharges, op: sum, values: [{ field: self.fineReceivable.balance }] }\n { target: openCosts, op: sum, values: [{ field: self.costReceivable.balance }] }\n ]\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 invoke: [{ selection: { instrument: current(), reference: \"borrowerLimit\", anchor: self.borrowerLimit, states: [active], limit: 1, where: { id: { field: self.id }, openSlices: { literal: 0 }, openCharges: { literal: \"0\" }, openCosts: { literal: \"0\" } } }, action: complete, input: {} }]\n }\n action cancel { from: quoted, to: cancelled }\n action void { from: signed, to: cancelled, actor: { party: borrower } }\n action unwind { allowZero: true,\n from: active, to: cancelled, actor: { party: capital }\n calculate: [\n { target: refundWindow, op: shift, date: { field: self.now }, milliseconds: { literal: refund_within }, direction: after }\n { target: principalOutstanding, op: sum, values: [{ field: self.principalReceivable.balance }] }\n { target: principalRepaid, op: subtract, base: { field: self.principal }, subtract: [{ field: self.principalOutstanding }] }\n ]\n set: { refundUntil: { field: self.refundWindow } }\n when disburse_to is borrower { requires true == false }\n when returned_goods is refund_all {\n requires count of { instrument: payment, reference: \"plan\", anchor: self.id, states: [paid], limit: 1, batch: true } == 0\n requires count of { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [collected], limit: 1, batch: true } == 0\n requires count of { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [collected], limit: 1, batch: true } == 0\n }\n requires count of { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [assessed], limit: 1, batch: true } == 0\n requires count of { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [assessed], limit: 1, batch: true } == 0\n when disburse_to is funds { invoke: [{ reference: self.funds, action: refund, input: { plan: { field: self.id }, principal: { field: self.principalOutstanding } } }] }\n when disburse_to is seller {\n moves self.principalOutstanding from seller to self.capital economics { purpose: principal, sourceParty: seller }\n moves self.principalRepaid from seller to self.borrower economics { purpose: principal, sourceParty: seller }\n }\n moves self.principalOutstanding from self.principalReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.profitReceivable.balance from self.profitReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.profitEarned.balance from self.profitEarned to self.debt economics { purpose: internal, sourceParty: programOperator }\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: max_term, order: [position] }, action: cancel, input: {} }]\n }\n action unwind_undelivered { allowZero: true,\n from: active, to: cancelled, actor: { party: programOperator }\n calculate: [{ target: refundWindow, op: shift, date: { field: self.now }, milliseconds: { literal: refund_within }, direction: after }]\n set: { refundUntil: { field: self.refundWindow } }\n when disburse_to is borrower { requires true == false }\n when disburse_to is seller { requires true == false }\n requires count of { instrument: payment, reference: \"plan\", anchor: self.id, states: [paid], limit: 1, batch: true } == 0\n requires count of { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [collected], limit: 1, batch: true } == 0\n requires count of { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [collected], limit: 1, batch: true } == 0\n moves self.principalReceivable.balance from self.principalReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.profitReceivable.balance from self.profitReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.profitEarned.balance from self.profitEarned to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.fineReceivable.balance from self.fineReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.costReceivable.balance from self.costReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due], limit: max_term, order: [position] }, action: cancel, input: {} }]\n invoke: [{ selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [proposed, assessed], limit: 366 }, action: cancel_undelivered, input: {} }, { selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [proposed, assessed], limit: 366 }, action: cancel_undelivered, input: {} }]\n when disburse_to is funds { invoke: [{ reference: self.funds, action: cancel_undelivered, input: { plan: { field: self.id } } }] }\n }\n action return_hold {\n from: paid, to: paid, actor: { party: programOperator }\n requires self.refundUntil < self.now\n when disburse_to is borrower { requires true == false }\n when disburse_to is seller { requires true == false }\n when returned_goods is refund_all { requires true == false }\n when disburse_to is funds {\n invoke: [{ reference: self.funds, action: return_paid, input: { plan: { field: self.id } } }]\n }\n }\n action unwind_paid {\n from: paid, to: unwinding, actor: { party: programOperator }\n when disburse_to is borrower { requires true == false }\n when disburse_to is seller { requires true == false }\n when disburse_to is funds {\n requires self.funds.funds.deliverBy < self.now\n when returned_goods is keep_profit { requires self.funds.funds in [funded] }\n when returned_goods is refund_all { requires self.funds.funds in [funded, return_verified] }\n }\n invoke: [{ reference: self.id, action: unwind_batch, input: {} }]\n }\n action unwind_step {\n from: unwinding, to: unwinding, actor: clock, due: { at: self.unwindAt }\n invoke: [{ reference: self.id, action: unwind_batch, input: {} }]\n }\n // One batch stays under one 253-transfer operation: 64 payments at two\n // transfers, 16 fine and 16 cost receipts at one, and the closing transfers.\n action unwind_batch {\n from: unwinding, to: unwinding, actor: { parent: current() }\n calculate: [{ target: unwindAt, op: shift, date: { field: self.now }, milliseconds: { literal: 1s }, direction: after }]\n invoke: [\n { selection: { instrument: payment, reference: \"plan\", anchor: self.id, states: [paid], limit: 64, batch: true }, action: unwind_paid, input: {} }\n { selection: { instrument: all(financing.late_charge.receipt), reference: \"plan\", anchor: self.id, states: [paid], limit: 16, batch: true }, action: unwind, input: {} }\n { selection: { instrument: all(financing.late_charge.cost.receipt), reference: \"plan\", anchor: self.id, states: [paid], limit: 16, batch: true }, action: unwind, input: {} }\n { reference: self.id, action: unwind_check, input: {} }\n ]\n }\n action unwind_check {\n from: unwinding, to: unwinding, actor: { parent: current() }\n calculate: [\n { target: paymentsLeft, op: aggregate, selection: { instrument: payment, reference: \"plan\", anchor: self.id, states: [paid], limit: 1, batch: true }, measure: count }\n { target: finesLeft, op: aggregate, selection: { instrument: all(financing.late_charge.receipt), reference: \"plan\", anchor: self.id, states: [paid], limit: 1, batch: true }, measure: count }\n { target: costsLeft, op: aggregate, selection: { instrument: all(financing.late_charge.cost.receipt), reference: \"plan\", anchor: self.id, states: [paid], limit: 1, batch: true }, measure: count }\n ]\n invoke: [{ selection: { instrument: current(), reference: \"borrowerLimit\", anchor: self.borrowerLimit, states: [unwinding], limit: 1, where: { id: { field: self.id }, paymentsLeft: { literal: 0 }, finesLeft: { literal: 0 }, costsLeft: { literal: 0 } } }, action: finish_unwind, input: {} }]\n }\n action finish_unwind { allowZero: true,\n from: unwinding, to: cancelled, actor: { parent: current() }\n calculate: [{ target: payoffRefunds, op: aggregate, selection: { instrument: settlement, reference: \"plan\", anchor: self.id, states: [recorded], limit: 1, where: { identity: { field: self.settlementIdentity } } }, measure: count }]\n moves self.principalReceivable.balance from self.principalReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.profitReceivable.balance from self.profitReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.profitEarned.balance from self.profitEarned to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.fineReceivable.balance from self.fineReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.costReceivable.balance from self.costReceivable to self.debt economics { purpose: internal, sourceParty: programOperator }\n invoke: [{ selection: { instrument: settlement, reference: \"plan\", anchor: self.id, states: [recorded], limit: 1, where: { identity: { field: self.settlementIdentity } } }, action: unwind, input: {} }, { reference: self.id, action: unwind_payoff_profit, guard: { kind: compare, left: { field: self.payoffRefunds }, operator: \"==\", right: { literal: 1 } }, input: {} }]\n invoke: [{ selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [collected], limit: 4, where: { payoffLed: { literal: 1 } } }, action: unwind_payoff, input: {} }, { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [collected], limit: 4, where: { payoffLed: { literal: 1 } } }, action: unwind_payoff, input: {} }]\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.id, states: [pending, due, paid], limit: max_term, order: [position] }, action: cancel, input: {} }]\n invoke: [{ selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.id, states: [proposed, assessed, collected], limit: 366 }, action: cancel_undelivered, input: {} }, { selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.id, states: [proposed, assessed, collected], limit: 366 }, action: cancel_undelivered, input: {} }]\n when disburse_to is funds {\n when returned_goods is keep_profit { invoke: [{ reference: self.funds, action: unwind_paid_undelivered, input: { plan: { field: self.id } } }] }\n when returned_goods is refund_all { invoke: [{ reference: self.funds, action: unwind_paid, input: { plan: { field: self.id } } }] }\n }\n }\n action unwind_payoff_profit { allowZero: true,\n from: cancelled, to: cancelled, actor: { parent: current() }\n moves self.payoffProfit from self.profitIncome to self.borrower economics { recipient: capital, company: { purpose: earning, sourceParty: capital, reversalOf: self.payoffReceipt }, participant: unclassified }\n }\n records {\n write_off_request: {\n fields { plan: ref<parent>, overdueSlice: ref<slice> }\n lifecycle { states: [requested, applied, cancelled], initial: requested }\n action create { requires self.overdueSlice.plan == self.plan; requires self.plan in [active] }\n action apply {\n from: requested, to: applied, actor: { party: capital }\n invoke: [{ reference: self.plan, action: write_off, input: { overdueSlice: { field: self.overdueSlice } } }]\n }\n action cancel { from: requested, to: cancelled }\n }\n payoff_quote: {\n fields {\n plan: ref<parent>, revision: text?, effectiveAt: date?, expiresAt: date = after(self.createdAt, payoff_quote_expiry)\n principal: money?, earnedProfit: money?, unearnedProfit: money?, rebate: money?, fines: money?, costs: money?, gross: money?, amount: money?\n }\n lifecycle { states: [quoted], initial: quoted }\n action create {\n requires self.plan in [active]\n set: { revision: { field: self.productRevision }, effectiveAt: { field: self.now } }\n calculate: [\n { target: principal, op: sum, values: [{ field: self.plan.principalReceivable.balance }] }\n { target: earnedProfit, op: sum, values: [{ field: self.plan.profitEarned.balance }] }\n { target: unearnedProfit, op: sum, values: [{ field: self.plan.profitReceivable.balance }] }\n { target: rebate, op: rate, base: { field: self.unearnedProfit }, bps: { literal: payoff_rebate }, rounding: floor }\n { target: fines, op: sum, values: [{ field: self.plan.fineReceivable.balance }] }\n { target: costs, op: sum, values: [{ field: self.plan.costReceivable.balance }] }\n { target: gross, op: sum, values: [{ field: self.principal }, { field: self.earnedProfit }, { field: self.unearnedProfit }, { field: self.fines }, { field: self.costs }] }\n { target: amount, op: subtract, base: { field: self.gross }, subtract: [{ field: self.rebate }] }\n ]\n }\n }\n amendment: {\n fields {\n plan: ref<parent>, dates: list(date, max_term), agreement: text, waiverPercent: percent, waiverEvidence: text, maximumWaiver: percent = waiver_limit\n revision: text?, acceptedAt: date?, staleReason: text?, expiresAt: date = after(self.createdAt, amendment_expiry)\n fineDisposition: enum(carry, require_waiver) = assessed_fines, addedProfit: money = 0 SAR\n principalSnapshot: money?, earnedProfitSnapshot: money?, unearnedProfitSnapshot: money?, finesSnapshot: money?, costsSnapshot: money?\n finesWaived: money?, costsWaived: money?\n extension: duration = max_extension, maximum: integer = max_amendments\n }\n lifecycle { states: [proposed, applied, declined, withdrawn, expired, superseded], initial: proposed }\n action create {\n actor: { party: capital }\n requires self.plan in [active]; requires self.waiverPercent <= self.maximumWaiver\n set: { revision: { field: self.productRevision } }\n calculate: [\n { target: principalSnapshot, op: sum, values: [{ field: self.plan.principalReceivable.balance }] }\n { target: earnedProfitSnapshot, op: sum, values: [{ field: self.plan.profitEarned.balance }] }\n { target: unearnedProfitSnapshot, op: sum, values: [{ field: self.plan.profitReceivable.balance }] }\n { target: finesSnapshot, op: sum, values: [{ field: self.plan.fineReceivable.balance }] }\n { target: costsSnapshot, op: sum, values: [{ field: self.plan.costReceivable.balance }] }\n ]\n requires count of { instrument: current(), reference: \"plan\", anchor: self.plan, states: [applied], limit: 366 } < self.maximum\n invoke: [{ range: { count: { field: self.plan.months }, maximum: max_term, bind: position }, instrument: proposed_date, action: create, input: { amendment: { field: self.id }, position: { field: position } } }, { selection: { instrument: proposed_date, reference: \"amendment\", anchor: self.id, states: [recorded], limit: max_term, where: { first: { literal: 0 } } }, action: check_order, input: {} }]\n }\n action accept {\n from: proposed, to: applied, actor: { party: borrower }, deadline: { at: self.expiresAt }\n requires self.plan in [active]; requires self.revision == self.productRevision\n requires count of { instrument: current(), reference: \"plan\", anchor: self.plan, states: [applied], limit: 366 } < self.maximum\n set: { acceptedAt: { field: self.now } }\n when assessed_fines is require_waiver { requires self.waiverPercent == 10000 }\n invoke: [{ selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366 }, action: waive_for_amendment, input: { amendment: { field: self.id } } }, { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [assessed, collected], limit: 366 }, action: waive_for_amendment, input: { amendment: { field: self.id } } }, { reference: self.id, action: record_waivers, input: {} }]\n invoke: [{ selection: { instrument: all(collections.case), reference: \"plan\", anchor: self.plan, states: [opened, assigned], limit: 366 }, action: recall, input: {} }, { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [proposed], limit: 366 }, action: cancel_for_amendment, input: {} }, { selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [proposed], limit: 366 }, action: cancel_for_amendment, input: {} }]\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due], limit: max_term, order: [position] }, action: amend, input: { amendment: { field: self.id } } }]\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [paid], limit: max_term }, action: verify_fixed_date, input: { amendment: { field: self.id } } }]\n }\n // The waivers are state on each charge; the plan's claims drop once per kind.\n action record_waivers { allowZero: true,\n from: applied, to: applied, actor: { parent: current() }\n calculate: [\n { target: finesWaived, op: aggregate, selection: { instrument: all(financing.late_charge.waiver), reference: \"amendment\", anchor: self.id, states: [recorded], limit: 366 }, measure: { sum: \"amount\" } }\n { target: costsWaived, op: aggregate, selection: { instrument: all(financing.late_charge.cost.waiver), reference: \"amendment\", anchor: self.id, states: [recorded], limit: 366 }, measure: { sum: \"amount\" } }\n ]\n moves self.finesWaived from self.plan.fineReceivable to self.plan.debt economics { purpose: internal, sourceParty: programOperator }\n moves self.costsWaived from self.plan.costReceivable to self.plan.debt economics { purpose: internal, sourceParty: programOperator }\n }\n action withdraw { from: proposed, to: withdrawn, actor: { party: capital } }\n action decline { from: proposed, to: declined, actor: { party: borrower } }\n action expire { from: proposed, to: expired, actor: clock, due: { at: self.expiresAt } }\n action supersede { from: proposed, to: superseded, requires self.revision != self.productRevision, set: { staleReason: { literal: \"economic_revision_changed\" } } }\n }\n proposed_date: {\n fields { amendment: ref<amendment>, position: integer(1, max_term), date: date = at(self.amendment.dates, self.position), first: integer = divide(1, self.position), prior: integer = subtract(self.position, 1), previousPosition: integer = sum(self.prior, self.first), previous: date = at(self.amendment.dates, self.previousPosition) }\n lifecycle { states: [recorded], initial: recorded }\n action create { actor: { parent: amendment }, input { amendment: ref<amendment>, position: integer(1, max_term) }, requires self.date >= self.previous }\n action check_order { from: recorded, to: recorded, actor: { parent: amendment }, requires self.date > self.previous }\n }\n date_change: {\n fields { amendment: ref<amendment>, slice: ref<slice>, oldDate: date, newDate: date }\n lifecycle { states: [recorded], initial: recorded }\n action create { actor: { parent: slice }, input { amendment: ref<amendment>, slice: ref<slice>, oldDate: date, newDate: date }, requires unique \"amended_slice\" on [self.amendment, self.slice] }\n }\n settlement: {\n fields { plan: ref<parent>, identity: text, principal: money, profit: money, loss: money, kind: enum(cash, loss), share: money?, retainedProfit: money?\n allocatedPayable: account(capital, cash, \"allocatedProfitPayable\"), capital: account(capital, cash, \"capital\"), profitIncome: account(capital, cash, \"profitIncome\"), lossAccount: account(capital, claim, \"loss\") }\n lifecycle { states: [recorded, distributed, refunded], initial: recorded }\n action create { allowZero: true,\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 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 }] }]\n moves self.share from self.profitIncome to self.allocatedPayable economics { purpose: internal, sourceParty: capital }\n }\n action refund { allowZero: true,\n from: recorded, to: refunded, actor: { parent: payment }\n moves self.share from self.allocatedPayable to self.profitIncome economics { purpose: internal, sourceParty: capital }\n }\n action distribute { from: recorded, to: distributed, actor: { parent: all(lending.distribution) } }\n // profitIncome is one account per capital party, so refunding profit a\n // distribution already paid out would spend other plans' profit. unwind_paid\n // unwinds only settlements still recorded, and each payment refunds its\n // profit only when its settlement was one of them.\n action unwind { allowZero: true,\n from: recorded, to: refunded, actor: { parent: [parent, payment] }\n moves self.share from self.allocatedPayable to self.profitIncome economics { purpose: internal, sourceParty: capital }\n }\n }\n slice: {\n revisioned: true\n fields {\n plan: ref<parent>, borrowerLimit: ref<limits>, portfolioLimit: ref<portfolio>, position: integer(1, max_term)\n originalDueAt: date = at(self.plan.dates, self.position), dueAt: date?, nextDueAt: date?, previousDueAt: date?, prior: integer = subtract(self.position, 1), previousPosition: integer = sum(self.prior, self.first), previousDate: date = at(self.plan.dates, self.previousPosition), extensionLimit: date = after(self.originalDueAt, max_extension), lossEligibleAt: date?\n first: integer = divide(1, self.position)\n principalBase: money?, principalAllocated: money?, principalRemainder: money?, principalAdjustment: money?\n profitBase: money?, profitAllocated: money?, profitRemainder: money?, profitAdjustment: money?\n principal: money, profit: money, instalment: money\n openPrincipal: money?, openProfit: money?, earnedProfit: money?, payoffIdentity: text?\n collectibleProfit: money?, collectibleTotal: money?, paymentBudget: money?, principalRatio: money?, principalBasePayment: money?, profitBudget: money?\n principalTake: money?, profitTake: money?, afterTake: money?, openProfitTake: money?, earnedProfitTake: money?, taken: money?\n ratioDenominator: integer = sum(10000, profit_rate)\n }\n lifecycle { states: [draft, pending, due, paid, written_off, cancelled], initial: draft }\n action create {\n actor: { parent: parent }\n input { plan: ref<parent>, borrowerLimit: ref<limits>, portfolioLimit: ref<portfolio>, position: integer(1, max_term) }\n set: { dueAt: { field: self.originalDueAt } }\n calculate: [\n { target: openPrincipal, op: sum, values: [{ literal: \"0\" }] }\n { target: openProfit, op: sum, values: [{ literal: \"0\" }] }\n { target: earnedProfit, op: sum, values: [{ literal: \"0\" }] }\n ]\n when pricing is flat_total {\n calculate: [\n { target: principalBase, op: divide, amount: { field: self.plan.principal }, divisor: { field: self.plan.months }, rounding: floor }\n { target: principalAllocated, op: multiply, amount: { field: self.principalBase }, units: { field: self.plan.months } }\n { target: principalRemainder, op: subtract, base: { field: self.plan.principal }, subtract: [{ field: self.principalAllocated }] }\n { target: principalAdjustment, op: multiply, amount: { field: self.principalRemainder }, units: { field: self.first } }\n { target: principal, op: sum, values: [{ field: self.principalBase }, { field: self.principalAdjustment }] }\n { target: profitBase, op: divide, amount: { field: self.plan.flatProfit }, divisor: { field: self.plan.months }, rounding: floor }\n { target: profitAllocated, op: multiply, amount: { field: self.profitBase }, units: { field: self.plan.months } }\n { target: profitRemainder, op: subtract, base: { field: self.plan.flatProfit }, subtract: [{ field: self.profitAllocated }] }\n { target: profitAdjustment, op: multiply, amount: { field: self.profitRemainder }, units: { field: self.first } }\n { target: profit, op: sum, values: [{ field: self.profitBase }, { field: self.profitAdjustment }] }\n { target: instalment, op: sum, values: [{ field: self.principal }, { field: self.profit }] }\n ]\n }\n when pricing is amortizing {\n calculate: [\n { target: principal, op: annuity, amount: { field: self.plan.principal }, rate: { literal: profit_rate }, periods: { field: self.plan.months }, position: { field: self.position }, part: principal }\n { target: profit, op: annuity, amount: { field: self.plan.principal }, rate: { literal: profit_rate }, periods: { field: self.plan.months }, position: { field: self.position }, part: interest }\n { target: instalment, op: sum, values: [{ field: self.principal }, { field: self.profit }] }\n ]\n }\n invoke: [{ reference: self.id, action: refresh_loss_date, input: {} }]\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 requires self.originalDueAt > self.now; requires self.originalDueAt >= self.previousDate\n }\n action check_order { from: draft, to: draft, actor: { parent: parent }, requires self.originalDueAt > self.previousDate }\n action refresh_loss_date {\n from: [draft, pending, due], to: draft, actor: { parent: current() }\n calculate: [{ target: lossEligibleAt, op: shift, date: { field: self.dueAt }, milliseconds: { literal: write_off_after }, direction: after }]\n }\n action amend {\n from: [pending, due], to: pending, actor: { parent: amendment }, input { amendment: ref<amendment> }\n requires input.amendment.plan == self.plan\n when allow_overdue is blocked { requires self.dueAt > self.now }\n calculate: [\n { target: nextDueAt, op: at, list: input.amendment.dates, position: { field: self.position } }\n { target: lossEligibleAt, op: shift, date: { field: self.nextDueAt }, milliseconds: { literal: write_off_after }, direction: after }\n ]\n requires self.nextDueAt > self.now; requires self.nextDueAt >= self.dueAt; requires self.nextDueAt <= self.extensionLimit\n set: { previousDueAt: { field: self.dueAt }, dueAt: { field: self.nextDueAt } }\n invoke: [{ instrument: date_change, action: create, input: { amendment: { field: input.amendment }, slice: { field: self.id }, oldDate: { field: self.previousDueAt }, newDate: { field: self.nextDueAt } } }]\n when profit_earned is by_schedule { invoke: [{ selection: { instrument: recognition, reference: \"slice\", anchor: self.id, states: [pending], limit: 1 }, action: reschedule, input: {} }] }\n }\n action verify_fixed_date {\n from: paid, to: paid, actor: { parent: amendment }, input { amendment: ref<amendment> }\n calculate: [{ target: nextDueAt, op: at, list: input.amendment.dates, position: { field: self.position } }]\n requires self.nextDueAt == self.dueAt\n }\n // The plan posts the claims; a slice keeps its share as state.\n action activate {\n from: draft, to: pending, actor: { parent: parent }\n requires self.dueAt > self.now\n calculate: [{ target: openPrincipal, op: sum, values: [{ field: self.principal }] }]\n when profit_earned is on_payment { calculate: [{ target: openProfit, op: sum, values: [{ field: self.profit }] }] }\n when profit_earned is by_schedule {\n calculate: [{ target: openProfit, op: sum, values: [{ field: self.profit }] }]\n invoke: [{ instrument: recognition, action: create, input: { slice: { field: self.id } } }]\n }\n when profit_earned is at_disbursement { calculate: [{ target: earnedProfit, op: sum, values: [{ field: self.profit }] }] }\n }\n action mature {\n from: pending, to: due, actor: clock, due: { at: self.dueAt }\n }\n action recognise {\n from: [pending, due, paid, written_off, cancelled], to: preserve, actor: { parent: recognition }\n calculate: [{ target: earnedProfit, op: sum, values: [{ field: self.earnedProfit }, { field: self.openProfit }] }]\n invoke: [{ reference: self.id, action: clear_unearned, input: {} }]\n }\n action clear_unearned {\n from: [pending, due, paid, written_off, cancelled], to: preserve, actor: { parent: current() }\n calculate: [{ target: openProfit, op: sum, values: [{ literal: \"0\" }] }]\n }\n action collect {\n from: [pending, due], to: preserve, 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.openProfit }] }] }\n when profit_earned is by_schedule { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.earnedProfit }] }] }\n when profit_earned is at_disbursement { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.earnedProfit }] }] }\n calculate: [\n { target: principalTake, op: minimum, values: [{ field: input.payment.unapplied }, { field: self.openPrincipal }] }\n { target: afterTake, op: subtract, base: { field: input.payment.unapplied }, subtract: [{ field: self.principalTake }] }\n { target: profitTake, op: minimum, values: [{ field: self.afterTake }, { field: self.collectibleProfit }] }\n ]\n invoke: [{ reference: self.id, action: take, input: { payment: { field: input.payment } } }]\n }\n action collect_waterfall {\n from: [pending, due], to: preserve, 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.openProfit }] }] }\n when profit_earned is by_schedule { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.earnedProfit }] }] }\n when profit_earned is at_disbursement { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.earnedProfit }] }] }\n calculate: [\n { target: profitTake, op: minimum, values: [{ field: input.payment.unapplied }, { field: self.collectibleProfit }] }\n { target: afterTake, op: subtract, base: { field: input.payment.unapplied }, subtract: [{ field: self.profitTake }] }\n { target: principalTake, op: minimum, values: [{ field: self.afterTake }, { field: self.openPrincipal }] }\n ]\n invoke: [{ reference: self.id, action: take, input: { payment: { field: input.payment } } }]\n }\n action collect_pro_rata {\n from: [pending, due], to: preserve, 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.openProfit }] }] }\n when profit_earned is by_schedule { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.earnedProfit }] }] }\n when profit_earned is at_disbursement { calculate: [{ target: collectibleProfit, op: sum, values: [{ field: self.earnedProfit }] }] }\n calculate: [\n { target: collectibleTotal, op: sum, values: [{ field: self.openPrincipal }, { field: self.collectibleProfit }] }\n { target: paymentBudget, op: minimum, values: [{ field: input.payment.unapplied }, { field: self.collectibleTotal }] }\n ]\n when pricing is flat_total { calculate: [{ target: principalRatio, op: ratio, amount: { field: self.paymentBudget }, numerator: { literal: 10000 }, denominator: { field: self.ratioDenominator }, rounding: floor }] }\n when pricing is amortizing { calculate: [{ target: principalRatio, op: ratio, amount: { field: self.paymentBudget }, numerator: { field: self.principal }, denominator: { field: self.instalment }, rounding: floor }] }\n calculate: [\n { target: principalBasePayment, op: minimum, values: [{ field: self.principalRatio }, { field: self.openPrincipal }] }\n { target: profitBudget, op: subtract, base: { field: self.paymentBudget }, subtract: [{ field: self.principalBasePayment }] }\n { target: profitTake, op: minimum, values: [{ field: self.profitBudget }, { field: self.collectibleProfit }] }\n { target: principalTake, op: subtract, base: { field: self.paymentBudget }, subtract: [{ field: self.profitTake }] }\n ]\n invoke: [{ reference: self.id, action: take, input: { payment: { field: input.payment } } }]\n }\n // A collect action chose principalTake and profitTake; take records them\n // as pieces, lowers the slice's open amounts and the payment's unapplied\n // cash. The payment posts the cash and claim transfers once.\n action take {\n from: [pending, due], to: preserve, actor: { parent: current() }, input { payment: ref<payment> }\n when profit_earned is on_payment { calculate: [{ target: openProfitTake, op: sum, values: [{ field: self.profitTake }] }, { target: earnedProfitTake, op: sum, values: [{ literal: \"0\" }] }] }\n when profit_earned is by_schedule { calculate: [{ target: openProfitTake, op: sum, values: [{ literal: \"0\" }] }, { target: earnedProfitTake, op: sum, values: [{ field: self.profitTake }] }] }\n when profit_earned is at_disbursement { calculate: [{ target: openProfitTake, op: sum, values: [{ literal: \"0\" }] }, { target: earnedProfitTake, op: sum, values: [{ field: self.profitTake }] }] }\n calculate: [\n { target: taken, op: sum, values: [{ field: self.principalTake }, { field: self.profitTake }] }\n { target: openPrincipal, op: subtract, base: { field: self.openPrincipal }, subtract: [{ field: self.principalTake }] }\n { target: openProfit, op: subtract, base: { field: self.openProfit }, subtract: [{ field: self.openProfitTake }] }\n { target: earnedProfit, op: subtract, base: { field: self.earnedProfit }, subtract: [{ field: self.earnedProfitTake }] }\n ]\n invoke: [\n { instrument: principal_piece, action: create, guard: { kind: compare, left: { field: self.principalTake }, operator: \">\", right: { literal: \"0\" } }, input: { plan: { field: self.plan }, slice: { field: self.id }, payment: { field: input.payment }, amount: { field: self.principalTake } } }\n { instrument: profit_piece, action: create, guard: { kind: compare, left: { field: self.profitTake }, operator: \">\", right: { literal: \"0\" } }, input: { plan: { field: self.plan }, slice: { field: self.id }, payment: { field: input.payment }, amount: { field: self.profitTake } } }\n { reference: input.payment, action: consume, input: { amount: { field: self.taken } } }\n { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [pending, due], limit: 1, where: { id: { field: self.id }, openPrincipal: { literal: \"0\" }, openProfit: { literal: \"0\" }, earnedProfit: { literal: \"0\" } } }, action: complete, input: {} }\n ]\n }\n action complete {\n from: [pending, due], to: paid\n requires self.openPrincipal == \"0\"; requires self.openProfit == \"0\"; requires self.earnedProfit == \"0\"\n }\n action unpay {\n from: [pending, due, paid], to: pending, actor: { parent: [principal_piece, profit_piece] }\n input { principal: money, profit: money }\n calculate: [{ target: openPrincipal, op: sum, values: [{ field: self.openPrincipal }, { field: input.principal }] }]\n when profit_earned is on_payment { calculate: [{ target: openProfit, op: sum, values: [{ field: self.openProfit }, { field: input.profit }] }] }\n when profit_earned is by_schedule { calculate: [{ target: earnedProfit, op: sum, values: [{ field: self.earnedProfit }, { field: input.profit }] }] }\n when profit_earned is at_disbursement { calculate: [{ target: earnedProfit, op: sum, values: [{ field: self.earnedProfit }, { field: input.profit }] }] }\n }\n action payoff {\n from: [pending, due], to: paid, actor: { parent: parent }, input { identity: text }\n set: { payoffIdentity: { field: input.identity } }\n calculate: [{ target: openPrincipal, op: sum, values: [{ literal: \"0\" }] }, { target: openProfit, op: sum, values: [{ literal: \"0\" }] }, { target: earnedProfit, op: sum, values: [{ literal: \"0\" }] }]\n }\n action write_off {\n from: [pending, due], to: written_off, actor: { parent: parent }\n calculate: [{ target: openPrincipal, op: sum, values: [{ literal: \"0\" }] }, { target: openProfit, op: sum, values: [{ literal: \"0\" }] }, { target: earnedProfit, op: sum, values: [{ literal: \"0\" }] }]\n }\n action cancel {\n from: [pending, due, paid], to: cancelled, actor: { parent: parent }\n calculate: [{ target: openPrincipal, op: sum, values: [{ literal: \"0\" }] }, { target: openProfit, op: sum, values: [{ literal: \"0\" }] }, { target: earnedProfit, op: sum, values: [{ literal: \"0\" }] }]\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 reschedule { from: pending, to: pending, actor: { parent: slice }, calculate: [{ target: dueAt, op: shift, date: { field: self.slice.dueAt }, milliseconds: { literal: 0 }, direction: after }] }\n action mature { allowZero: true,\n from: pending, to: recognised, actor: clock, due: { at: self.dueAt }\n moves self.slice.openProfit from self.slice.plan.profitReceivable to self.slice.plan.profitEarned economics { purpose: internal, sourceParty: programOperator }\n invoke: [{ reference: self.slice, action: recognise, input: {} }]\n }\n }\n payment: {\n revisioned: true\n fields { plan: ref<parent>, amount: money, paymentIdentity: text, held: account of self, cashReceipt: text?\n outstandingPrincipal: money?, outstandingProfit: money?, outstandingFines: money?, outstandingCosts: money?, outstandingTotal: money?, unapplied: money?, principalReturned: money?, profitReturned: money?, settled: integer? }\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, actor: { party: borrower }\n calculate: [{ target: outstandingPrincipal, op: sum, values: [{ field: self.plan.principalReceivable.balance }] }]\n when profit_earned is on_payment { calculate: [{ target: outstandingProfit, op: sum, values: [{ field: self.plan.profitReceivable.balance }] }] }\n when profit_earned is by_schedule { calculate: [{ target: outstandingProfit, op: sum, values: [{ field: self.plan.profitEarned.balance }] }] }\n when profit_earned is at_disbursement { calculate: [{ target: outstandingProfit, op: sum, values: [{ field: self.plan.profitEarned.balance }] }] }\n when apply is fines_profit_principal {\n calculate: [{ target: outstandingFines, op: sum, values: [{ field: self.plan.fineReceivable.balance }] }, { target: outstandingCosts, op: sum, values: [{ field: self.plan.costReceivable.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 economics { purpose: principal, sourceParty: borrower }\n when apply is fines_profit_principal {\n invoke: [{ selection: { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [assessed], limit: charge_limit, order: [overdueAt] }, action: collect, guard: { kind: compare, left: { field: self.held.balance }, operator: \">\", right: { literal: \"0\" } }, input: { payment: { field: self.id } } }, { selection: { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [assessed], limit: charge_limit, order: [overdueAt] }, action: collect, guard: { kind: compare, left: { field: self.held.balance }, operator: \">\", right: { literal: \"0\" } }, input: { payment: { field: self.id } } }]\n }\n invoke: [{ reference: self.id, action: allocate, input: {} }, { reference: self.id, action: record, input: {} }]\n }\n action allocate {\n from: paid, to: paid, actor: { parent: current() }\n calculate: [{ target: unapplied, op: sum, values: [{ field: self.held.balance }] }]\n when apply is principal_profit {\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due], limit: max_term, order: [position] }, action: collect, guard: { kind: compare, left: { field: self.unapplied }, operator: \">\", right: { literal: \"0\" } }, input: { payment: { field: self.id } } }]\n }\n when apply is fines_profit_principal {\n invoke: [{ selection: { instrument: slice, reference: \"plan\", anchor: self.plan, states: [pending, due], limit: max_term, order: [position] }, action: collect_waterfall, guard: { kind: compare, left: { field: self.unapplied }, operator: \">\", right: { literal: \"0\" } }, 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: max_term, order: [position] }, action: collect_pro_rata, guard: { kind: compare, left: { field: self.unapplied }, operator: \">\", right: { literal: \"0\" } }, input: { payment: { field: self.id } } }]\n }\n }\n action consume {\n from: paid, to: paid, actor: { parent: slice }, input { amount: money }\n calculate: [{ target: unapplied, op: subtract, base: { field: self.unapplied }, subtract: [{ field: input.amount }] }]\n }\n action record { allowZero: true,\n from: paid, to: paid, actor: { parent: current() }\n requires self.unapplied == \"0\"\n calculate: [{ target: principalReturned, op: aggregate, selection: { instrument: principal_piece, reference: \"payment\", anchor: self.id, states: [paid], limit: max_term }, measure: { sum: \"amount\" } }, { target: profitReturned, op: aggregate, selection: { instrument: profit_piece, reference: \"payment\", anchor: self.id, states: [paid], limit: max_term }, measure: { sum: \"amount\" } }]\n moves self.principalReturned from self.held to self.plan.capital economics { purpose: principal, sourceParty: programOperator }\n moves self.profitReturned from self.held to self.plan.profitIncome capture \"cashReceipt\" economics { recipient: capital, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: programOperator } }\n moves self.principalReturned from self.plan.principalReceivable to self.plan.debt economics { purpose: internal, sourceParty: programOperator }\n when profit_earned is on_payment { moves self.profitReturned from self.plan.profitReceivable to self.plan.debt economics { purpose: internal, sourceParty: programOperator } }\n when profit_earned is by_schedule { moves self.profitReturned from self.plan.profitEarned to self.plan.debt economics { purpose: internal, sourceParty: programOperator } }\n when profit_earned is at_disbursement { moves self.profitReturned from self.plan.profitEarned to self.plan.debt economics { purpose: internal, sourceParty: programOperator } }\n invoke: [{ reference: self.plan, action: record_payment, input: { identity: { field: self.paymentIdentity }, principal: { field: self.principalReturned }, profit: { field: self.profitReturned } } }]\n }\n // unwind_paid refunds this payment's profit only when its settlement is\n // still recorded; a distributed settlement keeps it with investors.\n action unwind_paid {\n from: paid, to: refunded, actor: { parent: parent }\n calculate: [{ target: settled, op: aggregate, selection: { instrument: settlement, reference: \"plan\", anchor: self.plan, states: [recorded], limit: 1, where: { identity: { field: self.paymentIdentity } } }, measure: count }]\n invoke: [{ selection: { instrument: settlement, reference: \"plan\", anchor: self.plan, states: [recorded], limit: 1, where: { identity: { field: self.paymentIdentity } } }, action: unwind, input: {} }, { reference: self.id, action: unwind_profit, guard: { kind: compare, left: { field: self.settled }, operator: \"==\", right: { literal: 1 } }, input: {} }]\n }\n action unwind_profit { allowZero: true,\n from: refunded, to: refunded, actor: { parent: current() }\n moves self.profitReturned from self.plan.profitIncome to self.plan.borrower economics { recipient: capital, company: { purpose: earning, sourceParty: capital, reversalOf: self.cashReceipt }, participant: unclassified }\n }\n action refund { allowZero: true,\n from: paid, to: refunded, actor: { party: capital }, deadline: { at: self.plan.refundUntil }\n requires unique \"settlement_consumption\" on [self.plan, self.paymentIdentity]; requires self.plan in [active, paid]\n requires count of { instrument: settlement, reference: \"plan\", anchor: self.plan, states: [recorded], limit: 1, where: { identity: { field: self.paymentIdentity } } } == 1\n moves self.principalReturned from self.plan.capital to self.plan.borrower economics { purpose: principal, sourceParty: capital }\n moves self.profitReturned from self.plan.profitIncome to self.plan.borrower economics { recipient: capital, company: { purpose: earning, sourceParty: capital, reversalOf: self.cashReceipt }, participant: unclassified }\n moves self.principalReturned from self.plan.debt to self.plan.principalReceivable economics { purpose: internal, sourceParty: borrower }\n when profit_earned is on_payment { moves self.profitReturned from self.plan.debt to self.plan.profitReceivable economics { purpose: internal, sourceParty: borrower } }\n when profit_earned is by_schedule { moves self.profitReturned from self.plan.debt to self.plan.profitEarned economics { purpose: internal, sourceParty: borrower } }\n when profit_earned is at_disbursement { moves self.profitReturned from self.plan.debt to self.plan.profitEarned economics { purpose: internal, sourceParty: borrower } }\n invoke: [{ selection: { instrument: settlement, reference: \"plan\", anchor: self.plan, states: [recorded], limit: 1, where: { identity: { field: self.paymentIdentity } } }, action: refund, input: {} }]\n when apply is fines_profit_principal {\n invoke: [{ selection: { instrument: all(financing.late_charge.receipt), reference: \"payment\", anchor: self.id, states: [paid], limit: charge_limit }, action: refund, input: {} }, { selection: { instrument: all(financing.late_charge.cost.receipt), reference: \"payment\", anchor: self.id, states: [paid], limit: charge_limit }, action: refund, input: {} }]\n }\n invoke: [{ reference: self.plan, action: restore, input: {} }, { selection: { instrument: principal_piece, reference: \"payment\", anchor: self.id, states: [paid], limit: max_term }, action: refund, input: {} }, { selection: { instrument: profit_piece, reference: \"payment\", anchor: self.id, states: [paid], limit: max_term }, action: refund, input: {} }]\n }\n }\n principal_piece: {\n fields { plan: ref<parent>, slice: ref<slice>, payment: ref<payment>, amount: money }\n lifecycle { states: [paid, refunded], initial: paid }\n action create {\n actor: { parent: slice }\n input { plan: ref<parent>, slice: ref<slice>, payment: ref<payment>, amount: money }\n requires unique \"principal_receipt\" on [self.slice, self.payment]\n }\n action refund {\n from: paid, to: refunded, actor: { parent: payment }\n invoke: [{ reference: self.slice, action: unpay, input: { principal: { field: self.amount }, profit: { literal: \"0\" } } }]\n }\n }\n profit_piece: {\n fields { plan: ref<parent>, slice: ref<slice>, payment: ref<payment>, amount: money }\n lifecycle { states: [paid, refunded], initial: paid }\n action create {\n actor: { parent: slice }\n input { plan: ref<parent>, slice: ref<slice>, payment: ref<payment>, amount: money }\n requires unique \"profit_receipt\" on [self.slice, self.payment]\n }\n action refund {\n from: paid, to: refunded, actor: { parent: payment }\n invoke: [{ reference: self.slice, action: unpay, input: { principal: { literal: \"0\" }, profit: { field: self.amount } } }]\n }\n }\n }\n}\n\n// A late charge and its recovery costs keep their open amount as state. The\n// plan's fineReceivable and costReceivable hold the claims, so assessment,\n// waiver and refund post one claim transfer each, and payoff and amendment post\n// one per attachment or kind, not one per charge.\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, borrower: party = party(person)) {\n parameterDiagnostics {\n fine {\n accepts: \"a fixed amount\"\n percentage: \"a percentage of overdue debt\"\n fix: \"Use a fixed amount only if that is the intended policy. A percentage charge needs an authored rate calculation; do not approximate it with a cash amount.\"\n }\n }\n revisioned: true\n familyRevision: 1\n summary: \"Separate 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?, payoffAmount: money?, payoffReceipt: text?, payoffLed: integer?\n open: money?, take: money?\n }\n lifecycle { states: [proposed, assessed, collected, waived], initial: proposed }\n action create { input { slice: ref<on.slice>? }, calculate: [{ target: overdueAt, op: shift, date: { field: self.slice.dueAt }, milliseconds: { literal: grace }, direction: after }, { target: payoffAmount, op: sum, values: [{ literal: \"0\" }] }, { target: open, op: sum, values: [{ literal: \"0\" }] }], requires unique \"late_assessment\" on [self.slice, self.overdueAt]; requires self.borrower == self.slice.plan.borrower; requires self.plan == self.slice.plan; requires count of { instrument: all(financing.late_charge), reference: \"plan\", anchor: self.plan, states: [proposed, assessed, collected], limit: 366 } < self.plan.historyLimit }\n action assess { allowZero: true,\n from: proposed, to: assessed, actor: clock, due: { at: self.overdueAt }\n requires self.slice.openPrincipal > \"0\"\n calculate: [{ target: open, op: sum, values: [{ field: self.fine }] }]\n moves self.fine from self.plan.debt to self.plan.fineReceivable economics { purpose: internal, sourceParty: borrower }\n }\n action collect {\n from: [assessed, collected], to: assessed, actor: { parent: child(on, payment) }, input { payment: ref<on.payment> }\n requires input.payment in [paid]\n requires input.payment.plan == self.plan\n calculate: [{ target: take, op: minimum, values: [{ field: input.payment.held.balance }, { field: self.open }] }]\n invoke: [{ instrument: receipt, action: create, guard: { kind: compare, left: { field: self.take }, operator: \">\", right: { literal: \"0\" } }, input: { plan: { field: self.plan }, assessment: { field: self.id }, payment: { field: input.payment }, amount: { field: self.take } } }, { reference: self.id, action: reduce, input: {} }, { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, open: { literal: \"0\" } } }, action: finish, input: {} }]\n }\n // The oldest open charge of an attachment settles them all in one transfer.\n action payoff { allowZero: true,\n from: assessed, to: collected, actor: { parent: on }\n requires self.plan in [paid]\n calculate: [{ target: payoffAmount, op: aggregate, selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 366 }, measure: { sum: \"open\" } }]\n set: { payoffLed: { literal: 1 } }\n moves self.payoffAmount from self.plan.borrower to fines_to capture \"payoffReceipt\" economics { recipient: fines_to, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: borrower } }\n moves self.payoffAmount from self.plan.fineReceivable to self.plan.debt economics { purpose: internal, sourceParty: programOperator }\n invoke: [{ selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 366 }, action: close, input: {} }, { reference: self.id, action: close, input: {} }]\n }\n action close { from: [assessed, collected], to: collected, actor: { parent: current() }, calculate: [{ target: open, op: sum, values: [{ literal: \"0\" }] }] }\n action unwind_payoff { allowZero: true,\n from: collected, to: collected, actor: { parent: on }\n set: { payoffLed: { literal: 2 } }\n moves self.payoffAmount from fines_to to self.plan.borrower economics { recipient: fines_to, company: { purpose: earning, sourceParty: fines_to, reversalOf: self.payoffReceipt }, participant: unclassified }\n }\n action finish { from: assessed, to: collected, actor: { parent: current() }, requires self.open == \"0\" }\n action reduce { from: [assessed, collected, waived], to: preserve, actor: { parent: current() }, calculate: [{ target: open, op: subtract, base: { field: self.open }, subtract: [{ field: self.take }] }] }\n action cancel { from: proposed, to: waived, actor: { party: programOperator } }\n action cancel_for_amendment { from: proposed, to: waived, actor: { parent: child(on, amendment) } }\n action cancel_undelivered { from: [proposed, assessed, collected], to: waived, actor: { parent: on }, calculate: [{ target: open, op: sum, values: [{ literal: \"0\" }] }] }\n action waive_for_amendment {\n from: [assessed, collected], to: assessed, actor: { parent: child(on, amendment) }, input { amendment: ref<on.amendment> }\n requires input.amendment.plan == self.plan; requires input.amendment in [applied]\n calculate: [{ target: take, op: rate, base: { field: self.open }, bps: { field: input.amendment.waiverPercent }, rounding: floor }]\n invoke: [{ instrument: waiver, action: create, input: { assessment: { field: self.id }, amendment: { field: input.amendment }, amount: { field: self.take } } }, { reference: self.id, action: reduce, input: {} }]\n }\n action waive { allowZero: true,\n from: [assessed, collected], to: waived, actor: { parent: waiver_request }, input { reason: text, evidence: text }\n calculate: [{ target: take, op: sum, values: [{ field: self.open }] }]\n moves self.take from self.plan.fineReceivable to self.plan.debt economics { purpose: internal, sourceParty: programOperator }\n invoke: [{ reference: self.id, action: reduce, input: {} }]\n }\n action refund {\n from: [assessed, collected], to: preserve, actor: { party: fines_to }, input { payment: ref<on.payment> }, deadline: { at: self.plan.refundUntil }\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: {} }]\n }\n action reopen {\n from: [assessed, collected], to: assessed, actor: { parent: receipt }, input { amount: money }\n calculate: [{ target: open, op: sum, values: [{ field: self.open }, { field: input.amount }] }]\n }\n records {\n waiver_request: {\n fields { assessment: ref<parent>, reason: text, evidence: text }\n lifecycle { states: [requested, applied, cancelled], initial: requested }\n action create { requires self.assessment in [assessed, collected] }\n action apply {\n from: requested, to: applied, actor: { party: fines_to }, input { reason: text, evidence: text }\n invoke: [{ reference: self.assessment, action: waive, input: { reason: { field: input.reason }, evidence: { field: input.evidence } } }]\n }\n action cancel { from: requested, to: cancelled }\n }\n waiver: {\n fields { assessment: ref<parent>, amendment: ref<on.amendment>, amount: money }\n lifecycle { states: [recorded], initial: recorded }\n action create {\n actor: { parent: parent }, input { assessment: ref<parent>, amendment: ref<on.amendment>, amount: money }\n requires unique \"amendment_waiver\" on [self.assessment, self.amendment]\n }\n }\n receipt: {\n fields { cashReceipt: text?, plan: ref<on>, assessment: ref<parent>, payment: ref<on.payment>, amount: money }\n lifecycle { states: [paid, refunded], initial: paid }\n action create { actor: { parent: parent }, input { plan: ref<on>, assessment: ref<parent>, payment: ref<on.payment>, amount: money }, 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: pass_through, sourceParty: programOperator } }; moves self.amount from self.plan.fineReceivable to self.plan.debt economics { purpose: internal, sourceParty: programOperator } }\n action refund {\n from: paid, to: refunded, actor: { parent: [parent, child(on, payment)] }\n 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 }\n moves self.amount from self.plan.debt to self.plan.fineReceivable economics { purpose: internal, sourceParty: borrower }\n invoke: [{ reference: self.assessment, action: reopen, input: { amount: { field: self.amount } } }]\n }\n // unwind_paid returns the cash; the plan cancels the claims itself.\n action unwind { from: paid, to: refunded, actor: { parent: on }, 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 } }\n }\n\n cost: {\n revisioned: true\n fields {\n plan: ref<on>, assessment: ref<parent>, overdueAt: date?, evidence: text, evidencedCost: money, amount: money = minimum(self.evidencedCost, cap), payoffAmount: money?, payoffReceipt: text?, payoffLed: integer?\n open: money?, take: money?\n }\n lifecycle { states: [proposed, assessed, collected, waived], initial: proposed }\n action create { actor: { party: programOperator }, calculate: [{ target: overdueAt, op: shift, date: { field: self.assessment.overdueAt }, milliseconds: { literal: 0 }, direction: after }, { target: payoffAmount, op: sum, values: [{ literal: \"0\" }] }, { target: open, op: sum, values: [{ literal: \"0\" }] }], requires unique \"recovery_assessment\" on [self.assessment]; requires self.plan == self.assessment.plan; requires count of { instrument: all(financing.late_charge.cost), reference: \"plan\", anchor: self.plan, states: [proposed, assessed, collected], limit: 366 } < self.plan.historyLimit }\n action assess { allowZero: true,\n from: proposed, to: assessed, actor: clock, due: { at: self.assessment.overdueAt }\n requires self.assessment.slice.openPrincipal > \"0\"\n calculate: [{ target: open, op: sum, values: [{ field: self.amount }] }]\n moves self.amount from self.plan.debt to self.plan.costReceivable economics { purpose: internal, sourceParty: borrower }\n }\n action collect {\n from: [assessed, collected], to: assessed, actor: { parent: child(on, payment) }, input { payment: ref<on.payment> }\n requires input.payment in [paid]\n requires input.payment.plan == self.plan\n calculate: [{ target: take, op: minimum, values: [{ field: input.payment.held.balance }, { field: self.open }] }]\n invoke: [{ instrument: receipt, action: create, guard: { kind: compare, left: { field: self.take }, operator: \">\", right: { literal: \"0\" } }, input: { plan: { field: self.plan }, assessment: { field: self.id }, payment: { field: input.payment }, amount: { field: self.take } } }, { reference: self.id, action: reduce, input: {} }, { selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 1, where: { id: { field: self.id }, open: { literal: \"0\" } } }, action: finish, input: {} }]\n }\n action payoff { allowZero: true,\n from: assessed, to: collected, actor: { parent: on }\n requires self.plan in [paid]\n calculate: [{ target: payoffAmount, op: aggregate, selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 366 }, measure: { sum: \"open\" } }]\n set: { payoffLed: { literal: 1 } }\n moves self.payoffAmount from self.plan.borrower to costs_to capture \"payoffReceipt\" economics { recipient: costs_to, company: { purpose: earning, sourceParty: borrower }, participant: { purpose: pass_through, sourceParty: borrower } }\n moves self.payoffAmount from self.plan.costReceivable to self.plan.debt economics { purpose: internal, sourceParty: programOperator }\n invoke: [{ selection: { instrument: current(), reference: \"plan\", anchor: self.plan, states: [assessed], limit: 366 }, action: close, input: {} }, { reference: self.id, action: close, input: {} }]\n }\n action close { from: [assessed, collected], to: collected, actor: { parent: current() }, calculate: [{ target: open, op: sum, values: [{ literal: \"0\" }] }] }\n action unwind_payoff { allowZero: true,\n from: collected, to: collected, actor: { parent: on }\n set: { payoffLed: { literal: 2 } }\n moves self.payoffAmount from costs_to to self.plan.borrower economics { recipient: costs_to, company: { purpose: earning, sourceParty: costs_to, reversalOf: self.payoffReceipt }, participant: unclassified }\n }\n action finish { from: assessed, to: collected, actor: { parent: current() }, requires self.open == \"0\" }\n action reduce { from: [assessed, collected, waived], to: preserve, actor: { parent: current() }, calculate: [{ target: open, op: subtract, base: { field: self.open }, subtract: [{ field: self.take }] }] }\n action cancel { from: proposed, to: waived, actor: { party: programOperator } }\n action cancel_for_amendment { from: proposed, to: waived, actor: { parent: child(on, amendment) } }\n action cancel_undelivered { from: [proposed, assessed, collected], to: waived, actor: { parent: on }, calculate: [{ target: open, op: sum, values: [{ literal: \"0\" }] }] }\n action waive_for_amendment {\n from: [assessed, collected], to: assessed, actor: { parent: child(on, amendment) }, input { amendment: ref<on.amendment> }\n requires input.amendment.plan == self.plan; requires input.amendment in [applied]\n calculate: [{ target: take, op: rate, base: { field: self.open }, bps: { field: input.amendment.waiverPercent }, rounding: floor }]\n invoke: [{ instrument: waiver, action: create, input: { assessment: { field: self.id }, amendment: { field: input.amendment }, amount: { field: self.take } } }, { reference: self.id, action: reduce, input: {} }]\n }\n action waive { allowZero: true,\n from: [assessed, collected], to: waived, actor: { parent: waiver_request }, input { reason: text, evidence: text }\n calculate: [{ target: take, op: sum, values: [{ field: self.open }] }]\n moves self.take from self.plan.costReceivable to self.plan.debt economics { purpose: internal, sourceParty: programOperator }\n invoke: [{ reference: self.id, action: reduce, input: {} }]\n }\n action refund {\n from: [assessed, collected], to: preserve, actor: { party: costs_to }, input { payment: ref<on.payment> }, deadline: { at: self.plan.refundUntil }\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: {} }]\n }\n action reopen {\n from: [assessed, collected], to: assessed, actor: { parent: receipt }, input { amount: money }\n calculate: [{ target: open, op: sum, values: [{ field: self.open }, { field: input.amount }] }]\n }\n records {\n waiver_request: {\n fields { assessment: ref<parent>, reason: text, evidence: text }\n lifecycle { states: [requested, applied, cancelled], initial: requested }\n action create { requires self.assessment in [assessed, collected] }\n action apply {\n from: requested, to: applied, actor: { party: costs_to }, input { reason: text, evidence: text }\n invoke: [{ reference: self.assessment, action: waive, input: { reason: { field: input.reason }, evidence: { field: input.evidence } } }]\n }\n action cancel { from: requested, to: cancelled }\n }\n waiver: {\n fields { assessment: ref<parent>, amendment: ref<on.amendment>, amount: money }\n lifecycle { states: [recorded], initial: recorded }\n action create {\n actor: { parent: parent }, input { assessment: ref<parent>, amendment: ref<on.amendment>, amount: money }\n requires unique \"amendment_waiver\" on [self.assessment, self.amendment]\n }\n }\n receipt: {\n fields { cashReceipt: text?, plan: ref<on>, assessment: ref<parent>, payment: ref<on.payment>, amount: money }\n lifecycle { states: [paid, refunded], initial: paid }\n action create { actor: { parent: parent }, input { plan: ref<on>, assessment: ref<parent>, payment: ref<on.payment>, amount: money }, 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: pass_through, sourceParty: programOperator } }; moves self.amount from self.plan.costReceivable to self.plan.debt economics { purpose: internal, sourceParty: programOperator } }\n action refund {\n from: paid, to: refunded, actor: { parent: [parent, child(on, payment)] }\n 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 }\n moves self.amount from self.plan.debt to self.plan.costReceivable economics { purpose: internal, sourceParty: borrower }\n invoke: [{ reference: self.assessment, action: reopen, input: { amount: { field: self.amount } } }]\n }\n action unwind { from: paid, to: refunded, actor: { parent: on }, 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 } }\n }\n }\n }\n }\n}\n\ninstrument limits(per_borrower: money, borrower: party = party(person), active_plans: integer = 1) {\n familyRevision: 1\n scope: product\n summary: \"One outstanding balance ceiling per borrower.\"\n fields { borrower: account of borrower, limit: money = per_borrower, activePlans: integer = active_plans }\n lifecycle { states: [pending, approved], initial: pending }\n action create { actor: { party: borrower }, requires unique \"borrower_limit\" on [self.borrower] }\n action approve { from: pending, to: approved, actor: { party: programOperator } }\n}\n\ninstrument portfolio_limit(limit: money) {\n familyRevision: 1\n scope: product\n summary: \"One shared ceiling on the principal the product may hold.\"\n fields { key: text = \"portfolio\", limit: money = limit }\n lifecycle { states: [pending, approved], initial: pending }\n action create { actor: { party: programOperator }, requires unique \"portfolio_limit\" on [self.key] }\n action approve { from: pending, to: approved, actor: { party: programOperator } }\n}\n\ninstrument credit_line(borrower: party = programOperator, adapter: text, limit: money, expires: date) {\n familyRevision: 1\n summary: \"A revolving facility from an outside lender; each draw is a separate immutable advance.\"\n fields { borrower: account of borrower, facility: account(borrower, cash, \"facility\"), debt: account(borrower, claim, contra, \"debt\"), limit: money = limit, expiresAt: date = expires }\n lifecycle { states: [pending, active, suspended, closed], initial: pending }\n action create { actor: { party: borrower } }\n action activate {\n from: pending, to: active, actor: { party: borrower }\n subject { adapter: adapter }\n }\n action suspend { from: active, to: suspended, actor: { party: borrower } }\n action resume { from: suspended, to: active, actor: { party: borrower } }\n action close { from: [active, suspended], to: closed, actor: { party: borrower }, 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, borrower: party = programOperator) {\n familyRevision: 1\n summary: \"A single facility draw with an immutable principal and full repayment.\"\n fields { line: ref<line>, borrower: account of borrower, amount: money = amount, principalReceivable: account(self, claim) }\n lifecycle { states: [pending, drawn, repaid, cancelled], initial: pending }\n action create { actor: { party: borrower }, requires self.borrower == self.line.borrower; 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, actor: { party: borrower }\n requires self.line in [active]\n deadline: { at: self.line.expiresAt }\n moves self.amount from self.line.facility to self.line.borrower; moves self.amount from self.line.debt to self.principalReceivable\n }\n action repay { from: drawn, to: repaid, actor: { party: borrower }, moves self.amount from self.line.borrower to self.line.facility; moves self.amount from self.principalReceivable to self.line.debt }\n action cancel { from: pending, to: cancelled, actor: { party: borrower } }\n}\n"],
9
+ ["insurance.hsx", "header insurance\n\n// Economics: Company commission is earning; refunds reverse its captured transfer.\n// Outside broker commissions and insurer premiums are pass-through.\n// Claim moves remain unclassified until their money purpose is declared.\n\n// Expose cover.create, activate and cancel separately. The adapter names a\n// registered boundary adapter (conformance_boundary in sandbox). covers is an\n// optional link to a sibling attachment; the attached object is already the\n// insured thing. claim_limit is the sum insured: approved and paid claims on one\n// cover, across every claim attachment, never total more. Activation binds adapter;\n// each slice needs a separately created unique period and an active cover to collect.\n// Collection debits holder for insurerPremium to the insurer and commission to\n// broker as two moves. Broker defaults to programOperator; bind a declared business\n// for a distinct agency. The two amounts sum to premium. Zero portions are allowed.\n// Cover.cancel invokes refund only on paid slices, before each startsAt. It returns\n// insurerPremium from insurer and commission from broker to holder. Active or\n// expired periods are excluded; insufficient recipient funds refuse the reversal.\n// Each refund is two transfers, so cancel refunds 126 paid slices per operation.\n// A cover with more reads cancelling, and its cancel_step clock refunds the next\n// 126 a second later until none remain; then it reads cancelled.\n// Slice refund is parent-owned, not a public alias. Expose cover.cancel instead.\n// Claims require active cover. Expose claim.create, approve, deny and pay as needed.\n// Inspector approves OR denies from submitted. After approval only pay or clock\n// expiry can consume the reservation; deny is never available after approval.\n// Inspector is a bound party, not necessarily staff. These are ledger transfers;\n// outside settlement needs the boundary protocol, not a claim of provider success.\n\n// Cost: each slice collection or refund declares two transfers. Claim approval\n// reserves once; pay posts once and expiry voids once. Cover cancellation adds\n// at most 252 transfers per step. Run hsx cost for composed counts, not provider prices.\n\ninstrument cover(holder: party, adapter: text, commission: percent = 0%, broker: party = programOperator, covers: ref?, premium: money = runtime, claim_limit: money = runtime) {\n summary: \"Recurring cover bound to an outside insurer across an ADL boundary.\"\n fields { covers: ref<covers>?, holder: account of holder, insurer: account(adapter(adapter), cash, \"premium\"), expiresAt: date, claimLimit: money = claim_limit, cancelAt: date?, slicesLeft: integer? }\n lifecycle { states: [pending, active, cancelling, cancelled, expired], initial: pending }\n action create { actor: { party: holder } }\n action activate {\n from: pending, to: active, actor: { party: programOperator }\n subject { adapter: adapter }\n }\n action cancel {\n from: active, to: cancelling, actor: { party: holder }\n invoke: [{ reference: self.id, action: cancel_batch, input: {} }]\n }\n action cancel_step { from: cancelling, to: preserve, actor: clock, due: { at: self.cancelAt }, invoke: [{ reference: self.id, action: cancel_batch, input: {} }] }\n action cancel_batch {\n from: cancelling, to: preserve, actor: { parent: current() }\n calculate: [{ target: cancelAt, op: shift, date: { field: self.now }, milliseconds: { literal: 1000 }, direction: after }]\n invoke: [{ selection: { instrument: slice, reference: \"cover\", anchor: self.id, states: [paid], limit: 126, batch: true, order: [startsAt] }, action: refund, input: {} }]\n invoke: [{ reference: self.id, action: cancel_check, input: {} }]\n }\n action cancel_check {\n from: cancelling, to: preserve, actor: { parent: current() }\n calculate: [{ target: slicesLeft, op: aggregate, selection: { instrument: slice, reference: \"cover\", anchor: self.id, states: [paid], limit: 1, batch: true }, measure: count }]\n invoke: [{ reference: self.id, action: finish_cancel, guard: { kind: compare, left: { field: self.slicesLeft }, operator: \"==\", right: { literal: 0 } }, input: {} }]\n }\n action finish_cancel { from: cancelling, to: cancelled, actor: { parent: current() } }\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>, premium: money = premium, startsAt: date, endsAt: date\n commission: money = rate(self.premium, commission)\n insurerPremium: money = subtract(self.premium, self.commission), commissionReceipt: text?\n }\n lifecycle { states: [pending, paid, active, expired, refunded], initial: pending }\n action create {\n requires self.startsAt < self.endsAt\n requires unique \"premium_period\" on [self.cover, self.startsAt, self.endsAt]\n }\n action collect {\n allowZero: true\n requires self.premium > \"0\"\n from: pending, to: paid, actor: { party: holder }\n requires self.cover in [active]\n moves self.insurerPremium from holder to self.cover.insurer economics { purpose: pass_through, sourceParty: holder }\n moves self.commission from holder to broker capture \"commissionReceipt\" economics { recipient: broker, company: { purpose: earning, sourceParty: holder }, participant: { purpose: pass_through, sourceParty: holder } }\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 allowZero: true\n requires self.premium > \"0\"\n from: paid, to: refunded, actor: { parent: parent }, deadline: { at: self.startsAt }\n moves self.insurerPremium from self.cover.insurer to holder economics { purpose: pass_through, sourceParty: programOperator }\n moves self.commission from broker to holder economics { recipient: broker, company: { purpose: earning, sourceParty: broker, reversalOf: self.commissionReceipt }, participant: { purpose: pass_through, sourceParty: broker } }\n }\n }\n }\n}\n\ninstrument claim(cover: ref<insurance.cover>, inspector: party) {\n summary: \"A claim 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 invariants sum \"amount\" of { instrument: all(insurance.claim), reference: \"cover\", anchor: self.cover, states: [approved, paid], limit: 366 } <= self.cover.claimLimit\n action create { requires self.cover in [active] }\n action approve {\n from: submitted, to: approved\n actor: { party: inspector }\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, actor: { party: inspector }, deadline: { at: self.expiresAt }, moves post self.reservation }\n action deny { from: submitted, to: denied, actor: { party: inspector } }\n action expire { from: approved, to: expired, actor: clock, due: { at: self.expiresAt }, moves void self.reservation }\n}\n"],
10
+ ["lending.hsx", "header lending\n\n// Economics: Funding and commitment returns are principal. Distribution tax is\n// pass-through; own-account fee and claim allocations are internal. Mixed\n// principal/profit distributions and unbound source owners remain unclassified.\n\n// Round target is plan.principal from runtime subject.price, not its credit limit.\n// The operator opens the round and closes it before closesAt. Expose\n// round.create and close plus commitment.create and withdraw. A commitment\n// debits the bound investor's original active wallet before closesAt. Investor cap\n// aggregates by investor across wallets. A round still open at closesAt fails,\n// even when fully committed, and refunds those original wallets.\n// Closing needs the exact target; it funds plan.capital and does not disburse the\n// loan. Expose plan.disburse separately after signing and limit approval.\n// Distribution.create needs a recorded settlement matching the plan. Only the\n// payout consumes it: distribute_cash or distribute_loss claims the settlement\n// and marks it distributed, so the plan's unwind_paid keeps that profit, while an\n// abandoned distribution leaves the settlement refundable.\n// Prepare cash or loss first, then create shares against funded commitments of\n// that round. Distribution needs pending share weights equal to the round target.\n// Cash fee is a percentage of retained profit, VAT a percentage of that fee.\n// Principal plus retained profit less fee and VAT goes to weighted wallets;\n// floored residual goes to residual_to. Loss mode moves claim balances, not cash.\n// Child share execution is parent-owned. No report or clock proves outside payout.\n\n// Cost: round.create declares one owned account. Close transfers its balance\n// and invokes commitments; failure invokes their refunds. Distribution adds moves\n// and bounded share invocations. Run hsx cost for counts after policy selection.\n// A round takes at most 248 commitments, so failure refunds them in 248 ledger\n// transfers and a cash distribution pays every share in 253, the most one\n// ledger request takes.\n\ninstrument round(borrower: party, plan: ref<financing.installments> = object(financing.installments), operator: party = programOperator, 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, plan: ref<plan>, price: money = self.plan.principal, closesAt: date\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 { actor: { party: operator }, requires unique \"funding_plan\" on [self.plan]; requires self.borrower == self.plan.borrower }\n action close {\n from: open, to: funded, actor: { party: operator }\n requires sum \"amount\" of { instrument: commitments, reference: \"round\", anchor: self.id, states: [committed], limit: 248 } == self.price\n requires self.held.balance == self.price\n moves self.price from self.held to self.plan.capital economics { purpose: principal, sourceParty: programOperator }\n invoke: [{ selection: { instrument: commitments, reference: \"round\", anchor: self.id, states: [committed], limit: 248 }, action: fund, input: {} }]\n }\n action fail {\n from: open, to: failed, actor: clock, due: { at: self.closesAt }\n invoke: [{ selection: { instrument: commitments, reference: \"round\", anchor: self.id, states: [committed], limit: 248 }, 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>, investor: account of investor, 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: 248, where: { investor: { field: self.investor } } } <= self.round.maximumTicket\n invariants sum \"amount\" of { instrument: all(lending.commitment), reference: \"round\", anchor: self.round, states: [committed, funded], limit: 248 } <= self.round.price\n invariants count of { instrument: all(lending.commitment), reference: \"round\", anchor: self.round, states: [committed, funded], limit: 248 } <= 248\n action create {\n actor: { party: investor }\n requires self.round in [open]\n requires self.wallet in [active]\n requires self.wallet.holder == self.investor\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 economics { purpose: principal, sourceParty: programOperator }\n }\n action fund { from: committed, to: funded, actor: { parent: round } }\n action withdraw {\n from: committed, to: withdrawn, actor: { party: investor }\n requires self.round in [open]\n deadline: { at: self.round.closesAt }\n moves self.amount from self.round.held to self.wallet.held economics { purpose: principal, sourceParty: programOperator }\n }\n action refund {\n from: committed, to: refunded, actor: { parent: round }\n moves self.amount from self.round.held to self.wallet.held economics { purpose: principal, sourceParty: programOperator }\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, operator: 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 {\n requires self.round in [funded]; requires self.source in [recorded]; requires self.source.plan == self.round.plan\n }\n action prepare_cash {\n from: pending, to: cash_ready\n requires self.mode == \"cash\"; requires self.source.kind == \"cash\"; requires self.source in [recorded]\n calculate: [\n { target: \"principal\", op: \"sum\", values: [{ field: self.source.principal }] }\n { target: \"profit\", op: \"sum\", values: [{ field: self.source.retainedProfit }] }\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\"; requires self.source in [recorded]\n calculate: [{ target: \"net\", op: \"sum\", values: [{ field: self.source.loss }] }]\n }\n action distribute_cash { allowZero: true,\n from: cash_ready, to: distributed, actor: { party: operator }\n requires self.source in [recorded]; requires unique \"settlement_consumption\" on [self.source.plan, self.source.identity]\n requires sum \"weight\" of { instrument: share, reference: \"distribution\", anchor: self.id, states: [pending], limit: 248 } == 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 economics { purpose: internal, sourceParty: programOperator }; moves self.vat from self.held to programTax economics { purpose: pass_through, sourceParty: programOperator }\n invoke: [{ reference: self.source, action: distribute, input: {} }, { selection: { instrument: share, reference: \"distribution\", anchor: self.id, states: [pending], limit: 248 }, action: cash, input: {} }, { reference: self.id, action: residual_cash, input: {} }]\n }\n action residual_cash { allowZero: true,\n from: distributed, to: distributed, actor: { parent: current() }\n moves self.held.balance from self.held to residual_to\n }\n action distribute_loss { allowZero: true,\n from: loss_ready, to: distributed, actor: { party: operator }\n requires self.source in [recorded]; requires unique \"settlement_consumption\" on [self.source.plan, self.source.identity]\n requires sum \"weight\" of { instrument: share, reference: \"distribution\", anchor: self.id, states: [pending], limit: 248 } == self.round.price\n moves self.net from self.source.lossAccount to self.losses\n invoke: [{ reference: self.source, action: distribute, input: {} }, { selection: { instrument: share, reference: \"distribution\", anchor: self.id, states: [pending], limit: 248 }, action: loss, input: {} }, { reference: self.id, action: residual_loss, input: {} }]\n }\n action residual_loss { allowZero: true,\n from: distributed, to: distributed, actor: { parent: current() }\n moves self.losses.balance from self.losses to self.residualLoss economics { purpose: internal, sourceParty: programOperator }\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 { allowZero: true,\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 { 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 } }\n }\n }\n}\n"],
11
11
  ["marketplace.hsx", "header marketplace\n\n// Economics: Deposit funding, escrow credit and returns are principal. Retention is\n// earning for the company or passes the buyer's cash through to a bound outside recipient.\n\n// Listing, order and reservation are separate agreements. Expose their create\n// and decision actions individually. Order fulfillment does not move escrow cash;\n// only the fulfiller marks it, the Product operator unless the seller is bound.\n// Pair an order with escrow.hold and expose its fund, deliver, accept, dispute,\n// verify_return and refund aliases. Refund needs disputed -> return_verified,\n// with payee evidence, then returns the full price to payer; accept pays payee.\n// A reservation holds its own deposit. Activate requires an active listing and\n// no placed order. Only a declared converter may invoke credit. A financing\n// plan on the same hold credits it when the lender disburses. Credit consumes the\n// deposit once, credits at most the contribution, and returns excess to buyer.\n// Expose cancel, seller_cancel or operator_cancel for the intended actors.\n// Buyer cancel and expiry use configured refund percentages; seller/operator\n// cancellation return the whole reservation balance. Converted money is in escrow,\n// so subsequent return verification and refund use the escrow aliases.\n\n// Cost: listing and order actions declare no transfers. Reservation.create\n// declares one owned account; activate declares one deposit transfer. Cancellation\n// and credit split that balance into moves. Run hsx cost for the composed counts.\n\ninstrument listing(seller: party) {\n revisioned: true\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 {\n from: draft, to: active, actor: { party: seller }\n }\n action withdraw { from: active, to: withdrawn, actor: { party: seller }, requires count of { instrument: all(marketplace.reservation), reference: \"listing\", anchor: self.id, states: [active], limit: 366 } == 0 }\n action sell { from: active, to: sold, actor: { party: seller }, requires count of { instrument: all(marketplace.reservation), reference: \"listing\", anchor: self.id, states: [active], limit: 366 } == 0 }\n}\n\ninstrument order(listing: ref<marketplace.listing>, buyer: party, fulfiller: party = programOperator) {\n revisioned: true\n summary: \"A buyer's order for one listing at its declared price.\"\n fields { listing: ref<listing>, buyer: account of buyer, price: money, reservations: integer?, ownReservations: integer?, blockingQuotes: integer?, ownBlockingQuotes: integer? }\n lifecycle { states: [quoted, placed, fulfilled, cancelled], initial: quoted }\n action create {\n actor: { party: buyer }\n requires self.listing in [active]\n calculate: [\n { target: blockingQuotes, op: aggregate, selection: { instrument: all(marketplace.reservation), reference: \"listing\", anchor: self.listing, states: [active], limit: 366, where: { quotePolicy: { literal: \"blocked\" } } }, measure: count }\n { target: ownBlockingQuotes, op: aggregate, selection: { instrument: all(marketplace.reservation), reference: \"listing\", anchor: self.listing, states: [active], limit: 366, where: { quotePolicy: { literal: \"blocked\" }, buyer: { field: self.buyer } } }, measure: count }\n ]\n requires self.blockingQuotes == self.ownBlockingQuotes\n requires self.price == self.listing.price\n }\n action commit {\n from: [quoted, placed], to: placed\n requires self.listing in [active]\n calculate: [\n { target: reservations, op: aggregate, selection: { instrument: all(marketplace.reservation), reference: \"listing\", anchor: self.listing, states: [active], limit: 366 }, measure: count }\n { target: ownReservations, op: aggregate, selection: { instrument: all(marketplace.reservation), reference: \"listing\", anchor: self.listing, states: [active], limit: 366, where: { buyer: { field: self.buyer } } }, measure: count }\n ]\n requires self.reservations == self.ownReservations\n }\n invariants count of { instrument: all(marketplace.order), reference: \"listing\", anchor: self.listing, states: [placed, fulfilled], limit: 366 } <= 1\n action fulfill { from: placed, to: fulfilled, actor: { party: fulfiller } }\n action cancel { from: [quoted, placed], to: cancelled, actor: { party: buyer } }\n}\n\ninstrument reservation(listing: ref<marketplace.listing>, funds: ref<escrow.hold>, converters: ref[], buyer: party, seller: party, expires_after: duration = 48h, deposit: money = 1000 SAR, cancellation_refund: percent = 100%, expiry_refund: percent = 100%, retained_to: party = programOperator, operator: party = programOperator, competing_quotes: enum(allowed, blocked) = allowed) {\n revisioned: true\n summary: \"Exclusive timed listing hold with explicit deposit credit and refund.\"\n fields {\n listing: ref<listing>, funds: ref<funds>, buyer: account of buyer, seller: account of seller, price: money, terms: text\n held: account of self, quotePolicy: enum(allowed, blocked) = competing_quotes, deposit: money = deposit, proposalExpiresAt: date = after(self.createdAt, expires_after), expiresAt: date?\n credit: money?, refund: money?, retained: money?, dispositionAt: date?, reason: text?\n }\n lifecycle { states: [proposed, active, converted, cancelled, expired], initial: proposed }\n invariants count of { instrument: all(marketplace.reservation), reference: \"listing\", anchor: self.listing, states: [active], limit: 366 } <= 1\n action create { actor: { party: buyer }, requires self.listing in [active]; requires self.seller == self.listing.seller; requires self.price == self.listing.price }\n action activate {\n from: proposed, to: active, actor: { party: buyer }, deadline: { at: self.proposalExpiresAt }\n calculate: [{ target: expiresAt, op: shift, date: { field: self.now }, milliseconds: { literal: expires_after }, direction: after }]\n requires self.listing in [active]; requires self.price == self.listing.price\n requires count of { instrument: all(marketplace.order), reference: \"listing\", anchor: self.listing, states: [placed, fulfilled], limit: 366 } == 0\n moves self.deposit from self.buyer to self.held economics { purpose: principal, sourceParty: buyer }\n }\n action credit { allowZero: true,\n from: active, to: converted, actor: { parent: converters }, deadline: { at: self.expiresAt }\n input { funds: ref<funds>, contribution: money }\n requires input.funds == self.funds; requires input.funds in [pending, funded]; requires input.funds.payer == self.buyer; requires input.funds.price == self.price\n requires input.contribution <= self.price\n 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 }] }]\n set: { dispositionAt: { field: self.now } }\n moves self.credit from self.held to input.funds.held economics { purpose: principal, sourceParty: programOperator }\n moves self.refund from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }\n }\n action cancel { allowZero: true,\n from: active, to: cancelled, actor: { party: buyer }, input { reason: text }\n 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 }] }]\n set: { reason: { field: input.reason }, dispositionAt: { field: self.now } }\n 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: pass_through, sourceParty: programOperator } }\n }\n action seller_cancel {\n from: active, to: cancelled, actor: { party: seller }, input { reason: text }\n set: { reason: { field: input.reason }, dispositionAt: { field: self.now } }\n moves self.held.balance from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }\n }\n action operator_cancel {\n from: active, to: cancelled, actor: { party: operator }, input { reason: text }\n set: { reason: { field: input.reason }, dispositionAt: { field: self.now } }\n moves self.held.balance from self.held to self.buyer economics { purpose: principal, sourceParty: programOperator }\n }\n action withdraw { from: proposed, to: cancelled, actor: { party: buyer } }\n action expire { allowZero: true,\n from: active, to: expired, actor: clock, due: { at: self.expiresAt }\n 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 }] }]\n set: { dispositionAt: { field: self.now } }\n 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: pass_through, sourceParty: programOperator } }\n }\n action expire_proposal { from: proposed, to: expired, actor: clock, due: { at: self.proposalExpiresAt } }\n}\n"],
12
- ["money.hsx", "header money\n\n// Economics: Held funding and returns are principal. Release to the company realizes\n// earnings; release to another participant passes the payer's cash through. A late\n// fee charge is the same: earnings for the company, pass-through for another payee.\n// Generic transfers, splits, schedules, swaps, boundary payouts and metered fees\n// retain no assumed purpose.\n\n// Expose each attachment's create and caller actions explicitly. A transfer or\n// split pays once; a hold exposes fund, release and refund separately. Release\n// pays payee and refund returns payer. released_by runs release and defaults to\n// payee, so a shop that is payee keeps a deposit without acting for its customer.\n// Bind released_by: payer for an escrow-style hold that only the payer releases.\n// Only the payee refunds. A hold has no dispute or damage decision.\n// The payee proposes a schedule and only the payer activates or cancels it; the\n// payee stops it. Without every, create makes count occurrences on the listed\n// dates and they sum to amount. With every (1 month, 2 weeks), each occurrence\n// charges amount, the first at startsAt, and paying one creates the next, so only\n// one piece waits ahead. Months step from startsAt and clamp to the month's end.\n// create refuses a startsAt in the past. An authored count ends it after count\n// pieces; without one it runs until stopped or cancelled. Each due occurrence pays\n// only while the schedule is active, and one clock drain charges at most 126\n// pieces; the next drain continues a plan that fell further behind.\n// A pool accepts whole contributions only up to its remaining target and at most\n// 366 paid records. Expose pay to release the exact target. Clock failure refunds\n// original contributors; excess acceptance and partial contribution are absent.\n// A swap reserves both legs before exchange or voids reservations on expiry.\n// Payout instruct reserves across the selected adapter; confirm/reject require\n// matching terminal instruction evidence. An acknowledgement cannot settle it.\n// Metered bill charges a unique usage identity at the fixed unit price, only\n// under an active mandate the payer created: bills stop at its expiresAt, and at\n// most 366 billed events across every metered attachment on the mandate may sum\n// their payer debit, buyer fee and tax included, to its limit. The payer revokes\n// it to stop billing. Only the payee cancels its own unbilled usage.\n// The payer creates a late fee against its dueAt, which rename can bind to the\n// record's own due field. Once dueAt plus grace plus one period has passed, the\n// clock charges amount from payer to payee for each whole period, and the last\n// charge takes only what is left under cap; then the fee is capped. The payee runs\n// stop when the obligation is met. Stop keeps what was owed: each charge due at or\n// before it still posts, and the fee settles until the last of those posts, then\n// stops. A period still running at the stop is not charged. A charge the payer cannot fund refuses as clock work and charging waits\n// for its retry; the payee runs waive to forgive what is still owed. Grace is at\n// least one second; there are no percentage or interest-style fees.\n\n// Cost: transfer.pay declares one transfer. Hold.create declares one owned account;\n// fund, release and refund each declare one transfer. Schedules and pools add bounded\n// child invocations. Each late fee charge declares one transfer, and cap may be at most\n// 366 times amount. Run hsx cost on the composed program for counts, not riyal prices.\n\ninstrument transfer(payer: party, payee: party, amount: money = runtime) {\n summary: \"One transfer between the bound parties.\"\n fields { amount: money = amount }\n lifecycle { states: [pending, paid, cancelled], initial: pending }\n action create { actor: { party: payer }, requires self.amount > \"0\" }\n action pay {\n from: pending, to: paid, actor: { party: payer }\n moves self.amount from payer to payee\n }\n action cancel { from: pending, to: cancelled, actor: { party: payer } }\n}\n\ninstrument hold(payer: party, payee: party, amount: money = runtime, released_by: party = payee) {\n summary: \"Hold the declared amount until release or refund.\"\n fields { payer: account of payer, payee: account of payee, amount: money = amount, price: money = self.amount, held: account of self }\n lifecycle { states: [pending, funded, released, refunded, cancelled], initial: pending }\n action create { }\n action fund {\n from: pending, to: funded, actor: { party: payer }\n moves self.amount from payer to self.held economics { purpose: principal, sourceParty: payer }\n }\n action confirm {\n from: pending, to: funded\n requires self.held.balance == self.amount\n }\n action release {\n from: funded, to: released, actor: { party: released_by }\n moves self.amount from self.held to payee economics { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: pass_through, sourceParty: programOperator } }\n }\n action refund {\n from: funded, to: refunded, actor: { party: payee }\n moves self.amount from self.held to payer economics { purpose: principal, sourceParty: programOperator }\n }\n action cancel { from: pending, to: cancelled }\n}\n\ninstrument split(payer: party, amount: money = runtime, shares: split = { programOperator: 100% }) {\n summary: \"Split one amount; the last declared recipient receives the rounding remainder.\"\n fields { amount: money = amount }\n lifecycle { states: [pending, paid, cancelled], initial: pending }\n action create {}\n action pay { allowZero: true, requires self.amount > \"0\"; from: pending, to: paid, actor: { party: payer }, moves self.amount from payer shares shares }\n action cancel { from: pending, to: cancelled }\n}\n\ninstrument schedule(payer: party, payee: party, amount: money = runtime, count: integer(1, 366) = 12, every: period?) {\n summary: \"Pieces due on listed dates that sum to the total, or one amount each period from a start date.\"\n fields {\n amount: money = amount\n when every is unset { count: integer = count, dates: list(date, count) }\n when every is set { startsAt: date }\n }\n lifecycle { states: [draft, active, complete, cancelled], initial: draft }\n action create {\n actor: { party: payee }\n when every is unset { invoke: [{ range: { count: { literal: count }, maximum: count, bind: position }, instrument: occurrence, action: create, input: { schedule: { field: self.id }, position: { field: position } } }] }\n when every is set {\n requires self.startsAt >= self.now\n invoke: [{ instrument: occurrence, action: create, input: { schedule: { field: self.id }, position: { literal: 1 } } }]\n }\n }\n action activate { from: draft, to: active, actor: { party: payer } }\n action complete {\n from: active, to: complete\n requires count of { instrument: occurrence, reference: \"schedule\", anchor: self.id, states: [pending], limit: 366 } == 0\n }\n action cancel { from: [draft, active], to: cancelled, actor: { party: payer } }\n action stop { from: active, to: cancelled, actor: { party: payee } }\n records {\n occurrence: {\n fields {\n schedule: ref<parent>\n when every is unset {\n position: integer(1, count), dueAt: date = at(self.schedule.dates, self.position)\n base: money = divide(self.schedule.amount, count)\n allocated: money = multiply(self.base, count)\n remainder: money = subtract(self.schedule.amount, self.allocated)\n first: integer = divide(1, self.position)\n adjustment: money = multiply(self.remainder, self.first)\n amount: money = sum(self.base, self.adjustment)\n }\n when every is set {\n position: integer, offset: integer = subtract(self.position, 1), following: integer = sum(self.position, 1)\n dueAt: date = after(self.schedule.startsAt, every, self.offset)\n amount: money = self.schedule.amount\n }\n }\n lifecycle { states: [pending, paid, cancelled], initial: pending }\n action create {\n actor: { parent: [parent, current()] }\n input { schedule: ref<parent>, when every is unset { position: integer(1, count) } when every is set { position: integer } }\n requires unique \"scheduled_position\" on [self.schedule, self.position]\n }\n action pay {\n allowZero: true, from: pending, to: paid, actor: clock, due: { at: self.dueAt }\n requires self.schedule in [active]\n moves self.amount from payer to payee\n when every is set {\n when count is set { invoke: [{ instrument: current(), action: create, guard: { kind: compare, left: { field: self.position }, operator: \"<\", right: { literal: count } }, input: { schedule: { field: self.schedule }, position: { field: self.following } } }] }\n when count is unset { invoke: [{ instrument: current(), action: create, input: { schedule: { field: self.schedule }, position: { field: self.following } } }] }\n }\n }\n action cancel { from: pending, to: cancelled, requires self.schedule in [cancelled] }\n }\n }\n}\n\ninstrument pool(payer: party, payee: party, target: money, closes: date) {\n summary: \"Contributions fund one threshold or return to their original contributor.\"\n fields { target: money = target, closesAt: date = closes, held: account of self }\n lifecycle { states: [open, paid, failed], initial: open }\n action create { }\n action pay {\n from: open, to: paid, actor: { party: payee }\n requires self.held.balance == self.target\n moves self.target from self.held to payee economics { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: pass_through, sourceParty: programOperator } }\n }\n action fail {\n from: open, to: failed, actor: clock, due: { at: self.closesAt }\n requires self.held.balance < self.target\n invoke: [{ selection: { instrument: contribution, reference: \"pool\", anchor: self.id, states: [paid], limit: 366 }, action: refund, input: {} }]\n }\n records {\n contribution: {\n fields { pool: ref<parent>, payer: account of payer, amount: money, remaining: money? }\n lifecycle { states: [pending, paid, refunded], initial: pending }\n invariants count of { instrument: current(), reference: \"pool\", anchor: self.pool, states: [paid], limit: 366 } <= 366\n action create { requires self.pool in [open] }\n 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 } }\n action refund { from: paid, to: refunded, actor: { parent: parent }, moves self.amount from self.pool.held to self.payer economics { purpose: principal, sourceParty: programOperator } }\n }\n }\n}\n\ninstrument swap(first: party, second: party, first_amount: money, second_amount: money, expires: date) {\n summary: \"Two reservations settle together or both return.\"\n fields { firstAmount: money = first_amount, secondAmount: money = second_amount, expiresAt: date = expires, firstReceipt: text?, secondReceipt: text? }\n lifecycle { states: [pending, first_ready, second_ready, both_ready, exchanged, cancelled], initial: pending }\n action create {}\n action fund_first { from: pending, to: first_ready, actor: { party: first }, deadline: { at: self.expiresAt }, moves reserve self.firstAmount from first to second capture \"firstReceipt\" }\n action fund_second { from: first_ready, to: both_ready, actor: { party: second }, deadline: { at: self.expiresAt }, moves reserve self.secondAmount from second to first capture \"secondReceipt\" }\n action start_second { from: pending, to: second_ready, actor: { party: second }, deadline: { at: self.expiresAt }, moves reserve self.secondAmount from second to first capture \"secondReceipt\" }\n action finish_first { from: second_ready, to: both_ready, actor: { party: first }, deadline: { at: self.expiresAt }, moves reserve self.firstAmount from first to second capture \"firstReceipt\" }\n action expire_second { from: second_ready, to: cancelled, actor: clock, due: { at: self.expiresAt }, moves void self.secondReceipt }\n action exchange { from: both_ready, to: exchanged, actor: { party: first }, moves post self.firstReceipt; moves post self.secondReceipt }\n action cancel { from: pending, to: cancelled }\n action expire_first { from: first_ready, to: cancelled, actor: clock, due: { at: self.expiresAt }, moves void self.firstReceipt }\n action expire_both { from: both_ready, to: cancelled, actor: clock, due: { at: self.expiresAt }, moves void self.firstReceipt; moves void self.secondReceipt }\n}\n\ninstrument payout(payer: party, payee: party, adapter: text, amount: money = runtime) {\n summary: \"Pay the recipient when the provider confirms settlement.\"\n fields { amount: money = amount }\n lifecycle { states: [pending, instructed, settled, rejected], initial: pending }\n action create {}\n action instruct {\n from: pending, to: instructed, actor: { party: payer }\n moves reserve self.amount from payer to payee boundary adapter\n }\n action confirm {\n from: instructed, to: settled\n moves post instruct\n }\n action reject {\n from: instructed, to: rejected\n moves void instruct\n }\n}\n\ninstrument mandate(payer: party, payee: party) {\n summary: \"A payer's permission for one payee to charge up to a total until it expires.\"\n fields { payer: account of payer, payee: account of payee, limit: money, expiresAt: date }\n lifecycle { states: [active, revoked], initial: active }\n action create { actor: { party: payer }, requires self.limit > \"0\" }\n action revoke { from: active, to: revoked, actor: { party: payer } }\n}\n\ninstrument metered(payer: party, payee: party, unit_price: money, units: integer = 1, fee: fee = { seller: 0% }, mandate: ref<money.mandate> = object(money.mandate)) {\n summary: \"A unique usage event priced once at the fixed unit price.\"\n fields { usageIdentity: text, mandate: ref<mandate>, payer: account of payer, payee: account of payee, unitPrice: money = unit_price, units: integer = units, amount: money = multiply(self.unitPrice, self.units) }\n lifecycle { states: [recorded, billed, cancelled], initial: recorded }\n invariants sum \"bill_move1_debit\" of { instrument: all(money.metered), reference: \"mandate\", anchor: self.mandate, states: [billed], limit: 366 } <= self.mandate.limit\n action create { requires unique \"usage_event\" on [self.usageIdentity]; requires self.mandate.payer == self.payer; requires self.mandate.payee == self.payee }\n action bill { allowZero: true, requires self.amount > \"0\"; from: recorded, to: billed, actor: { party: payee }, deadline: { at: self.mandate.expiresAt }, requires self.mandate in [active], moves self.amount from payer to payee fee fee }\n action cancel { from: recorded, to: cancelled, actor: { party: payee } }\n}\n\ninstrument late_fee(payer: party, payee: party, amount: money, cap: money, period: duration = 1d, grace: duration = 1h) {\n summary: \"Charge a fixed fee for each period a due time stays unmet, up to a cap.\"\n fields {\n payer: account of payer, payee: account of payee, amount: money = amount, cap: money = cap, ceiling: money = multiply(self.amount, 366)\n dueAt: date, graceEndsAt: date?, firstAt: date?, nextAt: date?, followingAt: date?, charge: money?, left: money?, remaining: money?, stoppedAt: date?\n }\n lifecycle { states: [running, settling, capped, stopped], initial: running }\n action create {\n actor: { party: payer }\n requires self.amount > \"0\"\n requires self.cap >= self.amount\n requires self.cap <= self.ceiling\n calculate: [{ target: graceEndsAt, op: shift, date: { field: self.dueAt }, milliseconds: { literal: grace }, direction: after }, { target: firstAt, op: shift, date: { field: self.graceEndsAt }, milliseconds: { literal: period }, direction: after }]\n set: { nextAt: { field: self.firstAt }, left: { field: self.cap } }\n }\n action charge {\n summary: \"Charge late fee\"\n from: running, to: running, actor: clock, due: { at: self.nextAt }\n calculate: [{ target: charge, op: minimum, values: [{ field: self.amount }, { field: self.left }] }, { target: remaining, op: subtract, base: { field: self.left }, subtract: [{ field: self.charge }] }, { target: followingAt, op: shift, date: { field: self.nextAt }, milliseconds: { literal: period }, direction: after }]\n set: { left: { field: self.remaining }, nextAt: { field: self.followingAt } }\n moves self.charge from payer to payee economics { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: pass_through, sourceParty: payer } }\n invoke: [{ selection: { instrument: current(), reference: \"payer\", anchor: self.payer, states: [running], limit: 1, where: { id: { field: self.id }, left: { literal: \"0\" } } }, action: finish, input: {} }]\n }\n action collect {\n summary: \"Collect owed late fee\"\n from: settling, to: settling, actor: clock, due: { at: self.nextAt }\n calculate: [{ target: charge, op: minimum, values: [{ field: self.amount }, { field: self.left }] }, { target: remaining, op: subtract, base: { field: self.left }, subtract: [{ field: self.charge }] }, { target: followingAt, op: shift, date: { field: self.nextAt }, milliseconds: { literal: period }, direction: after }]\n set: { left: { field: self.remaining }, nextAt: { field: self.followingAt } }\n moves self.charge from payer to payee economics { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: pass_through, sourceParty: payer } }\n invoke: [\n { reference: self.id, action: settle, guard: { kind: compare, left: { field: self.nextAt }, operator: \">\", right: { field: self.stoppedAt } }, input: {} }\n { selection: { instrument: current(), reference: \"payer\", anchor: self.payer, states: [settling], limit: 1, where: { id: { field: self.id }, left: { literal: \"0\" } } }, action: finish, input: {} }\n ]\n }\n action finish { from: [running, settling], to: capped, actor: { parent: current() } }\n action stop {\n from: running, to: settling, actor: { party: payee }\n set: { stoppedAt: { field: self.now } }\n invoke: [{ reference: self.id, action: settle, guard: { kind: compare, left: { field: self.nextAt }, operator: \">\", right: { field: self.stoppedAt } }, input: {} }]\n }\n action settle { from: settling, to: stopped, actor: { parent: current() } }\n action waive { from: settling, to: stopped, actor: { party: payee } }\n}\n"],
12
+ ["money.hsx", "header money\n\n// Economics: Held funding and returns are principal. Release to the company realizes\n// earnings; release to another participant passes the payer's cash through. A late\n// fee charge is the same: earnings for the company, pass-through for another payee.\n// Generic transfers, splits, schedules, swaps, boundary payouts and metered fees\n// retain no assumed purpose.\n\n// Expose each attachment's create and caller actions explicitly. A transfer or\n// split pays once; a hold exposes fund, release and refund separately. Release\n// pays payee and refund returns payer. released_by runs release and defaults to\n// payee, so a shop that is payee keeps a deposit without acting for its customer.\n// Bind released_by: payer for an escrow-style hold that only the payer releases.\n// Only the payee refunds. A hold has no dispute or damage decision.\n// The payee proposes a schedule and only the payer activates or cancels it; the\n// payee stops it. Without every, count is required and create makes count\n// occurrences on the listed dates that sum to amount. With every (1 month, 2\n// weeks), each occurrence charges amount, the first at startsAt, and paying one\n// creates the next, so only one piece waits ahead. Months step from startsAt and\n// clamp to the month's end. create refuses a startsAt in the past. An authored\n// count ends it after count pieces; without one it runs until stopped or\n// cancelled. The schedule keeps count as a field only when it is set, so reads\n// name a piece \"2 of 12\" or, open-ended, \"#2\". Each due occurrence pays\n// only while the schedule is active, and one clock drain posts at most the 253\n// ledger transfers one request takes, 253 one-transfer pieces; the next drain\n// continues a plan that fell further behind.\n// A pool accepts whole contributions only up to its remaining target and at most\n// 253 paid records, so a failure refunds every contributor in one ledger request.\n// Expose pay to release the exact target. Clock failure refunds original\n// contributors; excess acceptance and partial contribution are absent.\n// A swap reserves both legs before exchange or voids reservations on expiry.\n// Payout instruct reserves across the selected adapter; confirm/reject require\n// matching terminal instruction evidence. An acknowledgement cannot settle it.\n// Metered bill charges a unique usage identity at the fixed unit price, only\n// under an active mandate the payer created: bills stop at its expiresAt, and at\n// most 366 billed events across every metered attachment on the mandate may sum\n// their payer debit, buyer fee and tax included, to its limit. The payer revokes\n// it to stop billing. Only the payee cancels its own unbilled usage.\n// The company starts a late fee against its dueAt, so late tracking never waits\n// on the payer; rename can bind dueAt to the record's own due field. Once dueAt\n// plus grace plus one period has passed, the clock charges amount from payer to\n// payee for each whole period, and the last charge takes only what is left under\n// cap; then the fee is capped. Charge k is due at dueAt plus grace plus k\n// periods. create copies dueAt. When any action on the record changes the bound\n// field, follow runs on the fee in the same request and reads the field as it\n// stands; the payee's reschedule runs follow directly. Follow keeps the charges\n// already posted and moves the rest later, never earlier, because fees run from\n// the dueAt set at create; past ones post on the next clock run. The clock never\n// runs twice at one instant, so follow also needs the next charge after the last\n// posted one. A move that breaks either rule refuses reschedule, while another\n// action's change leaves the fee where it was and still runs. Period counts\n// whole seconds. The payee runs stop when the obligation is met. Stop keeps what\n// was owed: each charge due at or before it still posts, and the fee settles\n// until the last of those posts, then stops. A period still running at the stop\n// is not charged. A charge the payer cannot fund refuses as clock work and\n// charging waits for its retry; the payee runs waive to forgive what is still\n// owed. Grace is at least one second; there are no percentage or interest-style\n// fees. Bind a hold's late_fee to the late fee on its object and refund also\n// runs stop on that fee while it is running, so returning the deposit ends both.\n// The link sits on refund because every good return refunds, and a fee already\n// capped or stopped is skipped rather than blocking the refund. The hold links\n// the fee at create, so the fee is agreed first, with the same payer and payee.\n\n// Cost: transfer.pay declares one transfer. Hold.create declares one owned account;\n// fund, release and refund each declare one transfer. Schedules and pools add bounded\n// child invocations. Each late fee charge declares one transfer, and cap may be at most\n// 366 times amount. Run hsx cost on the composed program for counts, not riyal prices.\n\ninstrument transfer(payer: party, payee: party, amount: money = runtime) {\n summary: \"One transfer between the bound parties.\"\n fields { amount: money = amount }\n lifecycle { states: [pending, paid, cancelled], initial: pending }\n action create { actor: { party: payer }, requires self.amount > \"0\" }\n action pay {\n from: pending, to: paid, actor: { party: payer }\n moves self.amount from payer to payee\n }\n action cancel { from: pending, to: cancelled, actor: { party: payer } }\n}\n\ninstrument hold(payer: party, payee: party, amount: money = runtime, released_by: party = payee, late_fee: ref<money.late_fee>?) {\n summary: \"Hold the declared amount until release or refund.\"\n fields {\n payer: account of payer, payee: account of payee, amount: money = amount, price: money = self.amount, held: account of self\n when late_fee is set { lateFee: ref<late_fee> }\n }\n lifecycle { states: [pending, funded, released, refunded, cancelled], initial: pending }\n action create {\n when late_fee is set {\n requires self.lateFee.payer == self.payer\n requires self.lateFee.payee == self.payee\n }\n }\n action fund {\n from: pending, to: funded, actor: { party: payer }\n moves self.amount from payer to self.held economics { purpose: principal, sourceParty: payer }\n }\n action confirm {\n from: pending, to: funded\n requires self.held.balance == self.amount\n }\n action release {\n from: funded, to: released, actor: { party: released_by }\n moves self.amount from self.held to payee economics { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: pass_through, sourceParty: programOperator } }\n }\n action refund {\n from: funded, to: refunded, actor: { party: payee }\n moves self.amount from self.held to payer economics { purpose: principal, sourceParty: programOperator }\n when late_fee is set { invoke: [{ selection: { instrument: late_fee, reference: \"payer\", anchor: self.payer, states: [running], limit: 1, where: { id: { field: self.lateFee } } }, action: stop, input: {} }] }\n }\n action cancel { from: pending, to: cancelled }\n}\n\ninstrument split(payer: party, amount: money = runtime, shares: split = { programOperator: 100% }) {\n summary: \"Split one amount; the last declared recipient receives the rounding remainder.\"\n fields { amount: money = amount }\n lifecycle { states: [pending, paid, cancelled], initial: pending }\n action create {}\n action pay { allowZero: true, requires self.amount > \"0\"; from: pending, to: paid, actor: { party: payer }, moves self.amount from payer shares shares }\n action cancel { from: pending, to: cancelled }\n}\n\ninstrument schedule(payer: party, payee: party, amount: money = runtime, count: integer(1, 366)?, every: period?) {\n summary: \"Pieces due on listed dates that sum to the total, or one amount each period from a start date until stopped, or for count periods.\"\n dependencies {\n count {\n selector: every, is: unset\n message: \"Attachment `{attachment}` charges on a list of dates, so it needs `count`, the number of dates.\"\n fix: \"Add `count: 3` for three dated pieces, or add `every: 1 month` to charge each month until stopped or cancelled.\"\n }\n }\n fields {\n amount: money = amount\n when every is unset { count: integer = count, dates: list(date, count) }\n when every is set {\n startsAt: date\n when count is set { count: integer = count }\n }\n }\n lifecycle { states: [draft, active, complete, cancelled], initial: draft }\n action create {\n actor: { party: payee }\n when every is unset { invoke: [{ range: { count: { literal: count }, maximum: count, bind: position }, instrument: occurrence, action: create, input: { schedule: { field: self.id }, position: { field: position } } }] }\n when every is set {\n requires self.startsAt >= self.now\n invoke: [{ instrument: occurrence, action: create, input: { schedule: { field: self.id }, position: { literal: 1 } } }]\n }\n }\n action activate { from: draft, to: active, actor: { party: payer } }\n action complete {\n from: active, to: complete\n requires count of { instrument: occurrence, reference: \"schedule\", anchor: self.id, states: [pending], limit: 366 } == 0\n }\n action cancel { from: [draft, active], to: cancelled, actor: { party: payer } }\n action stop { from: active, to: cancelled, actor: { party: payee } }\n records {\n occurrence: {\n fields {\n schedule: ref<parent>\n when every is unset {\n position: integer(1, count), dueAt: date = at(self.schedule.dates, self.position)\n base: money = divide(self.schedule.amount, count)\n allocated: money = multiply(self.base, count)\n remainder: money = subtract(self.schedule.amount, self.allocated)\n first: integer = divide(1, self.position)\n adjustment: money = multiply(self.remainder, self.first)\n amount: money = sum(self.base, self.adjustment)\n }\n when every is set {\n position: integer, offset: integer = subtract(self.position, 1), following: integer = sum(self.position, 1)\n dueAt: date = after(self.schedule.startsAt, every, self.offset)\n amount: money = self.schedule.amount\n }\n }\n lifecycle { states: [pending, paid, cancelled], initial: pending }\n action create {\n actor: { parent: [parent, current()] }\n input { schedule: ref<parent>, when every is unset { position: integer(1, count) } when every is set { position: integer } }\n requires unique \"scheduled_position\" on [self.schedule, self.position]\n }\n action pay {\n allowZero: true, from: pending, to: paid, actor: clock, due: { at: self.dueAt }\n requires self.schedule in [active]\n moves self.amount from payer to payee\n when every is set {\n when count is set { invoke: [{ instrument: current(), action: create, guard: { kind: compare, left: { field: self.position }, operator: \"<\", right: { literal: count } }, input: { schedule: { field: self.schedule }, position: { field: self.following } } }] }\n when count is unset { invoke: [{ instrument: current(), action: create, input: { schedule: { field: self.schedule }, position: { field: self.following } } }] }\n }\n }\n action cancel { from: pending, to: cancelled, requires self.schedule in [cancelled] }\n }\n }\n}\n\ninstrument pool(payer: party, payee: party, target: money, closes: date) {\n summary: \"Contributions fund one threshold or return to their original contributor.\"\n fields { target: money = target, closesAt: date = closes, held: account of self }\n lifecycle { states: [open, paid, failed], initial: open }\n action create { }\n action pay {\n from: open, to: paid, actor: { party: payee }\n requires self.held.balance == self.target\n moves self.target from self.held to payee economics { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: pass_through, sourceParty: programOperator } }\n }\n action fail {\n from: open, to: failed, actor: clock, due: { at: self.closesAt }\n requires self.held.balance < self.target\n invoke: [{ selection: { instrument: contribution, reference: \"pool\", anchor: self.id, states: [paid], limit: 253 }, action: refund, input: {} }]\n }\n records {\n contribution: {\n fields { pool: ref<parent>, payer: account of payer, amount: money, remaining: money? }\n lifecycle { states: [pending, paid, refunded], initial: pending }\n invariants count of { instrument: current(), reference: \"pool\", anchor: self.pool, states: [paid], limit: 253 } <= 253\n action create { requires self.pool in [open] }\n 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 } }\n action refund { from: paid, to: refunded, actor: { parent: parent }, moves self.amount from self.pool.held to self.payer economics { purpose: principal, sourceParty: programOperator } }\n }\n }\n}\n\ninstrument swap(first: party, second: party, first_amount: money, second_amount: money, expires: date) {\n summary: \"Two reservations settle together or both return.\"\n fields { firstAmount: money = first_amount, secondAmount: money = second_amount, expiresAt: date = expires, firstReceipt: text?, secondReceipt: text? }\n lifecycle { states: [pending, first_ready, second_ready, both_ready, exchanged, cancelled], initial: pending }\n action create {}\n action fund_first { from: pending, to: first_ready, actor: { party: first }, deadline: { at: self.expiresAt }, moves reserve self.firstAmount from first to second capture \"firstReceipt\" }\n action fund_second { from: first_ready, to: both_ready, actor: { party: second }, deadline: { at: self.expiresAt }, moves reserve self.secondAmount from second to first capture \"secondReceipt\" }\n action start_second { from: pending, to: second_ready, actor: { party: second }, deadline: { at: self.expiresAt }, moves reserve self.secondAmount from second to first capture \"secondReceipt\" }\n action finish_first { from: second_ready, to: both_ready, actor: { party: first }, deadline: { at: self.expiresAt }, moves reserve self.firstAmount from first to second capture \"firstReceipt\" }\n action expire_second { from: second_ready, to: cancelled, actor: clock, due: { at: self.expiresAt }, moves void self.secondReceipt }\n action exchange { from: both_ready, to: exchanged, actor: { party: first }, moves post self.firstReceipt; moves post self.secondReceipt }\n action cancel { from: pending, to: cancelled }\n action expire_first { from: first_ready, to: cancelled, actor: clock, due: { at: self.expiresAt }, moves void self.firstReceipt }\n action expire_both { from: both_ready, to: cancelled, actor: clock, due: { at: self.expiresAt }, moves void self.firstReceipt; moves void self.secondReceipt }\n}\n\ninstrument payout(payer: party, payee: party, adapter: text, amount: money = runtime) {\n summary: \"Pay the recipient when the provider confirms settlement.\"\n fields { amount: money = amount }\n lifecycle { states: [pending, instructed, settled, rejected], initial: pending }\n action create {}\n action instruct {\n from: pending, to: instructed, actor: { party: payer }\n moves reserve self.amount from payer to payee boundary adapter\n }\n action confirm {\n from: instructed, to: settled\n moves post instruct\n }\n action reject {\n from: instructed, to: rejected\n moves void instruct\n }\n}\n\ninstrument mandate(payer: party, payee: party) {\n summary: \"A payer's permission for one payee to charge up to a total until it expires.\"\n fields { payer: account of payer, payee: account of payee, limit: money, expiresAt: date }\n lifecycle { states: [active, revoked], initial: active }\n action create { actor: { party: payer }, requires self.limit > \"0\" }\n action revoke { from: active, to: revoked, actor: { party: payer } }\n}\n\ninstrument metered(payer: party, payee: party, unit_price: money, units: integer = 1, fee: fee = { seller: 0% }, mandate: ref<money.mandate> = object(money.mandate)) {\n summary: \"A unique usage event priced once at the fixed unit price.\"\n fields { usageIdentity: text, mandate: ref<mandate>, payer: account of payer, payee: account of payee, unitPrice: money = unit_price, units: integer = units, amount: money = multiply(self.unitPrice, self.units) }\n lifecycle { states: [recorded, billed, cancelled], initial: recorded }\n invariants sum \"bill_move1_debit\" of { instrument: all(money.metered), reference: \"mandate\", anchor: self.mandate, states: [billed], limit: 366 } <= self.mandate.limit\n action create { requires unique \"usage_event\" on [self.usageIdentity]; requires self.mandate.payer == self.payer; requires self.mandate.payee == self.payee }\n action bill { allowZero: true, requires self.amount > \"0\"; from: recorded, to: billed, actor: { party: payee }, deadline: { at: self.mandate.expiresAt }, requires self.mandate in [active], moves self.amount from payer to payee fee fee }\n action cancel { from: recorded, to: cancelled, actor: { party: payee } }\n}\n\ninstrument late_fee(payer: party, payee: party, amount: money, cap: money, period: duration = 1d, grace: duration = 1h) {\n summary: \"Charge a fixed fee for each period a due time stays unmet, up to a cap.\"\n fields {\n payer: account of payer, payee: account of payee, amount: money = amount, cap: money = cap, ceiling: money = multiply(self.amount, 366)\n dueAt: date, graceEndsAt: date?, firstAt: date?, nextAt: date?, followingAt: date?, charge: money?, left: money?, remaining: money?, stoppedAt: date?\n stride: integer?, strideAt: date?, elapsed: integer?, lastAt: date?\n }\n lifecycle { states: [running, settling, capped, stopped], initial: running }\n action create {\n actor: { party: programOperator }\n requires self.amount > \"0\"\n requires self.cap >= self.amount\n requires self.cap <= self.ceiling\n calculate: [{ target: graceEndsAt, op: shift, date: { field: self.dueAt }, milliseconds: { literal: grace }, direction: after }, { target: firstAt, op: shift, date: { field: self.graceEndsAt }, milliseconds: { literal: period }, direction: after }, { target: stride, op: divide, amount: { literal: period }, divisor: { literal: 1000 }, rounding: floor }, { target: strideAt, op: step, date: { field: self.graceEndsAt }, period: { literal: \"PT1S\" }, times: { field: self.stride } }, { target: elapsed, op: sum, values: [{ literal: 0 }] }]\n requires self.strideAt == self.firstAt\n set: { nextAt: { field: self.firstAt }, left: { field: self.cap }, lastAt: { literal: \"1970-01-01T00:00:00.000Z\" } }\n }\n action charge {\n summary: \"Charge late fee\"\n from: running, to: running, actor: clock, due: { at: self.nextAt }\n calculate: [{ target: charge, op: minimum, values: [{ field: self.amount }, { field: self.left }] }, { target: remaining, op: subtract, base: { field: self.left }, subtract: [{ field: self.charge }] }, { target: followingAt, op: shift, date: { field: self.nextAt }, milliseconds: { literal: period }, direction: after }, { target: elapsed, op: sum, values: [{ field: self.elapsed }, { field: self.stride }] }]\n set: { left: { field: self.remaining }, nextAt: { field: self.followingAt }, lastAt: { field: self.nextAt } }\n moves self.charge from payer to payee economics { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: pass_through, sourceParty: payer } }\n invoke: [{ selection: { instrument: current(), reference: \"payer\", anchor: self.payer, states: [running], limit: 1, where: { id: { field: self.id }, left: { literal: \"0\" } } }, action: finish, input: {} }]\n }\n action reschedule {\n summary: \"Move the due time\"\n from: running, to: running, actor: { party: payee }\n subject { dueAt: date }\n invoke: [{ reference: self.id, action: follow, input: {} }]\n }\n action follow {\n summary: \"Follow the due time\"\n from: running, to: running, follows: dueAt\n subject { dueAt: date }\n // Fees run from the dueAt set at create, so the date only moves later.\n requires subject.dueAt >= self.dueAt\n calculate: [{ target: graceEndsAt, op: shift, date: { field: subject.dueAt }, milliseconds: { literal: grace }, direction: after }, { target: firstAt, op: shift, date: { field: self.graceEndsAt }, milliseconds: { literal: period }, direction: after }, { target: followingAt, op: step, date: { field: self.firstAt }, period: { literal: \"PT1S\" }, times: { field: self.elapsed } }]\n requires self.followingAt > self.lastAt\n set: { dueAt: { field: subject.dueAt }, nextAt: { field: self.followingAt } }\n }\n action collect {\n summary: \"Collect owed late fee\"\n from: settling, to: settling, actor: clock, due: { at: self.nextAt }\n calculate: [{ target: charge, op: minimum, values: [{ field: self.amount }, { field: self.left }] }, { target: remaining, op: subtract, base: { field: self.left }, subtract: [{ field: self.charge }] }, { target: followingAt, op: shift, date: { field: self.nextAt }, milliseconds: { literal: period }, direction: after }]\n set: { left: { field: self.remaining }, nextAt: { field: self.followingAt } }\n moves self.charge from payer to payee economics { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: pass_through, sourceParty: payer } }\n invoke: [\n { reference: self.id, action: settle, guard: { kind: compare, left: { field: self.nextAt }, operator: \">\", right: { field: self.stoppedAt } }, input: {} }\n { selection: { instrument: current(), reference: \"payer\", anchor: self.payer, states: [settling], limit: 1, where: { id: { field: self.id }, left: { literal: \"0\" } } }, action: finish, input: {} }\n ]\n }\n action finish { from: [running, settling], to: capped, actor: { parent: current() } }\n action stop {\n from: running, to: settling, actor: { party: payee }\n set: { stoppedAt: { field: self.now } }\n invoke: [{ reference: self.id, action: settle, guard: { kind: compare, left: { field: self.nextAt }, operator: \">\", right: { field: self.stoppedAt } }, input: {} }]\n }\n action settle { from: settling, to: stopped, actor: { parent: current() } }\n action waive { from: settling, to: stopped, actor: { party: payee } }\n}\n"],
13
13
  ["purchase.hsx", "header purchase\n\n// A financed purchase connects a repayment plan, a delivery hold and optional\n// marketplace reservations. The hold blocks refunds while checkout is active.\n// Debt cancellation returns outstanding capital before the buyer's own cash.\ninstrument checkout(plans: ref<financing.installments>[], funds: ref<escrow.hold>, borrower: party, capital: party = programOperator) {\n summary: \"Fund a purchase and return lender capital before refunding the buyer.\"\n fields {\n funds: ref<funds>, borrower: account of borrower\n downPaymentCredit: money?, downPaymentRemaining: money?\n }\n lifecycle { states: [pending, active, closed], initial: pending }\n action create { actor: { party: borrower } }\n action check {\n from: pending, to: pending, actor: { parent: plans }\n input { plan: ref<plans> }\n requires input.plan.funds == self.id\n requires input.plan.borrower == self.borrower\n requires input.plan.borrower == self.funds.payer\n requires input.plan.price == self.funds.price\n }\n action collect { allowZero: true,\n from: pending, to: pending, actor: { parent: plans }\n input { plan: ref<plans> }\n requires input.plan.funds == self.id\n requires self.funds in [pending]\n calculate: [{ target: downPaymentCredit, op: minimum, values: [{ field: self.funds.held.balance }, { field: input.plan.downPayment }] }, { target: downPaymentRemaining, op: subtract, base: { field: input.plan.downPayment }, subtract: [{ field: self.downPaymentCredit }] }]\n moves self.downPaymentRemaining from self.borrower to self.funds.held economics { purpose: principal, sourceParty: borrower }\n }\n action disburse {\n from: pending, to: active, actor: { parent: plans }\n input { plan: ref<plans> }\n requires input.plan.funds == self.id\n requires self.funds in [pending]\n invoke: [{ selection: { instrument: all(marketplace.reservation), reference: \"funds\", anchor: self.funds, states: [active], limit: 1 }, action: credit, input: { funds: { field: self.funds }, contribution: { field: input.plan.downPayment } } }, { reference: self.id, action: fund, input: { plan: { field: input.plan } } }]\n }\n action fund { allowZero: true,\n from: active, to: active, actor: { parent: current() }\n input { plan: ref<plans> }\n calculate: [{ target: downPaymentCredit, op: minimum, values: [{ field: self.funds.held.balance }, { field: input.plan.downPayment }] }, { target: downPaymentRemaining, op: subtract, base: { field: input.plan.downPayment }, subtract: [{ field: self.downPaymentCredit }] }]\n moves self.downPaymentRemaining from self.borrower to self.funds.held economics { purpose: principal, sourceParty: borrower }\n moves input.plan.principal from input.plan.capital to self.funds.held economics { purpose: principal, sourceParty: capital }\n invoke: [{ reference: self.funds, action: confirm, input: {} }]\n }\n action write_off {\n from: active, to: active, actor: { parent: plans }\n input { plan: ref<plans> }\n requires input.plan.funds == self.id\n requires self.funds in [released]\n }\n action refund { allowZero: true,\n from: active, to: closed, actor: { parent: plans }\n input { plan: ref<plans>, principal: money }\n requires input.plan.funds == self.id\n requires self.funds in [return_verified]\n moves input.principal from self.funds.held to input.plan.capital economics { purpose: principal, sourceParty: capital }\n }\n action cancel_undelivered { allowZero: true,\n from: active, to: closed, actor: { parent: plans }\n input { plan: ref<plans> }\n requires input.plan.funds == self.id\n requires self.funds in [funded]\n moves input.plan.principal from self.funds.held to input.plan.capital economics { purpose: principal, sourceParty: capital }\n invoke: [{ reference: self.funds, action: finish_refund, input: {} }]\n }\n action return_paid {\n from: active, to: closed, actor: { parent: plans }\n input { plan: ref<plans> }\n requires input.plan.funds == self.id\n requires self.funds in [return_verified]\n invoke: [{ reference: self.funds, action: finish_refund, input: {} }]\n }\n action unwind_paid_undelivered {\n from: active, to: closed, actor: { parent: plans }\n input { plan: ref<plans> }\n requires input.plan.funds == self.id\n requires self.funds in [funded]\n requires self.funds.deliverBy < self.now\n invoke: [{ reference: self.funds, action: finish_refund, input: {} }]\n }\n action unwind_paid {\n from: active, to: closed, actor: { parent: plans }\n input { plan: ref<plans> }\n requires input.plan.funds == self.id\n requires self.funds in [funded, return_verified]\n requires self.funds.deliverBy < self.now\n invoke: [{ reference: self.funds, action: finish_refund, input: {} }]\n }\n}\n"],
14
14
  ["rental.hsx", "header rental\n\n// One hire per security agreement, including ended hires.\n// Pickup makes hire payable to the operator; cancellation before pickup refunds both holds.\ninstrument hire_charge(renter: party, security: ref<rental.deposit>) {\n fields { security: ref<security>, held: account of self }\n lifecycle { states: [pending, funded, released, cancelled], initial: pending }\n action create {\n actor: { party: renter }\n requires count of { instrument: current(), reference: \"security\", anchor: self.security, states: [pending, funded, released, cancelled], limit: 1 } == 0\n }\n action fund {\n from: pending, to: funded, actor: { party: renter }\n requires self.security in [pending, funded, hired, returned]\n moves 250 SAR from renter to self.held economics { purpose: principal, sourceParty: renter }\n }\n action release {\n from: funded, to: released, actor: { party: renter }\n requires self.security in [hired, returned]\n moves self.held.balance from self.held to programOperator economics { purpose: earning, sourceParty: renter }\n }\n action refund { allowZero: true,\n from: [pending, funded], to: cancelled, actor: { parent: security }\n moves self.held.balance from self.held to renter economics { purpose: principal, sourceParty: programOperator }\n }\n action cancel {\n from: [pending, funded], to: preserve, actor: { party: renter }\n invoke: [{ reference: self.security, action: cancel, input: {} }]\n }\n}\n\n// Security stays refundable. Only the operator records pickup and damage.\ninstrument deposit(renter: party, hire: ref<rental.hire_charge>) {\n summary: \"Refund rental security on return, less an authorized damage amount.\"\n fields { renter: account of renter, held: account of self, amount: money = subject.price, refund: money? }\n lifecycle { states: [pending, funded, hired, returned, cancelled], initial: pending }\n action create { actor: { party: renter }, subject { price: money }, requires self.amount > \"0\" }\n action fund {\n from: pending, to: funded, actor: { party: renter }\n moves self.amount from self.renter to self.held economics { purpose: principal, sourceParty: renter }\n }\n action pickup { from: funded, to: hired, actor: { party: programOperator } }\n action return {\n from: hired, to: returned, actor: { party: programOperator }\n input { returnReference: text }\n moves self.held.balance from self.held to self.renter economics { purpose: principal, sourceParty: programOperator }\n }\n action withhold { allowZero: true,\n from: hired, to: returned, actor: { party: programOperator }\n input { damage: money, damageReference: text }\n requires input.damage > \"0\"\n requires input.damage <= self.held.balance\n calculate: [{ target: refund, op: subtract, base: { field: self.held.balance }, subtract: [{ field: input.damage }] }]\n moves input.damage from self.held to programOperator economics { purpose: earning, sourceParty: renter }\n moves self.refund from self.held to self.renter economics { purpose: principal, sourceParty: programOperator }\n }\n action refund_before_pickup { allowZero: true,\n from: [pending, funded], to: cancelled, actor: { party: renter }\n moves self.held.balance from self.held to self.renter economics { purpose: principal, sourceParty: programOperator }\n invoke: [{ selection: { instrument: hire, reference: \"security\", anchor: self.id, states: [pending, funded], limit: 1 }, action: refund, input: {} }]\n }\n action cancel { allowZero: true,\n from: [pending, funded], to: cancelled, actor: { party: renter }\n moves self.held.balance from self.held to self.renter economics { purpose: principal, sourceParty: programOperator }\n invoke: [{ selection: { instrument: hire, reference: \"security\", anchor: self.id, states: [pending, funded], limit: 1 }, action: refund, input: {} }]\n }\n}\n\n"],
15
- ["reporting.hsx", "header reporting\n\n// Attach portfolio to one or more financing plans. Its only lifecycle action is\n// create; reports use the declared report request/read roles, not a money action.\n// Aging selects active facilities and includes earned profit when deciding arrears.\n// The default-rate report measures period-end stock, not new default incidence.\n// Paid facilities are excluded and write-offs counted separately. Amounts are riyal\n// minor units; declared scale and rounding govern ratios. Missing identity joins\n// or unreconciled schedule counts refuse.\n\n// Cost: portfolio.create declares no transfers, owned accounts or invocations.\n// That zero instruction count does not price report capture, rendering, storage or\n// release. The host owns those charges and their execution.\n\ninstrument portfolio(on: ref<financing.installments>[], default_days: integer(1, 3650) = 90, retention_years: integer(1, 100) = 10, aging_first_days: integer(1, 3650) = 30, aging_second_days: integer(1, 3650) = 60, aging_third_days: integer(1, 3650) = 90, ratio_scale: integer(1, 1000000) = 10000, ratio_rounding: enum(floor, halfUp) = floor) {\n summary: \"Declared financing reports evaluated over frozen Product facts.\"\n fields {}\n lifecycle { states: [declared], initial: declared }\n action create {}\n constraints { aging_first_days: less_than(aging_second_days), aging_second_days: less_than(aging_third_days) }\n reports: [\n {\n identity: { id: \"portfolio_aging\", version: 1, description: \"Period-end outstanding principal by oldest unpaid installment. Remaining scheduled profit is distinct from accrued profit. Restructuring evidence is unavailable.\" },\n scope: { kind: \"product\", classification: \"internal\", currency: \"SAR\" },\n datasets: [\n {\n id: \"facilities\",\n source: \"instrument\",\n instruments: on,\n rowKey: \"facilityId\",\n columns: [\n {\n name: \"facilityId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"borrowerAccount\",\n field: \"borrower\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"state\",\n field: \"status\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"originalPrincipal\",\n field: \"principal\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"scheduleCount\",\n field: \"months\",\n type: { kind: \"integer\" },\n required: true\n },\n {\n name: \"recordedCreation\",\n field: \"createdAt\",\n type: { kind: \"date\" },\n required: true\n }\n ],\n expressions: [\n {\n id: \"activeState\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"active\"\n },\n {\n id: \"paidState\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"paid\"\n },\n {\n id: \"writtenState\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"written_off\"\n },\n { id: \"active\", op: \"equal\", left: \"state\", right: \"activeState\" },\n { id: \"paid\", op: \"equal\", left: \"state\", right: \"paidState\" },\n { id: \"writtenOff\", op: \"equal\", left: \"state\", right: \"writtenState\" },\n { id: \"activeOrPaid\", op: \"or\", left: \"active\", right: \"paid\" },\n { id: \"financed\", op: \"or\", left: \"active\", right: \"writtenOff\" }\n ],\n selection: \"active\"\n },\n {\n id: \"schedule\",\n source: \"instrument\",\n instruments: child(on, slice),\n rowKey: \"sliceId\",\n columns: [\n {\n name: \"sliceId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"planId\",\n field: \"plan\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"due\",\n field: \"dueAt\",\n type: { kind: \"date\" },\n required: true\n },\n {\n name: \"principal\",\n field: \"principalReceivable.balance\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"profit\",\n field: \"profitReceivable.balance\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"earnedProfit\",\n field: \"profitEarned.balance\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"scheduledPrincipal\",\n field: \"principal\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n }\n ],\n expressions: [\n {\n id: \"zeroMoney\",\n op: \"literal\",\n type: { kind: \"money\", currency: \"SAR\" },\n value: \"0\"\n },\n {\n id: \"zeroDays\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: 0\n },\n { id: \"observed\", op: \"parameter\", name: \"observationAt\" },\n { id: \"scheduledOutstanding\", op: \"sum\", left: \"principal\", right: \"profit\" },\n { id: \"totalOutstanding\", op: \"sum\", left: \"scheduledOutstanding\", right: \"earnedProfit\" },\n { id: \"unpaid\", op: \"less\", left: \"zeroMoney\", right: \"totalOutstanding\" },\n { id: \"elapsed\", op: \"daysBetween\", left: \"due\", right: \"observed\" },\n { id: \"nonnegativeDays\", op: \"maximum\", left: \"elapsed\", right: \"zeroDays\" },\n { id: \"daysPastDue\", op: \"choose\", condition: \"unpaid\", yes: \"nonnegativeDays\", no: \"zeroDays\" }\n ]\n },\n {\n id: \"borrowerAccounts\",\n source: \"account\",\n instruments: [ ],\n rowKey: \"accountId\",\n columns: [\n {\n name: \"accountId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"participant\",\n field: \"ownerParticipantId\",\n type: { kind: \"text\" },\n required: false\n }\n ],\n expressions: [ ]\n },\n {\n id: \"borrowers\",\n source: \"identity\",\n instruments: [ ],\n rowKey: \"customerId\",\n columns: [\n {\n name: \"customerId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"participantId\",\n field: \"participantId\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"entityId\",\n field: \"entityId\",\n type: { kind: \"text\" },\n required: true\n }\n ],\n expressions: [ ]\n }\n ],\n time: { timezone: \"Asia/Riyadh\", boundary: \"startInclusiveEndExclusive\", observation: \"periodEnd\", history: \"retainedOnly\" },\n selection: { dataset: \"facilities\" },\n calculation: {\n joins: [\n {\n dataset: \"schedule\",\n local: \"facilityId\",\n foreign: \"planId\",\n cardinality: \"many\",\n missing: \"refuse\",\n aggregates: [\n { name: \"outstandingPrincipal\", op: \"sum\", value: \"principal\" },\n { name: \"remainingScheduledProfit\", op: \"sum\", value: \"profit\" },\n { name: \"scheduledPrincipalTotal\", op: \"sum\", value: \"scheduledPrincipal\" },\n { name: \"capturedScheduleCount\", op: \"count\" },\n { name: \"oldestUnpaidDays\", op: \"maximum\", value: \"daysPastDue\" }\n ]\n },\n {\n dataset: \"borrowerAccounts\",\n local: \"borrowerAccount\",\n foreign: \"accountId\",\n cardinality: \"one\",\n missing: \"refuse\",\n aggregates: [\n { name: \"borrowerParticipant\", op: \"minimum\", value: \"participant\" }\n ]\n },\n {\n dataset: \"borrowers\",\n local: \"borrowerParticipant\",\n foreign: \"participantId\",\n cardinality: \"one\",\n missing: \"refuse\",\n aggregates: [\n { name: \"borrowerEntity\", op: \"minimum\", value: \"entityId\" }\n ]\n }\n ],\n expressions: [\n {\n id: \"day0\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: 0\n },\n {\n id: \"day30\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: aging_first_days\n },\n {\n id: \"day60\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: aging_second_days\n },\n {\n id: \"day90\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: aging_third_days\n },\n {\n id: \"band0\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"current\"\n },\n {\n id: \"band30\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"first\"\n },\n {\n id: \"band60\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"second\"\n },\n {\n id: \"band90\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"third\"\n },\n {\n id: \"bandLate\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"later\"\n },\n { id: \"current\", op: \"atMost\", left: \"oldestUnpaidDays\", right: \"day0\" },\n { id: \"first\", op: \"atMost\", left: \"oldestUnpaidDays\", right: \"day30\" },\n { id: \"second\", op: \"atMost\", left: \"oldestUnpaidDays\", right: \"day60\" },\n { id: \"third\", op: \"atMost\", left: \"oldestUnpaidDays\", right: \"day90\" },\n { id: \"lateBand\", op: \"choose\", condition: \"third\", yes: \"band90\", no: \"bandLate\" },\n { id: \"secondBand\", op: \"choose\", condition: \"second\", yes: \"band60\", no: \"lateBand\" },\n { id: \"firstBand\", op: \"choose\", condition: \"first\", yes: \"band30\", no: \"secondBand\" },\n { id: \"agingBand\", op: \"choose\", condition: \"current\", yes: \"band0\", no: \"firstBand\" }\n ],\n groupBy: [ \"agingBand\" ],\n aggregates: [\n { name: \"facilities\", op: \"count\" },\n { name: \"principalMinor\", op: \"sum\", value: \"outstandingPrincipal\" },\n { name: \"scheduledProfitMinor\", op: \"sum\", value: \"remainingScheduledProfit\" }\n ],\n resultExpressions: [ ]\n },\n validation: {\n empty: \"noEligibleFacilities\",\n required: [ \"borrowerEntity\" ],\n reconcile: [ ],\n rowReconcile: [\n { left: \"originalPrincipal\", right: \"scheduledPrincipalTotal\" },\n { left: \"scheduleCount\", right: \"capturedScheduleCount\" }\n ],\n unavailableFacts: [ ],\n },\n output: {\n profile: \"internal.v1\",\n formats: [ \"json\", \"csv\" ],\n columns: [\n {\n name: \"agingBand\",\n label: \"agingBand\",\n type: { kind: \"text\" }\n },\n {\n name: \"facilities\",\n label: \"facilities\",\n type: { kind: \"integer\" }\n },\n {\n name: \"principalMinor\",\n label: \"principalMinor\",\n type: { kind: \"money\", currency: \"SAR\" }\n },\n {\n name: \"scheduledProfitMinor\",\n label: \"scheduledProfitMinor\",\n type: { kind: \"money\", currency: \"SAR\" }\n }\n ],\n sort: [ \"agingBand\" ]\n },\n authority: {\n request: [ \"owner\", \"finance\" ],\n read: [ \"owner\", \"admin\", \"operations\", \"finance\", \"viewer\" ],\n release: [ ],\n retention: { policy: \"report_replay\", years: retention_years }\n }\n },\n {\n identity: { id: \"period_end_outstanding_principal_default_rate\", version: 1, description: \"Current active facilities with any unpaid installment at least the declared default days past due, observed at period end. Cure when arrears clear. Count and outstanding-principal weighted rates in the declared scale exclude paid and written-off facilities; write-offs are counted separately. This is a stock measure, not a new-default incidence or origination cohort rate.\" },\n scope: { kind: \"product\", classification: \"internal\", currency: \"SAR\" },\n datasets: [\n {\n id: \"facilities\",\n source: \"instrument\",\n instruments: on,\n rowKey: \"facilityId\",\n columns: [\n {\n name: \"facilityId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"borrowerAccount\",\n field: \"borrower\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"state\",\n field: \"status\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"originalPrincipal\",\n field: \"principal\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"scheduleCount\",\n field: \"months\",\n type: { kind: \"integer\" },\n required: true\n },\n {\n name: \"recordedCreation\",\n field: \"createdAt\",\n type: { kind: \"date\" },\n required: true\n }\n ],\n expressions: [\n {\n id: \"activeState\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"active\"\n },\n {\n id: \"paidState\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"paid\"\n },\n {\n id: \"writtenState\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"written_off\"\n },\n { id: \"active\", op: \"equal\", left: \"state\", right: \"activeState\" },\n { id: \"paid\", op: \"equal\", left: \"state\", right: \"paidState\" },\n { id: \"writtenOff\", op: \"equal\", left: \"state\", right: \"writtenState\" },\n { id: \"activeOrPaid\", op: \"or\", left: \"active\", right: \"paid\" },\n { id: \"financed\", op: \"or\", left: \"active\", right: \"writtenOff\" }\n ],\n selection: \"financed\"\n },\n {\n id: \"schedule\",\n source: \"instrument\",\n instruments: child(on, slice),\n rowKey: \"sliceId\",\n columns: [\n {\n name: \"sliceId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"planId\",\n field: \"plan\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"due\",\n field: \"dueAt\",\n type: { kind: \"date\" },\n required: true\n },\n {\n name: \"principal\",\n field: \"principalReceivable.balance\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"profit\",\n field: \"profitReceivable.balance\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"earnedProfit\",\n field: \"profitEarned.balance\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"scheduledPrincipal\",\n field: \"principal\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n }\n ],\n expressions: [\n {\n id: \"zeroMoney\",\n op: \"literal\",\n type: { kind: \"money\", currency: \"SAR\" },\n value: \"0\"\n },\n {\n id: \"zeroDays\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: 0\n },\n { id: \"observed\", op: \"parameter\", name: \"observationAt\" },\n { id: \"scheduledOutstanding\", op: \"sum\", left: \"principal\", right: \"profit\" },\n { id: \"totalOutstanding\", op: \"sum\", left: \"scheduledOutstanding\", right: \"earnedProfit\" },\n { id: \"unpaid\", op: \"less\", left: \"zeroMoney\", right: \"totalOutstanding\" },\n { id: \"elapsed\", op: \"daysBetween\", left: \"due\", right: \"observed\" },\n { id: \"nonnegativeDays\", op: \"maximum\", left: \"elapsed\", right: \"zeroDays\" },\n { id: \"daysPastDue\", op: \"choose\", condition: \"unpaid\", yes: \"nonnegativeDays\", no: \"zeroDays\" }\n ]\n },\n {\n id: \"borrowerAccounts\",\n source: \"account\",\n instruments: [ ],\n rowKey: \"accountId\",\n columns: [\n {\n name: \"accountId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"participant\",\n field: \"ownerParticipantId\",\n type: { kind: \"text\" },\n required: false\n }\n ],\n expressions: [ ]\n },\n {\n id: \"borrowers\",\n source: \"identity\",\n instruments: [ ],\n rowKey: \"customerId\",\n columns: [\n {\n name: \"customerId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"participantId\",\n field: \"participantId\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"entityId\",\n field: \"entityId\",\n type: { kind: \"text\" },\n required: true\n }\n ],\n expressions: [ ]\n }\n ],\n time: { timezone: \"Asia/Riyadh\", boundary: \"startInclusiveEndExclusive\", observation: \"periodEnd\", history: \"retainedOnly\" },\n selection: { dataset: \"facilities\" },\n calculation: {\n joins: [\n {\n dataset: \"schedule\",\n local: \"facilityId\",\n foreign: \"planId\",\n cardinality: \"many\",\n missing: \"refuse\",\n aggregates: [\n { name: \"outstandingPrincipal\", op: \"sum\", value: \"principal\" },\n { name: \"remainingScheduledProfit\", op: \"sum\", value: \"profit\" },\n { name: \"scheduledPrincipalTotal\", op: \"sum\", value: \"scheduledPrincipal\" },\n { name: \"capturedScheduleCount\", op: \"count\" },\n { name: \"oldestUnpaidDays\", op: \"maximum\", value: \"daysPastDue\" }\n ]\n },\n {\n dataset: \"borrowerAccounts\",\n local: \"borrowerAccount\",\n foreign: \"accountId\",\n cardinality: \"one\",\n missing: \"refuse\",\n aggregates: [\n { name: \"borrowerParticipant\", op: \"minimum\", value: \"participant\" }\n ]\n },\n {\n dataset: \"borrowers\",\n local: \"borrowerParticipant\",\n foreign: \"participantId\",\n cardinality: \"one\",\n missing: \"refuse\",\n aggregates: [\n { name: \"borrowerEntity\", op: \"minimum\", value: \"entityId\" }\n ]\n }\n ],\n expressions: [\n {\n id: \"threshold\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: default_days\n },\n {\n id: \"zero\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: 0\n },\n {\n id: \"one\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: 1\n },\n {\n id: \"zeroMoney\",\n op: \"literal\",\n type: { kind: \"money\", currency: \"SAR\" },\n value: \"0\"\n },\n { id: \"pastThreshold\", op: \"atMost\", left: \"threshold\", right: \"oldestUnpaidDays\" },\n { id: \"isDefault\", op: \"and\", left: \"active\", right: \"pastThreshold\" },\n { id: \"activeCount\", op: \"choose\", condition: \"active\", yes: \"one\", no: \"zero\" },\n { id: \"defaultCount\", op: \"choose\", condition: \"isDefault\", yes: \"one\", no: \"zero\" },\n { id: \"writeOffCount\", op: \"choose\", condition: \"writtenOff\", yes: \"one\", no: \"zero\" },\n { id: \"activePrincipal\", op: \"choose\", condition: \"active\", yes: \"outstandingPrincipal\", no: \"zeroMoney\" },\n { id: \"defaultPrincipal\", op: \"choose\", condition: \"isDefault\", yes: \"outstandingPrincipal\", no: \"zeroMoney\" }\n ],\n groupBy: [ ],\n aggregates: [\n { name: \"activeFacilities\", op: \"sum\", value: \"activeCount\" },\n { name: \"defaultFacilities\", op: \"sum\", value: \"defaultCount\" },\n { name: \"writtenOffFacilities\", op: \"sum\", value: \"writeOffCount\" },\n { name: \"activePrincipalMinor\", op: \"sum\", value: \"activePrincipal\" },\n { name: \"defaultPrincipalMinor\", op: \"sum\", value: \"defaultPrincipal\" }\n ],\n resultExpressions: [\n { id: \"countRate\", op: \"ratio\", numerator: \"defaultFacilities\", denominator: \"activeFacilities\", scale: ratio_scale, rounding: ratio_rounding, zero: \"null\" },\n { id: \"principalRate\", op: \"ratio\", numerator: \"defaultPrincipalMinor\", denominator: \"activePrincipalMinor\", scale: ratio_scale, rounding: ratio_rounding, zero: \"null\" },\n {\n id: \"restructuringEvidence\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"unavailable\"\n },\n {\n id: \"defaultDays\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: default_days\n },\n {\n id: \"rateScale\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: ratio_scale\n }\n ]\n },\n validation: {\n empty: \"refuse\",\n required: [ \"borrowerEntity\" ],\n reconcile: [ ],\n rowReconcile: [\n { left: \"originalPrincipal\", right: \"scheduledPrincipalTotal\" },\n { left: \"scheduleCount\", right: \"capturedScheduleCount\" }\n ],\n unavailableFacts: [ ],\n },\n output: {\n profile: \"internal.v1\",\n formats: [ \"json\", \"csv\" ],\n columns: [\n {\n name: \"activeFacilities\",\n label: \"activeFacilities\",\n type: { kind: \"integer\" }\n },\n {\n name: \"defaultFacilities\",\n label: \"defaultFacilities\",\n type: { kind: \"integer\" }\n },\n {\n name: \"writtenOffFacilities\",\n label: \"writtenOffFacilities\",\n type: { kind: \"integer\" }\n },\n {\n name: \"activePrincipalMinor\",\n label: \"activePrincipalMinor\",\n type: { kind: \"money\", currency: \"SAR\" }\n },\n {\n name: \"defaultPrincipalMinor\",\n label: \"defaultPrincipalMinor\",\n type: { kind: \"money\", currency: \"SAR\" }\n },\n {\n name: \"countRate\",\n label: \"countRate\",\n type: { kind: \"integer\" }\n },\n {\n name: \"principalRate\",\n label: \"principalRate\",\n type: { kind: \"integer\" }\n },\n {\n name: \"restructuringEvidence\",\n label: \"restructuringEvidence\",\n type: { kind: \"text\" }\n },\n {\n name: \"defaultDays\",\n label: \"defaultDays\",\n type: { kind: \"integer\" }\n },\n {\n name: \"rateScale\",\n label: \"rateScale\",\n type: { kind: \"integer\" }\n }\n ],\n sort: [ \"activeFacilities\" ]\n },\n authority: {\n request: [ \"owner\", \"finance\" ],\n read: [ \"owner\", \"admin\", \"operations\", \"finance\", \"viewer\" ],\n release: [ ],\n retention: { policy: \"report_replay\", years: retention_years }\n }\n }\n ]\n}\n"],
15
+ ["reporting.hsx", "header reporting\n\n// Attach portfolio to one or more financing plans. Its only lifecycle action is\n// create; reports use the declared report request/read roles, not a money action.\n// Aging selects active facilities and includes earned profit when deciding arrears.\n// The default-rate report measures period-end stock, not new default incidence.\n// Paid facilities are excluded and write-offs counted separately. Amounts are riyal\n// minor units; declared scale and rounding govern ratios. Missing identity joins\n// or unreconciled schedule counts refuse.\n\n// Cost: portfolio.create declares no transfers, owned accounts or invocations.\n// That zero instruction count does not price report capture, rendering, storage or\n// release. The host owns those charges and their execution.\n\ninstrument portfolio(on: ref<financing.installments>[], default_days: integer(1, 3650) = 90, retention_years: integer(1, 100) = 10, aging_first_days: integer(1, 3650) = 30, aging_second_days: integer(1, 3650) = 60, aging_third_days: integer(1, 3650) = 90, ratio_scale: integer(1, 1000000) = 10000, ratio_rounding: enum(floor, halfUp) = floor) {\n summary: \"Declared financing reports evaluated over frozen Product facts.\"\n fields {}\n lifecycle { states: [declared], initial: declared }\n action create {}\n constraints { aging_first_days: less_than(aging_second_days), aging_second_days: less_than(aging_third_days) }\n reports: [\n {\n identity: { id: \"portfolio_aging\", version: 1, description: \"Period-end outstanding principal by oldest unpaid installment. Remaining scheduled profit is distinct from accrued profit. Restructuring evidence is unavailable.\" },\n scope: { kind: \"product\", classification: \"internal\", currency: \"SAR\" },\n datasets: [\n {\n id: \"facilities\",\n source: \"instrument\",\n instruments: on,\n rowKey: \"facilityId\",\n columns: [\n {\n name: \"facilityId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"borrowerAccount\",\n field: \"borrower\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"state\",\n field: \"status\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"originalPrincipal\",\n field: \"principal\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"scheduleCount\",\n field: \"months\",\n type: { kind: \"integer\" },\n required: true\n },\n {\n name: \"recordedCreation\",\n field: \"createdAt\",\n type: { kind: \"date\" },\n required: true\n }\n ],\n expressions: [\n {\n id: \"activeState\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"active\"\n },\n {\n id: \"paidState\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"paid\"\n },\n {\n id: \"writtenState\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"written_off\"\n },\n { id: \"active\", op: \"equal\", left: \"state\", right: \"activeState\" },\n { id: \"paid\", op: \"equal\", left: \"state\", right: \"paidState\" },\n { id: \"writtenOff\", op: \"equal\", left: \"state\", right: \"writtenState\" },\n { id: \"activeOrPaid\", op: \"or\", left: \"active\", right: \"paid\" },\n { id: \"financed\", op: \"or\", left: \"active\", right: \"writtenOff\" }\n ],\n selection: \"active\"\n },\n {\n id: \"schedule\",\n source: \"instrument\",\n instruments: child(on, slice),\n rowKey: \"sliceId\",\n columns: [\n {\n name: \"sliceId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"planId\",\n field: \"plan\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"due\",\n field: \"dueAt\",\n type: { kind: \"date\" },\n required: true\n },\n {\n name: \"principal\",\n field: \"openPrincipal\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"profit\",\n field: \"openProfit\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"earnedProfit\",\n field: \"earnedProfit\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"scheduledPrincipal\",\n field: \"principal\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n }\n ],\n expressions: [\n {\n id: \"zeroMoney\",\n op: \"literal\",\n type: { kind: \"money\", currency: \"SAR\" },\n value: \"0\"\n },\n {\n id: \"zeroDays\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: 0\n },\n { id: \"observed\", op: \"parameter\", name: \"observationAt\" },\n { id: \"scheduledOutstanding\", op: \"sum\", left: \"principal\", right: \"profit\" },\n { id: \"totalOutstanding\", op: \"sum\", left: \"scheduledOutstanding\", right: \"earnedProfit\" },\n { id: \"unpaid\", op: \"less\", left: \"zeroMoney\", right: \"totalOutstanding\" },\n { id: \"elapsed\", op: \"daysBetween\", left: \"due\", right: \"observed\" },\n { id: \"nonnegativeDays\", op: \"maximum\", left: \"elapsed\", right: \"zeroDays\" },\n { id: \"daysPastDue\", op: \"choose\", condition: \"unpaid\", yes: \"nonnegativeDays\", no: \"zeroDays\" }\n ]\n },\n {\n id: \"borrowerAccounts\",\n source: \"account\",\n instruments: [ ],\n rowKey: \"accountId\",\n columns: [\n {\n name: \"accountId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"participant\",\n field: \"ownerParticipantId\",\n type: { kind: \"text\" },\n required: false\n }\n ],\n expressions: [ ]\n },\n {\n id: \"borrowers\",\n source: \"identity\",\n instruments: [ ],\n rowKey: \"customerId\",\n columns: [\n {\n name: \"customerId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"participantId\",\n field: \"participantId\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"entityId\",\n field: \"entityId\",\n type: { kind: \"text\" },\n required: true\n }\n ],\n expressions: [ ]\n }\n ],\n time: { timezone: \"Asia/Riyadh\", boundary: \"startInclusiveEndExclusive\", observation: \"periodEnd\", history: \"retainedOnly\" },\n selection: { dataset: \"facilities\" },\n calculation: {\n joins: [\n {\n dataset: \"schedule\",\n local: \"facilityId\",\n foreign: \"planId\",\n cardinality: \"many\",\n missing: \"refuse\",\n aggregates: [\n { name: \"outstandingPrincipal\", op: \"sum\", value: \"principal\" },\n { name: \"remainingScheduledProfit\", op: \"sum\", value: \"profit\" },\n { name: \"scheduledPrincipalTotal\", op: \"sum\", value: \"scheduledPrincipal\" },\n { name: \"capturedScheduleCount\", op: \"count\" },\n { name: \"oldestUnpaidDays\", op: \"maximum\", value: \"daysPastDue\" }\n ]\n },\n {\n dataset: \"borrowerAccounts\",\n local: \"borrowerAccount\",\n foreign: \"accountId\",\n cardinality: \"one\",\n missing: \"refuse\",\n aggregates: [\n { name: \"borrowerParticipant\", op: \"minimum\", value: \"participant\" }\n ]\n },\n {\n dataset: \"borrowers\",\n local: \"borrowerParticipant\",\n foreign: \"participantId\",\n cardinality: \"one\",\n missing: \"refuse\",\n aggregates: [\n { name: \"borrowerEntity\", op: \"minimum\", value: \"entityId\" }\n ]\n }\n ],\n expressions: [\n {\n id: \"day0\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: 0\n },\n {\n id: \"day30\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: aging_first_days\n },\n {\n id: \"day60\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: aging_second_days\n },\n {\n id: \"day90\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: aging_third_days\n },\n {\n id: \"band0\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"current\"\n },\n {\n id: \"band30\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"first\"\n },\n {\n id: \"band60\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"second\"\n },\n {\n id: \"band90\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"third\"\n },\n {\n id: \"bandLate\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"later\"\n },\n { id: \"current\", op: \"atMost\", left: \"oldestUnpaidDays\", right: \"day0\" },\n { id: \"first\", op: \"atMost\", left: \"oldestUnpaidDays\", right: \"day30\" },\n { id: \"second\", op: \"atMost\", left: \"oldestUnpaidDays\", right: \"day60\" },\n { id: \"third\", op: \"atMost\", left: \"oldestUnpaidDays\", right: \"day90\" },\n { id: \"lateBand\", op: \"choose\", condition: \"third\", yes: \"band90\", no: \"bandLate\" },\n { id: \"secondBand\", op: \"choose\", condition: \"second\", yes: \"band60\", no: \"lateBand\" },\n { id: \"firstBand\", op: \"choose\", condition: \"first\", yes: \"band30\", no: \"secondBand\" },\n { id: \"agingBand\", op: \"choose\", condition: \"current\", yes: \"band0\", no: \"firstBand\" }\n ],\n groupBy: [ \"agingBand\" ],\n aggregates: [\n { name: \"facilities\", op: \"count\" },\n { name: \"principalMinor\", op: \"sum\", value: \"outstandingPrincipal\" },\n { name: \"scheduledProfitMinor\", op: \"sum\", value: \"remainingScheduledProfit\" }\n ],\n resultExpressions: [ ]\n },\n validation: {\n empty: \"noEligibleFacilities\",\n required: [ \"borrowerEntity\" ],\n reconcile: [ ],\n rowReconcile: [\n { left: \"originalPrincipal\", right: \"scheduledPrincipalTotal\" },\n { left: \"scheduleCount\", right: \"capturedScheduleCount\" }\n ],\n unavailableFacts: [ ],\n },\n output: {\n profile: \"internal.v1\",\n formats: [ \"json\", \"csv\" ],\n columns: [\n {\n name: \"agingBand\",\n label: \"agingBand\",\n type: { kind: \"text\" }\n },\n {\n name: \"facilities\",\n label: \"facilities\",\n type: { kind: \"integer\" }\n },\n {\n name: \"principalMinor\",\n label: \"principalMinor\",\n type: { kind: \"money\", currency: \"SAR\" }\n },\n {\n name: \"scheduledProfitMinor\",\n label: \"scheduledProfitMinor\",\n type: { kind: \"money\", currency: \"SAR\" }\n }\n ],\n sort: [ \"agingBand\" ]\n },\n authority: {\n request: [ \"owner\", \"finance\" ],\n read: [ \"owner\", \"admin\", \"operations\", \"finance\", \"viewer\" ],\n release: [ ],\n retention: { policy: \"report_replay\", years: retention_years }\n }\n },\n {\n identity: { id: \"period_end_outstanding_principal_default_rate\", version: 1, description: \"Current active facilities with any unpaid installment at least the declared default days past due, observed at period end. Cure when arrears clear. Count and outstanding-principal weighted rates in the declared scale exclude paid and written-off facilities; write-offs are counted separately. This is a stock measure, not a new-default incidence or origination cohort rate.\" },\n scope: { kind: \"product\", classification: \"internal\", currency: \"SAR\" },\n datasets: [\n {\n id: \"facilities\",\n source: \"instrument\",\n instruments: on,\n rowKey: \"facilityId\",\n columns: [\n {\n name: \"facilityId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"borrowerAccount\",\n field: \"borrower\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"state\",\n field: \"status\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"originalPrincipal\",\n field: \"principal\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"scheduleCount\",\n field: \"months\",\n type: { kind: \"integer\" },\n required: true\n },\n {\n name: \"recordedCreation\",\n field: \"createdAt\",\n type: { kind: \"date\" },\n required: true\n }\n ],\n expressions: [\n {\n id: \"activeState\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"active\"\n },\n {\n id: \"paidState\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"paid\"\n },\n {\n id: \"writtenState\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"written_off\"\n },\n { id: \"active\", op: \"equal\", left: \"state\", right: \"activeState\" },\n { id: \"paid\", op: \"equal\", left: \"state\", right: \"paidState\" },\n { id: \"writtenOff\", op: \"equal\", left: \"state\", right: \"writtenState\" },\n { id: \"activeOrPaid\", op: \"or\", left: \"active\", right: \"paid\" },\n { id: \"financed\", op: \"or\", left: \"active\", right: \"writtenOff\" }\n ],\n selection: \"financed\"\n },\n {\n id: \"schedule\",\n source: \"instrument\",\n instruments: child(on, slice),\n rowKey: \"sliceId\",\n columns: [\n {\n name: \"sliceId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"planId\",\n field: \"plan\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"due\",\n field: \"dueAt\",\n type: { kind: \"date\" },\n required: true\n },\n {\n name: \"principal\",\n field: \"openPrincipal\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"profit\",\n field: \"openProfit\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"earnedProfit\",\n field: \"earnedProfit\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n },\n {\n name: \"scheduledPrincipal\",\n field: \"principal\",\n type: { kind: \"money\", currency: \"SAR\" },\n required: true\n }\n ],\n expressions: [\n {\n id: \"zeroMoney\",\n op: \"literal\",\n type: { kind: \"money\", currency: \"SAR\" },\n value: \"0\"\n },\n {\n id: \"zeroDays\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: 0\n },\n { id: \"observed\", op: \"parameter\", name: \"observationAt\" },\n { id: \"scheduledOutstanding\", op: \"sum\", left: \"principal\", right: \"profit\" },\n { id: \"totalOutstanding\", op: \"sum\", left: \"scheduledOutstanding\", right: \"earnedProfit\" },\n { id: \"unpaid\", op: \"less\", left: \"zeroMoney\", right: \"totalOutstanding\" },\n { id: \"elapsed\", op: \"daysBetween\", left: \"due\", right: \"observed\" },\n { id: \"nonnegativeDays\", op: \"maximum\", left: \"elapsed\", right: \"zeroDays\" },\n { id: \"daysPastDue\", op: \"choose\", condition: \"unpaid\", yes: \"nonnegativeDays\", no: \"zeroDays\" }\n ]\n },\n {\n id: \"borrowerAccounts\",\n source: \"account\",\n instruments: [ ],\n rowKey: \"accountId\",\n columns: [\n {\n name: \"accountId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"participant\",\n field: \"ownerParticipantId\",\n type: { kind: \"text\" },\n required: false\n }\n ],\n expressions: [ ]\n },\n {\n id: \"borrowers\",\n source: \"identity\",\n instruments: [ ],\n rowKey: \"customerId\",\n columns: [\n {\n name: \"customerId\",\n field: \"id\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"participantId\",\n field: \"participantId\",\n type: { kind: \"text\" },\n required: true\n },\n {\n name: \"entityId\",\n field: \"entityId\",\n type: { kind: \"text\" },\n required: true\n }\n ],\n expressions: [ ]\n }\n ],\n time: { timezone: \"Asia/Riyadh\", boundary: \"startInclusiveEndExclusive\", observation: \"periodEnd\", history: \"retainedOnly\" },\n selection: { dataset: \"facilities\" },\n calculation: {\n joins: [\n {\n dataset: \"schedule\",\n local: \"facilityId\",\n foreign: \"planId\",\n cardinality: \"many\",\n missing: \"refuse\",\n aggregates: [\n { name: \"outstandingPrincipal\", op: \"sum\", value: \"principal\" },\n { name: \"remainingScheduledProfit\", op: \"sum\", value: \"profit\" },\n { name: \"scheduledPrincipalTotal\", op: \"sum\", value: \"scheduledPrincipal\" },\n { name: \"capturedScheduleCount\", op: \"count\" },\n { name: \"oldestUnpaidDays\", op: \"maximum\", value: \"daysPastDue\" }\n ]\n },\n {\n dataset: \"borrowerAccounts\",\n local: \"borrowerAccount\",\n foreign: \"accountId\",\n cardinality: \"one\",\n missing: \"refuse\",\n aggregates: [\n { name: \"borrowerParticipant\", op: \"minimum\", value: \"participant\" }\n ]\n },\n {\n dataset: \"borrowers\",\n local: \"borrowerParticipant\",\n foreign: \"participantId\",\n cardinality: \"one\",\n missing: \"refuse\",\n aggregates: [\n { name: \"borrowerEntity\", op: \"minimum\", value: \"entityId\" }\n ]\n }\n ],\n expressions: [\n {\n id: \"threshold\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: default_days\n },\n {\n id: \"zero\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: 0\n },\n {\n id: \"one\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: 1\n },\n {\n id: \"zeroMoney\",\n op: \"literal\",\n type: { kind: \"money\", currency: \"SAR\" },\n value: \"0\"\n },\n { id: \"pastThreshold\", op: \"atMost\", left: \"threshold\", right: \"oldestUnpaidDays\" },\n { id: \"isDefault\", op: \"and\", left: \"active\", right: \"pastThreshold\" },\n { id: \"activeCount\", op: \"choose\", condition: \"active\", yes: \"one\", no: \"zero\" },\n { id: \"defaultCount\", op: \"choose\", condition: \"isDefault\", yes: \"one\", no: \"zero\" },\n { id: \"writeOffCount\", op: \"choose\", condition: \"writtenOff\", yes: \"one\", no: \"zero\" },\n { id: \"activePrincipal\", op: \"choose\", condition: \"active\", yes: \"outstandingPrincipal\", no: \"zeroMoney\" },\n { id: \"defaultPrincipal\", op: \"choose\", condition: \"isDefault\", yes: \"outstandingPrincipal\", no: \"zeroMoney\" }\n ],\n groupBy: [ ],\n aggregates: [\n { name: \"activeFacilities\", op: \"sum\", value: \"activeCount\" },\n { name: \"defaultFacilities\", op: \"sum\", value: \"defaultCount\" },\n { name: \"writtenOffFacilities\", op: \"sum\", value: \"writeOffCount\" },\n { name: \"activePrincipalMinor\", op: \"sum\", value: \"activePrincipal\" },\n { name: \"defaultPrincipalMinor\", op: \"sum\", value: \"defaultPrincipal\" }\n ],\n resultExpressions: [\n { id: \"countRate\", op: \"ratio\", numerator: \"defaultFacilities\", denominator: \"activeFacilities\", scale: ratio_scale, rounding: ratio_rounding, zero: \"null\" },\n { id: \"principalRate\", op: \"ratio\", numerator: \"defaultPrincipalMinor\", denominator: \"activePrincipalMinor\", scale: ratio_scale, rounding: ratio_rounding, zero: \"null\" },\n {\n id: \"restructuringEvidence\",\n op: \"literal\",\n type: { kind: \"text\" },\n value: \"unavailable\"\n },\n {\n id: \"defaultDays\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: default_days\n },\n {\n id: \"rateScale\",\n op: \"literal\",\n type: { kind: \"integer\" },\n value: ratio_scale\n }\n ]\n },\n validation: {\n empty: \"refuse\",\n required: [ \"borrowerEntity\" ],\n reconcile: [ ],\n rowReconcile: [\n { left: \"originalPrincipal\", right: \"scheduledPrincipalTotal\" },\n { left: \"scheduleCount\", right: \"capturedScheduleCount\" }\n ],\n unavailableFacts: [ ],\n },\n output: {\n profile: \"internal.v1\",\n formats: [ \"json\", \"csv\" ],\n columns: [\n {\n name: \"activeFacilities\",\n label: \"activeFacilities\",\n type: { kind: \"integer\" }\n },\n {\n name: \"defaultFacilities\",\n label: \"defaultFacilities\",\n type: { kind: \"integer\" }\n },\n {\n name: \"writtenOffFacilities\",\n label: \"writtenOffFacilities\",\n type: { kind: \"integer\" }\n },\n {\n name: \"activePrincipalMinor\",\n label: \"activePrincipalMinor\",\n type: { kind: \"money\", currency: \"SAR\" }\n },\n {\n name: \"defaultPrincipalMinor\",\n label: \"defaultPrincipalMinor\",\n type: { kind: \"money\", currency: \"SAR\" }\n },\n {\n name: \"countRate\",\n label: \"countRate\",\n type: { kind: \"integer\" }\n },\n {\n name: \"principalRate\",\n label: \"principalRate\",\n type: { kind: \"integer\" }\n },\n {\n name: \"restructuringEvidence\",\n label: \"restructuringEvidence\",\n type: { kind: \"text\" }\n },\n {\n name: \"defaultDays\",\n label: \"defaultDays\",\n type: { kind: \"integer\" }\n },\n {\n name: \"rateScale\",\n label: \"rateScale\",\n type: { kind: \"integer\" }\n }\n ],\n sort: [ \"activeFacilities\" ]\n },\n authority: {\n request: [ \"owner\", \"finance\" ],\n read: [ \"owner\", \"admin\", \"operations\", \"finance\", \"viewer\" ],\n release: [ ],\n retention: { policy: \"report_replay\", years: retention_years }\n }\n }\n ]\n}\n"],
16
16
  ["savings.hsx", "header savings\n\n// Economics: Contributions and returned pots are principal, not company earnings.\n\n// Expose circle.create and membership.create; create one pending contribution\n// record per member per circle date before membership.activate. Circle activation\n// is clock-owned and needs exactly members joined memberships at or after startsAt.\n// Membership.activate needs the active circle and its full pending schedule.\n// Membership.received means the member received the pot. Contribution.paid means\n// one contribution was collected. Neither record's state proves the other's state.\n// A member can have received the pot with future unpaid contributions, or paid\n// a contribution while their membership still waits for its payout seat.\n// Receive counts preceding received memberships, never paid contributions.\n// Eight members at 300 riyals require 2,400 riyals per payout; seven payments supply 2,100,\n// so a full payout lacks 300 unless other cash exists. There is no reduced payout.\n// Contribution.pay has a due time and no deadline or prior-payment requirement.\n// Late and out-of-order collection is admitted while membership is active or\n// received and circle is active. Clock admission does not promise scheduler retry.\n// Circle.close needs every membership received and an empty held account.\n// Only the Product operator disbands a forming circle.\n// Circle creation collects circleDates, one date per member for contributions and payouts.\n\n// Cost: circle.create declares one owned account. Each contribution payment\n// and each pot payout declares one transfer. Multiply by the actual member and\n// period counts for a completed circle; hsx cost reports per-action bounds.\n\ninstrument circle(contribution: money, members: integer(1, 60), starts: date, memberships: ref<savings.membership> = object(savings.membership)) {\n summary: \"A fixed group contributes on its explicit calendar and takes the pot in order.\"\n fields { contribution: money = contribution, members: integer = members, startsAt: date = starts, circleDates: list(date, members), pot: money = multiply(self.contribution, self.members), held: account of self }\n lifecycle { states: [forming, active, closed, disbanded], initial: forming }\n action create { }\n action activate {\n from: forming, to: active, actor: clock, due: { at: self.startsAt }\n requires count of { instrument: memberships, reference: \"circle\", anchor: self.id, states: [joined], limit: 60 } == self.members\n }\n action close {\n from: active, to: closed\n requires count of { instrument: memberships, reference: \"circle\", anchor: self.id, states: [received], limit: 60 } == self.members\n requires self.held.balance == \"0\"\n }\n action disband { from: forming, to: disbanded, actor: { party: programOperator } }\n}\n\ninstrument membership(circle: ref<savings.circle>, member: party) {\n summary: \"A member contributes on the circle calendar and receives the pot in the assigned seat.\"\n fields { circle: ref<circle>, member: account of member, seat: integer(1, 60), preceding: integer = subtract(self.seat, 1), receivesAt: date = at(self.circle.circleDates, self.seat), contribution: money = self.circle.contribution, total: money = self.circle.pot }\n lifecycle { states: [joined, active, received, withdrawn], initial: joined }\n action create { actor: { party: member }, requires self.seat <= self.circle.members; requires self.circle in [forming]; requires unique \"circle_seat\" on [self.circle, self.seat]; requires unique \"circle_member\" on [self.circle, self.member] }\n action activate {\n from: joined, to: active\n requires self.circle in [active]\n requires count of { instrument: contribution, reference: \"membership\", anchor: self.id, states: [pending], limit: 60 } == self.circle.members\n }\n action receive {\n from: active, to: received, actor: clock, due: { at: self.receivesAt }\n requires self.circle in [active]\n requires count of { instrument: all(savings.membership), reference: \"circle\", anchor: self.circle, states: [received], limit: 60 } == self.preceding\n moves self.total from self.circle.held to self.member economics { purpose: principal, sourceParty: programOperator }\n }\n action withdraw { from: joined, to: withdrawn, requires self.circle in [disbanded] }\n records {\n contribution: {\n fields { membership: ref<parent>, period: integer(1, 60), dueAt: date = at(self.membership.circle.circleDates, self.period), amount: money = self.membership.contribution }\n lifecycle { states: [pending, paid], initial: pending }\n action create { requires self.period <= self.membership.circle.members; requires self.membership in [joined]; requires unique \"seat_period\" on [self.membership, self.period] }\n 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 } }\n }\n }\n}\n"],
17
17
  ["wallet.hsx", "header wallet\n\n// Economics: Topups and withdrawals are excluded prepaid credit; a top-up fee is\n// Company earning. Spending remains\n// unclassified because the bound payee alone does not state the purchase purpose.\n\n// Expose balance.create, activate, topup and withdraw as needed. Holder moves\n// cash only while active. Freeze blocks new topups, withdrawals and spend reserves;\n// only the Product operator freezes or unfreezes.\n// Only the wallet holder creates a spend record, which checks its amount against\n// spendLimit; bind the spend holder to the balance holder.\n// Expose reserve, pay and cancel for the bound payee. Reserve requires an active\n// wallet before expiresAt; pay posts the whole reservation, cancel/expiry void it.\n// Existing reservations may still post after the wallet freezes. There is no\n// daily aggregate limit, partial spend or card-network settlement in this header.\n\n// Top-up fee: topup_fee takes a floored percentage of each top-up for the Company;\n// the wallet receives the rest. At 1%, a 100.00 top-up credits 99.00 and earns 1.00.\n// The default 0% moves nothing to the Company.\n\n// Cost: balance.create declares one owned account; topup declares two transfers\n// and withdraw one. Spend reserve, pay and cancel each declare one transfer\n// instruction. These are counts, not the executor tariff.\n\ninstrument balance(holder: party, spend_limit: money = 100000 SAR, topup_fee: percent = 0%) {\n summary: \"A holder's reusable balance with an immutable per-spend ceiling.\"\n fields { holder: account of holder, held: account of self, spendLimit: money = spend_limit, topupFee: money?, topupCredit: money? }\n lifecycle { states: [pending, active, frozen], initial: pending }\n action create { actor: { party: holder } }\n action activate { from: pending, to: active, actor: { party: holder } }\n action topup {\n allowZero: true, requires input.amount > \"0\"\n from: active, to: active, actor: { party: holder }\n input { amount: money }\n calculate: [\n { target: topupFee, op: rate, base: { field: input.amount }, bps: { literal: topup_fee }, rounding: floor }\n { target: topupCredit, op: subtract, base: { field: input.amount }, subtract: [{ field: self.topupFee }] }\n ]\n moves self.topupCredit from holder to self.held economics { purpose: prepaid_credit, sourceParty: holder }\n moves self.topupFee from holder to programOperator economics { purpose: earning, sourceParty: holder }\n }\n action withdraw {\n from: active, to: active, actor: { party: holder }\n input { amount: money }\n moves input.amount from self.held to holder economics { purpose: prepaid_credit, sourceParty: programOperator }\n }\n action freeze { from: active, to: frozen, actor: { party: programOperator } }\n action unfreeze { from: frozen, to: active, actor: { party: programOperator } }\n}\n\ninstrument spend(wallet: ref<wallet.balance>, payee: party, holder: party = party(person)) {\n summary: \"Reserve one wallet spend, then post or void the same reservation.\"\n fields { wallet: ref<wallet>, holder: account of holder, amount: money, expiresAt: date, reservation: text? }\n lifecycle { states: [pending, reserved, paid, cancelled, expired], initial: pending }\n action create {\n actor: { party: holder }\n requires self.wallet in [active]\n requires self.wallet.holder == self.holder\n requires self.amount <= self.wallet.spendLimit\n }\n action reserve {\n from: pending, to: reserved, actor: { party: payee }\n requires self.wallet in [active]\n deadline: { at: self.expiresAt }\n moves reserve self.amount from self.wallet.held to payee capture \"reservation\"\n }\n action pay { from: reserved, to: paid, actor: { party: payee }, moves post self.reservation }\n action cancel { from: reserved, to: cancelled, actor: { party: payee }, moves void self.reservation }\n action expire { from: reserved, to: expired, actor: clock, due: { at: self.expiresAt }, moves void self.reservation }\n}\n"],
18
18
  ]);