@hyperscale0/hsx 1.0.284 → 1.0.294

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.
@@ -7,11 +7,12 @@ export const BUNDLED_STD_FILES = new Map([
7
7
  ["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"],
8
8
  ["insurance.hsx", "header insurance\n\n// Economics: Company commission is earning; refunds reverse its captured transfer.\n// Outside broker commissions are pass-through. Adapter-owned premium and claim\n// accounts lack an authored source party, so their moves remain unclassified.\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\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\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"],
9
9
  ["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"],
10
- ["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 requires count of { instrument: current(), reference: \"listing\", anchor: self.listing, states: [placed, fulfilled], limit: 366 } <= 1\n }\n invariants count of { instrument: current(), 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: current(), 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 convert_cash {\n from: active, to: active, actor: { party: buyer }, deadline: { at: self.expiresAt }\n invoke: [{ reference: self.funds, action: fund, input: {} }]\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"],
10
+ ["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"],
11
11
  ["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. Generic transfers, splits,\n// schedules, swaps, boundary payouts and metered fees 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. A hold has no dispute or damage decision.\n// The payee proposes a schedule, which creates its count occurrences, and only\n// the payer activates or cancels it. Each due occurrence pays only while the\n// schedule is active. A due time promises no retry.\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\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. 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) {\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: payer }\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) {\n summary: \"A finite schedule whose dated pieces sum exactly to the declared total.\"\n fields { amount: money = amount, count: integer = count, dates: list(date, count) }\n lifecycle { states: [draft, active, complete, cancelled], initial: draft }\n action create {\n actor: { party: payee }\n invoke: [{ range: { count: { literal: count }, maximum: count, bind: position }, instrument: occurrence, action: create, input: { schedule: { field: self.id }, position: { field: position } } }]\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 records {\n occurrence: {\n fields {\n schedule: ref<parent>, 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 lifecycle { states: [pending, paid, cancelled], initial: pending }\n action create { actor: { parent: parent }, input { schedule: ref<parent>, position: integer(1, count) }, requires unique \"scheduled_position\" on [self.schedule, self.position] }\n action pay { allowZero: true, from: pending, to: paid, actor: clock, due: { at: self.dueAt }, requires self.schedule in [active], moves self.amount from payer to payee }\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"],
12
12
  ["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"],
13
+ ["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"],
13
14
  ["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"],
14
15
  ["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"],
15
- ["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// close requires no held cash. Only the Product operator freezes or unfreezes.\n// The holder closes the wallet, or the Product operator with operator_close.\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, closed], 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 action close { from: [pending, active], to: closed, actor: { party: holder }, requires self.held.balance == \"0\" }\n action operator_close { from: [pending, active], to: closed, actor: { party: programOperator }, requires self.held.balance == \"0\" }\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"],
16
+ ["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"],
16
17
  ]);
17
18
  //# sourceMappingURL=std-bundle.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"std-bundle.js","sourceRoot":"","sources":["../../src/std-bundle.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,MAAM,CAAC,MAAM,iBAAiB,GAAgC,IAAI,GAAG,CAAiB;IACpF,CAAC,aAAa,EAAE,m7LAAm7L,CAAC;IACp8L,CAAC,WAAW,EAAE,6wMAA6wM,CAAC;IAC5xM,CAAC,iBAAiB,EAAE,qrNAAqrN,CAAC;IAC1sN,CAAC,YAAY,EAAE,mkOAAmkO,CAAC;IACnlO,CAAC,eAAe,EAAE,kinFAAkinF,CAAC;IACrjnF,CAAC,eAAe,EAAE,41LAA41L,CAAC;IAC/2L,CAAC,aAAa,EAAE,03UAA03U,CAAC;IAC34U,CAAC,iBAAiB,EAAE,syTAAsyT,CAAC;IAC3zT,CAAC,WAAW,EAAE,ogYAAogY,CAAC;IACnhY,CAAC,cAAc,EAAE,svJAAsvJ,CAAC;IACxwJ,CAAC,eAAe,EAAE,4o1BAA4o1B,CAAC;IAC/p1B,CAAC,aAAa,EAAE,4hKAA4hK,CAAC;IAC7iK,CAAC,YAAY,EAAE,2zIAA2zI,CAAC;CAC50I,CAAC,CAAC"}
