@hyperscale0/hsx 1.0.130 → 1.0.134

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/std/cards.hsx CHANGED
@@ -2,7 +2,10 @@ header cards
2
2
 
3
3
  // Activate holder and card before creating and approving an authorization.
4
4
  // Only the Product operator activates, suspends or resumes a cardholder; the
5
- // holder freezes, unfreezes and cancels their own card.
5
+ // cardholder or the Product operator closes it. The card's person, bound to the
6
+ // cardholder's holder, freezes, unfreezes and cancels their own card. The issuer
7
+ // freezes it with issuer_freeze into blocked, which only issuer_unfreeze lifts,
8
+ // and cancels it with issuer_cancel.
6
9
  // Expose authorization.create, approve and capture; expose decline and reverse
7
10
  // separately if callers need those paths. Issuer declines only from pending;
8
11
  // merchant captures or reverses an approved reservation. Expiry voids approved
@@ -26,18 +29,22 @@ instrument cardholder(holder: party) {
26
29
  action activate { from: pending, to: active, actor: { party: programOperator } }
27
30
  action suspend { from: active, to: suspended, actor: { party: programOperator } }
28
31
  action resume { from: suspended, to: active, actor: { party: programOperator } }
29
- action close { from: [active, suspended], to: closed }
32
+ action close { from: [active, suspended], to: closed, actor: { party: holder } }
33
+ action operator_close { from: [active, suspended], to: closed, actor: { party: programOperator } }
30
34
  }
31
35
 