1
+ {"version":3,"file":"std-bundle.js","sourceRoot":"","sources":["../../src/std-bundle.ts"],"names":[],"mappings":"AAAA,oEAAoE;AAEpE,MAAM,CAAC,MAAM,iBAAiB,GAAgC,IAAI,GAAG,CAAiB;IACpF,CAAC,aAAa,EAAE,m7LAAm7L,CAAC;IACp8L,CAAC,WAAW,EAAE,6wMAA6wM,CAAC;IAC5xM,CAAC,iBAAiB,EAAE,qrNAAqrN,CAAC;IAC1sN,CAAC,YAAY,EAAE,mkOAAmkO,CAAC;IACnlO,CAAC,eAAe,EAAE,kinFAAkinF,CAAC;IACrjnF,CAAC,eAAe,EAAE,41LAA41L,CAAC;IAC/2L,CAAC,aAAa,EAAE,03UAA03U,CAAC;IAC34U,CAAC,iBAAiB,EAAE,ggTAAggT,CAAC;IACrhT,CAAC,WAAW,EAAE,ogYAAogY,CAAC;IACnhY,CAAC,cAAc,EAAE,svJAAsvJ,CAAC;IACxwJ,CAAC,YAAY,EAAE,y1HAAy1H,CAAC;IACz2H,CAAC,eAAe,EAAE,4o1BAA4o1B,CAAC;IAC/p1B,CAAC,aAAa,EAAE,4hKAA4hK,CAAC;IAC7iK,CAAC,YAAY,EAAE,u8HAAu8H,CAAC;CACx9H,CAAC,CAAC"}
package/docs/README.md CHANGED
@@ -56,6 +56,12 @@ and party IDs are not metadata supplied by the caller.
56
56
 
57
57
  ## A rental deposit in one hour
58
58
 
59
+ For a separate hire charge and refundable security, use
60
+ [rental-hire.hsx](../examples/rental-hire.hsx) and the `rental` header.
61
+ Its shared rules refund both paid parts on cancellation before pickup.
62
+ `complete_hire` requires recorded pickup, and an ended hire still counts toward
63
+ the one-hire limit. The operator records pickup, return and damage.
64
+
59
65
  Open [rental-deposit.hsx](../examples/rental-deposit.hsx). It is a complete source
60
66
  file for a customer renting equipment from the program operator. Copy it to
61
67
  `rental.hsx` and run the same check, build and cost commands against that file.
@@ -1,6 +1,6 @@
1
- // Riyadh catering cards lets staff reserve supplier purchases up to 5,000 SAR each.
1
+ // Boston catering cards lets staff reserve supplier purchases up to 5,000 SAR each.
2
2
  // Supplier cancellation releases the reservation; captured purchases support a full refund or a reviewed dispute.
3
- program team_expense_cards "Riyadh catering cards"
3
+ program team_expense_cards "Boston catering cards"
4
4
  use cards
5
5
  party supplier: business
6
6
 
@@ -1,6 +1,6 @@
1
- // Jeddah cafe equipment finance lends 24,000 SAR over 12 months and refers debt seven days overdue.
1
+ // Portland cafe equipment finance lends 24,000 SAR over 12 months and refers debt seven days overdue.
2
2
  // Its agency earns 10% of each recovery from the lender, with at most four contacts per 30 days.
3
- program business_collections "Jeddah cafe equipment finance"
3
+ program business_collections "Portland cafe equipment finance"
4
4
  use collections
5
5
  use financing
6
6
  party agency: business
@@ -1,6 +1,6 @@
1
- // Khobar used laptops holds a buyer's 2,300 SAR until the laptop arrives and passes inspection.
1
+ // Seattle used laptops holds a buyer's 2,300 SAR until the laptop arrives and passes inspection.
2
2
  // Delivery has seven days; the buyer has 48 hours to accept or dispute before the operator reviews the sale.
3
- program used_device_sales "Khobar used laptops"
3
+ program used_device_sales "Seattle used laptops"
4
4
  use escrow
5
5
  party seller: business
6
6
 
@@ -1,6 +1,6 @@
1
- // Riyadh language academy finance pays 6,900 SAR tuition to the academy at enrolment.
1
+ // Boston language academy finance pays 6,900 SAR tuition to the academy at enrolment.
2
2
  // The student repays three monthly instalments of 2,300 SAR with no financing profit or late fee.
3
- program tuition_instalments "Riyadh language academy finance"
3
+ program tuition_instalments "Boston language academy finance"
4
4
  use financing
5
5
  party academy: business
6
6
 
@@ -1,6 +1,6 @@
1
- // Jeddah device cover sells a 1,725 SAR tablet and a 115 SAR annual protection period.
1
+ // Portland device cover sells a 1,725 SAR tablet and a 115 SAR annual protection period.
2
2
  // The retailer keeps 10% of each premium; cancelled future periods reverse that commission and the insurer's portion.
3
- program device_insurance "Jeddah device cover"
3
+ program device_insurance "Portland device cover"
4
4
  use insurance
5
5
  use money
6
6
 
@@ -1,6 +1,6 @@
1
- // Qassim bakery funding raises 30,000 SAR for ovens from investors who commit at least 1,000 SAR each.
1
+ // Bristol bakery funding raises 30,000 SAR for ovens from investors who commit at least 1,000 SAR each.
2
2
  // An unclosed round refunds its wallets at expiry; funded loans distribute repayments or record investor losses.
3
- program community_business_lending "Qassim bakery funding"
3
+ program community_business_lending "Bristol bakery funding"
4
4
  use lending
5
5
  use financing
6
6
  use wallet
@@ -42,7 +42,6 @@ object business "Bakery oven funding" {
42
42
  expose activate as open_wallet
43
43
  expose topup as add_funds
44
44
  expose withdraw as withdraw_available_funds
45
- expose close as close_empty_wallet
46
45
  }
47
46
  attach funding = lending.round {
48
47
  borrower: owner, plan: loan, minimum_ticket: 1000 SAR, investor_cap: 25%
@@ -1,6 +1,6 @@
1
- // Riyadh used van finance funds a 34,500 SAR van over three monthly instalments.
1
+ // Boston used van finance funds a 34,500 SAR van over three monthly instalments.
2
2
  // The dealer is paid after delivery and acceptance; a verified return unwinds financing before the buyer gets a refund.
3
- program cars "Riyadh used van finance"
3
+ program cars "Boston used van finance"
4
4
  use escrow
5
5
  use financing
6
6
  use purchase
@@ -1,6 +1,6 @@
1
- // Riyadh design market sells a 2,000 SAR restaurant menu project with delivery in seven days.
1
+ // Boston design market sells a 2,000 SAR restaurant menu project with delivery in seven days.
2
2
  // The company keeps 10% plus 15% VAT on its fee; the designer receives 1,770 SAR after client acceptance.
3
- program freelance_marketplace "Riyadh design market"
3
+ program freelance_marketplace "Boston design market"
4
4
  use marketplace
5
5
  use escrow
6
6
  party designer: business
@@ -1,6 +1,6 @@
1
- // Riyadh tutoring studio charges 172.50 SAR for a private Arabic lesson.
1
+ // Boston tutoring studio charges 172.50 SAR for a private Arabic lesson.
2
2
  // A paid booking can be refunded before the lesson or if the tutor cannot teach.
3
- program tutoring_studio "Riyadh tutoring studio"
3
+ program tutoring_studio "Boston tutoring studio"
4
4
  use money
5
5
 
6
6
  // The customer is the object's owner. Fee: 0% on top of the lesson price.