32
- instrument card(holder: ref<cards.cardholder>, spend_limit: money) {
36
+ instrument card(holder: ref<cards.cardholder>, spend_limit: money, issuer: party = programOperator, person: party = party(person)) {
33
37
  summary: "A card with a per-spend ceiling that can be activated, frozen or cancelled."
34
- fields { holder: ref<holder>, spendLimit: money = spend_limit }
35
- lifecycle { states: [issued, active, frozen, cancelled], initial: issued }
36
- action create { requires self.holder in [active] }
38
+ fields { holder: ref<holder>, person: account of person, spendLimit: money = spend_limit }
39
+ lifecycle { states: [issued, active, frozen, blocked, cancelled], initial: issued }
40
+ action create { requires self.holder in [active]; requires self.holder.holder == self.person }
37
41
  action activate { from: issued, to: active, requires self.holder in [active] }
38
- action freeze { from: active, to: frozen }
39
- action unfreeze { from: frozen, to: active, requires self.holder in [active] }
40
- action cancel { from: [issued, active, frozen], to: cancelled }
42
+ action freeze { from: active, to: frozen, actor: { party: person } }
43
+ action unfreeze { from: frozen, to: active, actor: { party: person }, requires self.holder in [active] }
44
+ action issuer_freeze { from: [active, frozen], to: blocked, actor: { party: issuer } }
45
+ action issuer_unfreeze { from: [frozen, blocked], to: active, actor: { party: issuer }, requires self.holder in [active] }
46
+ action cancel { from: [issued, active, frozen, blocked], to: cancelled, actor: { party: person } }
47
+ action issuer_cancel { from: [issued, active, frozen, blocked], to: cancelled, actor: { party: issuer } }
41
48
  }
42
49
 
43
50
  instrument authorization(card: ref<cards.card>, merchant: party, issuer: party = programOperator) {
package/std/escrow.hsx CHANGED
@@ -15,14 +15,23 @@ header escrow
15
15
  // cancels the plan; after that, refund returns the rest. Before delivery the
16
16
  // Product operator runs the plan's unwind_undelivered instead, which invokes
17
17
  // unwind_financed here to return the rest to the payer and close the hold.
18
- // After a paid plan's refund window, the plan's return_hold runs it from funded
19
- // or return_verified to return the whole balance to the payer.
20
- // Only an installments plan can run confirm and unwind_financed; without
21
- // financing neither action exists, so no hold reaches funded without fundedAt. The plan's confirm leaves fundedAt unset, so
22
- // refund_undelivered never comes due on a financed hold and no schedule offers it.
18
+ // For a paid plan, the plan's unwind_paid runs unwind_financed from funded after
19
+ // deliverBy, and return_hold or unwind_paid runs it from return_verified,
20
+ // depending on the plan's returned_goods.
21
+ // Only an installments plan can run confirm and unwind_financed. In a program
22
+ // without financing neither action exists, so every hold reaches funded through
23
+ // fund, which sets fundedAt. The plan's confirm leaves fundedAt unset, so
24
+ // refund_undelivered never comes due on a financed hold and no schedule offers
25
+ // it. Confirm sets deliverBy, deliver_within after confirmation, and the plan's
26
+ // unwind_paid waits for it so the payee keeps the whole delivery window.
23
27
  // Expose refund_undelivered to let the payer take the whole held price back once
24
28
  // deliver_within has passed since funding without delivery. It is a payer action
25
29
  // that becomes available at that time; nothing runs it automatically.
30
+ // The Product operator settles any disputed hold: settle_release pays the payee
31
+ // as acceptance would, and settle_return moves it to return_verified. Without a
32
+ // live plan, settle_return also runs settle_refund to return the whole balance
33
+ // to the payer. A financed return continues on the plan's returned-goods path,
34
+ // and once that plan is cancelled the operator's settle_refund returns the rest.
26
35
  // Acceptance expiry enters disputed, never released. Neither verify_return nor
27
36
  // refund becomes public merely because dispute is exposed. Clock actions remain
28
37
  // internal. Expose cancel for a pending hold, including a checkout-funded hold;
@@ -38,7 +47,7 @@ instrument hold(payer: party = party(person), payee: party = programOperator, ac
38
47
  summary: "Hold the subject price through delivery, acceptance and verified return."
39
48
  fields {
40
49
  payer: account of payer, payee: account of payee
41
- held: account of self, fundedAt: date?, deliveredAt: date?
50
+ held: account of self, fundedAt: date?, deliverBy: date?, deliveredAt: date?, openPlans: integer?
42
51
  price: money = subject.price
43
52
  }
44
53
  lifecycle { states: [pending, funded, delivered, disputed, return_verified, released, refunded, cancelled], initial: pending }
@@ -54,6 +63,7 @@ instrument hold(payer: party = party(person), payee: party = programOperator, ac
54
63
  action confirm {
55
64
  from: pending, to: funded, actor: { parent: all(financing.installments) }
56
65
  requires self.held.balance == self.price
66
+ calculate: [{ target: deliverBy, op: shift, date: { field: self.now }, milliseconds: { literal: deliver_within }, direction: after }]
57
67
  }
58
68
  action deliver {
59
69
  from: funded, to: delivered, actor: { party: payee }
@@ -77,6 +87,22 @@ instrument hold(payer: party = party(person), payee: party = programOperator, ac
77
87
  from: disputed, to: return_verified, actor: { party: payee }
78
88
  input { returnEvidence: text }
79
89
  }
90
+ action settle_release { allowZero: true, requires self.price > "0";
91
+ from: disputed, to: released, actor: { party: programOperator }
92
+ input { ruling: text }
93
+ moves self.price from self.held to payee fee fee economics { payee: { recipient: payee, company: { purpose: earning, sourceParty: payer }, participant: { purpose: pass_through, sourceParty: programOperator } }, fee: { purpose: earning, sourceParty: payer }, tax: { purpose: pass_through, sourceParty: programOperator } }
94
+ }
95
+ action settle_return {
96
+ from: disputed, to: return_verified, actor: { party: programOperator }
97
+ input { ruling: text }
98
+ calculate: [{ target: openPlans, op: aggregate, selection: { instrument: all(financing.installments), reference: "funds", anchor: self.id, states: [quoted, signed, active, paid, written_off], limit: 1 }, measure: count }]
99
+ invoke: [{ reference: self.id, action: settle_refund, guard: { kind: compare, left: { field: self.openPlans }, operator: "==", right: { literal: 0 } }, input: {} }]
100
+ }
101
+ action settle_refund { allowZero: true,
102
+ from: return_verified, to: refunded, actor: { party: programOperator }
103
+ requires count of { instrument: all(financing.installments), reference: "funds", anchor: self.id, states: [quoted, signed, active, paid, written_off], limit: 1 } == 0
104
+ moves self.held.balance from self.held to payer economics { purpose: principal, sourceParty: programOperator }
105
+ }
80
106
  action refund {
81
107
  from: [funded, dispute.refund_after], to: refunded, actor: { party: payee }
82
108
  requires count of { instrument: all(financing.installments), reference: "funds", anchor: self.id, states: [quoted, signed, active, paid, written_off], limit: 1 } == 0