@hyperscale0/cli 1.0.0-beta.1 → 1.0.0-beta.10
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/README.md +61 -21
- package/hyperscale.js +65 -38
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -2,18 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
The Hyperscale founder command line. It logs a founder in, discovers public
|
|
4
4
|
Blueprints, composes Products, manages sandbox API keys, and runs one Product's
|
|
5
|
-
frozen public
|
|
5
|
+
frozen public actions.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Install
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @hyperscale0/cli
|
|
11
|
+
# or run directly with bunx / npx
|
|
12
|
+
bunx @hyperscale0/cli --help
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quickstart
|
|
16
|
+
|
|
17
|
+
Mint a founder PAT in the portal at https://hyperscale0.ai/desk. Open Security,
|
|
18
|
+
then Personal access tokens. Unapproved founders can request access at
|
|
19
|
+
https://hyperscale0.ai/request-access.
|
|
10
20
|
|
|
11
21
|
```bash
|
|
12
|
-
export HYPERSCALE_TOKEN
|
|
13
|
-
bunx @hyperscale0/cli auth login
|
|
22
|
+
export HYPERSCALE_TOKEN="<your founder PAT>"
|
|
23
|
+
bunx @hyperscale0/cli auth login --no-browser
|
|
14
24
|
bunx @hyperscale0/cli whoami
|
|
25
|
+
bunx @hyperscale0/cli start --blueprint vehicle-escrow-marketplace --json
|
|
15
26
|
bunx @hyperscale0/cli blueprint list
|
|
16
|
-
bunx @hyperscale0/cli product create --blueprint
|
|
27
|
+
bunx @hyperscale0/cli product create --blueprint luxury-goods-consignment-escrow --name "Luxury Consignment"
|
|
28
|
+
bunx @hyperscale0/cli product select <Product id>
|
|
17
29
|
bunx @hyperscale0/cli key create --name "Founder laptop"
|
|
18
30
|
bunx @hyperscale0/cli compose check product.hsx
|
|
19
31
|
bunx @hyperscale0/cli compose plan product.hsx
|
|
@@ -23,35 +35,63 @@ bunx @hyperscale0/cli team invite --email developer@example.com --role developer
|
|
|
23
35
|
bunx @hyperscale0/cli activity list
|
|
24
36
|
bunx @hyperscale0/cli ops list payment
|
|
25
37
|
|
|
26
|
-
export HYPERSCALE_API_KEY
|
|
27
|
-
bunx @hyperscale0/cli product
|
|
28
|
-
bunx @hyperscale0/cli product
|
|
29
|
-
bunx @hyperscale0/cli product run
|
|
38
|
+
export HYPERSCALE_API_KEY="<your Product API key>"
|
|
39
|
+
bunx @hyperscale0/cli product actions
|
|
40
|
+
bunx @hyperscale0/cli product actions escrow_order.placeBuyerHold --json
|
|
41
|
+
bunx @hyperscale0/cli product run escrow_order.placeBuyerHold --input '{"escrowOrderId":"eord_sandbox_..."}'
|
|
30
42
|
bunx @hyperscale0/cli call account.list --input '{"limit":5}'
|
|
31
43
|
```
|
|
32
44
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
45
|
+
## Commands
|
|
46
|
+
|
|
47
|
+
`product actions` lists the frozen Product surface. Pass one exact public
|
|
48
|
+
operation id such as `escrow_order.placeBuyerHold` to return its full input
|
|
49
|
+
schema, output schema, policies, build id, surface version, and operation-set
|
|
50
|
+
digest.
|
|
51
|
+
`start` asks which catalog company to build in a terminal. Scripts and agents
|
|
52
|
+
pass `--blueprint <slug>` to skip the prompt. `product select <Product id>`
|
|
53
|
+
stores the default Product used by compose, key, and Product commands when
|
|
54
|
+
`--product` is absent.
|
|
36
55
|
`compose check` compiles textual HSX and runs the independent composer check.
|
|
37
56
|
`compose plan` diffs it against the selected Product. `compose apply`
|
|
38
57
|
recomposes that Product and requires `--confirm`, or `--yes` for an agent.
|
|
39
58
|
Compiler or composer refusal exits 2. Transport and server failure exit 1.
|
|
40
59
|
`npx @hyperscale0/cli` runs the same commands. Add
|
|
41
60
|
`--json` for machine-readable success and failure output.
|
|
61
|
+
`auth login --no-browser` skips the localhost browser callback. Without a PAT,
|
|
62
|
+
it prints the PAT desk and request-access URL. With `--token` or
|
|
63
|
+
`HYPERSCALE_TOKEN`, it validates and stores that founder PAT without opening a
|
|
64
|
+
browser.
|
|
42
65
|
|
|
43
|
-
Founder
|
|
44
|
-
`
|
|
45
|
-
`
|
|
46
|
-
|
|
66
|
+
Founder PAT commands are `auth`, `whoami`, `product create/list/show/select`,
|
|
67
|
+
`compose plan/apply`, `key`, `team`, and `activity`. They use
|
|
68
|
+
`--token`, `HYPERSCALE_TOKEN`, or a stored login in that order. Product API
|
|
69
|
+
key commands are `product actions/run`, `ops list`, and `call`. They use
|
|
70
|
+
`HYPERSCALE_API_KEY` and need no founder login profile. `compose check`
|
|
71
|
+
runs locally when no founder credential exists. On a clean machine, set the
|
|
72
|
+
Product API key and pass `--product <id>`. Use `--base-url` and
|
|
47
73
|
`--environment` when their defaults do not name the Product's plane.
|
|
48
74
|
|
|
49
75
|
Point it at another host with `--base-url`, and at the live plane with
|
|
50
76
|
`--environment live`. Live keys and sandbox keys are never interchangeable.
|
|
51
|
-
The CLI stores the founder PAT in macOS Keychain
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
77
|
+
The CLI stores the founder PAT in macOS Keychain by default. If Keychain is
|
|
78
|
+
unavailable, it falls back to an owner-only 0600 file under
|
|
79
|
+
`HYPERSCALE_CONFIG_DIR`, or `~/.config/hyperscale` by default. Set
|
|
80
|
+
`HYPERSCALE_CREDENTIAL_STORE=file` to choose that file store and skip
|
|
81
|
+
Keychain access. `auth logout` deletes local state and does not revoke the
|
|
82
|
+
PAT. `auth logout --revoke` revokes the active PAT before deleting local
|
|
83
|
+
state. Passkey login stays in the portal at
|
|
55
84
|
https://hyperscale0.ai/signin.
|
|
56
85
|
|
|
57
86
|
Run `bunx @hyperscale0/cli --help` for the full option list.
|
|
87
|
+
|
|
88
|
+
## Reference
|
|
89
|
+
|
|
90
|
+
- [Portal desk](https://hyperscale0.ai/desk)
|
|
91
|
+
- [Developer entry point](https://hyperscale0.ai/developers)
|
|
92
|
+
- [Documentation](https://hyperscale0.ai/docs)
|
|
93
|
+
|
|
94
|
+
## Security and license
|
|
95
|
+
|
|
96
|
+
- Security: https://hyperscale0.ai/security
|
|
97
|
+
- License: LicenseRef-Hyperscale-Proprietary
|
package/hyperscale.js
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var xe=["advance","captured_payment","conditional_disbursement","credit_facility","deposit","funding_round","held_payment","instant_transfer","metered","pooled_split","premium_forward","recurring_collection","rotating_pool","scheduled","settlement_batch","swap","weighted_distribution"],le={advance:{eventCap:2,keys:["against","amount","count","every","fee","first_due","funder","to"],referenceableExits:[],required:["funder","to","amount"]},captured_payment:{eventCap:4,keys:["amount","capture_mode","correction","correction_mode","external_reversal","fees","negative_position","payee","payer","reserve_until","timeout"],referenceableExits:[],required:["payer","payee","amount","capture_mode","reserve_until","correction","external_reversal","correction_mode","negative_position","timeout"]},conditional_disbursement:{eventCap:1,keys:["amount","cap","decision","destination","recovery_policy","reopen_policy","source"],referenceableExits:[],required:["source","destination","cap","amount","decision","reopen_policy","recovery_policy"]},credit_facility:{eventCap:1,keys:["availability_policy","borrower","close_policy","draw_destination","expires_at","expiry_policy","lender","limit","obligation"],referenceableExits:[],required:["lender","borrower","draw_destination","limit","expires_at","obligation","availability_policy","expiry_policy","close_policy"]},deposit:{eventCap:1,keys:["amount","claim","holder","payer","return"],referenceableExits:[],required:["payer","holder","amount","claim","return"]},funding_round:{eventCap:4,keys:["beneficiary","cancel_policy","close_by","close_policy","commitment","contributor","fail_policy","max_contributors","overfund_policy","target"],referenceableExits:[],required:["contributor","beneficiary","target","commitment","max_contributors","close_by","close_policy","overfund_policy","cancel_policy","fail_policy"]},held_payment:{eventCap:7,keys:["amount","fees","on_cancel","payer","payee","release"],referenceableExits:["release"],required:["payer","payee","amount","release"]},instant_transfer:{eventCap:3,keys:["amount","fees","payer","payee"],referenceableExits:[],required:["payer","payee","amount"]},metered:{eventCap:14,keys:["close_by","payer","payee","rates"],maxRates:14,referenceableExits:[],required:["payer","payee","rates","close_by"]},pooled_split:{eventCap:14,keys:["amount","payer","payout_due","split"],maxRecipients:7,referenceableExits:[],required:["payer","amount","split","payout_due"]},premium_forward:{eventCap:6,keys:["amount","bind","carrier","commission","endorsement","endorsement_policy","lapse_policy","on_cancel","payer","policy_ref","renewal_due","renewal_policy"],referenceableExits:[],required:["payer","carrier","amount","bind"]},recurring_collection:{eventCap:0,keys:["attempt_policy","failure_policy","mandate","obligation","period_idempotency","retry_policy"],referenceableExits:[],required:["obligation","mandate","attempt_policy","period_idempotency","retry_policy","failure_policy"]},rotating_pool:{eventCap:3,keys:["contribution","count","default_policy","every","exit_policy","first_due","guarantee_policy","guarantor","members","payout_order"],referenceableExits:[],required:["members","contribution","count","every","first_due","payout_order","default_policy","guarantee_policy","exit_policy"]},scheduled:{eventCap:3,keys:["advance_to","amount","count","debtor","delinquency_policy","every","first_due","mode","partial_payment","payer","payee","refund_policy","repayment_matching","reschedule_policy"],referenceableExits:["obligation"],required:["payer","payee","amount","count","every","first_due"]},settlement_batch:{eventCap:1,keys:["close_trigger","external_reversal_offsets","fee_entries","negative_position","payout_destination","payout_acknowledgement","payout_beneficiary_ref","settlement_account","source_capture_refs"],referenceableExits:[],required:["settlement_account","source_capture_refs","fee_entries","external_reversal_offsets","close_trigger","payout_destination","negative_position","payout_acknowledgement","payout_beneficiary_ref"]},swap:{eventCap:10,keys:["amounts","between","dispute","fees","release"],referenceableExits:[],required:["between","amounts","release"]},weighted_distribution:{eventCap:1,keys:["amount","correction_policy","max_recipients","recipient","record_at","rounding_policy","snapshot","source","weight","withholding_policy"],referenceableExits:[],required:["source","recipient","amount","weight","max_recipients","record_at","snapshot","rounding_policy","withholding_policy","correction_policy"]}};var We=["business","person"],Ge=["access","claim","good","service","ticket"];var kn=["count","every","first_due"],Xe=/^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/,be=/^[a-z][A-Za-z0-9]*$/,_n=/^[A-Z]{3}$/,Ce=1e4;function An(e){let t=[],n=(i,m)=>{t.push({message:m,severity:"error",span:i})},r=(i,m)=>{t.push({message:m,severity:"warning",span:i})},o=[],a=e.decls.filter(i=>i.kind==="program"),l=a[0];l||n({end:0,start:0},'the file needs a program header naming the company, like: program used_car_escrow "Used-car escrow"');for(let i of a.slice(1))n(i.span,"a file declares exactly one program");l&&!Xe.test(l.name.name)&&n(l.name.span,`the program name must be snake_case, like used_car_escrow; "${l.name.name}" is not`);let s=new Map;for(let i of e.decls)if(i.kind==="import"){if(i.from.value!=="settlement"){n(i.from.span,`"${i.from.value}" is not an importable module; the settlement algebra lives in "settlement"`);continue}for(let m of i.names){if(!xe.includes(m.name)){n(m.span,`"settlement" has no archetype named ${m.name}; it offers ${xe.join(", ")}`);continue}s.has(m.name)&&r(m.span,`${m.name} is imported more than once`),s.set(m.name,m.span)}}let u=new Map,_=(i,m)=>{if(i.name==="platform"||i.name==="escrow")return n(i.span,`the name ${i.name} is reserved: the platform and each settlement's escrow are always present without being declared`),!1;let c=u.get(i.name);return c?(n(i.span,`the name ${i.name} is already taken by a ${c.kind}; every party, asset, settlement, and port needs its own name`),!1):Xe.test(i.name)?(u.set(i.name,{kind:m,span:i.span}),!0):(n(i.span,`${m} names are snake_case; "${i.name}" is not`),!1)},v=new Map,P=new Map;for(let i of e.decls){if(i.kind==="party"){if(!_(i.name,"party"))continue;if(!We.includes(i.partyKind.name)){n(i.partyKind.span,`a party is a ${We.join(" or a ")}; "${i.partyKind.name}" is neither`);continue}i.attrs&&n(i.attrs.span,`party ${i.name.name} takes no attribute block yet`),v.set(i.name.name,{kind:i.partyKind.name,name:i.name.name,origin:i.span})}if(i.kind==="asset"){if(!_(i.name,"asset"))continue;if(!Ge.includes(i.assetKind.name)){n(i.assetKind.span,`an asset is one of ${Ge.join(", ")}; "${i.assetKind.name}" is none of those`);continue}let m="on_platform";for(let c of i.attrs?.entries??[]){if(c.key.name!=="title_transfer"){n(c.key.span,`asset ${i.name.name} does not understand "${c.key.name}"; the only attribute is title_transfer`);continue}let y=c.value;y.kind==="ident"&&(y.name==="off_platform"||y.name==="on_platform")?m=y.name:n(y.span,"title_transfer is either on_platform or off_platform")}P.set(i.name.name,{kind:i.assetKind.name,name:i.name.name,origin:i.span,titleTransfer:m})}}let w=e.decls.filter(i=>i.kind==="port"),g=e.decls.filter(i=>i.kind==="settlement");for(let i of g)_(i.name,"settlement");let C=new Set;for(let i of w)_(i.name,"port")&&C.add(i.name.name);let D=(i,m,c)=>{let y=new Map;for(let d of i.entries){if(!m.includes(d.key.name)){n(d.key.span,`${c} does not understand "${d.key.name}"; it takes ${m.join(", ")}`);continue}if(y.has(d.key.name)){n(d.key.span,`${c} sets ${d.key.name} twice`);continue}y.set(d.key.name,d)}return y},I=(i,m)=>{i.qualifiers.length>0&&n(i.span,`${i.key.name} on ${m} takes no ( ... ) qualifier`)},Z=new Set,ee=(i,m)=>{if(i.kind==="ident"&&v.has(i.name))return Z.add(i.name),i.name;n(i.span,i.kind==="ident"?`${m} must name a declared party; there is no party named ${i.name}`:`${m} must name a declared party`)},te=new Set,J=[],h=new Set(["currency","feeAmount","repayableAmount","serviceFeeAmount","clawbackAt"]),T=[/^piece\d+Amount$/,/^installment\d+Amount$/,/^repayment\d+Amount$/,/^carve(?:Hold|Recourse\d+)Id$/,/ShareAmount$/,/AccountId$/],q=(i,m,c)=>h.has(i)||T.some(y=>y.test(i))?(n(m,`${c} names a field ${i}, but the compiler reserves that name for a generated field; pick another name`),!0):!1,A=(i,m)=>{if(!i)return;I(i,m);let c=i.value;if(c.kind==="binding"&&c.type.kind==="call"&&c.type.callee.name==="money"&&c.type.args.length===1&&c.type.args[0]?.kind==="ident"){let y=c.type.args[0].name;if(!be.test(c.name.name))n(c.name.span,`the ${i.key.name} field is a camelCase name like price; "${c.name.name}" is not`);else if(!_n.test(y))n(c.type.args[0].span,`"${y}" is not a currency code; use three capital letters like SAR`);else if(!q(c.name.name,c.name.span,m))return{currency:y,name:c.name.name,origin:c.span};return}n(c.span,`${m} declares ${i.key.name} as a typed field, like: ${i.key.name}: price: money(SAR)`)},R=(i,m,c,y=!1)=>{if(!i)return;I(i,m);let d=i.value;if(d.kind!=="port_ref"){n(d.span,`${m} needs a ${c} decision, like: ${i.key.name}: port ${i.key.name}_decided`);return}if(d.within){n(d.within.span,`${i.key.name} on ${m} has no time window; only dispute accepts "within <duration>"`);return}if(d.deadline&&!y){n(d.deadline.span,`${i.key.name} on ${m} has no date default; only a held payment's release falls back to a date`);return}if(!C.has(d.name.name)){n(d.name.span,`${m} decides ${c} through port ${d.name.name}, but no port with that name is declared`);return}let k;if(d.deadline){if(!be.test(d.deadline.name)){n(d.deadline.span,`at( ... ) names a camelCase date field, like at(releaseDueAt); "${d.deadline.name}" is not`);return}if(q(d.deadline.name,d.deadline.span,m))return;k=d.deadline.name}return te.add(d.name.name),{...k?{deadlineField:k}:{},origin:d.span,port:d.name.name}},N=(i,m,c="dispute")=>{if(!i)return;I(i,m);let y=i.value;if(y.kind!=="port_ref"){n(y.span,`${m} needs one ${c} decision through a fixed windowed port`);return}if(!C.has(y.name.name)){n(y.name.span,`${m} routes ${c} through port ${y.name.name}, but no port with that name is declared`);return}if(!y.within){n(y.span,`${m} ${c} needs a fixed window, like: ${i.key.name}: port ${y.name.name} within P14D`);return}let d=y.within.name,k=/^P([1-9]\d{0,3})([DW])$/.exec(d);if(!k){n(y.within.span,`${c} on ${m} uses a fixed duration in days or weeks, like P14D; calendar months cannot define an exact money deadline`);return}let L=Number(k[1]),j=k[2]==="W"?L*7:L;return te.add(y.name.name),{origin:y.span,port:y.name.name,window:{days:j,raw:d}}},M=(i,m,c)=>{if(i){if(I(i,m),i.value.kind!=="percent"){n(i.value.span,`${c} on ${m} must be a percent`);return}if(i.value.bps>=Ce){n(i.value.span,`a ${i.value.raw}% ${c} consumes the whole amount; it stays under 100%`);return}return i.value.bps===0&&r(i.value.span,`${c} on ${m} is 0%; drop the entry if none is meant`),i.value.bps}},oe=(i,m,c,y)=>{let d=[];if(!i)return d;if(I(i,m),i.value.kind!=="block")return n(i.value.span,"fees is a block of party shares, like: fees { buyer: 1% }"),d;for(let k of i.value.entries){let L=k.key.name;if(L!==c&&L!==y){n(k.key.span,`fees are borne by this settlement's payer or payee; ${L} is neither`);continue}if(d.some(j=>j.bearer===L)){n(k.key.span,`${m} sets a fee for ${L} twice`);continue}if(k.value.kind!=="percent"){n(k.value.span,`the fee for ${L} must be a percent`);continue}if(k.value.bps>=Ce){n(k.value.span,`a ${k.value.raw}% fee consumes the whole amount; fees stay under 100%`);continue}k.value.bps===0&&r(k.value.span,`the fee for ${L} is 0%; drop the entry if no fee is meant`),d.push({bearer:L,bps:k.value.bps,origin:k.span})}return d},de=(i,m,c)=>{let y=[];if(!i)return y;if(I(i,m),i.value.kind!=="block")return n(i.value.span,"fees is a block of exact on-top money fields, like: fees { buyer: buyerFee: money(SAR) }"),y;for(let d of i.value.entries){let k=d.key.name;if(!c.includes(k)){n(d.key.span,`swap fees are borne by one of its two parties; ${k} is not in between`);continue}if(y.some(j=>j.bearer===k)){n(d.key.span,`${m} sets a fee for ${k} twice`);continue}let L=A(d,`${m} fee for ${k}`);L&&y.push({amount:L,bearer:k})}return y},pe=(i,m,c,y,d)=>{if(i.value.kind!=="block"){n(i.value.span,`${i.key.name} on ${m} is a block of percent shares, like: { ${c[0]??"party"}: 100% }`);return}let k=[],L,j=0,p=!0;for(let f of i.value.entries){let b=f.key.name;if(b==="remainder_to"){if(!d){n(f.key.span,`${m} does not take remainder_to here; the first share carries the integer remainder`),p=!1;continue}if(f.value.kind!=="ident"){n(f.value.span,"remainder_to names one of the recipients"),p=!1;continue}if(L){n(f.key.span,`${m} sets remainder_to twice`),p=!1;continue}L={name:f.value.name,span:f.value.span};continue}if(!c.includes(b)){n(f.key.span,`the ${i.key.name} split goes to ${y}; ${b} is not among them`),p=!1;continue}if(Z.add(b),k.some($=>$.to===b)){n(f.key.span,`${m} splits to ${b} twice`),p=!1;continue}if(f.value.kind!=="percent"){n(f.value.span,`the share for ${b} must be a percent`),p=!1;continue}if(f.value.bps===0){n(f.value.span,`the share for ${b} is 0%; drop ${b} from the split instead of giving it nothing`),p=!1;continue}k.push({bps:f.value.bps,origin:f.span,to:b}),j+=f.value.bps}if(p&&j!==Ce&&(n(i.value.span,`the ${i.key.name} split must account for exactly 100%; these shares total ${(j/100).toFixed(2).replace(/\.?0+$/,"")}%`),p=!1),L&&!k.some(f=>f.to===L?.name)&&(n(L.span,`remainder_to must name one of the split's recipients; ${L.name} holds no share`),p=!1),!(!p||k.length===0))return{...L?{remainderTo:L.name}:{},shares:k}},me=(i,m,c,y)=>{if(!i)return;let d=i.qualifiers[0];if(i.qualifiers.length!==1||d?.name!=="funded"){n(i.span,"on_cancel states the phase it covers; today that is on_cancel(funded)");return}let k=pe(i,m,c,y,!1);if(k)return{origin:i.span,shares:k.shares,when:"funded"}},fe=(i,m)=>{if(i){if(I(i,m),i.value.kind==="ident"&&be.test(i.value.name))return q(i.value.name,i.value.span,m)?void 0:i.value.name;n(i.value.span,`${i.key.name} on ${m} names a camelCase date field, like: ${i.key.name}: dueDate`)}},Ae=(i,m)=>{if(i){if(I(i,m),i.value.kind==="ident"&&be.test(i.value.name))return q(i.value.name,i.value.span,m)?void 0:i.value.name;n(i.value.span,`${i.key.name} on ${m} names a camelCase lineage field, like: ${i.key.name}: captureReference`)}},G=(i,m,c,y)=>i?(I(i,m),i.value.kind==="ident"&&i.value.name===c?!0:(n(i.value.span,`${i.key.name} on ${m} is ${c}; ${y}`),!1)):!1,$n=(i,m,c,y,d)=>{if(!i)return;I(i,m);let k=i.value.kind==="number"?Number(i.value.raw):Number.NaN;if(Number.isInteger(k)&&k>=y&&k<=d)return k;n(i.value.span,`${c} on ${m} is a literal integer from ${y} through ${d}`)},bn=(i,m,c,y,d)=>{if(!i)return;if(I(i,m),i.value.kind!=="list"||i.value.items.length<y||i.value.items.length>d){n(i.value.span,`${c} on ${m} lists ${y} through ${d} declared parties`);return}let k=i.value.items.map(L=>ee(L,`${m} ${c}`)).filter(L=>L!==void 0);if(new Set(k).size!==k.length){n(i.value.span,`${c} on ${m} must not repeat a party`);return}return k.length===i.value.items.length?k:void 0},He=(i,m,c,y=12)=>{let d=i.get("count"),k=i.get("every"),L;if(d){I(d,m);let f=d.value,b=f.kind==="number"?Number(f.raw):Number.NaN;Number.isInteger(b)&&b>=2&&b<=y?L=b:n(f.span,`count on ${m} is a literal number of anchors between 2 and ${y}; the schedule stays finite by construction`)}let j;if(k){I(k,m);let f=k.value,b=f.kind==="ident"?f.name:f.kind==="string"?f.value:void 0,$=b?/^P([1-9]\d{0,3})([DW])$/.exec(b):null;if($&&b){let F=Number($[1]);j={days:$[2]==="W"?F*7:F,raw:b}}else n(f.span,`every on ${m} is a fixed duration in days or weeks, like P30D or P2W; calendar months drift and cannot anchor an exact schedule`)}let p=fe(i.get("first_due"),m);if(!(L===void 0||!j||!p))return{count:L,every:j,firstDueField:p,origin:c}},Ye=(i,m)=>{I(i,m);let c=i.value;if(c.kind!=="settlement_ref"){n(c.span,`${m} draws against a held payment's release, like: against: retention.release`);return}let y=c.owner.name,d=g.find(j=>j.name.name===y);if(!d){let j=u.get(y);n(c.owner.span,j?`${m} references ${y}, which is a ${j.kind}; settlement exits belong to settlements`:`${m} references ${y}, but no settlement with that name is declared`);return}let k=d.archetype.name;if(!xe.includes(k))return;let L=le[k].referenceableExits;if(!L.includes(c.member.name)){let j=L.length>0?`it exposes ${L.join(", ")}`:"it exposes no referenceable exits";n(c.member.span,`${m} references ${y}.${c.member.name}, but ${k} does not expose that exit; ${j}`);return}return{exit:c.member.name,origin:c.span,settlement:y,targetArchetype:k}},tt=(i,m,c)=>{let y=i.get("against"),d=kn.filter(L=>i.has(L));if(y&&d.length>0){n(y.span,`${m} is repaid by a carve and by its own schedule (${d.join(", ")}); an advance draws on one source`);return}if(!y){if(d.length===0){n(c,`${m} needs a repayment source: against: <hold>.release carves it out of a hold's release, or count + every + first_due collects it on a schedule`);return}for(let j of kn)i.has(j)||n(c,`${m} is missing ${j}`);let L=He(i,m,c);return L?{kind:"schedule",schedule:L}:void 0}let k=Ye(y,m);return k?{kind:"carve",...k}:void 0};for(let i of g){let m=i.archetype.name;if(!s.has(m)){n(i.archetype.span,xe.includes(m)?`${m} must be imported first: import { ${m} } from "settlement"`:`there is no settlement archetype named ${m}`);continue}let c=`settlement ${i.name.name}`,y=le[m],d=D(i.body,[...y.keys,"derived_amount"],c);for(let p of y.required)d.has(p)||n(i.span,`${c} is missing ${p}`);let k=(p,f)=>{let b=d.get(p);if(b)return I(b,c),ee(b.value,`${c} ${f}`)},L=(p,f,b)=>p&&f&&p===f?(n(i.span,`${c} ${b}`),!1):!0,j=d.get("derived_amount");if(j)if(I(j,c),j.value.kind!=="block")n(j.value.span,"derived_amount is a block with field, source, rule, and bearer");else{let p=D(j.value,["field","source","rule","bearer"],`${c} derived_amount`);for(let K of["field","source","rule","bearer"])p.has(K)||n(j.span,`${c} derived_amount is missing ${K}`);let f=p.get("field")?.value,b=p.get("source")?.value,$=p.get("rule")?.value,F=p.get("bearer")?.value,S=f?.kind==="ident"?f.name:void 0,O=b?.kind==="ident"?b.name:void 0,z=F?ee(F,`${c} derived amount bearer`):void 0;f&&f.kind!=="ident"&&n(f.span,"derived amount field must be a camelCase identifier"),b&&b.kind!=="ident"&&n(b.span,"derived amount source must name one stored money field"),$&&$.kind!=="percent"&&n($.span,"derived_amount proves percentage-of rules only; fixed and tiered rules are refused"),$?.kind==="percent"&&($.bps<=0||$.bps>=Ce)&&n($.span,"derived amount percentage must be above 0% and below 100%"),S&&!be.test(S)&&n(f.span,`derived amount field ${S} must be camelCase`),O&&!be.test(O)&&n(b.span,`derived amount source ${O} must be camelCase`),S&&O&&S===O&&n(j.span,"derived amount field must differ from its source field"),S&&O&&z&&$?.kind==="percent"&&$.bps>0&&$.bps<Ce&&o.push({baseField:O,bearer:z,bps:$.bps,field:S,origin:j.span,settlement:i.name.name})}switch(m){case"captured_payment":{let p=k("payer","payer"),f=k("payee","payee"),b=L(p,f,`pays ${p} from ${p}; payer and payee must differ`),$=A(d.get("amount"),c),F=fe(d.get("reserve_until"),c),S=R(d.get("correction"),c,"payee correction"),O=N(d.get("external_reversal"),c,"external reversal"),z=G(d.get("capture_mode"),c,"partial_then_full","capture calls must leave a remainder and settle posts the final remainder"),K=G(d.get("correction_mode"),c,"full_only","repeated partial corrections are not representable yet, so the checker refuses them"),X=G(d.get("negative_position"),c,"reject","a correction or reversal must fail when the payee cannot fund it"),ae=G(d.get("timeout"),c,"reject","a timeout records no money movement; only a confirmed decision may reverse funds");if(d.has("fees")&&n(d.get("fees").span,`${c} does not price fees inside captured_payment; compose a separate fee settlement so capture and correction amounts stay exact`),$&&F===$.name){n(d.get("reserve_until")?.span??i.span,`${c} uses ${$.name} as both the reserved amount and reserve_until date field; they need distinct names`);break}p&&f&&$&&F&&S&&O&&z&&K&&X&&ae&&b&&J.push({amount:$,archetype:"captured_payment",correction:S,externalReversal:O,name:i.name.name,origin:i.span,payee:f,payer:p,reserveUntilField:F});break}case"settlement_batch":{let p=k("settlement_account","settlement account"),f=k("payout_destination","payout destination"),b=L(p,f,`routes payout from ${p} back to itself; settlement account and payout destination must differ`),$=Ae(d.get("source_capture_refs"),c),F=Ae(d.get("fee_entries"),c),S=Ae(d.get("external_reversal_offsets"),c),O=fe(d.get("close_trigger"),c),z=R(d.get("payout_acknowledgement"),c,"payout acknowledgement"),K=Ae(d.get("payout_beneficiary_ref"),c),X=G(d.get("negative_position"),c,"reject","offsets beyond gross capture entries must stop calculation and post no payout"),ae=[$,F,S,O,K].filter(Y=>Y!==void 0);if(new Set(ae).size!==ae.length){n(i.span,`${c} needs distinct source_capture_refs, fee_entries, external_reversal_offsets, close_trigger, and payout_beneficiary_ref field names`);break}p&&f&&$&&F&&S&&O&&z&&K&&X&&b&&J.push({archetype:"settlement_batch",closeTriggerField:O,externalReversalReferenceField:S,feeReferenceField:F,name:i.name.name,origin:i.span,payoutDestination:f,payoutAcknowledgement:z,payoutBeneficiaryReferenceField:K,settlementAccount:p,sourceCaptureReferenceField:$});break}case"funding_round":{let p=k("contributor","contributor"),f=k("beneficiary","beneficiary"),b=A(d.get("target"),c),$=A(d.get("commitment"),c),F=$n(d.get("max_contributors"),c,"max_contributors",2,1e4),S=fe(d.get("close_by"),c),O=[G(d.get("close_policy"),c,"threshold","close must follow the locked committed sum at the stored close date"),G(d.get("overfund_policy"),c,"reject","a commitment past the remaining target headroom must refuse"),G(d.get("cancel_policy"),c,"before_close","a commitment may cancel only while its parent remains open"),G(d.get("fail_policy"),c,"whole_commitment_refund","failure refunds each stored commitment whole")].every(Boolean),z=L(p,f,`uses ${p} as both contributor and beneficiary; the roles must differ`);b&&$&&b.currency!==$.currency&&n($.origin,`${c} mixes ${b.currency} and ${$.currency}; target and commitment need one currency`),b&&$&&b.name===$.name&&n($.origin,`${c} uses ${b.name} for both target and commitment; the parent and child amounts need distinct fields`),p&&f&&b&&$&&b.currency===$.currency&&b.name!==$.name&&F&&S&&O&&z&&J.push({archetype:"funding_round",beneficiary:f,cancelPolicy:"before_close",closeByField:S,closePolicy:"threshold",commitment:$,contributor:p,failPolicy:"whole_commitment_refund",maxContributors:F,name:i.name.name,origin:i.span,overfundPolicy:"reject",target:b});break}case"weighted_distribution":{let p=k("source","source"),f=k("recipient","recipient template"),b=A(d.get("amount"),c),$=A(d.get("weight"),c),F=$n(d.get("max_recipients"),c,"max_recipients",2,1e4),S=fe(d.get("record_at"),c),O=R(d.get("snapshot"),c,"entitlement snapshot"),z=[G(d.get("rounding_policy"),c,"largest_remainder","floor shares use a deterministic largest-remainder allocation with noun id as the tie-break"),G(d.get("withholding_policy"),c,"refuse","withholding needs its own proved retained-amount mechanism"),G(d.get("correction_policy"),c,"new_distribution","post-payout correction is a new linked distribution, never a rewrite or caller amount")].every(Boolean),K=L(p,f,`uses ${p} as both source and recipient; the roles must differ`);b&&$&&b.currency!==$.currency&&n($.origin,`${c} mixes ${b.currency} and ${$.currency}; pool and stored weights need one denomination`),b&&$&&b.name===$.name&&n($.origin,`${c} uses ${b.name} for both pool and weight; the fields must differ`),p&&f&&b&&$&&b.currency===$.currency&&b.name!==$.name&&F&&S&&O&&z&&K&&J.push({amount:b,archetype:"weighted_distribution",correctionPolicy:"new_distribution",maxRecipients:F,name:i.name.name,origin:i.span,recipient:f,recordAtField:S,roundingPolicy:"largest_remainder",snapshot:O,source:p,weight:$,withholdingPolicy:"refuse"});break}case"credit_facility":{let p=k("lender","lender"),f=k("borrower","borrower"),b=k("draw_destination","draw destination"),$=A(d.get("limit"),c),F=fe(d.get("expires_at"),c),S=d.get("obligation"),O=S?Ye(S,c):void 0,z=d.get("availability_policy"),K;z?.value.kind==="ident"&&(z.value.name==="revolving"||z.value.name==="non_revolving")?K=z.value.name:z&&n(z.value.span,`availability_policy on ${c} is revolving or non_revolving; the factpack does not justify an implicit choice`);let X=[G(d.get("expiry_policy"),c,"freeze_draws","expiry stops new draws without closing linked debt"),G(d.get("close_policy"),c,"no_open_draws","the facility closes only after every linked obligation resolves")].every(Boolean),ae=[L(p,f,`uses ${p} as both lender and borrower; the roles must differ`),L(p,b,`draws back to its lender ${p}; draw_destination must differ`)].every(Boolean);p&&f&&b&&$&&F&&O&&K&&X&&ae&&J.push({archetype:"credit_facility",availabilityPolicy:K,borrower:f,closePolicy:"no_open_draws",drawDestination:b,expiresAtField:F,expiryPolicy:"freeze_draws",lender:p,limit:$,name:i.name.name,obligation:O,origin:i.span});break}case"recurring_collection":{let p=d.get("obligation"),f=p?Ye(p,c):void 0,b=R(d.get("mandate"),c,"mandate evidence"),$=[G(d.get("attempt_policy"),c,"explicit","every attempt is a separate receipted call"),G(d.get("period_idempotency"),c,"obligation_and_anchor","the parent obligation and stored anchor form the period identity"),G(d.get("retry_policy"),c,"explicit_attempt","PRINCIPLES.md bans hidden retries; a retry needs a new explicit idempotency key"),G(d.get("failure_policy"),c,"parent_delinquency","the scheduled obligation owns due state and delinquency")].every(Boolean);f&&b&&$&&J.push({archetype:"recurring_collection",attemptPolicy:"explicit",failurePolicy:"parent_delinquency",mandate:b,name:i.name.name,obligation:f,origin:i.span,periodIdempotency:"obligation_and_anchor",retryPolicy:"explicit_attempt"});break}case"conditional_disbursement":{let p=k("source","source"),f=k("destination","destination"),b=A(d.get("cap"),c),$=A(d.get("amount"),c),F=R(d.get("decision"),c,"capped disbursement decision"),S=[G(d.get("reopen_policy"),c,"refuse","a closed decision cannot be reopened; create a new linked disbursement"),G(d.get("recovery_policy"),c,"separate_transfer","recovery is a new money movement with its own receipt")].every(Boolean),O=L(p,f,`pays ${p} from itself; source and destination must differ`);b&&$&&b.currency!==$.currency&&n($.origin,`${c} mixes ${b.currency} and ${$.currency}; cap and approved amount need one currency`),b&&$&&b.name===$.name&&n($.origin,`${c} uses ${b.name} for both cap and approved amount; the fields must differ`),p&&f&&b&&$&&b.currency===$.currency&&b.name!==$.name&&F&&S&&O&&J.push({amount:$,archetype:"conditional_disbursement",cap:b,decision:F,destination:f,name:i.name.name,origin:i.span,recoveryPolicy:"separate_transfer",reopenPolicy:"refuse",source:p});break}case"rotating_pool":{let p=bn(d.get("members"),c,"members",2,5),f=bn(d.get("payout_order"),c,"payout_order",2,5),b=A(d.get("contribution"),c),$=He(d,c,i.span,12),F=d.has("guarantor")?k("guarantor","guarantor"):void 0,S=[G(d.get("default_policy"),c,"due_condition","default follows an unmet stored contribution due condition"),G(d.get("guarantee_policy"),c,"funded_only","a guarantee changes money only through an explicit funded contribution"),G(d.get("exit_policy"),c,"before_activation_only","membership and order freeze before the first contribution")].every(Boolean),O=!0;if(p&&f){let z=new Set(p);(f.length!==p.length||f.some(K=>!z.has(K)))&&(n(d.get("payout_order")?.span??i.span,`${c} payout_order must contain every member exactly once`),O=!1)}p&&$&&$.count!==p.length&&(n(d.get("count")?.span??i.span,`${c} count ${$.count} must equal its ${p.length}-member roster`),O=!1),p&&F&&p.includes(F)&&(n(d.get("guarantor")?.span??i.span,`${c} guarantor must differ from every member`),O=!1),p&&F&&p.length>4&&(n(d.get("members")?.span??i.span,`${c} supports at most 4 members with a guarantor so every generated child binding stays within the 8-entry cap`),O=!1),p&&f&&b&&$&&S&&O&&J.push({archetype:"rotating_pool",contribution:b,defaultPolicy:"due_condition",exitPolicy:"before_activation_only",guaranteePolicy:"funded_only",...F?{guarantor:F}:{},members:p,name:i.name.name,origin:i.span,payoutOrder:f,schedule:$});break}case"swap":{let p=d.get("between"),f,b;p&&(I(p,c),p.value.kind!=="list"||p.value.items.length!==2?n(p.value.span,`${c} swaps between exactly two parties, like: between: [buyer, seller]`):(f=ee(p.value.items[0],`${c} first side`),b=ee(p.value.items[1],`${c} second side`),L(f,b,`names ${f} on both sides; the two swap parties must differ`)));let $=new Map,F=d.get("amounts");if(F)if(I(F,c),F.value.kind!=="block")n(F.value.span,`${c} amounts is a two-party block, like: amounts { buyer: buyerPays: money(SAR), seller: sellerPays: money(SAR) }`);else for(let Y of F.value.entries){let ne=Y.key.name;if(ne!==f&&ne!==b){n(Y.key.span,`${c} amount belongs to one of its two parties; ${ne} is not in between`);continue}if($.has(ne)){n(Y.key.span,`${c} declares more than one amount for ${ne}`);continue}let ie=A(Y,c);ie&&$.set(ne,ie)}let S=f?$.get(f):void 0,O=b?$.get(b):void 0;f&&!S&&n(F?.span??i.span,`${c} needs exactly one funded amount for ${f}`),b&&!O&&n(F?.span??i.span,`${c} needs exactly one funded amount for ${b}`),S&&O&&S.currency!==O.currency&&n(F?.span??i.span,`${c} cannot link ${S.currency} and ${O.currency} in one atomic ledger batch; both amounts need one currency`);let z=R(d.get("release"),c,"whole-trade release"),K=N(d.get("dispute"),c),X=de(d.get("fees"),c,[f,b]),ae=[S,O].filter(Y=>Y!==void 0);for(let Y of X)(ae.some(ne=>ne.name===Y.amount.name)||X.some(ne=>ne!==Y&&ne.amount.name===Y.amount.name))&&n(Y.amount.origin,`${c} fee field ${Y.amount.name} must be distinct from both principal and fee fields`),S&&Y.amount.currency!==S.currency&&n(Y.amount.origin,`${c} fee field ${Y.amount.name} must use the trade currency ${S.currency}`);if(f&&b&&S&&O&&S.currency===O.currency&&z){let Y=X.find(ie=>ie.bearer===f),ne=X.find(ie=>ie.bearer===b);J.push({archetype:"swap",...K?{dispute:K}:{},name:i.name.name,origin:i.span,release:z,sides:[{amount:S,...Y?{fee:Y}:{},party:f},{amount:O,...ne?{fee:ne}:{},party:b}]})}break}case"held_payment":{let p=k("payer","payer"),f=k("payee","payee"),b=L(p,f,`pays ${p} from ${p}; payer and payee must differ`),$=A(d.get("amount"),c),F=R(d.get("release"),c,"release",!0),S=oe(d.get("fees"),c,p,f),O=me(d.get("on_cancel"),c,[p,f].filter(z=>z!==void 0),"this settlement's payer or payee");if($&&F?.deadlineField===$.name){n(F.origin,`${c} uses ${$.name} as both the held amount and the release date field; they need distinct names`);break}p&&f&&$&&F&&b&&J.push({amount:$,archetype:"held_payment",fees:S,name:i.name.name,...O?{onCancel:O}:{},origin:i.span,payee:f,payer:p,release:{origin:F.origin,port:F.port},...F.deadlineField?{releaseDeadlineField:F.deadlineField}:{}});break}case"instant_transfer":{let p=k("payer","payer"),f=k("payee","payee"),b=L(p,f,`pays ${p} from ${p}; payer and payee must differ`),$=A(d.get("amount"),c),F=oe(d.get("fees"),c,p,f);p&&f&&$&&b&&J.push({amount:$,archetype:"instant_transfer",fees:F,name:i.name.name,origin:i.span,payee:f,payer:p});break}case"premium_forward":{let p=k("payer","payer"),f=k("carrier","carrier"),b=L(p,f,`forwards the premium from ${p} to ${p}; payer and carrier must differ`),$=A(d.get("amount"),c),F=R(d.get("bind"),c,"binding"),S=M(d.get("commission"),c,"commission")??0,O=me(d.get("on_cancel"),c,[p,f].filter(ie=>ie!==void 0),"this settlement's payer or carrier"),z=["policy_ref","renewal_due","renewal_policy","endorsement","endorsement_policy","lapse_policy"],K=z.some(ie=>d.has(ie));if(K)for(let ie of z)d.has(ie)||n(i.span,`${c} is missing ${ie}`);let X=K?Ae(d.get("policy_ref"),c):void 0,ae=K?fe(d.get("renewal_due"),c):void 0,Y=K?R(d.get("endorsement"),c,"endorsement evidence"):void 0,ne=K?[G(d.get("renewal_policy"),c,"explicit_new_forward","each renewal creates a new premium_forward instead of moving money from policy state"),G(d.get("endorsement_policy"),c,"non_money_only","a money adjustment needs a separate corrected movement"),G(d.get("lapse_policy"),c,"due_condition","lapse follows the stored renewal due condition")].every(Boolean):!0;if(p&&f&&$&&F&&b&&ne&&(!K||X&&ae&&Y)){let ie={amount:$,archetype:"premium_forward",bind:F,carrier:f,commissionBps:S,...Y?{endorsement:Y}:{},...K&&X&&ae&&Y?{endorsementPolicy:"non_money_only",lapsePolicy:"due_condition",policyReferenceField:X,renewalDueField:ae,renewalPolicy:"explicit_new_forward"}:{},name:i.name.name,...O?{onCancel:O}:{},origin:i.span,payer:p};J.push(ie)}break}case"deposit":{let p=k("payer","payer"),f=k("holder","holder"),b=L(p,f,`holds ${p}'s deposit for ${p}; payer and holder must differ`),$=A(d.get("amount"),c),F=R(d.get("claim"),c,"claim"),S=R(d.get("return"),c,"return");if(F&&S&&F.port===S.port){n(S.origin,`${c} claims and returns through the same port ${F.port}; the two exits need their own ports`);break}p&&f&&$&&F&&S&&b&&J.push({amount:$,archetype:"deposit",claim:F,holder:f,name:i.name.name,origin:i.span,payer:p,return:S});break}case"scheduled":{let p=k("payer","payer"),f=k("payee","payee"),b=L(p,f,`pays ${p} from ${p}; payer and payee must differ`),$=A(d.get("amount"),c),F=d.get("mode")?.value,S=F?.kind==="ident"&&F.name==="obligation",O=He(d,c,i.span,S?7:12);if($&&O&&$.name===O.firstDueField){n(O.origin,`${c} uses ${$.name} as both the amount and the first_due date field; they need distinct names`);break}let z=d.get("mode"),X=["advance_to","debtor","delinquency_policy","partial_payment","refund_policy","repayment_matching","reschedule_policy"].some(Re=>d.has(Re));if(!z&&X){n(i.span,`${c} uses obligation policies without mode: obligation`);break}if(!z){p&&f&&$&&O&&b&&J.push({amount:$,archetype:"scheduled",mode:"transfer",name:i.name.name,origin:i.span,payee:f,payer:p,schedule:O});break}if(!G(z,c,"obligation","omit mode for a fixed transfer schedule"))break;let ae=["debtor","partial_payment","repayment_matching","refund_policy","reschedule_policy","delinquency_policy"];for(let Re of ae)d.has(Re)||n(i.span,`${c} is missing ${Re}`);let Y=k("debtor","debtor"),ne=d.has("advance_to")?k("advance_to","advance recipient"):void 0,ie=[G(d.get("partial_payment"),c,"anchor_bound","payments must bind to one stored installment anchor"),G(d.get("repayment_matching"),c,"obligation_and_anchor","each payment must name both the obligation and its installment anchor; fuzzy or balance-wide matching is refused"),G(d.get("refund_policy"),c,"full_payment_only","a refund reverses one stored payment whole so it cannot exceed that payment"),G(d.get("reschedule_policy"),c,"refuse","forward-version carryover is not mechanically proven; create a new obligation after closing this one"),G(d.get("delinquency_policy"),c,"due_condition","delinquency must come from an unmet stored due anchor")].every(Boolean),Fe=[L(Y,f,`${c} names ${Y} as both debtor and settlement recipient; they must differ`),ne?L(ne,Y,`${c} advances to its debtor ${Y}; advance_to must name a distinct recipient`):!0].every(Boolean);p&&f&&$&&O&&b&&Y&&ie&&Fe&&J.push({...ne?{advanceTo:ne}:{},amount:$,archetype:"scheduled",debtor:Y,mode:"obligation",name:i.name.name,origin:i.span,payee:f,payer:p,schedule:O});break}case"advance":{let p=k("funder","funder"),f=k("to","advanced party"),b=L(p,f,`advances ${p} their own money; funder and advanced party must differ`),$=A(d.get("amount"),c),F=M(d.get("fee"),c,"fee")??0,S=tt(d,c,i.span);if($&&S?.kind==="schedule"&&$.name===S.schedule.firstDueField){n(S.schedule.origin,`${c} uses ${$.name} as both the amount and the first_due date field; they need distinct names`);break}p&&f&&$&&S&&b&&J.push({advanced:f,amount:$,archetype:"advance",feeBps:F,funder:p,name:i.name.name,origin:i.span,source:S});break}case"metered":{let p=k("payer","payer"),f=k("payee","payee"),b=L(p,f,`meters ${p} against ${p}; payer and payee must differ`),$=fe(d.get("close_by"),c),F=[],S=d.get("rates"),O=!0;if(S)if(I(S,c),S.value.kind!=="block")n(S.value.span,"rates is a block of per-unit prices, like: rates { api_call: unitFee: money(SAR) }");else{let z=le.metered.maxRates??le.metered.eventCap;S.value.entries.length>z&&(n(S.value.span,`${c} prices ${S.value.entries.length} meters, but metered allows at most ${z} so one settlement stays within its ${le.metered.eventCap}-event cap`),O=!1);for(let K of S.value.entries){if(!Xe.test(K.key.name)){n(K.key.span,`meter names are snake_case; "${K.key.name}" is not`);continue}if(F.some(Y=>Y.meter===K.key.name)){n(K.key.span,`${c} prices meter ${K.key.name} twice`);continue}let X=A(K,c);if(!X)continue;if(F.some(Y=>Y.field.name===X.name)){n(X.origin,`${c} reuses the field ${X.name} for two meters`);continue}let ae=F[0]?.field.currency;if(ae&&ae!==X.currency){n(X.origin,`${c} mixes ${ae} and ${X.currency}; one settlement meters in one currency`);continue}F.push({field:X,meter:K.key.name,origin:K.span})}S.value.entries.length===0&&n(S.value.span,`${c} prices no meters`)}if($&&F.some(z=>z.field.name===$)){n(i.span,`${c} uses ${$} as both a rate field and the close_by date field; they need distinct names`);break}p&&f&&$&&F.length>0&&b&&O&&J.push({archetype:"metered",closeByField:$,name:i.name.name,origin:i.span,payee:f,payer:p,rates:F});break}case"pooled_split":{let p=k("payer","payer"),f=A(d.get("amount"),c),b=fe(d.get("payout_due"),c),$=d.get("split"),F=[...v.keys()].filter(K=>K!==p),S=$?pe($,c,F,"declared parties other than the funder",!0):void 0;if(S&&S.shares.length<2){n($.value.span,`${c} splits to a single recipient; a pool distributes between at least two`);break}let O=le.pooled_split.maxRecipients??Math.floor(le.pooled_split.eventCap/2),z=!S||S.shares.length<=O;if(z||n($.value.span,`${c} splits to ${S.shares.length} recipients, but pooled_split allows at most ${O} so funding and payout stay within its ${le.pooled_split.eventCap}-event cap`),S){let K=new Map;for(let X of S.shares){let[ae="",...Y]=X.to.split("_"),ne=`${ae+Y.map(Fe=>Fe.charAt(0).toUpperCase()+Fe.slice(1)).join("")}ShareAmount`,ie=K.get(ne);ie&&n(X.origin,`${c} splits to ${ie} and ${X.to}, whose generated share fields both come out as ${ne}; rename one party`),K.set(ne,X.to)}}if(f&&b&&f.name===b){n(i.span,`${c} uses ${f.name} as both the amount and the payout_due date field; they need distinct names`);break}p&&f&&b&&S&&z&&J.push({amount:f,archetype:"pooled_split",distributeDueField:b,name:i.name.name,origin:i.span,payer:p,remainderTo:S.remainderTo??S.shares[0].to,shares:S.shares});break}}}let Ve=[];for(let i of w){let m=`port ${i.name.name}`,c=D(i.body,["allowed","shape"],m);c.has("allowed")||n(i.span,`${m} is missing allowed`);let y=[],d=c.get("allowed");if(d){I(d,m);let j=d.value;if(j.kind!=="list"||j.items.length===0)n(j.span,"allowed lists who may ask this question, like: allowed: [buyer]");else for(let p of j.items){let f=ee(p,`${m} allowed`);if(f){if(y.includes(f)){n(p.span,`${m} allows ${f} twice`);continue}y.push(f)}}}let k=[],L=c.get("shape");if(L)if(I(L,m),L.value.kind!=="block")n(L.value.span,"shape is a block of typed fields, like: shape { vehicleId: id(vehicle) }");else for(let j of L.value.entries){if(!be.test(j.key.name)){n(j.key.span,`shape fields are camelCase names; "${j.key.name}" is not`);continue}if(k.some(f=>f.name===j.key.name)){n(j.key.span,`${m} declares ${j.key.name} twice`);continue}let p=at(j.value);if(!p){n(j.value.span,`${j.key.name} needs a type: id(<asset>), money(<CUR>), text, or date`);continue}if(p.kind==="asset_id"&&!P.has(p.asset)){n(j.value.span,`id(${p.asset}) points at an asset that is not declared`);continue}if(p.kind==="money"&&!_n.test(p.currency)){n(j.value.span,`"${p.currency}" is not a currency code; use three capital letters like SAR`);continue}k.push({name:j.key.name,origin:j.span,type:p})}y.length>0&&Ve.push({allowed:y,fields:k,name:i.name.name,origin:i.span})}let ye=new Map(Ve.map(i=>[i.name,i]));for(let i of J){if(i.archetype==="captured_payment"){let y=ye.get(i.correction.port);y&&(y.allowed.length!==1||y.allowed[0]!==i.payee)&&n(y.origin,`captured_payment ${i.name} correction port ${y.name} must allow only its payee ${i.payee}`);let d=ye.get(i.externalReversal.port);d&&!d.fields.some(k=>k.name==="externalReference"&&k.type.kind==="text")&&n(d.origin,`captured_payment ${i.name} external reversal port ${d.name} needs shape { externalReference: text }`);continue}if(i.archetype==="settlement_batch"){let y=ye.get(i.payoutAcknowledgement.port);y&&!y.fields.some(d=>d.name==="acknowledgementReference"&&d.type.kind==="text")&&n(y.origin,`settlement_batch ${i.name} payout acknowledgement port ${y.name} needs shape { acknowledgementReference: text }`);continue}if(i.archetype==="weighted_distribution"){let y=ye.get(i.snapshot.port);y&&!y.fields.some(d=>d.name==="evidenceReference"&&d.type.kind==="text")&&n(y.origin,`weighted_distribution ${i.name} snapshot port ${y.name} needs shape { evidenceReference: text }`);continue}if(i.archetype==="recurring_collection"){let y=ye.get(i.mandate.port);y&&!y.fields.some(d=>d.name==="evidenceReference"&&d.type.kind==="text")&&n(y.origin,`recurring_collection ${i.name} mandate port ${y.name} needs shape { evidenceReference: text }`);continue}if(i.archetype==="conditional_disbursement"){let y=ye.get(i.decision.port);y&&(!y.fields.some(d=>d.name==="evidenceReference"&&d.type.kind==="text")||y.allowed.length!==1||y.allowed[0]!==i.source)&&n(y.origin,`conditional_disbursement ${i.name} decision port ${y.name} must allow only ${i.source} and needs shape { evidenceReference: text }`);continue}if(i.archetype==="premium_forward"&&i.endorsement){let y=ye.get(i.endorsement.port);y&&!y.fields.some(d=>d.name==="evidenceReference"&&d.type.kind==="text")&&n(y.origin,`premium_forward ${i.name} endorsement port ${y.name} needs shape { evidenceReference: text }`);continue}if(i.archetype!=="swap")continue;let m=new Set(i.sides.map(y=>y.party)),c=[{label:"release",portRef:i.release},...i.dispute?[{label:"dispute",portRef:i.dispute}]:[]];for(let y of c){let d=ye.get(y.portRef.port);if(d)for(let k of d.allowed)m.has(k)||n(d.origin,`swap ${i.name} ${y.label} port ${d.name} allows ${k}, but whole-trade decisions belong only to ${i.sides.map(L=>L.party).join(" or ")}`)}}let rt=new Map(J.filter(i=>i.archetype==="scheduled"&&i.mode==="obligation").map(i=>[i.name,i])),vn=new Map;for(let i of J){if(i.archetype!=="credit_facility"&&i.archetype!=="recurring_collection")continue;let m=rt.get(i.obligation.settlement),c=`settlement ${i.name}`;if(!m){n(i.obligation.origin,`${c} must compose with scheduled in mode: obligation; ${i.obligation.settlement} is not one`);continue}if(i.archetype==="credit_facility"){m.advanceTo&&n(i.obligation.origin,`${c} references ${m.name}, which already owns an advance; facility draws and obligation repayment must have one disbursement owner`),(m.payee!==i.lender||m.debtor!==i.borrower||m.amount.currency!==i.limit.currency)&&n(i.obligation.origin,`${c} must link an obligation whose payee is ${i.lender}, debtor is ${i.borrower}, and currency is ${i.limit.currency}`);continue}let y=ye.get(i.mandate.port),d=vn.get(m.name);d?n(i.obligation.origin,`${c} and settlement ${d} both collect ${m.name}; one obligation may have one collection policy owner`):vn.set(m.name,i.name),y&&(y.allowed.length!==1||y.allowed[0]!==m.payer)&&n(y.origin,`${c} mandate port ${y.name} must allow only the obligation payer ${m.payer}`)}let ot=new Map(J.filter(i=>i.archetype==="held_payment").map(i=>[i.name,i])),wn=new Map;for(let i of J){if(i.archetype!=="advance"||i.source.kind!=="carve")continue;let m=`settlement ${i.name}`,c=i.source.settlement,y=i.source.origin;if(i.source.targetArchetype!=="held_payment"||i.source.exit!=="release"){n(y,`${m} can only carve held_payment.release; ${c}.${i.source.exit} is a ${i.source.targetArchetype} exit`);continue}let d=ot.get(c);if(!d)continue;if(d.payee!==i.advanced){n(y,`${m} advances ${i.advanced}, but ${c} releases to ${d.payee}; an advance carves the release of the party it finances`);continue}if(d.amount.name!==i.amount.name){n(y,`${m} advances field ${i.amount.name}, but ${c}.release carries ${d.amount.name}; a carve must name the same money field`);continue}if(d.amount.currency!==i.amount.currency){n(y,`${m} advances ${i.amount.currency}, but ${c}.release carries ${d.amount.currency}; a carve must use one currency`);continue}if(i.feeBps>0){n(y,`${m} adds a fee to a carved advance, but ${c}.release can only prove repayment of the principal field; use a fee-free carve or a scheduled advance`);continue}if(d.fees.some(p=>p.bearer===d.payee&&p.bps>0)){n(y,`${m} carves ${c}.release after a payee fee reduces it; a carved hold must release the full principal field to the funder`);continue}if(d.payer===i.funder){n(y,`${i.funder} funds ${c} and finances it too; the party who pays the hold cannot be the funder its release repays`);continue}let k=wn.get(c);if(k){n(y,`${m} and settlement ${k} both draw against ${c}; one release repays one advance`);continue}if(wn.set(c,i.name),J.some(p=>p.archetype==="scheduled"&&p.mode==="transfer"&&p.payer===i.advanced&&p.payee===i.funder&&p.amount.name===i.amount.name&&p.amount.currency===i.amount.currency))continue;let j=`add a scheduled settlement collecting from the ${i.advanced.replaceAll("_"," ")} to the ${i.funder.replaceAll("_"," ")}`;if(d.onCancel){n(y,`${m} has no repayment path when ${c} is refunded instead of released; ${j}`);continue}r(y,`${m} has no repayment path if ${c} is abandoned before it funds; ${j}`)}for(let[i,m]of v)Z.has(i)||r(m.origin,`party ${i} is declared but no settlement or port involves them`);for(let i of w)C.has(i.name.name)&&!te.has(i.name.name)&&r(i.span,`port ${i.name.name} is declared but nothing releases through it`);for(let[i,m]of s)g.some(y=>y.archetype.name===i)||r(m,`${i} is imported but never instantiated`);return t.some(i=>i.severity==="error")||!l?{diagnostics:t}:{diagnostics:t,program:{assets:[...P.values()],derivedAmounts:o,name:l.name.name,parties:[...v.values()],ports:Ve,settlements:J,title:l.title?.value??it(l.name.name)}}}function at(e){if(e.kind==="ident"&&e.name==="text")return{kind:"text"};if(e.kind==="ident"&&e.name==="date")return{kind:"date"};if(e.kind==="call"&&e.args.length===1&&e.args[0]?.kind==="ident"){let t=e.args[0].name;if(e.callee.name==="id")return{asset:t,kind:"asset_id"};if(e.callee.name==="money")return{currency:t,kind:"money"}}}function it(e){let t=e.replaceAll("_"," ");return t.charAt(0).toUpperCase()+t.slice(1)}function xn(e){let t=[0];for(let n=0;n<e.length;n+=1)e.charCodeAt(n)===10&&t.push(n+1);return{length:e.length,starts:t}}function Cn(e,t){let n=Math.max(0,Math.min(t,e.length)),r=0,o=e.starts.length-1;for(;r<o;){let a=Math.floor((r+o+1)/2);e.starts[a]<=n?r=a:o=a-1}return{column:n-e.starts[r]+1,line:r+1}}var En=20,Sn=48,Ze=10000n;function st(e){if(!e)return{amountDependencies:[],amountMode:"fixed"};switch(e.kind){case"bounded_by_reference":return{amountDependencies:[U(e.reference)],amountMode:"runtime_bounded"};case"net_of_offsets":{if(e.offsets.length===0)throw new Error("net_of_offsets requires at least one offset event");return{amountDependencies:Pn(e.source,e.offsets),amountMode:"runtime_bounded"}}case"percent_of_reference":if(!Number.isInteger(e.bps)||e.bps<=0||e.bps>1e4)throw new Error("percent_of_reference bps must be an integer between 1 and 10000");return{amountDependencies:[U(e.reference)],amountMode:"runtime_bounded"};case"remainder":{if(e.consumed.length===0)throw new Error("remainder requires at least one consumed event");return{amountDependencies:Pn(e.source,e.consumed),amountMode:"remaining_balance"}}}}function Pn(e,t){let n=[e,...t].map(U);if(new Set(n).size!==n.length)throw new Error("amount dependency event keys must be distinct");return n}var In=160,ct=new Set(["amount","design","detail","headline","label","summary","title","trigger","why"]);function Qe(e,t){return typeof e=="string"?t!==void 0&&ct.has(t)&&e.length>In?`${e.slice(0,In-3)}...`:e:Array.isArray(e)?e.map(n=>Qe(n,t)):e!==null&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,Qe(r,n)])):e}function dt(e){return Qe(e)}function U(e){if(e.length<=40)return e;let t=2166136261;for(let n=0;n<e.length;n+=1)t=Math.imul(t^e.charCodeAt(n),16777619);return`${e.slice(0,33)}_${(t>>>0).toString(36).slice(0,6)}`}function lt(e){let t=e.amountDependency;if(!t)return e.amount;switch(t.kind){case"bounded_by_reference":return`Bounded by ${t.reference}: ${e.amount}`;case"net_of_offsets":return`Net of ${t.source} after ${t.offsets.join(", ")}: ${e.amount}`;case"percent_of_reference":return`${W(t.bps)} of ${t.reference}: ${e.amount}`;case"remainder":return`Remainder of ${t.source} after ${t.consumed.join(", ")}: ${e.amount}`}}function V(e){return{allocationTotalBps:0,amount:lt(e),...st(e.amountDependency),amountSchedule:[],distribution:"single",fromActor:e.fromActor,key:U(e.key),kind:e.kind,label:e.trigger,occurrence:e.occurrence??"once",timing:e.timing??"on_lifecycle",toActor:e.toActor,trigger:e.trigger}}function he(e,t,n,r){return e.map((o,a)=>({from:a===0?t:`${r}_${a}`,to:a===e.length-1?n:`${r}_${a+1}`}))}function De(e,t,n,r){let o=new Set;for(let a of t){if(a==="create"||o.has(a))return r.push({message:`settlement ${e} generates two verbs named "${a}"; rename the colliding port`,span:n}),!1;o.add(a)}return!0}function ge(e,t){return t.length>=2?[{pieces:[...t],total:e}]:[]}function ve(e){return e.length>0?{partitions:[...e]}:{}}function H(e){return{desc:e,type:"money"}}function se(e){return{desc:e,type:"date"}}function ut(e){return{desc:e,type:"date?"}}function pt(e){if(typeof e.prefix=="string")return e.prefix;let t=e.id,n=t.split("_");return(n.length>1?n.map(o=>o[0]).join(""):t.slice(0,4)).slice(0,8).padEnd(2,"x")}function mt(e,t){let n=new Set(e.filter(a=>!t.has(a.id)).map(pt)),r=0,o=()=>{for(;;){let a=String.fromCharCode(97+Math.floor(r/26)),l=String.fromCharCode(97+r%26);r+=1;let s=`zz${a}${l}`;if(!n.has(s))return n.add(s),s}};return e.map(a=>t.has(a.id)?{...a,prefix:o()}:a)}function Tn(e){let t=[],n=[],r=[],o=[],a=[],l=[],s=[],u=[],_=new Set,v=new Map,P=new Map(e.ports.map(h=>[h.name,h])),w=(h,T,q)=>{let A=P.get(T);return A||t.push({message:`settlement ${h.name} decides through an unknown port; the checker should have refused this program`,span:q}),A},g=new Map(e.settlements.flatMap(h=>h.archetype==="advance"&&h.source.kind==="carve"?[[h.source.settlement,h.funder]]:[])),C=new Map(e.settlements.flatMap(h=>{if(h.archetype!=="advance"||h.source.kind!=="carve")return[];let T=e.settlements.filter(q=>q.archetype==="scheduled"&&q.mode==="transfer"&&q.payer===h.advanced&&q.payee===h.funder&&q.amount.name===h.amount.name&&q.amount.currency===h.amount.currency);return[[h.name,T]]})),D=new Map(e.settlements.flatMap(h=>h.archetype==="recurring_collection"?[[h.obligation.settlement,h]]:[]));for(let h of e.settlements){let T;switch(h.archetype){case"held_payment":{let N=w(h,h.release.port,h.release.origin);if(!N)continue;T=kt(h,N,g.get(h.name),t);break}case"captured_payment":{let N=w(h,h.correction.port,h.correction.origin),M=w(h,h.externalReversal.port,h.externalReversal.origin);if(!N||!M)continue;T=xt(h,N,M,t);break}case"settlement_batch":{let N=w(h,h.payoutAcknowledgement.port,h.payoutAcknowledgement.origin);if(!N)continue;T=Ct(h,N,t);break}case"funding_round":T=St(h);break;case"weighted_distribution":{let N=w(h,h.snapshot.port,h.snapshot.origin);if(!N)continue;T=Pt(h,N);break}case"credit_facility":T=It(h);break;case"recurring_collection":continue;case"conditional_disbursement":{let N=w(h,h.decision.port,h.decision.origin);if(!N)continue;T=Tt(h,N);break}case"rotating_pool":T=Ft(h);break;case"premium_forward":{let N=w(h,h.bind.port,h.bind.origin),M=h.endorsement?w(h,h.endorsement.port,h.endorsement.origin):void 0;if(!N||h.endorsement&&!M)continue;T=_t(h,N,M,t);break}case"deposit":{let N=w(h,h.claim.port,h.claim.origin),M=w(h,h.return.port,h.return.origin);if(!N||!M)continue;T=Et(h,N,M,t);break}case"instant_transfer":T=At(h);break;case"scheduled":T=h.mode==="obligation"?Rt(h,D.get(h.name),D.has(h.name)?w(D.get(h.name),D.get(h.name).mandate.port,D.get(h.name).mandate.origin):void 0):Dt(h);break;case"advance":T=Nt(h,C.get(h.name)??[]);break;case"metered":T=Bt(h);break;case"pooled_split":T=jt(h);break;case"swap":{let N=w(h,h.release.port,h.release.origin),M=h.dispute?w(h,h.dispute.port,h.dispute.origin):void 0;if(!N||h.dispute&&!M)continue;T=wt(h,N,M);break}}if(!T)continue;let q=(e.derivedAmounts??[]).filter(N=>N.settlement===h.name);if(q.length>0&&(T=yt(T,h,q,t),!T))continue;let A=le[h.archetype].eventCap+q.length;if(T.moneyEvents.length>A){t.push({message:`settlement ${h.name} emits ${T.moneyEvents.length} money events, but ${h.archetype} carries a local cap of ${A}`,span:h.origin});continue}for(let N of[...T.moneyEvents,...T.rules]){let M=N.key,oe=v.get(M);oe&&t.push({message:`settlements ${oe} and ${h.name} both generate the internal key ${M}; rename one settlement (or its port or meter) so the generated keys stay distinct`,span:h.origin}),v.set(M,h.name)}n.push(T.settlement);let R=[T.noun,...T.extraNouns??[]];for(let N of R){let M=N.verbs;for(let[oe,de]of Object.entries(M)){if(Object.hasOwn(de,"due")||Object.hasOwn(de,"requiresSettlement"))continue;let pe=Fn(N.id,oe);pe.length<=Sn||t.push({message:`settlement ${h.name} generates public intent "${pe}" with ${pe.length} characters; rename the settlement so each public intent fits the ${Sn}-character camelName limit`,span:h.origin})}}r.push(...R);for(let N of T.generatedPrefixNounIds??[])_.add(N);o.push(...T.moneyEvents),a.push(...T.rules),l.push(...T.design),s.push(...T.feeLines),T.repeatableCounterparty&&u.push(T.repeatableCounterparty)}o.length>En&&t.push({message:`this program needs ${o.length} money events but a Business Frame carries at most ${En}; simplify the fee or cancellation terms, or drop a settlement`,span:e.settlements[0]?.origin??{end:0,start:0}}),t.push(...gt(o,e.settlements[0]?.origin??{end:0,start:0}));let I=ht(e,u);if(t.push(...I.issues),t.length>0)return{issues:t,ok:!1};let Z=ft(mt(r,_)),ee=e.assets.map(h=>({kind:h.name,title:B(h.name),value:"optional"})),te={hsx:1,nouns:Z,product:e.name,...ee.length>0?{subjects:ee}:{},title:e.title},J={actors:I.actors,confidence:"high",conservationGroups:[],design:l,feePolicy:s.length>0?"defined":"none",fees:s,headline:e.title,mechanics:vt(e.settlements),moneyEvents:o,offPlatform:e.assets.filter(h=>h.titleTransfer==="off_platform").map(h=>({label:`${B(h.name)} title transfer`,why:`Ownership of the ${h.name.replaceAll("_"," ")} changes hands outside the platform`})),openQuestions:[],rules:a,subjects:e.assets.map(h=>({kind:h.name,title:B(h.name)})),summary:qt(e)};return{ok:!0,value:{document:te,frame:dt(J),settlements:n}}}function ft(e){return e.map(t=>{let n=t.verbs;return{...t,verbs:Object.fromEntries(Object.entries(n).map(([r,o])=>[r,Object.hasOwn(o,"due")||Object.hasOwn(o,"requiresSettlement")?o:{...o,publicIntent:Fn(t.id,r)}]))}})}function Fn(e,t){let n=Q(e),r=n.charAt(0).toUpperCase()+n.slice(1);return`${Q(t)}${r}`}function yt(e,t,n,r){let o=e.noun,a={...o.fields??{}},l={...o.verbs??{}},s={...l.create??{}},u=[...s.moves??[]],_={...o.actors??{}},v=[],P=[...e.moneyEvents],w=[...e.feeLines];for(let g of n){let C=a[g.baseField];if(C===void 0||C.type!=="money"){r.push({message:`settlement ${t.name} derives ${g.field} from ${C===void 0?"unknown ":"non-money "}field ${g.baseField}; from must name a stored money field on the settlement owner`,span:g.origin});return}if(a[g.field]!==void 0){r.push({message:`settlement ${t.name} derives into existing field ${g.field}; choose a new derived amount field`,span:g.origin});return}let D=U(`${t.name}_derived_amount`);a[g.field]=H(`Machine-computed ${W(g.bps)} of ${g.baseField}; callers never supply it`),_[g.bearer]===void 0&&(_[g.bearer]="payer"),_.platform="beneficiary",v.push({field:g.field,rounding:"floor",rule:{bps:g.bps,kind:"percentage_of"},sourceField:g.baseField}),u.push({amount:g.field,from:g.bearer,key:"derived_amount",moneyEvent:D,operation:"create",to:"platform"}),P.push(V({amount:`The machine-computed ${g.field}`,fromActor:g.bearer,key:D,kind:"charge",toActor:"platform",trigger:`Collect ${g.field} with settlement creation`})),w.push({label:B(g.field),on:`each ${t.name.replaceAll("_"," ")}`,structure:`${W(g.bps)} of stored ${g.baseField}, computed by the runtime`})}return s.moves=u,l.create=s,{...e,design:[...e.design,`${t.name}: derived amounts are machine-computed from stored source fields before create movements; fixed and tiered rules are refused`],feeLines:w,moneyEvents:P,noun:{...o,actors:_,derivedAmounts:v,fields:a,verbs:l}}}function ht(e,t=[]){let n=$t(e.settlements),r=new Set(e.parties.map(s=>s.name)),o=new Map,a=[];for(let s of t){if(!r.has(s.key)){a.push({message:`repeatable counterparty ${s.key} is not a declared party`,span:s.origin});continue}let u=n.get(s.key);if(!u){a.push({message:`repeatable counterparty ${s.key} is not used by any settlement`,span:s.origin});continue}if(u!==s.role){a.push({message:`repeatable counterparty ${s.key} declares role ${s.role}, but its settlement uses role ${u}`,span:s.origin});continue}if(s.label.trim().length===0||s.label.length>160){a.push({message:`repeatable counterparty ${s.key} label must contain 1 through 160 characters`,span:s.origin});continue}if(!Number.isInteger(s.minCount)||!Number.isInteger(s.maxCount)||s.minCount<1||s.maxCount>1e4){a.push({message:`repeatable counterparty ${s.key} counts must be integers from 1 through 10000`,span:s.origin});continue}if(s.minCount>s.maxCount){a.push({message:`repeatable counterparty ${s.key} has minCount ${s.minCount} above maxCount ${s.maxCount}`,span:s.origin});continue}if(o.has(s.key)){a.push({message:`repeatable counterparty ${s.key} is declared twice`,span:s.origin});continue}o.set(s.key,s)}return{actors:[...e.parties.filter(s=>n.has(s.name)).map(s=>{let u=o.get(s.name);return u?{key:u.key,label:u.label,maxCount:u.maxCount,minCount:u.minCount,role:u.role}:{key:s.name,label:B(s.name),maxCount:1,minCount:1,role:n.get(s.name)}}),{key:"platform",label:"Platform",maxCount:1,minCount:1,role:"platform"}],issues:a}}function gt(e,t){let n=[],r=new Map;for(let u of e){if(typeof u.key!="string")continue;let _=Array.isArray(u.amountDependencies)?u.amountDependencies.filter(v=>typeof v=="string"):[];r.set(u.key,_)}for(let[u,_]of r)for(let v of _){if(v===u){n.push({message:`money event ${u} cannot depend on itself`,span:t});continue}r.has(v)||n.push({message:`money event ${u} depends on missing money event ${v}`,span:t})}let o=new Set,a=new Set,l=new Set,s=u=>{if(!(a.has(u)||l.has(u))){if(o.has(u)){l.add(u);return}o.add(u);for(let _ of r.get(u)??[])r.has(_)&&s(_),l.has(_)&&l.add(u);o.delete(u),a.add(u)}};for(let u of r.keys())s(u);return l.size>0&&n.push({message:`money event amount dependencies contain a cycle through ${[...l].sort().join(", ")}`,span:t}),n}function $t(e){let t=new Set,n=new Set,r=new Set,o=new Set;for(let s of e)switch(s.archetype){case"held_payment":case"captured_payment":case"instant_transfer":case"metered":t.add(s.payer),n.add(s.payee);break;case"scheduled":t.add(s.payer),n.add(s.payee),s.mode==="obligation"&&(t.add(s.debtor),s.advanceTo&&n.add(s.advanceTo));break;case"premium_forward":t.add(s.payer),r.add(s.carrier);break;case"deposit":t.add(s.payer),o.add(s.holder);break;case"advance":t.add(s.funder),n.add(s.advanced);break;case"pooled_split":t.add(s.payer);for(let u of s.shares)n.add(u.to);break;case"settlement_batch":t.add(s.settlementAccount),n.add(s.payoutDestination);break;case"funding_round":t.add(s.contributor),n.add(s.beneficiary);break;case"weighted_distribution":t.add(s.source),n.add(s.recipient);break;case"credit_facility":t.add(s.lender),n.add(s.borrower),n.add(s.drawDestination);break;case"recurring_collection":break;case"conditional_disbursement":t.add(s.source),n.add(s.destination);break;case"rotating_pool":for(let u of s.members)t.add(u),n.add(u);s.guarantor&&t.add(s.guarantor);break;case"swap":t.add(s.sides[0].party),n.add(s.sides[1].party);break}let a=new Map,l=(s,u)=>{for(let _ of s)a.has(_)||a.set(_,u)};return l(t,"payer"),l(r,"provider"),l(o,"holder"),l(n,"beneficiary"),a}var bt={advance:"credit",captured_payment:"escrow",conditional_disbursement:"marketplace",credit_facility:"credit",deposit:"escrow",funding_round:"credit",held_payment:"escrow",instant_transfer:"marketplace",metered:"recurring_billing",pooled_split:"marketplace",premium_forward:"insurance",recurring_collection:"recurring_billing",rotating_pool:"recurring_billing",scheduled:"recurring_billing",settlement_batch:"marketplace",swap:"escrow",weighted_distribution:"marketplace"};function vt(e){let t=new Set(e.map(n=>n.archetype==="scheduled"&&n.mode==="obligation"?"credit":bt[n.archetype]));return t.size>0?[...t]:["escrow"]}function wt(e,t,n){let r=e.name,[o,a]=e.sides,l=e.dispute?.window,s=l!==void 0&&l.days>0,u=U(`${r}_clawback_maturity`),_=[],v=(R,N,M,oe,de,pe)=>{let me=U(`${r}_${R}`);return _.push(V({amount:M,fromActor:oe,key:me,kind:N,toActor:de,trigger:pe})),me},P=v("side_a_fund","charge",`The full ${o.amount.name}`,o.party,"escrow",`Fund ${o.amount.name} into the shared trade escrow`),w=v("side_b_fund","charge",`The full ${a.amount.name}`,a.party,"escrow",`Fund ${a.amount.name} into the shared trade escrow`),g=v("side_a_release","payout",`The full ${o.amount.name}`,"escrow",a.party,`Release ${o.amount.name} across to ${a.party.replaceAll("_"," ")}`),C=v("side_b_release","payout",`The full ${a.amount.name}`,"escrow",o.party,`Release ${a.amount.name} across to ${o.party.replaceAll("_"," ")}`),D=v("side_a_cancel","refund",`The full ${o.amount.name}`,"escrow",o.party,`Return ${o.amount.name} to its original funder on cancellation`),I=v("side_b_cancel","refund",`The full ${a.amount.name}`,"escrow",a.party,`Return ${a.amount.name} to its original funder on cancellation`),Z=s?v("side_a_clawback","refund",`The full ${o.amount.name}`,"escrow",o.party,`Return ${o.amount.name} after the whole trade is disputed`):void 0,ee=s?v("side_b_clawback","refund",`The full ${a.amount.name}`,"escrow",a.party,`Return ${a.amount.name} after the whole trade is disputed`):void 0,te={[o.amount.name]:H(`Side A amount in ${o.amount.currency} minor units, held against the whole trade`),[a.amount.name]:H(`Side B amount in ${a.amount.currency} minor units, held against the whole trade`),...s?{clawbackAt:{type:"date?",desc:`Machine-owned end of the ${l?.raw??"fixed"} whole-trade dispute window`}}:{}},J=[{amount:o.amount.name,from:o.party,key:"side_a_principal",moneyEvent:P,operation:"create",to:"escrow"},{amount:a.amount.name,from:a.party,key:"side_b_principal",moneyEvent:w,operation:"create",to:"escrow"}],h=[];for(let[R,N]of e.sides.entries()){if(!N.fee)continue;let M=N.fee.amount.name;te[M]=H(`Exact ${N.party.replaceAll("_"," ")} service fee in ${N.fee.amount.currency} minor units, charged on top and never held`);let oe=v(R===0?"side_a_service_fee":"side_b_service_fee","charge",`The exact ${M}, on top`,N.party,"platform",`Collect the ${N.party.replaceAll("_"," ")} custody fee at funding`);J.push({amount:M,from:N.party,key:R===0?"side_a_service_fee":"side_b_service_fee",moneyEvent:oe,operation:"create",to:"platform"}),h.push({label:`${B(N.party)} custody fee`,on:`each funded ${r.replaceAll("_"," ")}`,structure:`Exact ${M}, on top`})}let T=[{amount:o.amount.name,from:"escrow",key:"side_a",moneyEvent:g,operation:s?"reserve":"create",to:a.party},{amount:a.amount.name,from:"escrow",key:"side_b",moneyEvent:C,operation:s?"reserve":"create",to:o.party}],q={abandon:{from:["created"],requiresDrainedAccount:{path:"refs.escrowAccountId"},summary:"Abandon the trade before its atomic funding batch",to:"abandoned"},cancel:{from:["funded"],moves:[{amount:o.amount.name,from:"escrow",key:"side_a_refund",moneyEvent:D,operation:"create",to:o.party},{amount:a.amount.name,from:"escrow",key:"side_b_refund",moneyEvent:I,operation:"create",to:a.party}],summary:"Cancel and return both trade principals atomically",to:"cancelled"},create:{summary:`Create a ${B(r).toLowerCase()} atomic trade`,to:"created"},fund:{from:["created"],moves:J,summary:"Fund both trade sides and collect on-top fees atomically",to:"funded"},release:{from:["funded"],moves:T,port:{allowed:[...t.allowed]},...s?{setsAt:{field:"clawbackAt",offset:l?.raw}}:{},summary:s?"Reserve both cross-payments for the whole-trade clawback window":"Post both cross-payments atomically",to:s?"released":"settled"}};s&&e.dispute&&n&&Z&&ee&&(q.post={due:{field:"clawbackAt",rule:u},from:["released"],moves:[{key:"side_a",operation:"post",reservation:"release_side_a"},{key:"side_b",operation:"post",reservation:"release_side_b"}],summary:"Post both trade reservations when the clawback window matures",to:"settled"},q.dispute={deadline:{field:"clawbackAt"},from:["released"],moves:[{key:"side_a_void",operation:"void",reason:"Whole trade disputed inside the clawback window",reservation:"release_side_a"},{key:"side_b_void",operation:"void",reason:"Whole trade disputed inside the clawback window",reservation:"release_side_b"},{amount:o.amount.name,clawbackOf:"release_side_a",from:"escrow",key:"side_a_refund",moneyEvent:Z,operation:"create",to:o.party},{amount:a.amount.name,clawbackOf:"release_side_b",from:"escrow",key:"side_b_refund",moneyEvent:ee,operation:"create",to:a.party}],port:{allowed:[...n.allowed]},summary:"Void both reservations, then refund both principals atomically",to:"clawed_back"});let A=[{allowedActors:[...t.allowed],detail:`${t.allowed.map(B).join(" or ")} confirms the whole exchange through ${t.name}`,dueDriven:!1,enforcement:"tenant_app",gatesEvent:g,key:U(`${r}_${t.name}_gate`),kind:"release_condition",label:`Whole trade released through ${t.name}`,tenantTunable:!1}];return s&&e.dispute&&n&&A.push({allowedActors:[],detail:`Both pending trade payouts post together at the immutable ${e.dispute.window.raw} cutoff`,dueDriven:!0,enforcement:"platform",gatesEvent:null,key:u,kind:"deadline",label:"Whole trade posts when its clawback window matures",tenantTunable:!1},{allowedActors:[...n.allowed],detail:`${n.allowed.map(B).join(" or ")} may dispute only before the immutable cutoff`,dueDriven:!1,enforcement:"tenant_app",gatesEvent:Z??null,key:U(`${r}_${n.name}_gate`),kind:"release_condition",label:`Whole trade disputed through ${n.name}`,tenantTunable:!1}),{design:[`${r}: exactly two parties, two same-currency principals, one escrow, and one linked batch per phase`,s?`${r}: ${l?.raw} whole-trade clawback; release reserves both legs, then exactly one grouped post or grouped void-and-refund wins`:`${r}: no clawback window; release posts both legs directly and exposes no pending or dispute surface`],feeLines:h,moneyEvents:_,noun:{actors:{[o.party]:"payer",[a.party]:"beneficiary",...h.length>0?{platform:"party"}:{}},desc:`Atomic swap between ${o.party.replaceAll("_"," ")} and ${a.party.replaceAll("_"," ")}; half-funded and half-released states do not exist`,distinctParties:!0,escrow:!0,fields:te,id:r,summary:`Two-party atomic trade between ${o.party.replaceAll("_"," ")} and ${a.party.replaceAll("_"," ")}`,title:B(r),verbs:q},rules:A,settlement:{name:r,pieces:[{bps:1e4,cancelTo:o.party,field:o.amount.name,origin:o.amount.origin,releaseTo:a.party},{bps:1e4,cancelTo:a.party,field:a.amount.name,origin:a.amount.origin,releaseTo:o.party}]}}}function kt(e,t,n,r){let o=e.fees.find(s=>s.bearer===e.payer),a=e.fees.find(s=>s.bearer===e.payee),l=Rn({amount:e.amount,carveTo:n,deadlineField:e.releaseDeadlineField,fundEventKind:"charge",fundTrigger:(s,u)=>`Fund piece ${s+1} of ${u} into escrow`,name:e.name,onCancel:e.onCancel,payee:e.payee,payeeFeeBps:a?.bps??0,payer:e.payer,payerFeeBps:o?.bps,port:t,releaseWord:"release"},r);if(l)return{...l,feeLines:[...o?[{label:`${B(e.payer)} service fee`,on:`each funded ${e.name.replaceAll("_"," ")}`,structure:`${W(o.bps)} of the ${e.amount.name}, on top`}]:[],...a?[{label:`${B(e.payee)} fee`,on:`each released ${e.name.replaceAll("_"," ")}`,structure:`${W(a.bps)} of the ${e.amount.name}, deducted from the payout`}]:[]],noun:{...l.noun,desc:`Held payment: the ${e.payer.replaceAll("_"," ")} funds ${e.amount.name} into this settlement's own escrow; ${t.allowed.map(s=>s.replaceAll("_"," ")).join(" or ")} confirms through ${t.name} to release${n?` to the ${n.replaceAll("_"," ")}, whose advance the ${e.payee.replaceAll("_"," ")} repays out of it`:""}`,summary:`Escrow-held payment from ${e.payer.replaceAll("_"," ")} to ${e.payee.replaceAll("_"," ")}`}}}function _t(e,t,n,r){let o=Rn({amount:e.amount,carveTo:void 0,deadlineField:void 0,fundEventKind:"premium",fundTrigger:(_,v)=>v===1?"Collect the premium into escrow":`Collect premium piece ${_+1} of ${v} into escrow`,name:e.name,onCancel:e.onCancel,payee:e.carrier,payeeFeeBps:e.commissionBps,payer:e.payer,payerFeeBps:void 0,port:t,releaseWord:"forward"},r);if(!o)return;let a=o.noun,l={...a.fields??{}},s={...a.verbs??{}},u=[...o.rules];if(e.policyReferenceField&&e.renewalDueField&&e.endorsement&&n){l[e.policyReferenceField]={desc:"Immutable external policy reference recorded with this forward",type:"text"},l[e.renewalDueField]=se("Stored renewal due condition for the forwarded policy"),s[e.endorsement.port]={captureInput:{endorsementEvidenceReference:"evidenceReference"},from:["released"],port:{allowed:n.allowed,fields:{evidenceReference:"text"}},summary:"Record one non-money endorsement from external evidence",to:"endorsed"};let _=U(`${e.name}_renewal_due`);s.lapse={due:{field:e.renewalDueField,rule:_},from:["released","endorsed"],requiresDrainedAccount:{path:"refs.escrowAccountId"},summary:"Mark the forwarded policy lapsed at its stored renewal due condition",to:"lapsed"},u.push({allowedActors:[],detail:"The stored renewal due condition changes policy state without moving money",dueDriven:!0,enforcement:"platform",gatesEvent:null,key:_,kind:"deadline",label:"Policy lapses at its stored renewal due condition",tenantTunable:!1})}return{...o,design:[`${e.name}: premium forwards to the ${e.carrier.replaceAll("_"," ")} exactly once on ${t.name}; ${W(e.commissionBps)} commission retained by the platform`,...e.policyReferenceField?[`${e.name}: extends premium_forward with stored policy reference, non-money endorsement evidence, and a due-only lapse; renewal creates a new forward`]:[]],feeLines:e.commissionBps>0?[{label:"Platform commission",on:`each bound ${e.name.replaceAll("_"," ")}`,structure:`${W(e.commissionBps)} of the ${e.amount.name}, deducted at forwarding`}]:[],noun:{...o.noun,fields:l,verbs:s,desc:`Premium forward: the ${e.payer.replaceAll("_"," ")} funds the ${e.amount.name} into this settlement's own escrow; binding through ${t.name} forwards it to the ${e.carrier.replaceAll("_"," ")} exactly once, minus the platform commission`,summary:`Premium held for the ${e.carrier.replaceAll("_"," ")} until the policy binds`},rules:u}}function Rn(e,t){let n=e.amount.name,r=Dn(e),o=r.length===1?r.map(A=>({...A,field:n})):r,a=e.name,l=e.carveTo??e.payee,s=l.replaceAll("_"," "),u={[n]:H(o.length===1?`The held amount in ${e.amount.currency} minor units, funded and paid out whole`:`The gross held amount in ${e.amount.currency} minor units; the piece fields below partition it exactly`)};for(let[A,R]of o.entries())R.field!==n&&(u[R.field]=H(Nn(R,A,n,e.amount.currency)));e.deadlineField&&(u[e.deadlineField]=se(`The date an undecided hold releases to the ${s} on; ${e.port.name} and cancellation decide only before it`)),e.payerFeeBps!==void 0&&(u.serviceFeeAmount=H(`${W(e.payerFeeBps)} of ${n}, the ${e.payer.replaceAll("_"," ")}-side service fee charged on top at funding; non-refundable`));let _=o.map((A,R)=>`fund_piece_${R+1}`);e.payerFeeBps!==void 0&&_.push("collect_service_fee");let v=o.map((A,R)=>R===0?e.port.name:`${e.releaseWord}_piece_${R+1}`),P=e.onCancel?o.map((A,R)=>R===0?"cancel":`refund_piece_${R+1}`):[],w=e.deadlineField?`${e.releaseWord}_on_deadline`:void 0,g=U(`${a}_${e.releaseWord}_deadline`),C=_.length-1,D=Array.from({length:C},(A,R)=>`unfund_piece_${R+1}`);if(!De(e.name,[..._,...v,...w?[w]:[],...P,"abandon",...D],e.port.origin,t))return;let I=he(_,"created","funded","funding"),Z=he(v,"funded","released","releasing"),ee=he(P,"funded","cancelled","cancelling"),te=[],J={},h=`${a}_fund`;te.push(V({amount:o.length===1?`The full ${n}`:`The ${n}, funded piece by piece`,fromActor:e.payer,key:h,kind:e.fundEventKind,...o.length>1?{occurrence:"repeatable"}:{},toActor:"escrow",trigger:e.fundTrigger(0,o.length)}));for(let[A,R]of o.entries())J[_[A]]={from:[I[A]?.from],moneyEvent:h,moves:[{key:"transfer",operation:"create",amount:R.field,from:e.payer,to:"escrow"}],summary:`Fund piece ${A+1} of the held amount into escrow`,to:I[A]?.to};if(e.payerFeeBps!==void 0){let A=_.length-1,R=`${a}_service_fee`;te.push(V({amount:`${W(e.payerFeeBps)} of the ${n}, on top`,fromActor:e.payer,key:R,kind:"charge",toActor:"platform",trigger:"Collect the service fee at funding"})),J.collect_service_fee={from:[I[A]?.from],moneyEvent:R,moves:[{key:"transfer",operation:"create",amount:"serviceFeeAmount",from:e.payer,to:"platform"}],summary:"Collect the payer-side service fee",to:I[A]?.to}}let T=new Map;for(let A of o)T.set(A.releaseTo,(T.get(A.releaseTo)??0)+1);for(let[A,R]of T){let N=o.filter(M=>M.releaseTo===A).reduce((M,oe)=>M+oe.bps,0);te.push(V({amount:`${W(N)} of the ${n}`,fromActor:"escrow",key:`${a}_release_${A}`,kind:"payout",...R>1?{occurrence:"repeatable"}:{},toActor:A,trigger:`Release to the ${A.replaceAll("_"," ")}`}))}for(let[A,R]of o.entries())J[v[A]]={...A===0&&e.deadlineField?{deadline:{field:e.deadlineField}}:{},from:[Z[A]?.from],moneyEvent:U(`${a}_release_${R.releaseTo}`),moves:[{key:"transfer",operation:"create",amount:R.field,from:"escrow",to:R.releaseTo}],...A===0?{port:{allowed:[...e.port.allowed],fields:Object.fromEntries(e.port.fields.map(N=>[N.name,"text"]))}}:{},summary:A===0?`Confirm through ${e.port.name} and start the ${e.releaseWord} payout`:`${B(e.releaseWord)} piece ${A+1} of the held amount`,to:Z[A]?.to};if(w&&e.deadlineField){let A=o[0];J[w]={due:{field:e.deadlineField,rule:g},from:[Z[0]?.from],moneyEvent:U(`${a}_release_${A.releaseTo}`),moves:[{key:"transfer",operation:"create",amount:A.field,from:"escrow",to:A.releaseTo}],summary:`Release to the ${A.releaseTo.replaceAll("_"," ")} when ${e.deadlineField} arrives undecided`,to:Z[0]?.to}}if(e.onCancel){let A=new Map;for(let R of o){let N=R.cancelTo;A.set(N,(A.get(N)??0)+1)}for(let[R,N]of A){let M=o.filter(oe=>oe.cancelTo===R).reduce((oe,de)=>oe+de.bps,0);te.push(V({amount:`${W(M)} of the ${n}`,fromActor:"escrow",key:`${a}_cancel_${R}`,kind:R===e.payer?"refund":"penalty",...N>1?{occurrence:"repeatable"}:{},toActor:R,trigger:`Return to the ${R.replaceAll("_"," ")} on cancellation`}))}for(let[R,N]of o.entries())J[P[R]]={...R===0&&e.deadlineField?{deadline:{field:e.deadlineField}}:{},from:[ee[R]?.from],moneyEvent:U(`${a}_cancel_${N.cancelTo}`),moves:[{key:"transfer",operation:"create",amount:N.field,from:"escrow",to:N.cancelTo}],summary:R===0?"Cancel the settlement and start the unwind":`Return piece ${R+1} on cancellation`,to:ee[R]?.to}}if(D.length>0){let A=`${a}_abandon`;te.push(V({amount:`The funded pieces of the ${n}, returned exactly`,fromActor:"escrow",key:A,kind:"refund",...D.length>1?{occurrence:"repeatable"}:{},toActor:e.payer,trigger:`Return the held pieces to the ${e.payer.replaceAll("_"," ")} on abandonment`}));for(let[R,N]of D.entries()){let M=R+1;J[N]={from:[`funding_${M}`,...M<C?[`abandoning_${M}`]:[]],moneyEvent:U(A),moves:[{key:"transfer",operation:"create",amount:o[R].field,from:"escrow",to:e.payer}],summary:`Return piece ${M} to the ${e.payer.replaceAll("_"," ")} on abandonment`,to:M===1?"abandoned":`abandoning_${M-1}`}}}J.abandon={from:["created"],requiresDrainedAccount:{path:"refs.escrowAccountId"},summary:"Abandon the settlement before any money is held",to:"abandoned"},J.create={summary:`Create a ${B(e.name).toLowerCase()} settlement`,to:"created"};let q=[{allowedActors:[...e.port.allowed],detail:`${e.port.allowed.map(B).join(" or ")} confirms through the tenant backend before ${e.deadlineField?`${e.deadlineField}, to decide ahead of it`:"any payout"}`,dueDriven:!1,enforcement:"tenant_app",gatesEvent:U(`${a}_release_${o[0].releaseTo}`),key:U(`${a}_${e.port.name}_gate`),kind:"release_condition",label:`${B(e.releaseWord)} decided through ${e.port.name}`,tenantTunable:!1}];return e.deadlineField&&q.push({allowedActors:[],detail:`A hold nobody decided releases to the ${s} on its stored ${e.deadlineField}, exactly once`,dueDriven:!0,enforcement:"platform",gatesEvent:null,key:g,kind:"deadline",label:`Undecided holds release on ${e.deadlineField}`,tenantTunable:!1}),{design:[`${a}: own escrow; ${o.length}-piece partition of ${n} (${o.map(A=>W(A.bps)).join(" + ")}); every exit drains every piece; abandonable before funded (created closes directly, funding states unwind piece by piece to the ${e.payer})`,...e.deadlineField?[`${a}: undecided holds release to the ${l} on ${e.deadlineField}; the port and the cancel decide only before that anchor`]:[],...e.carveTo?[`${a}: the ${e.payee}'s whole release share is carved to the ${e.carveTo}, who financed it; the platform fee and the cancellation split are untouched`]:[],...e.payerFeeBps!==void 0?[`${a}: ${W(e.payerFeeBps)} ${e.payer} service fee on top, straight to platform at funding`]:[]],feeLines:[],moneyEvents:te,noun:{actors:{[e.payer]:"payer",[e.payee]:"beneficiary",...e.carveTo?{[e.carveTo]:"party"}:{},platform:"party"},desc:`Held amount from ${e.payer.replaceAll("_"," ")} to ${e.payee.replaceAll("_"," ")}${e.carveTo?`, released to the ${s} against the advance it secures`:""}`,escrow:!0,fields:u,id:e.name,...ve(ge(n,o.map(A=>A.field))),summary:`Escrow-held amount from ${e.payer.replaceAll("_"," ")}`,title:B(e.name),verbs:J},rules:q,settlement:{name:e.name,pieces:o,...e.payerFeeBps!==void 0?{serviceFee:{bps:e.payerFeeBps,field:"serviceFeeAmount"}}:{}}}}function At(e){let t=e.fees.find(g=>g.bearer===e.payer),n=e.fees.find(g=>g.bearer===e.payee),r=e.amount.name,o=Dn({amount:e.amount,payee:e.payee,payeeFeeBps:n?.bps??0}),a=o.length===1?o.map(g=>({...g,field:r})):o,l=e.name,s={[r]:H(a.length===1?`The amount in ${e.amount.currency} minor units, paid through whole`:`The gross amount in ${e.amount.currency} minor units; the piece fields below partition it exactly`)};for(let[g,C]of a.entries())C.field!==r&&(s[C.field]=H(Nn(C,g,r,e.amount.currency)));t&&(s.serviceFeeAmount=H(`${W(t.bps)} of ${r}, the ${e.payer.replaceAll("_"," ")}-side service fee charged on top; non-refundable`));let u=a.map((g,C)=>`pay_piece_${C+1}`);t&&u.push("collect_service_fee");let _=he(u,"created","paid","paying"),v=[],P={create:{summary:`Create a ${B(l).toLowerCase()} payment`,to:"created"}};for(let[g,C]of a.entries()){let D=`${l}_pay_${g+1}`;v.push(V({amount:`${W(C.bps)} of the ${r}`,fromActor:e.payer,key:D,kind:"charge",toActor:C.releaseTo,trigger:`Pay piece ${g+1} straight to the ${C.releaseTo.replaceAll("_"," ")}`})),P[u[g]]={from:[_[g]?.from],moneyEvent:D,moves:[{key:"transfer",operation:"create",amount:C.field,from:e.payer,to:C.releaseTo}],summary:`Pay piece ${g+1} of the amount through`,to:_[g]?.to}}if(t){let g=u.length-1,C=`${l}_service_fee`;v.push(V({amount:`${W(t.bps)} of the ${r}, on top`,fromActor:e.payer,key:C,kind:"charge",toActor:"platform",trigger:"Collect the service fee with the payment"})),P.collect_service_fee={from:[_[g]?.from],moneyEvent:C,moves:[{key:"transfer",operation:"create",amount:"serviceFeeAmount",from:e.payer,to:"platform"}],summary:"Collect the payer-side service fee",to:_[g]?.to}}let w=t!==void 0||a.some(g=>g.releaseTo==="platform");return{design:[`${l}: instant pass-through; ${a.length}-piece partition of ${r} (${a.map(g=>W(g.bps)).join(" + ")}); no custody`],feeLines:[...t?[{label:`${B(e.payer)} service fee`,on:`each ${l.replaceAll("_"," ")}`,structure:`${W(t.bps)} of the ${r}, on top`}]:[],...n?[{label:`${B(e.payee)} fee`,on:`each ${l.replaceAll("_"," ")}`,structure:`${W(n.bps)} of the ${r}, deducted from the payout`}]:[]],moneyEvents:v,noun:{actors:{[e.payer]:"payer",[e.payee]:"beneficiary",...w?{platform:"party"}:{}},desc:`Instant transfer: the ${e.payer.replaceAll("_"," ")} pays ${r} straight through to the ${e.payee.replaceAll("_"," ")}, no custody`,fields:s,id:l,...ve(ge(r,a.map(g=>g.field))),summary:`Instant payment from ${e.payer.replaceAll("_"," ")} to ${e.payee.replaceAll("_"," ")}`,title:B(l),verbs:P},rules:[],settlement:{name:l,pieces:a,...t?{serviceFee:{bps:t.bps,field:"serviceFeeAmount"}}:{}}}}function xt(e,t,n,r){let o=e.name,a=e.amount.name,l="authorize_reservation",s="capturedAmount",u="reversalUntil",v=["authorize",...["capture","capture_more"],"settle","void","expire","settle_on_expiry",e.correction.port,e.externalReversal.port];if(!De(o,v,e.origin,r))return;let P=U(`${o}_reserve`),w=U(`${o}_capture`),g=U(`${o}_correction`),C=U(`${o}_external_reversal`),D=U(`${o}_reservation_expiry`),I=J=>({amount:"captureAmount",capture:{[s]:"postedAmount"},key:"post",operation:"post",...J?{partialOnly:!0}:{},reservation:l}),Z=()=>({amount:`refs.${s}`,clawbackOf:l,from:e.payee,key:"transfer",operation:"create",to:e.payer}),ee={create:{summary:`Create a ${B(o).toLowerCase()}`,to:"created"},authorize:{from:["created"],moneyEvent:P,moves:[{amount:a,from:e.payer,key:"reservation",operation:"reserve",to:e.payee}],summary:`Reserve the ${a} until ${e.reserveUntilField}`,to:"authorized"},capture:{deadline:{field:e.reserveUntilField},from:["authorized"],moneyEvent:w,moves:[I(!0)],summary:"Post one strict partial capture slice",to:"partially_captured"},capture_more:{deadline:{field:e.reserveUntilField},from:["partially_captured"],moneyEvent:w,moves:[I(!0)],summary:"Post another strict partial capture slice",to:"partially_captured"},settle:{deadline:{field:e.reserveUntilField},from:["authorized","partially_captured"],moneyEvent:w,moves:[{capture:{[s]:"postedAmount"},key:"post",operation:"post",reservation:l}],summary:"Post the full reserved remainder and settle",setsAt:{field:u,offset:e.externalReversal.window.raw},to:"settled"},void:{from:["authorized"],moves:[{key:"void",operation:"void",reason:"Reservation voided before any capture",reservation:l}],summary:"Release an entirely uncaptured reservation",to:"voided"},expire:{due:{field:e.reserveUntilField,rule:D},from:["authorized"],moves:[{key:"void",operation:"void",reason:"Uncaptured reservation expired",reservation:l}],summary:"Release an uncaptured reservation at expiry",to:"expired"},settle_on_expiry:{due:{field:e.reserveUntilField,rule:D},from:["partially_captured"],moves:[{key:"void",operation:"void",reason:"Uncaptured remainder released at expiry",reservation:l}],summary:"Release the uncaptured remainder and settle captured slices",setsAt:{field:u,offset:e.externalReversal.window.raw},to:"settled"},[e.correction.port]:{from:["settled"],moneyEvent:g,moves:[Z()],port:{allowed:t.allowed},summary:"Return the full captured amount on payee correction",to:"corrected"},[e.externalReversal.port]:{captureInput:{externalReference:"externalReference"},deadline:{field:u},from:["settled"],moneyEvent:C,moves:[Z()],port:{allowed:n.allowed,fields:{externalReference:"text"}},summary:"Return the full captured amount on an external reversal",to:"reversed"}},te=[V({amount:`The full ${a}`,fromActor:e.payer,key:P,kind:"hold",toActor:e.payee,trigger:`Reserve ${a} until ${e.reserveUntilField}`}),V({amount:`Each posted slice, never more than the remaining ${a}`,amountDependency:{kind:"bounded_by_reference",reference:P},fromActor:e.payer,key:w,kind:"payout",occurrence:"repeatable",toActor:e.payee,trigger:"Post a capture slice or the final remainder"}),V({amount:"100% of the cumulative captured amount",amountDependency:{bps:1e4,kind:"percent_of_reference",reference:w},fromActor:e.payee,key:g,kind:"refund",toActor:e.payer,trigger:"Apply one full payee correction"}),V({amount:"100% of the cumulative captured amount",amountDependency:{bps:1e4,kind:"percent_of_reference",reference:w},fromActor:e.payee,key:C,kind:"refund",toActor:e.payer,trigger:"Apply one full externally decided reversal"})];return{design:[`${o}: reserve ${a} until ${e.reserveUntilField}; capture in strict partial slices; post the remainder to settle; expiry releases only the uncaptured remainder`,`${o}: correction and external reversal each return the full captured amount once; insufficient payee funds reject the move instead of creating a negative position`],feeLines:[],moneyEvents:te,noun:{actors:{[e.payer]:"payer",[e.payee]:"beneficiary"},desc:"Payer reservation captured by the payee in slices within a fixed window",fields:{[a]:H(`Maximum captured amount in ${e.amount.currency} minor units`),[e.reserveUntilField]:se("Reservation expiry that releases any uncaptured remainder"),[u]:{desc:"Machine-owned external reversal cutoff anchored when settlement completes",type:"date?"}},id:o,summary:`Capture reservation from ${e.payer.replaceAll("_"," ")} to ${e.payee.replaceAll("_"," ")}`,title:B(o),verbs:ee},rules:[{allowedActors:[],detail:`At ${e.reserveUntilField}, the platform releases the uncaptured remainder and preserves any posted slices`,dueDriven:!0,enforcement:"platform",gatesEvent:null,key:D,kind:"deadline",label:`Uncaptured remainder releases on ${e.reserveUntilField}`,tenantTunable:!1},{allowedActors:[...t.allowed],detail:"The payee may return the full captured amount once",dueDriven:!1,enforcement:"tenant_app",gatesEvent:g,key:U(`${o}_${e.correction.port}_gate`),kind:"release_condition",label:"Full correction confirmed through the tenant backend",tenantTunable:!1},{allowedActors:[...n.allowed],detail:`A confirmed external decision may reverse the full captured amount within ${e.externalReversal.window.raw}; timeout moves nothing`,dueDriven:!1,enforcement:"tenant_app",gatesEvent:C,key:U(`${o}_${e.externalReversal.port}_gate`),kind:"release_condition",label:"External reversal confirmed through the tenant backend",tenantTunable:!1}],settlement:{name:o,pieces:[]}}}function Ct(e,t,n){let r=e.name,o=`${r}_capture_entry`,a=`${r}_credit_adjustment`,l=`${r}_debit_adjustment`,s=`${r.replaceAll(/_([a-z])/g,(C,D)=>D.toUpperCase())}Id`,u=U(`${r}_payout`),_=U(`${r}_close`);if(!De(r,["close","calculate","approve","instruct","reconcile",e.payoutAcknowledgement.port],e.origin,n))return;let v={[s]:{match:{"fields.currency":"fields.currency"},statuses:["open"]}},P={desc:"One gross capture entry linked to an open payout batch",fields:{amount:H("Gross captured amount in minor units"),currency:{desc:"ISO 4217 currency shared with the payout batch",type:"currency"},[s]:{desc:"Open batch this capture entry accrues into",type:`ref:${r}`},[e.sourceCaptureReferenceField]:{desc:"Immutable source capture reference",type:"text"}},id:o,summary:"Gross capture lineage entry",title:`${B(r)} Capture Entry`,verbs:{create:{requires:v,summary:"Create a capture lineage entry on an open batch",to:"created"},accrue:{from:["created"],requires:v,summary:"Accrue the capture entry into the open batch",to:"accrued"}}},w=(C,D)=>({desc:`One ${D} adjustment linked to an open payout batch; closed batches stay unchanged`,fields:{amount:H(`${B(D)} adjustment amount in minor units`),currency:{desc:"ISO 4217 currency shared with the payout batch",type:"currency"},adjustmentReference:{desc:"Immutable explicit adjustment reference",type:"text"},[s]:{desc:"Open batch this adjustment applies to",type:`ref:${r}`},[e.externalReversalReferenceField]:{desc:"Optional externally decided reversal reference",type:"text?"},[e.feeReferenceField]:{desc:"Optional fee entry reference",type:"text?"},[e.sourceCaptureReferenceField]:{desc:"Original capture reference that this adjustment corrects",type:"text"}},id:C,summary:`${B(D)} adjustment with capture lineage`,title:`${B(r)} ${B(D)} Adjustment`,verbs:{create:{requires:v,summary:`Create a ${D} adjustment on an open batch`,to:"created"},adjust:{from:["created"],requires:v,summary:`Apply the ${D} adjustment to the open batch`,to:"applied"},correct:{from:["created"],requires:v,summary:"Record a later correction on this open batch instead of changing the closed source batch",to:"applied"}}}),g={create:{summary:`Open a ${B(r).toLowerCase()}`,to:"open"},close:{due:{field:e.closeTriggerField,rule:_},from:["open"],summary:"Freeze the batch and stop all new entries",to:"closed"},calculate:{from:["closed"],signedSum:{amountRef:"netPayable",onNegative:"refuse",onZero:"refuse",sources:[{amountField:"amount",nounId:o,refField:s,sign:"add",statuses:["accrued"],subtotalRef:"grossCaptureAmount"},{amountField:"amount",nounId:a,refField:s,sign:"add",statuses:["applied"],subtotalRef:"creditAdjustmentAmount"},{amountField:"amount",nounId:l,refField:s,sign:"subtract",statuses:["applied"],subtotalRef:"debitAdjustmentAmount"}]},summary:"Prove and freeze the one signed net payable amount",to:"calculated"},approve:{from:["calculated"],summary:"Approve the frozen payable without recomputing it",to:"approved"},instruct:{from:["approved"],moneyEvent:u,payout:{amount:"refs.netPayable",beneficiaryField:e.payoutBeneficiaryReferenceField,beneficiaryPartyField:`${Q(e.payoutDestination)}AccountId`,capture:"payoutId",currencyField:"currency",sourceAccountField:`${Q(e.settlementAccount)}AccountId`,speed:"standard"},summary:"Create one idempotent payout from the frozen net payable",to:"instructed"},[e.payoutAcknowledgement.port]:{captureInput:{acknowledgementReference:"acknowledgementReference"},from:["instructed"],port:{allowed:t.allowed,fields:{acknowledgementReference:"text"}},summary:"Record the tenant's payout acknowledgement in the receipt",to:"acknowledged"},reconcile:{from:["instructed","acknowledged"],requiresSettlement:{capture:"settlementEvidenceId",payoutRef:"payoutId"},summary:"Record durable evidence that the payout settled",to:"reconciled"}};return{design:[`${r}: capture entries plus signed adjustments freeze at ${e.closeTriggerField}; calculate persists gross, credit, debit, and net refs; negative or zero net refuses`,`${r}: instruct creates one payout intent for the frozen refs.netPayable; only matched settlement evidence can reconcile it`],extraNouns:[P,w(a,"credit"),w(l,"debit")],feeLines:[],moneyEvents:[V({amount:"The frozen signed sum of gross capture entries plus credit adjustments minus debit adjustments",fromActor:e.settlementAccount,key:u,kind:"payout",toActor:e.payoutDestination,trigger:"Instruct the approved batch payout exactly once"})],noun:{actors:{[e.payoutDestination]:"beneficiary",[e.settlementAccount]:"payer"},desc:"Immutable batch of capture lineage and signed adjustments that creates one payout",fields:{[e.closeTriggerField]:se("Date the open batch freezes against later entries"),currency:{desc:"ISO 4217 currency shared by the batch and payout instruction",type:"currency"},[e.payoutBeneficiaryReferenceField]:{desc:"Beneficiary ID for the payout instruction",type:"beneficiary"}},id:r,summary:`Payout batch from ${e.settlementAccount.replaceAll("_"," ")} to ${e.payoutDestination.replaceAll("_"," ")}`,title:B(r),verbs:g},rules:[{allowedActors:[],detail:`At ${e.closeTriggerField}, the platform closes the batch and every child reference gate refuses later entries`,dueDriven:!0,enforcement:"platform",gatesEvent:null,key:_,kind:"deadline",label:`Batch freezes on ${e.closeTriggerField}`,tenantTunable:!1}],settlement:{name:r,pieces:[]}}}function Et(e,t,n,r){let o=e.name,a=e.amount.name;if(!De(o,["place_deposit",t.name,n.name],e.origin,r))return;let l=`${o}_hold_1`,s=[V({amount:`The full ${a}`,fromActor:e.payer,key:l,kind:"hold",toActor:e.holder,trigger:`Reserve the ${a} in the ${e.holder.replaceAll("_"," ")}'s favor`})],u={create:{summary:`Create a ${B(o).toLowerCase()}`,to:"created"},place_deposit:{from:["created"],moves:[{key:"reservation",operation:"reserve",amount:a,from:e.payer,to:e.holder}],moneyEvent:l,summary:`Reserve the ${a} against the ${e.payer.replaceAll("_"," ")}'s account`,to:"held"},[t.name]:{from:["held"],moves:[{key:"post",operation:"post",reservation:"place_deposit_reservation"}],summary:`Claim the deposit for the ${e.holder.replaceAll("_"," ")} through ${t.name}`,to:"claimed"},[n.name]:{from:["held"],summary:`Return the deposit to the ${e.payer.replaceAll("_"," ")} through ${n.name}`,to:"returned",moves:[{key:"void",operation:"void",reason:"Deposit returned in full",reservation:"place_deposit_reservation"}]}},_=(v,P)=>({allowedActors:[...v.allowed],detail:`${v.allowed.map(B).join(" or ")} decides through the tenant backend`,dueDriven:!1,enforcement:"tenant_app",gatesEvent:null,key:U(`${o}_${v.name}_gate`),kind:"release_condition",label:`${P} decided through ${v.name}`,tenantTunable:!1});return{design:[`${o}: ${a} held as a reservation on the ${e.payer.replaceAll("_"," ")}'s account; claimed whole through ${t.name} or returned whole through ${n.name}`],feeLines:[],moneyEvents:s,noun:{actors:{[e.payer]:"payer",[e.holder]:"beneficiary"},desc:`Deposit: the ${a} is reserved against the ${e.payer.replaceAll("_"," ")}'s account in the ${e.holder.replaceAll("_"," ")}'s favor, then claimed or returned in full`,fields:{[a]:H(`The deposit amount in ${e.amount.currency} minor units, reserved in full and fully accounted on claim or return`)},id:o,summary:`Refundable deposit from ${e.payer.replaceAll("_"," ")} held for ${e.holder.replaceAll("_"," ")}`,title:B(o),verbs:u},rules:[_(t,"Claim"),_(n,"Return")],settlement:{name:o,pieces:[]}}}function en(e){let t=Math.floor(Number(Ze)/e),n=Array.from({length:e},()=>t);return n[0]=Number(Ze)-t*(e-1),n}function St(e){let t=e.name,n=`${t}_commitment`,r=`${Q(t)}Id`,o=U(`${t}_commit`),a=U(`${t}_cancel`),l=U(`${t}_collect`),s=U(`${t}_refund`),u=U(`${t}_close`),_=w=>[{check:{amountField:"amount",kind:w,targetField:e.target.name},nounId:n,over:"children",refField:r,statuses:["committed"]}],v=w=>({[r]:{bind:{currency:"fields.currency",[`${Q(e.beneficiary)}AccountId`]:`fields.${Q(e.beneficiary)}AccountId`},statuses:w}}),P=w=>({[r]:{match:{"fields.currency":"fields.currency",[`fields.${Q(e.beneficiary)}AccountId`]:`fields.${Q(e.beneficiary)}AccountId`},statuses:w}});return{design:[`${t}: reuses the catalog funding round and commitment mechanism; the parent lock caps committed rows by target and contributor count`,`${t}: the stored close anchor chooses threshold activation or failure; each commitment then moves whole from its own custody`],extraNouns:[{actors:{[e.beneficiary]:"beneficiary",[e.contributor]:"payer"},desc:`One whole commitment linked to ${t}`,escrow:!0,fields:{amount:H("One whole commitment amount"),currency:{desc:"Currency derived from the funding round",type:"currency"},[r]:{desc:`The exact ${t}`,type:`ref:${t}`}},id:n,summary:`Whole commitment to ${t}`,title:`${B(t)} Commitment`,verbs:{create:{moneyEvent:o,moves:[{amount:"amount",from:e.contributor,key:"commit",operation:"create",to:"escrow"}],requires:v(["open"]),requiresExposure:[{amountField:"amount",anchorField:r,capField:e.target.name,capOnAnchor:!0,childNounId:n,statuses:["committed"]}],summary:"Store one whole commitment without exceeding the round target",to:"committed"},cancel:{from:["committed"],moneyEvent:a,moves:[{amount:"amount",from:"escrow",key:"cancel",operation:"create",to:e.contributor}],requires:P(["open"]),summary:"Cancel one commitment while the round is open",to:"cancelled"},collect:{from:["committed"],moneyEvent:l,moves:[{amount:"amount",from:"escrow",key:"collect",operation:"create",to:e.beneficiary}],requires:P(["active"]),summary:"Collect one successful commitment whole",to:"collected"},refund:{from:["committed"],moneyEvent:s,moves:[{amount:"amount",from:"escrow",key:"refund",operation:"create",to:e.contributor}],requires:P(["failed"]),summary:"Refund one failed-round commitment whole",to:"refunded"}}}],generatedPrefixNounIds:[n],feeLines:[],moneyEvents:[V({amount:"One stored commitment",fromActor:e.contributor,key:o,kind:"charge",occurrence:"repeatable",toActor:"escrow",trigger:"Create one target-capped commitment"}),V({amount:"One stored commitment whole",fromActor:"escrow",key:a,kind:"refund",occurrence:"repeatable",toActor:e.contributor,trigger:"Cancel before close"}),V({amount:"One stored commitment whole",fromActor:"escrow",key:l,kind:"payout",occurrence:"repeatable",toActor:e.beneficiary,trigger:"Collect after threshold close"}),V({amount:"One stored commitment whole",fromActor:"escrow",key:s,kind:"refund",occurrence:"repeatable",toActor:e.contributor,trigger:"Refund after failed close"})],noun:{actors:{[e.beneficiary]:"beneficiary"},aggregateInvariants:[{childField:"amount",childNounId:n,childRefField:r,childStatuses:["committed"],parentField:e.target.name},{count:!0,childNounId:n,childRefField:r,childStatuses:["committed"],parentField:"maxContributors"}],desc:"All-or-nothing aggregate funding threshold",fields:{currency:{desc:`Currency fixed to ${e.target.currency}`,type:"currency"},[e.target.name]:H(`Funding target in ${e.target.currency} minor units`),[e.closeByField]:se("Stored close anchor"),maxContributors:{desc:`Exactly ${e.maxContributors} admitted contributors`,type:`const:${e.maxContributors}`}},id:t,summary:`Threshold funding round for ${e.beneficiary.replaceAll("_"," ")}`,title:B(t),verbs:{create:{summary:"Open the funding round",to:"open"},activate:{due:{field:e.closeByField,rule:u},from:["open"],requiresAggregate:_("sum_at_least"),summary:"Activate when commitments meet the target",to:"active"},fail:{due:{field:e.closeByField,rule:u},from:["open"],requiresAggregate:_("sum_below"),summary:"Fail when commitments remain below target",to:"failed"},close:{from:["active"],requiresAggregate:[{check:{kind:"all_in"},nounId:n,over:"children",refField:r,statuses:["cancelled","collected"]}],summary:"Settle after every admitted row is collected or was cancelled before activation",to:"settled"}}},rules:[{allowedActors:[],detail:"The stored close anchor compares committed rows with the target",dueDriven:!0,enforcement:"platform",gatesEvent:null,key:u,kind:"deadline",label:"Round closes against its stored threshold",tenantTunable:!1}],settlement:{name:t,pieces:[]}}}function Pt(e,t){let n=e.name,r=`${n}_entitlement`,o=`${Q(n)}Id`,a=U(`${n}_payout`),l=s=>({[o]:{bind:{currency:"fields.currency",[`${Q(e.source)}AccountId`]:`fields.${Q(e.source)}AccountId`},statuses:s}});return{design:[`${n}: reuses the catalog largest-remainder distribution; the evidence port freezes the claimant set before any payout`],extraNouns:[{actors:{[e.recipient]:"beneficiary",[e.source]:"payer"},desc:`One frozen weighted entitlement in ${n}`,fields:{currency:{desc:"Currency derived from the distribution",type:"currency"},[o]:{desc:`The exact ${n}`,type:`ref:${n}`},[e.weight.name]:H("Stored non-negative entitlement weight")},id:r,summary:`Frozen entitlement in ${n}`,title:`${B(n)} Entitlement`,verbs:{create:{requires:l(["open"]),summary:"Record one entitlement before snapshot",to:"recorded"},payout:{distribute:{amountRef:"payoutShare",onZero:"skip_steps",pool:{from:"parent",path:`fields.${e.amount.name}`},refField:o,statuses:["recorded","paid"],weightField:e.weight.name},from:["recorded"],moneyEvent:a,moves:[{amount:"refs.payoutShare",from:e.source,key:"payout",operation:"create",to:e.recipient}],requires:{[o]:{match:{"fields.currency":"fields.currency",[`fields.${Q(e.source)}AccountId`]:`fields.${Q(e.source)}AccountId`},statuses:["snapshotted"]}},summary:"Pay the deterministic largest-remainder share once",to:"paid"}}}],generatedPrefixNounIds:[r],feeLines:[],moneyEvents:[V({amount:"A deterministic largest-remainder share of the stored pool",fromActor:e.source,key:a,kind:"payout",occurrence:"repeatable",toActor:e.recipient,trigger:"Pay one frozen entitlement"})],noun:{actors:{[e.source]:"payer"},aggregateInvariants:[{count:!0,childNounId:r,childRefField:o,childStatuses:["recorded","paid"],parentField:"maxRecipients"}],desc:"Evidence-frozen weighted distribution",fields:{currency:{desc:`Currency fixed to ${e.amount.currency}`,type:"currency"},[e.amount.name]:H(`Distribution pool in ${e.amount.currency} minor units`),[e.recordAtField]:se("Stored record date"),maxRecipients:{desc:`Exactly ${e.maxRecipients} frozen entitlement rows`,type:`const:${e.maxRecipients}`}},id:n,summary:"Frozen largest-remainder distribution",title:B(n),verbs:{create:{summary:"Open entitlement recording",to:"open"},[e.snapshot.port]:{captureInput:{snapshotEvidenceReference:"evidenceReference"},from:["open"],port:{allowed:t.allowed,fields:{evidenceReference:"text"}},summary:"Freeze the entitlement set from stored evidence",to:"snapshotted"}}},rules:[],settlement:{name:n,pieces:[]}}}function It(e){let t=e.name,n=`${t}_draw`,r=`${Q(t)}Id`,o=`${Q(e.obligation.settlement)}Id`,a=U(`${t}_draw`),l=U(`${t}_expiry`),s=e.availabilityPolicy==="revolving"?["drawn"]:["drawn","resolved"];return{design:[`${t}: owns reusable draw capacity only; ${e.obligation.settlement} remains the sole repayment and delinquency owner`],extraNouns:[{actors:{[e.drawDestination]:"beneficiary",[e.lender]:"payer"},desc:`One capacity-capped draw linked to ${e.obligation.settlement}`,fields:{amount:H("One draw amount"),currency:{desc:"Currency derived from the facility",type:"currency"},[r]:{desc:`The exact ${t}`,type:`ref:${t}`},[o]:{desc:"The sole repayment obligation",type:`ref:${e.obligation.settlement}`}},id:n,summary:`Draw from ${t}`,title:`${B(t)} Draw`,verbs:{create:{moneyEvent:a,moves:[{amount:"amount",from:e.lender,key:"draw",operation:"create",to:e.drawDestination}],requires:{[r]:{bind:{currency:"fields.currency",[`${Q(e.drawDestination)}AccountId`]:`fields.${Q(e.drawDestination)}AccountId`,[`${Q(e.lender)}AccountId`]:`fields.${Q(e.lender)}AccountId`},statuses:["active"]},[o]:{statuses:["active"],unique:!0}},requiresExposure:[{amountField:"amount",anchorField:r,capField:e.limit.name,capOnAnchor:!0,childNounId:n,statuses:s}],summary:"Create one draw under the locked facility capacity",to:"drawn"},resolve:{from:["drawn"],requires:{[o]:["repaid","written_off"]},summary:"Release revolving capacity only after the linked obligation resolves",to:"resolved"}}}],generatedPrefixNounIds:[n],feeLines:[],moneyEvents:[V({amount:"One draw under the stored facility limit",fromActor:e.lender,key:a,kind:"payout",occurrence:"repeatable",toActor:e.drawDestination,trigger:"Admit one linked draw"})],noun:{actors:{[e.borrower]:"party",[e.drawDestination]:"beneficiary",[e.lender]:"payer"},desc:"Reusable capacity with repayment delegated to one scheduled obligation",fields:{currency:{desc:`Currency fixed to ${e.limit.currency}`,type:"currency"},[e.limit.name]:H(`Facility limit in ${e.limit.currency} minor units`),[e.expiresAtField]:se("Stored draw expiry")},id:t,summary:`Draw capacity for ${e.borrower.replaceAll("_"," ")}`,title:B(t),verbs:{create:{summary:"Open the facility",to:"active"},freeze:{due:{field:e.expiresAtField,rule:l},from:["active"],summary:"Freeze new draws at expiry",to:"frozen"},close:{from:["active","frozen"],requiresAggregate:[{check:{kind:"all_in"},nounId:n,over:"children",refField:r,statuses:["resolved"]}],summary:"Close only when every admitted draw resolved",to:"closed"}}},rules:[{allowedActors:[],detail:"The stored expiry freezes new draws without changing repayment state",dueDriven:!0,enforcement:"platform",gatesEvent:null,key:l,kind:"deadline",label:"Facility freezes at expiry",tenantTunable:!1}],settlement:{name:t,pieces:[]}}}function Tt(e,t){let n=e.name,r=`${n}_approved_amount`,o=`${Q(n)}Id`,a=U(`${n}_payout`),l=`${Q(e.source)}AccountId`,s=`${Q(e.destination)}AccountId`,u={[o]:{match:{"fields.currency":"fields.currency",[`fields.${s}`]:`fields.${s}`,[`fields.${l}`]:`fields.${l}`},statuses:["submitted"]}};return{design:[`${n}: a stored external decision may approve one amount under the cap; recovery requires a separate transfer`],extraNouns:[{actors:{[e.destination]:"beneficiary",[e.source]:"payer"},desc:`One evidence-gated amount under ${n}`,fields:{amount:H("Approved amount under the parent cap"),currency:{desc:"Currency derived from the parent cap",type:"currency"},[o]:{desc:`The exact ${n}`,type:`ref:${n}`}},id:r,summary:`Approved amount under ${n}`,title:`${B(n)} Approved Amount`,verbs:{create:{requires:{[o]:{bind:{currency:"fields.currency",[s]:`fields.${s}`,[l]:`fields.${l}`},statuses:["submitted"],unique:!0}},summary:"Create one candidate amount under the parent",to:"created"},approve:{captureInput:{decisionEvidenceReference:"evidenceReference"},from:["created"],port:{allowed:t.allowed,fields:{evidenceReference:"text"}},requires:u,requiresExposure:[{amountField:"amount",anchorField:o,capField:e.cap.name,capOnAnchor:!0,childNounId:r,statuses:["approved","paid"]}],summary:"Store one externally approved amount under the cap",to:"approved"},pay:{from:["approved"],moneyEvent:a,moves:[{amount:"amount",from:e.source,key:"payout",operation:"create",to:e.destination}],requires:u,summary:"Pay the stored approved amount once",to:"paid"}}}],generatedPrefixNounIds:[r],feeLines:[],moneyEvents:[V({amount:"The stored approved amount under the cap",fromActor:e.source,key:a,kind:"payout",occurrence:"repeatable",toActor:e.destination,trigger:"Pay one approved amount"})],noun:{actors:{[e.destination]:"beneficiary",[e.source]:"payer"},desc:"Capped disbursement controlled by stored external evidence",fields:{currency:{desc:`Currency fixed to ${e.cap.currency}`,type:"currency"},[e.cap.name]:H(`Disbursement cap in ${e.cap.currency} minor units`)},id:n,summary:`Capped disbursement to ${e.destination.replaceAll("_"," ")}`,title:B(n),verbs:{create:{summary:"Submit the capped disbursement",to:"submitted"},deny:{captureInput:{decisionEvidenceReference:"evidenceReference"},from:["submitted"],port:{allowed:t.allowed,fields:{evidenceReference:"text"}},requiresAggregate:[{check:{kind:"all_in"},nounId:r,over:"children",refField:o,statuses:["created"]}],summary:"Record a denial without moving money",to:"denied"}}},rules:[],settlement:{name:n,pieces:[]}}}function Ft(e){let t=e.name,n=`${Q(t)}Id`,r=U(`${t}_contribution`),o=U(`${t}_guarantee_contribution`),a=U(`${t}_payout`),l=[...new Set([...e.members,...e.payoutOrder,...e.guarantor?[e.guarantor]:[]])],s=Object.fromEntries(l.map(P=>{let w=`${Q(P)}AccountId`;return[w,`fields.${w}`]})),u=e.members.map(P=>`${t}_${P}_contribution`),_=e.members.map((P,w)=>{let g=u[w],C={create:{requires:{[n]:{bind:{currency:"fields.currency",...s,[e.schedule.firstDueField]:`fields.${e.schedule.firstDueField}`,[e.contribution.name]:`fields.${e.contribution.name}`},statuses:["forming"],unique:!0}},summary:`Create the fixed contribution row for ${P.replaceAll("_"," ")}`,to:"cycle_1_due"}};for(let D=0;D<e.schedule.count;D+=1){let I=D+1,Z=`cycle_${I}_due`,ee=`cycle_${I}_defaulted`,te=`cycle_${I}_funded`,J=`cycle_${I}_guaranteed`,h=I===e.schedule.count?"final_paid":`cycle_${I+1}_due`,T=U(`${t}_cycle_${I}_due`),q=e.contribution.name,A=e.contribution.name,R={field:e.schedule.firstDueField,rule:T,...Ee(e.schedule,D)};C[`contribute_cycle_${I}`]={due:R,from:[Z],moneyEvent:r,moves:[{amount:q,from:P,key:"contribution",operation:"create",to:"escrow"}],requires:{[n]:[`active_cycle_${I}`]},summary:`Fund ${P.replaceAll("_"," ")}'s cycle ${I} contribution`,to:te},C[`mark_default_cycle_${I}`]={due:R,from:[Z],requires:{[n]:[`active_cycle_${I}`]},summary:`Mark the stored cycle ${I} due condition`,to:ee},e.guarantor&&(C[`guarantee_cycle_${I}`]={from:[ee],moneyEvent:o,moves:[{amount:A,from:e.guarantor,key:"guarantee",operation:"create",to:"escrow"}],requires:{[n]:[`active_cycle_${I}`]},summary:`Fund the defaulted cycle ${I} amount before payout`,to:J}),C[`pay_cycle_${I}`]={from:[te],moneyEvent:a,moves:[{amount:q,from:"escrow",key:"payout",operation:"create",to:e.payoutOrder[D]}],requires:{[n]:[`cycle_${I}_ready`]},summary:`Pay this member's stored contribution into cycle ${I}'s shared pot recipient`,to:h},e.guarantor&&(C[`pay_guaranteed_cycle_${I}`]={from:[J],moneyEvent:a,moves:[{amount:A,from:"escrow",key:"payout",operation:"create",to:e.payoutOrder[D]}],requires:{[n]:[`cycle_${I}_ready`]},summary:`Pay the funded default into cycle ${I}'s stored recipient`,to:h})}return C.close={from:["final_paid"],requiresDrainedAccount:{path:"refs.escrowAccountId"},summary:"Complete after the final payout drains this member custody",to:"completed"},{actors:Object.fromEntries([[P,"payer"],...e.guarantor?[[e.guarantor,"payer"]]:[],...e.payoutOrder.map(D=>[D,"beneficiary"])]),desc:`Fixed contribution row for ${P.replaceAll("_"," ")}`,escrow:!0,fields:{[e.contribution.name]:H("Exact contribution amount shared by every cycle"),currency:{desc:"Currency derived from the pool",type:"currency"},[e.schedule.firstDueField]:se("First due anchor derived from the pool"),[n]:{desc:`The exact ${t}`,type:`ref:${t}`}},id:g,summary:`${P.replaceAll("_"," ")} contribution row`,title:`${B(t)} ${B(P)} Contribution`,verbs:C}}),v={create:{summary:"Create the fixed roster before activation",to:"forming"},cancel:{from:["forming"],summary:"Cancel before activation without moving money",to:"cancelled"},activate:{from:["forming"],requiresAggregate:u.map(P=>({check:{kind:"count_equals_field",field:"one"},nounId:P,over:"children",refField:n,statuses:["cycle_1_due"]})),summary:"Activate only after every fixed member row exists once",to:"active_cycle_1"}};for(let P=0;P<e.schedule.count;P+=1){let w=P+1;v[`ready_cycle_${w}`]={from:[`active_cycle_${w}`],requiresAggregate:u.map(g=>({check:{kind:"all_in"},nounId:g,over:"children",refField:n,statuses:[`cycle_${w}_funded`,...e.guarantor?[`cycle_${w}_guaranteed`]:[]]})),summary:`Lock cycle ${w} only after every member row is funded or guaranteed`,to:`cycle_${w}_ready`},v[`advance_cycle_${w}`]={from:[`cycle_${w}_ready`],requiresAggregate:u.map(g=>({check:{kind:"all_in"},nounId:g,over:"children",refField:n,statuses:[w===e.schedule.count?"completed":`cycle_${w+1}_due`]})),summary:w===e.schedule.count?"Complete after the final shared pot pays":`Advance after every cycle ${w} contribution pays`,to:w===e.schedule.count?"completed":`active_cycle_${w+1}`}}return{design:[`${t}: fixed roster and stored payout order; one member-specific row per member avoids tuple identity and keeps each cycle idempotent`],extraNouns:_,generatedPrefixNounIds:u,feeLines:[],moneyEvents:[V({amount:"One exact member contribution",fromActor:e.members[0],key:r,kind:"charge",occurrence:"repeatable",toActor:"escrow",trigger:"Fund one member and cycle"}),...e.guarantor?[V({amount:"One exact defaulted contribution",fromActor:e.guarantor,key:o,kind:"charge",occurrence:"repeatable",toActor:"escrow",trigger:"Fund one defaulted member and cycle"})]:[],V({amount:"One exact member contribution from the cycle pot",fromActor:"escrow",key:a,kind:"payout",occurrence:"repeatable",toActor:e.payoutOrder[0],trigger:"Pay the stored cycle recipient"})],noun:{actors:Object.fromEntries([...e.members.map(P=>[P,"party"]),...e.guarantor?[[e.guarantor,"payer"]]:[]]),desc:"Fixed rotating contribution and payout order",fields:{currency:{desc:`Currency fixed to ${e.contribution.currency}`,type:"currency"},[e.contribution.name]:H(`Exact contribution in ${e.contribution.currency} minor units`),[e.schedule.firstDueField]:se("Stored first contribution due date"),one:{desc:"Exact fixed member-row count",type:"const:1"}},id:t,summary:`${e.members.length}-member rotating pool`,title:B(t),verbs:v},rules:Array.from({length:e.schedule.count},(P,w)=>({allowedActors:[],detail:`Cycle ${w+1} default follows its stored due condition`,dueDriven:!0,enforcement:"platform",gatesEvent:null,key:U(`${t}_cycle_${w+1}_due`),kind:"deadline",label:`Cycle ${w+1} due condition`,tenantTunable:!1})),settlement:{name:t,pieces:[]}}}function Ee(e,t){return t===0?{}:{offset:`P${e.every.days*t}D`}}function Rt(e,t,n){let r=e.name,o=e.amount.name,a=`${r.replaceAll(/_([a-z])/g,(T,q)=>q.toUpperCase())}Id`,l=en(e.schedule.count),s=l.map((T,q)=>`installment${q+1}Amount`),u=l.map((T,q)=>`${r}_installment_${q+1}_payment`),_="active",v=T=>`installment_${T+1}_delinquent`,P=l.map((T,q)=>v(q)),w=[_,...P],g=U(`${r}_repayment`),C=U(`${r}_refund`),D=U(`${r}_advance`),I={currency:{desc:`Currency fixed to ${e.amount.currency}`,type:"currency"},[o]:H(`The principal in ${e.amount.currency} minor units; the stored installment anchors partition it exactly`),[e.schedule.firstDueField]:se(`Due date of the first installment; later anchors use fixed offsets of ${e.schedule.every.raw}`)};for(let[T,q]of s.entries())I[q]=H(`Stored amount for installment ${T+1} of ${e.schedule.count}${T===0?" (carries the integer-division remainder)":""}`),I[`installment${T+1}DelinquentAfter`]=ut(`Machine-set marker proving installment ${T+1} reached its stored due date while unpaid`);let Z=u.map((T,q)=>({childField:"amount",childNounId:T,childRefField:a,childStatuses:["paid"],parentField:s[q]})),ee={create:{summary:`Create a ${B(r).toLowerCase()} obligation`,to:"draft"},approve:{from:["draft"],summary:"Approve the immutable principal partition and stored anchors",to:e.advanceTo?"approved":_},...e.advanceTo?{advance:{from:["approved"],moneyEvent:D,moves:[{amount:o,from:e.payee,key:"advance",operation:"create",to:e.advanceTo}],summary:`Advance the principal to the ${e.advanceTo.replaceAll("_"," ")}; the internal ledger receipt is the confirmation`,to:_}}:{},write_off:{from:["draft",...e.advanceTo?["approved"]:[],...w],summary:"Write off the remaining exposure without moving money",to:"written_off"}},te=[];for(let[T,q]of u.entries()){let A=T+1,R=U(`${r}_installment_${A}_due`),N={field:e.schedule.firstDueField,rule:R,...Ee(e.schedule,T)},M=oe=>[{check:{amountField:"amount",kind:oe,targetField:s[T]},nounId:q,over:"children",refField:a,statuses:["paid"]}];ee[`mark_installment_${A}_delinquent`]={due:N,from:w.filter(oe=>oe!==v(T)),requiresAggregate:M("sum_below"),setsAt:{field:`installment${A}DelinquentAfter`,marker:!0,offset:"PT1S"},summary:`Mark installment ${A} delinquent only when its due anchor is unmet`,to:v(T)},ee[`collect_installment_${A}`]={due:N,from:P,requiresAggregate:M("sum_exactly"),summary:`Close delinquent installment ${A} after linked payments reach its stored amount`,to:_},te.push({allowedActors:[],detail:`At stored anchor ${A}, the platform compares paid child rows with ${s[T]} and chooses paid or delinquent`,dueDriven:!0,enforcement:"platform",gatesEvent:null,key:R,kind:"deadline",label:`Installment ${A} resolves from its stored due condition`,tenantTunable:!1})}let J=U(`${r}_completion_due`);ee.complete={due:{field:e.schedule.firstDueField,rule:J,...Ee(e.schedule,l.length-1)},from:w,requiresAggregate:u.map((T,q)=>({check:{amountField:"amount",kind:"sum_exactly",targetField:s[q]},nounId:T,over:"children",refField:a,statuses:["paid"]})),summary:"Close the obligation only after every stored anchor is paid exactly",to:"repaid"},te.push({allowedActors:[],detail:"After the final stored anchor, the platform closes only when every anchor is paid exactly",dueDriven:!0,enforcement:"platform",gatesEvent:null,key:J,kind:"deadline",label:"Obligation completion follows exact aggregate repayment",tenantTunable:!1});let h=T=>{let q=T+1,A=u[T],R=w,N=`${e.payer.replaceAll(/_([a-z])/g,(pe,me)=>me.toUpperCase())}AccountId`,M=`${e.payee.replaceAll(/_([a-z])/g,(pe,me)=>me.toUpperCase())}AccountId`,oe={[a]:{bind:{currency:"fields.currency",[N]:`fields.${N}`,[M]:`fields.${M}`},statuses:R}},de={[a]:{match:{"fields.currency":"fields.currency",[`fields.${N}`]:`fields.${N}`,[`fields.${M}`]:`fields.${M}`},statuses:R}};return{actors:{[e.payee]:"beneficiary",[e.payer]:"payer"},desc:`One partial or full payment bound to installment ${q} of ${r}; the operation name fixes the anchor and ${a} fixes the obligation`,fields:{amount:H(`Positive payment amount capped with its paid siblings at ${s[T]}`),currency:{desc:"ISO 4217 currency derived from the obligation",type:"currency"},[a]:{desc:`The exact ${r.replaceAll("_"," ")} this payment belongs to`,type:`ref:${r}`}},id:A,summary:`Anchor-bound payment for installment ${q}`,title:`${B(r)} Installment ${q} Payment`,verbs:{create:{requires:oe,summary:`Create a payment record for installment ${q}`,to:"created"},repay:{...t&&n?{captureInput:{mandateEvidenceReference:"evidenceReference"},port:{allowed:n.allowed,fields:{evidenceReference:"text"}}}:{},from:["created"],moneyEvent:g,moves:[{amount:"amount",from:e.payer,key:"repayment",operation:"create",to:e.payee}],requires:de,requiresExposure:[{amountField:"amount",anchorField:a,capField:s[T],capOnAnchor:!0,childNounId:A,statuses:["paid"]}],summary:`Pay a partial or full amount against installment ${q}`,to:"paid"},refund:{from:["paid"],moneyEvent:C,moves:[{amount:"amount",from:e.payee,key:"refund",operation:"create",to:e.payer}],requires:de,summary:`Refund this one stored installment ${q} payment whole`,to:"refunded"}}}};return{design:[`${r}: existing scheduled mechanism in obligation mode; principal partitions into ${e.schedule.count} stored anchors; each payment operation names one anchor and one obligation`,`${r}: partial and early payments serialize under per-anchor aggregate caps; each refund reverses one paid row whole; rescheduling is refused by the checker`,`${r}: due-only delinquency and write-off change state without money; ${e.advanceTo?"advance is an internal ledger movement with no provider claim":"no advance is emitted"}`,...t?[`${t.name}: explicit collection attempts reuse ${r}'s anchor-bound repayment verbs; mandate evidence is captured per attempt; failures remain receipted failures and delinquency stays on ${r}`]:[]],extraNouns:u.map((T,q)=>h(q)),generatedPrefixNounIds:u,feeLines:[],moneyEvents:[...e.advanceTo?[V({amount:`The full ${o}`,fromActor:e.payee,key:D,kind:"payout",toActor:e.advanceTo,trigger:"Advance the approved principal once"})]:[],V({amount:"A positive amount capped by its stored installment anchor",fromActor:e.payer,key:g,kind:"installment",occurrence:"repeatable",toActor:e.payee,trigger:"Pay one anchor-bound partial or full installment amount"}),V({amount:"Exactly one stored paid installment payment",fromActor:e.payee,key:C,kind:"refund",occurrence:"repeatable",toActor:e.payer,trigger:"Refund one linked paid installment payment whole"})],noun:{actors:{...e.advanceTo?{[e.advanceTo]:"beneficiary"}:{},[e.payee]:"beneficiary",[e.payer]:"payer",[e.debtor]:"party"},aggregateInvariants:Z,desc:`Installment obligation for ${e.debtor.replaceAll("_"," ")}; ${e.payer.replaceAll("_"," ")} pays ${e.payee.replaceAll("_"," ")} against exact stored anchors`,fields:I,id:r,...ve(ge(o,s)),summary:`${e.schedule.count}-anchor obligation for ${e.debtor.replaceAll("_"," ")}`,title:B(r),verbs:ee},rules:te,settlement:{name:r,pieces:[]}}}function Dt(e){let t=e.name,n=e.amount.name,{schedule:r}=e,o=`${t}_schedule`,a=en(r.count),l={[n]:H(`The total scheduled amount in ${e.amount.currency} minor units; the installment fields below partition it exactly`),[r.firstDueField]:se(`Due date of the first installment; installment k falls ${r.every.raw} after its predecessor`)},s=a.map((g,C)=>{let D=`installment${C+1}Amount`;return l[D]=H(`Installment ${C+1} of ${r.count}${C===0?" (carries the integer-division remainder)":""}: about ${W(a[C])} of ${n}, collected on its own stored-date anchor`),D}),u=a.map((g,C)=>`pay_installment_${C+1}`),_=he(u,"active","settled","collecting"),v=`${t}_installments`,P=[V({amount:`The ${n}, partitioned into ${r.count} installments`,fromActor:e.payer,key:v,kind:"installment",occurrence:"repeatable",toActor:e.payee,trigger:`Collect each of the ${r.count} installments on its stored due date`})],w={create:{summary:`Create a ${B(t).toLowerCase()} plan`,to:"active"}};for(let[g,C]of s.entries())w[u[g]]={due:{field:r.firstDueField,rule:o,...Ee(r,g)},from:[_[g]?.from],moneyEvent:v,moves:[{key:"transfer",operation:"create",amount:C,from:e.payer,to:e.payee}],summary:`Collect installment ${g+1} of ${r.count}`,to:_[g]?.to};return{design:[`${t}: ${r.count} installments every ${r.every.raw} from ${r.firstDueField}; finite by construction, one idempotent anchor per installment`],feeLines:[],moneyEvents:P,noun:{actors:{[e.payer]:"payer",[e.payee]:"beneficiary"},desc:`Scheduled payment: the ${e.payer.replaceAll("_"," ")} pays ${n} to the ${e.payee.replaceAll("_"," ")} in ${r.count} installments, one every ${r.every.raw}`,fields:l,id:t,...ve(ge(n,s)),summary:`${r.count}-installment schedule from ${e.payer.replaceAll("_"," ")} to ${e.payee.replaceAll("_"," ")}`,title:B(t),verbs:w},rules:[{allowedActors:[],detail:`Each of the ${r.count} installments is collected once from its stored due date`,dueDriven:!0,enforcement:"platform",gatesEvent:null,key:o,kind:"deadline",label:"Installments collected on their stored due dates",tenantTunable:!1}],settlement:{name:t,pieces:[]}}}function Nt(e,t){return e.source.kind==="carve"?Lt(e,e.source.settlement,t):Ot(e,e.source.schedule)}function Lt(e,t,n){let r=e.name,o=e.amount.name,a=e.feeBps>0,l=e.advanced.replaceAll("_"," "),s=e.funder.replaceAll("_"," "),u=t.replaceAll("_"," "),v=[{field:"carveHoldId",statuses:["funded"],target:t},...n.map((w,g)=>({field:`carveRecourse${g+1}Id`,statuses:["active"],target:w.name}))],P={[o]:H(`The advanced amount in ${e.amount.currency} minor units, disbursed to the ${l} up front`),...Object.fromEntries(v.map(w=>[w.field,{desc:`The ${w.target.replaceAll("_"," ")} bound to this advance`,type:`ref:${w.target}`}])),...a?{feeAmount:H(`${W(e.feeBps)} of ${o}, the funder's discount owed on top of the advance`),repayableAmount:H(`${o} + feeAmount: what the ${u} release owes the ${s}`)}:{}};return{design:[`${r}: ${o} advanced to the ${e.advanced} up front and repaid by carving the ${t} release${a?`; repayableAmount = ${o} + ${W(e.feeBps)} fee`:""}`],feeLines:a?[{label:`${B(e.funder)} discount`,on:`each ${r.replaceAll("_"," ")}`,structure:`${W(e.feeBps)} of the ${o}, owed on top out of the ${u} release`}]:[],moneyEvents:[V({amount:`The full ${o}`,fromActor:e.funder,key:`${r}_disburse`,kind:"payout",toActor:e.advanced,trigger:`Disburse the advance to the ${l}`})],noun:{actors:{[e.advanced]:"beneficiary",[e.funder]:"payer"},desc:`Advance: the ${s} disburses ${o} to the ${l} and is repaid out of the ${u} release, which pays the ${s} in the ${l}'s place${a?", plus the funder's discount":""}`,fields:P,id:r,...ve(a?ge("repayableAmount",[o,"feeAmount"]):[]),summary:`Advance to the ${l} repaid by carving the ${u} release`,title:B(r),verbs:{create:{summary:`Create a ${B(r).toLowerCase()}`,to:"created"},disburse:{from:["created"],moneyEvent:`${r}_disburse`,moves:[{key:"transfer",operation:"create",amount:o,from:e.funder,to:e.advanced}],requires:Object.fromEntries(v.map(w=>[w.field,{match:{[`fields.${o}`]:`fields.${o}`,"fields.currency":"fields.currency"},statuses:w.statuses}])),summary:`Disburse the ${o} to the ${l}`,to:"advanced"},settle:{from:["advanced"],summary:`Close the advance once the ${u} has released to the ${s}`,to:"repaid"}}},rules:[{allowedActors:[],detail:`The ${u} releases the ${l}'s whole share to the ${s} instead of to the ${l}; the advance is repaid out of that release and never out of new money`,dueDriven:!1,enforcement:"platform",gatesEvent:null,key:`${r}_carve`,kind:"release_condition",label:`Repaid by carving the ${u} release`,tenantTunable:!1}],settlement:{name:r,pieces:[]}}}function Ot(e,t){let n=e.name,r=e.amount.name,o=`${n}_schedule`,a=en(t.count),l=e.feeBps>0,s=l?"repayableAmount":r,u={[r]:H(`The advanced amount in ${e.amount.currency} minor units, disbursed to the ${e.advanced.replaceAll("_"," ")} up front`),...l?{feeAmount:H(`${W(e.feeBps)} of ${r}, the funder's discount repaid on top of the advance`),repayableAmount:H(`${r} + feeAmount: the total the repayment fields below partition exactly`)}:{},[t.firstDueField]:se(`Due date of the first repayment; repayment k falls ${t.every.raw} after its predecessor`)},_=a.map((D,I)=>{let Z=`repayment${I+1}Amount`;return u[Z]=H(`Repayment ${I+1} of ${t.count}${I===0?" (carries the integer-division remainder)":""}: about ${W(a[I])} of ${s}, collected on its own stored-date anchor`),Z}),v=a.map((D,I)=>`collect_repayment_${I+1}`),P=he(v,"advanced","repaid","repaying"),w=[V({amount:`The full ${r}`,fromActor:e.funder,key:`${n}_disburse`,kind:"payout",toActor:e.advanced,trigger:`Disburse the advance to the ${e.advanced.replaceAll("_"," ")}`})],g={create:{summary:`Create a ${B(n).toLowerCase()}`,to:"created"},disburse:{from:["created"],moneyEvent:`${n}_disburse`,moves:[{key:"transfer",operation:"create",amount:r,from:e.funder,to:e.advanced}],summary:`Disburse the ${r} to the ${e.advanced.replaceAll("_"," ")}`,to:"advanced"}},C=`${n}_repayments`;w.push(V({amount:`The ${s}, partitioned into ${t.count} repayments`,fromActor:e.advanced,key:C,kind:"installment",occurrence:"repeatable",toActor:e.funder,trigger:`Collect each of the ${t.count} repayments on its stored due date`}));for(let[D,I]of _.entries()){let Z=C;g[v[D]]={due:{field:t.firstDueField,rule:o,...Ee(t,D)},from:[P[D]?.from],moneyEvent:Z,moves:[{key:"transfer",operation:"create",amount:I,from:e.advanced,to:e.funder}],summary:`Collect repayment ${D+1} of ${t.count}`,to:P[D]?.to}}return{design:[`${n}: ${r} advanced up front; ${t.count} repayments every ${t.every.raw} conserve against ${s}${l?` (advance + ${W(e.feeBps)} fee)`:""}`],feeLines:l?[{label:`${B(e.funder)} discount`,on:`each ${n.replaceAll("_"," ")}`,structure:`${W(e.feeBps)} of the ${r}, repaid on top of the advance`}]:[],moneyEvents:w,noun:{actors:{[e.funder]:"payer",[e.advanced]:"beneficiary"},desc:`Advance: the ${e.funder.replaceAll("_"," ")} disburses ${r} to the ${e.advanced.replaceAll("_"," ")}, repaid over ${t.count} scheduled repayments${l?" plus the funder's discount":""}`,fields:u,id:n,...ve([...ge(s,_),...l?ge("repayableAmount",[r,"feeAmount"]):[]]),summary:`Advance to ${e.advanced.replaceAll("_"," ")} repaid over ${t.count} anchors`,title:B(n),verbs:g},rules:[{allowedActors:[],detail:`Each of the ${t.count} repayments is collected once from its stored due date`,dueDriven:!0,enforcement:"platform",gatesEvent:null,key:o,kind:"deadline",label:"Repayments collected on their stored due dates",tenantTunable:!1}],settlement:{name:n,pieces:[]}}}function Bt(e){let t=e.name,n=`${t}_period`,r=e.rates[0]?.field.currency??"SAR",o={[e.closeByField]:se("End of this metering period; the close makes further charges unreachable")};for(let s of e.rates)o[s.field.name]=H(`Per-unit price of ${s.meter.replaceAll("_"," ")} in ${r} minor units, committed at period open`);let a=[],l={close_period:{due:{field:e.closeByField,rule:n},from:["open"],summary:"Close the metering period; no further usage can be charged",to:"closed"},create:{summary:`Open a ${B(t).toLowerCase()} period with its committed rate card`,to:"open"}};for(let s of e.rates){let u=U(`${t}_${s.meter}`);a.push(V({amount:`The committed ${s.field.name} per unit`,fromActor:e.payer,key:u,kind:"charge",occurrence:"repeatable",timing:"external_schedule",toActor:e.payee,trigger:`Charge one ${s.meter.replaceAll("_"," ")} at the committed rate`})),l[`charge_${s.meter}`]={from:["open"],moneyEvent:u,moves:[{key:"transfer",operation:"create",amount:s.field.name,from:e.payer,to:e.payee}],summary:`Charge one metered ${s.meter.replaceAll("_"," ")}; the emission is the transfer itself`,to:"open"}}return{design:[`${t}: committed rate card (${e.rates.map(s=>s.meter).join(", ")}); each usage charge IS the ledger transfer; period closes on ${e.closeByField}`],feeLines:[],moneyEvents:a,noun:{actors:{[e.payer]:"payer",[e.payee]:"beneficiary"},desc:`Metered usage: the ${e.payer.replaceAll("_"," ")} is charged per unit at the committed rate card until the period closes on its stored end date`,fields:o,id:t,summary:`Metered charges from ${e.payer.replaceAll("_"," ")} on a committed rate card`,title:B(t),verbs:l},rules:[{allowedActors:[],detail:"The period closes once from its stored end date",dueDriven:!0,enforcement:"platform",gatesEvent:null,key:n,kind:"deadline",label:"Period closed on its stored end date",tenantTunable:!1}],settlement:{name:t,pieces:[]}}}function jt(e){let t=e.name,n=e.amount.name,r=`${t}_payout`,o=e.shares.findIndex(g=>g.to===e.remainderTo),a=e.shares.map(g=>({bps:g.bps,field:`${Q(g.to)}ShareAmount`,origin:g.origin,releaseTo:g.to})),l={[n]:H(`The pooled period total in ${e.amount.currency} minor units; the share fields below partition it exactly`),[e.distributeDueField]:se("The period's payout date; the pool distributes from it")};for(let[g,C]of a.entries()){let D=g===Math.max(o,0)?" (carries the integer-division remainder)":"";l[C.field]=H(`${W(C.bps)} of ${n}${D}: the ${C.releaseTo.replaceAll("_"," ")}'s share. Computed as floor(${n} * ${C.bps} / 10000) in ${e.amount.currency} minor units`)}let s=a.map((g,C)=>`fund_share_${C+1}`),u=a.map((g,C)=>`distribute_share_${C+1}`),_=he(s,"created","pooled","pooling"),v=he(u,"pooled","distributed","distributing"),P=[],w={create:{summary:`Open a ${B(t).toLowerCase()} period`,to:"created"}};for(let[g,C]of a.entries()){let D=`${t}_pool_${g+1}`;P.push(V({amount:`${W(C.bps)} of the ${n}`,fromActor:e.payer,key:D,kind:"charge",toActor:"escrow",trigger:`Pool the ${C.releaseTo.replaceAll("_"," ")}'s share for the period`})),w[s[g]]={from:[_[g]?.from],moneyEvent:D,moves:[{key:"transfer",operation:"create",amount:C.field,from:e.payer,to:"escrow"}],summary:`Pool share ${g+1} of the period total`,to:_[g]?.to}}for(let[g,C]of a.entries()){let D=`${t}_payout_${g+1}`;P.push(V({amount:`${W(C.bps)} of the ${n}`,fromActor:"escrow",key:D,kind:"payout",toActor:C.releaseTo,trigger:`Distribute the ${C.releaseTo.replaceAll("_"," ")}'s share on the payout date`})),w[u[g]]={due:{field:e.distributeDueField,rule:r},from:[v[g]?.from],moneyEvent:D,moves:[{key:"transfer",operation:"create",amount:C.field,from:"escrow",to:C.releaseTo}],summary:`Distribute the ${C.releaseTo.replaceAll("_"," ")}'s share of the pool`,to:v[g]?.to}}return{design:[`${t}: pool of ${n} partitioned ${a.map(g=>`${W(g.bps)} ${g.releaseTo}`).join(" + ")}; distributes in full on ${e.distributeDueField}; remainder to ${e.remainderTo}`],feeLines:[],moneyEvents:P,noun:{actors:{[e.payer]:"payer",...Object.fromEntries(e.shares.map(g=>[g.to,"beneficiary"]))},desc:`Pooled split: the ${e.payer.replaceAll("_"," ")} pools the period's ${n} share by share; the pool distributes to every recipient in full on the stored payout date`,escrow:!0,fields:l,id:t,...ve(ge(n,a.map(g=>g.field))),summary:`Period pool from ${e.payer.replaceAll("_"," ")} split ${e.shares.length} ways`,title:B(t),verbs:w},rules:[{allowedActors:[],detail:"Every share of the pool distributes once from the stored payout date",dueDriven:!0,enforcement:"platform",gatesEvent:null,key:r,kind:"deadline",label:"Pool distributed on its stored payout date",tenantTunable:!1}],settlement:{name:t,pieces:a}}}function Dn(e){let t=Number(Ze),n=e.carveTo??e.payee,r=[];e.payeeFeeBps<t&&r.push({end:t-e.payeeFeeBps,to:n}),e.payeeFeeBps>0&&r.push({end:t,to:"platform"});let o=[],a=0;for(let v of e.onCancel?.shares??[])a+=v.bps,o.push({end:a,origin:v.origin,to:v.to});let l=[...new Set([...r.map(v=>v.end),...o.map(v=>v.end),t])].sort((v,P)=>v-P),s=(v,P)=>v.find(w=>P<w.end),u=[],_=0;for(let v of l){if(v<=_)continue;let P=s(r,_),w=s(o,_);u.push({bps:v-_,...w?{cancelTo:w.to}:{},field:`piece${u.length+1}Amount`,origin:w?.origin??e.amount.origin,releaseTo:P?.to??n}),_=v}return u}function Nn(e,t,n,r){let o=e.cancelTo?`; on cancellation to the ${e.cancelTo.replaceAll("_"," ")}`:"",a=t===0?" (carries the integer-division remainder)":"";return`${W(e.bps)} of ${n}${a}: released to the ${e.releaseTo.replaceAll("_"," ")}${o}. Computed as floor(${n} * ${e.bps} / 10000) in ${r} minor units`}function W(e){let t=e/100;return`${Number.isInteger(t)?t:t.toFixed(2).replace(/0$/,"")}%`}function qt(e){let t=new Map(e.settlements.flatMap(r=>r.archetype==="advance"&&r.source.kind==="carve"?[[r.source.settlement,r.funder]]:[]));return`${e.settlements.map(r=>{switch(r.archetype){case"held_payment":{let o=r.onCancel?`; cancellation splits the held amount ${r.onCancel.shares.map(s=>`${W(s.bps)} to the ${s.to.replaceAll("_"," ")}`).join(" and ")}`:"",a=t.get(r.name),l=a?`the ${a.replaceAll("_"," ")} is paid on confirmed release, in the ${r.payee.replaceAll("_"," ")}'s place`:`the ${r.payee.replaceAll("_"," ")} is paid on confirmed release`;return`The ${r.payer.replaceAll("_"," ")} funds ${r.amount.name} into escrow and ${l}${o}`}case"captured_payment":return`The ${r.payer.replaceAll("_"," ")}'s ${r.amount.name} is reserved until ${r.reserveUntilField}, captured by the ${r.payee.replaceAll("_"," ")} in strict partial slices, then settled or released`;case"instant_transfer":return`The ${r.payer.replaceAll("_"," ")} pays ${r.amount.name} straight through to the ${r.payee.replaceAll("_"," ")}`;case"premium_forward":return`The ${r.payer.replaceAll("_"," ")}'s ${r.amount.name} forwards to the ${r.carrier.replaceAll("_"," ")} exactly once on binding`;case"deposit":return`The ${r.payer.replaceAll("_"," ")}'s ${r.amount.name} is reserved for the ${r.holder.replaceAll("_"," ")} until claimed or returned`;case"scheduled":return r.mode==="obligation"?`The ${r.debtor.replaceAll("_"," ")} owes ${r.amount.name}; ${r.advanceTo?`the ${r.payee.replaceAll("_"," ")} advances it to the ${r.advanceTo.replaceAll("_"," ")}, then `:""}the ${r.payer.replaceAll("_"," ")} repays the ${r.payee.replaceAll("_"," ")} over ${r.schedule.count} anchor-bound installments`:`The ${r.payer.replaceAll("_"," ")} pays ${r.amount.name} to the ${r.payee.replaceAll("_"," ")} over ${r.schedule.count} scheduled installments`;case"advance":return r.source.kind==="carve"?`The ${r.funder.replaceAll("_"," ")} advances ${r.amount.name} to the ${r.advanced.replaceAll("_"," ")}, repaid out of the ${r.source.settlement.replaceAll("_"," ")} release`:`The ${r.funder.replaceAll("_"," ")} advances ${r.amount.name} to the ${r.advanced.replaceAll("_"," ")}, repaid over ${r.source.schedule.count} anchors`;case"metered":return`The ${r.payer.replaceAll("_"," ")} is charged per metered unit at a committed rate card until the period closes`;case"pooled_split":return`The ${r.payer.replaceAll("_"," ")} pools ${r.amount.name} and it distributes ${r.shares.length} ways on the payout date`;case"settlement_batch":return`The ${r.settlementAccount.replaceAll("_"," ")} freezes capture lineage and pays one signed net amount to the ${r.payoutDestination.replaceAll("_"," ")}`;case"funding_round":return`The ${r.contributor.replaceAll("_"," ")} commits under ${r.target.name} until the stored close anchor activates or fails the round`;case"weighted_distribution":return`The ${r.source.replaceAll("_"," ")} pays a frozen claimant set by deterministic largest remainder`;case"credit_facility":return`The ${r.lender.replaceAll("_"," ")} admits draws under ${r.limit.name}; ${r.obligation.settlement.replaceAll("_"," ")} owns repayment`;case"recurring_collection":return`${r.name.replaceAll("_"," ")} adds explicit mandate evidence to ${r.obligation.settlement.replaceAll("_"," ")} repayment attempts`;case"conditional_disbursement":return`The ${r.source.replaceAll("_"," ")} pays one evidence-approved amount under ${r.cap.name} to the ${r.destination.replaceAll("_"," ")}`;case"rotating_pool":return`${r.members.length} fixed members contribute one exact amount per cycle in a stored payout order`;case"swap":return`The ${r.sides[0].party.replaceAll("_"," ")} and ${r.sides[1].party.replaceAll("_"," ")} fund one shared escrow and the entire two-sided trade releases or reverses together`}}).join(". ")}.`.slice(0,400)}function Q(e){let[t,...n]=e.split("_");return(t??"")+n.map(r=>r.charAt(0).toUpperCase()+r.slice(1)).join("")}function B(e){let t=e.replaceAll("_"," ");return t.charAt(0).toUpperCase()+t.slice(1)}var Jt=["asset","from","import","party","port","program","settlement"],Ln=new Set(["{","}","(",")","[","]",":",",","=","|","."]),Mt=new Set(Jt),Ut=e=>/[A-Za-z]/.test(e),Kt=e=>/[A-Za-z0-9_]/.test(e),Ne=e=>e>="0"&&e<="9";function On(e){let t=[],n=[],r=0,o=(a,l,s,u=s)=>{t.push({kind:a,span:{end:r,start:l},text:s,value:u})};for(;r<e.length;){let a=e[r];if(a===" "||a===" "||a==="\r"||a===`
|
|
3
|
-
`){r+=1;continue}if(a==="/"&&e[r+1]==="/"){for(;r<e.length&&e[r]!==`
|
|
4
|
-
`;)r+=1;continue}if(Ln.has(a)){let s=r;r+=1,o("punct",s,a);continue}if(a==='"'){let s=r;r+=1;let u="",_=!1;for(;r<e.length;){let v=e[r];if(v==='"'){r+=1,_=!0;break}if(v===`
|
|
5
|
-
`)break;u+=v,r+=1}_||n.push({message:"this string never closes; add the ending double quote",span:{end:r,start:s}}),o("string",s,e.slice(s,r),u);continue}if(Ne(a)){let s=r;for(;r<e.length&&Ne(e[r]);)r+=1;if(e[r]==="."&&Ne(e[r+1]??""))for(r+=1;r<e.length&&Ne(e[r]);)r+=1;let u=e.slice(s,r);e[r]==="%"?(r+=1,o("percent",s,e.slice(s,r),u)):o("number",s,u,u);continue}if(Ut(a)){let s=r;for(;r<e.length&&Kt(e[r]);)r+=1;let u=e.slice(s,r);o(Mt.has(u)?"keyword":"ident",s,u);continue}let l=r;for(;r<e.length&&!/[\sA-Za-z0-9_"]/.test(e[r])&&!Ln.has(e[r])&&!(e[r]==="/"&&e[r+1]==="/");)r+=1;r===l&&(r+=1),n.push({message:`"${e.slice(l,r)}" is not part of the HSX language`,span:{end:r,start:l}})}return t.push({kind:"eof",span:{end:e.length,start:e.length},text:"",value:""}),{diagnostics:n,tokens:t}}var Se=Object.freeze({maxNestingDepth:64,maxSourceBytes:262144});function Bn(e){let t=new TextEncoder().encode(e).byteLength;if(t>Se.maxSourceBytes)return{diagnostics:[{message:`this file is ${t} bytes; HSX reads at most ${Se.maxSourceBytes}`,span:{end:0,start:0}}],program:{decls:[],span:{end:0,start:0}}};let n=On(e),r=new nn(n.tokens,[...n.diagnostics]),o=r.parseProgram(e.length);return{diagnostics:r.diagnostics,program:o}}var nn=class{diagnostics;tokens;index=0;depth=0;constructor(t,n){this.tokens=t,this.diagnostics=n}parseProgram(t){let n=[];for(;!this.at("eof");){let r=this.parseDecl();if(r){n.push(r);continue}this.recoverToDecl()}return{decls:n,span:{end:t,start:0}}}parseDecl(){let t=this.peek();if(t.kind!=="keyword"||t.text==="from"){this.error(t.span,t.kind==="eof"?"the program ends unexpectedly":`expected a declaration (program, import, party, asset, settlement, or port), found "${t.text}"`);return}switch(t.text){case"program":return this.parseProgramDecl();case"import":return this.parseImportDecl();case"party":return this.parsePartyDecl();case"asset":return this.parseAssetDecl();case"settlement":return this.parseSettlementDecl();case"port":return this.parsePortDecl();default:this.error(t.span,`"${t.text}" cannot start a declaration`),this.advance();return}}parseProgramDecl(){let t=this.advance(),n=this.expectIdent("the program needs a snake_case name");if(!n)return;let r;if(this.at("string")){let o=this.advance();r={kind:"string",span:o.span,value:o.value}}return{kind:"program",name:n,span:this.spanFrom(t.span),...r?{title:r}:{}}}parseImportDecl(){let t=this.advance();if(!this.expectPunct("{",'import lists its names in braces: import { held_payment } from "settlement"'))return;let n=[];for(;!this.atPunct("}")&&!this.at("eof");){let o=this.expectIdent("expected an imported name");if(!o)return;n.push(o),this.atPunct(",")&&this.advance()}if(!this.expectPunct("}","the import name list never closes"))return;if(!this.at("keyword")||this.peek().text!=="from"){this.error(this.peek().span,'import needs from: import { held_payment } from "settlement"');return}if(this.advance(),!this.at("string")){this.error(this.peek().span,'the import source must be a quoted module name like "settlement"');return}let r=this.advance();return n.length===0&&this.error(t.span,"import brings in at least one name"),{from:{kind:"string",span:r.span,value:r.value},kind:"import",names:n,span:this.spanFrom(t.span)}}parsePartyDecl(){let t=this.advance(),n=this.expectIdent("the party needs a name, like: party buyer: person");if(!n||!this.expectPunct(":",`party ${n.name} needs a kind, like: party ${n.name}: person`))return;let r=this.expectIdent(`expected a kind for party ${n.name}`);if(!r)return;let o=this.atPunct("{")?this.parseBlock():void 0;return{...o?{attrs:o}:{},kind:"party",name:n,partyKind:r,span:this.spanFrom(t.span)}}parseAssetDecl(){let t=this.advance(),n=this.expectIdent("the asset needs a name, like: asset vehicle: good");if(!n||!this.expectPunct(":",`asset ${n.name} needs a kind, like: asset ${n.name}: good`))return;let r=this.expectIdent(`expected a kind for asset ${n.name}`);if(!r)return;let o=this.atPunct("{")?this.parseBlock():void 0;return{assetKind:r,...o?{attrs:o}:{},kind:"asset",name:n,span:this.spanFrom(t.span)}}parseSettlementDecl(){let t=this.advance(),n=this.expectIdent("the settlement needs a name, like: settlement sale = held_payment { ... }");if(!n||!this.expectPunct("=",`settlement ${n.name} instantiates an archetype: settlement ${n.name} = held_payment { ... }`))return;let r=this.expectIdent(`expected an archetype name for settlement ${n.name}`);if(!r)return;if(!this.atPunct("{")){this.error(this.peek().span,`settlement ${n.name} needs a body in braces`);return}let o=this.parseBlock();if(o)return{archetype:r,body:o,kind:"settlement",name:n,span:this.spanFrom(t.span)}}parsePortDecl(){let t=this.advance(),n=this.expectIdent("the port needs a name, like: port confirm_handover { ... }");if(!n)return;if(!this.atPunct("{")){this.error(this.peek().span,`port ${n.name} needs a body in braces`);return}let r=this.parseBlock();if(r)return{body:r,kind:"port",name:n,span:this.spanFrom(t.span)}}enterNesting(t){return this.depth>=Se.maxNestingDepth?(this.error(t,`this nests past the parser's depth budget of ${Se.maxNestingDepth}; flatten it`),!1):(this.depth+=1,!0)}parseBlock(){if(!this.enterNesting(this.peek().span))return;let t=this.parseBlockUnguarded();return this.depth-=1,t}parseBlockUnguarded(){let t=this.advance(),n=[];for(;!this.atPunct("}")&&!this.at("eof");){let r=this.index,o=this.parseEntry();if(!o){this.recoverInBlock(),this.index===r&&this.advance();continue}n.push(o),this.atPunct(",")&&this.advance()}return this.expectPunct("}","this block never closes; add the matching }")?{entries:n,kind:"block",span:this.spanFrom(t.span)}:{entries:n,kind:"block",span:this.spanFrom(t.span)}}parseEntry(){let t=this.expectIdent("expected an entry name here");if(!t)return;let n=[];if(this.atPunct("(")){for(this.advance();!this.atPunct(")")&&!this.at("eof");){let o=this.expectIdent(`expected a qualifier inside ${t.name}( ... )`);if(!o)return;n.push(o),this.atPunct(",")&&this.advance()}if(!this.expectPunct(")",`${t.name}( ... ) never closes`))return}let r;if(this.atPunct("{"))r=this.parseBlock();else if(this.atPunct(":"))this.advance(),r=this.parseExpr();else{this.error(this.peek().span,`entry ${t.name} needs a value: either "${t.name}: <value>" or "${t.name} { ... }"`);return}if(r)return{key:t,qualifiers:n,span:{end:r.span.end,start:t.span.start},value:r}}parseExpr(){if(!this.enterNesting(this.peek().span))return;let t=this.parseExprUnguarded();return this.depth-=1,t}parseExprUnguarded(){let t=this.peek();if(t.kind==="string")return this.advance(),{kind:"string",span:t.span,value:t.value};if(t.kind==="number")return this.advance(),{kind:"number",raw:t.value,span:t.span};if(t.kind==="percent"){this.advance();let n=zt(t.value);return n===void 0?(this.error(t.span,`${t.text} is finer than the money system can settle; percents go down to a hundredth (basis point), like 99.75%`),{bps:0,kind:"percent",raw:t.value,span:t.span}):{bps:n,kind:"percent",raw:t.value,span:t.span}}if(this.atPunct("[")){let n=this.advance(),r=[];for(;!this.atPunct("]")&&!this.at("eof");){let o=this.parseExpr();if(!o)return;r.push(o),this.atPunct(",")&&this.advance()}return this.expectPunct("]","this list never closes; add the matching ]")?{items:r,kind:"list",span:this.spanFrom(n.span)}:void 0}if(this.atPunct("{"))return this.parseBlock();if(t.kind==="keyword"&&t.text==="port"){let n=this.advance(),r=this.expectIdent("expected a port name after the port keyword");if(!r)return;let o;if(this.at("ident")&&this.peek().text==="within"&&(this.advance(),o=this.expectIdent("expected a fixed duration after within, like P14D"),!o))return;let a;if(this.atPunct("|")){if(this.advance(),!this.at("ident")||this.peek().text!=="at"){this.error(this.peek().span,"after | comes the date the platform decides on, like: | at(releaseDueAt)");return}if(this.advance(),!this.expectPunct("(","at names its date field in parentheses: at(releaseDueAt)")||(a=this.expectIdent("expected a stored date field inside at( ... ), like at(releaseDueAt)"),!a)||!this.expectPunct(")","at( ... ) never closes"))return}return{...a?{deadline:a}:{},kind:"port_ref",name:r,span:this.spanFrom(n.span),...o?{within:o}:{}}}if(t.kind==="ident"){let n=this.parseIdent();if(this.atPunct(".")){this.advance();let r=this.expectIdent(`expected the exit after ${n.name}., like ${n.name}.release`);return r?{kind:"settlement_ref",member:r,owner:n,span:{end:r.span.end,start:n.span.start}}:void 0}if(this.atPunct("(")){this.advance();let r=[];for(;!this.atPunct(")")&&!this.at("eof");){let o=this.parseExpr();if(!o)return;r.push(o),this.atPunct(",")&&this.advance()}return this.expectPunct(")",`${n.name}( ... ) never closes`)?{args:r,callee:n,kind:"call",span:this.spanFrom(n.span)}:void 0}if(this.atPunct(":")){this.advance();let r=this.parseExpr();return r?{kind:"binding",name:n,span:{end:r.span.end,start:n.span.start},type:r}:void 0}return n}this.error(t.span,t.kind==="eof"?"the program ends where a value was expected":`"${t.text}" is not a value HSX understands here`)}recoverToDecl(){for(;!this.at("eof");){let t=this.peek();if(t.kind==="keyword"&&t.text!=="from")return;this.advance()}}recoverInBlock(){let t=0;for(;!this.at("eof");){let n=this.peek();if(n.kind==="punct"){if((n.text==="{"||n.text==="["||n.text==="(")&&(t+=1),n.text==="}"||n.text==="]"||n.text===")"){if(t===0)return;t-=1}if(n.text===","&&t===0){this.advance();return}}if(n.kind==="keyword"&&t===0)return;this.advance()}}peek(){return this.tokens[this.index]}previous(){return this.tokens[Math.max(0,this.index-1)]}advance(){let t=this.peek();return t.kind!=="eof"&&(this.index+=1),t}at(t){return this.peek().kind===t}atPunct(t){let n=this.peek();return n.kind==="punct"&&n.text===t}parseIdent(){let t=this.advance();return{kind:"ident",name:t.text,span:t.span}}expectIdent(t){if(this.at("ident"))return this.parseIdent();this.error(this.peek().span,t)}expectPunct(t,n){return this.atPunct(t)?(this.advance(),!0):(this.error(this.peek().span,n),!1)}spanFrom(t){return{end:this.previous().span.end,start:t.start}}error(t,n){this.diagnostics.push({message:n,span:t})}};function zt(e){let[t="0",n=""]=e.split(".");if(n.length>2)return;let r=n.padEnd(2,"0");return Number(t)*100+Number(r===""?"0":r)}function tn(e){let t=[],n=xn(e),r=(s,u,_,v)=>{let P=Cn(n,v);t.push({column:P.column,line:P.line,message:_,severity:u,stage:s})},o=Bn(e);for(let s of o.diagnostics)r("parse","error",s.message,s.span.start);if(o.diagnostics.length>0)return{diagnostics:t,verdict:"invalid"};let a=An(o.program);for(let s of a.diagnostics)r("check",s.severity,s.message,s.span.start);if(!a.program)return{diagnostics:t,verdict:"invalid"};let l=Tn(a.program);if(!l.ok){for(let s of l.issues)r("lower","error",s.message,s.span.start);return{diagnostics:t,verdict:"invalid"}}return{artifacts:{document:l.value.document,frame:l.value.frame},diagnostics:t,verdict:t.length>0?"warning":"valid"}}import{spawn as Ht}from"node:child_process";import{createHash as Yt}from"node:crypto";import{chmod as rn,mkdir as Vt,readdir as Wt,readFile as je,rename as Gt,unlink as Xt,writeFile as Zt}from"node:fs/promises";import{homedir as Qt}from"node:os";import{basename as er,dirname as an,join as qe}from"node:path";var Le="https://hyperscale0.ai",cn="sandbox",dn="hyperscale-cli-session",nr="/v1/personal-access-tokens/current",jn=process.platform==="darwin"?"/usr/bin/security":null,tr="config.json",Jn=3e4,rr=`hyperscale <command> [options]
|
|
2
|
+
import{spawn as Se}from"node:child_process";import{createHash as Ke}from"node:crypto";import{createServer as Ye}from"node:http";import{createInterface as Fe}from"node:readline/promises";import{chmod as X,mkdir as qe,readdir as Me,readFile as q,rename as ze,unlink as Ve,writeFile as We}from"node:fs/promises";import{homedir as Ge}from"node:os";import{basename as Xe,dirname as te,join as M}from"node:path";var ce="https://hyperscale0.ai",ue="sandbox",de="hyperscale-cli-session",Qe="/v1/personal-access-tokens/current",ne=process.platform==="darwin"?"/usr/bin/security":null,Ze="config.json",oe="https://hyperscale0.ai/desk/security/tokens",O="https://hyperscale0.ai/request-access",C=`Mint a founder PAT in the portal at ${oe}. Open Security, then Personal access tokens.`,et=`Not logged in. Run "hyperscale auth login" to open portal sign-in. In a headless environment, ${C} Then set HYPERSCALE_TOKEN or pass --token. Unapproved founders can request access at ${O}.`,tt=`Run "hyperscale auth login". For headless use, ${C} Unapproved founders can request access at ${O}.`,re=3e4,nt=2e3,ot=120*1e3,rt=/^prd_(sandbox|live)_[a-z0-9]{8,64}$/,at=`hyperscale <command> [options]
|
|
6
3
|
|
|
7
4
|
Commands:
|
|
8
|
-
|
|
5
|
+
start Create a Product and run its first published journey step
|
|
6
|
+
auth login Sign in through the portal or save a founder PAT
|
|
9
7
|
auth status Verify and show the active founder PAT
|
|
10
8
|
auth logout [--revoke] Forget the local founder PAT, optionally revoke it
|
|
11
9
|
blueprint list List public Blueprints without authentication
|
|
@@ -13,9 +11,10 @@ Commands:
|
|
|
13
11
|
product create Create a Product from a Blueprint
|
|
14
12
|
product list List Products in the signed-in company
|
|
15
13
|
product show [id] Show a Product (default: selected Product)
|
|
16
|
-
product
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
product select <id> Select the default Product for later commands
|
|
15
|
+
product actions [operation-id]
|
|
16
|
+
List frozen public actions or describe one exactly
|
|
17
|
+
product run <operation-id> Run one frozen public action
|
|
19
18
|
compose check <file.hsx> Compile and check an HSX program
|
|
20
19
|
compose plan <file.hsx> Diff an HSX program against the selected Product
|
|
21
20
|
compose apply <file.hsx> Recompose the selected Product from checked HSX
|
|
@@ -32,46 +31,55 @@ Commands:
|
|
|
32
31
|
Options:
|
|
33
32
|
--token <pat> Founder PAT (default: $HYPERSCALE_TOKEN)
|
|
34
33
|
--revoke Revoke the active founder PAT during auth logout
|
|
34
|
+
--no-browser Skip browser login and print the founder PAT path
|
|
35
35
|
--api-key <key> Product API key (default: $HYPERSCALE_API_KEY)
|
|
36
|
-
--base-url <url> API origin (default: $HYPERSCALE_BASE_URL, else ${
|
|
37
|
-
--environment <name> sandbox or live (default: $HYPERSCALE_ENVIRONMENT, else ${
|
|
36
|
+
--base-url <url> API origin (default: $HYPERSCALE_BASE_URL, else ${ce})
|
|
37
|
+
--environment <name> sandbox or live (default: $HYPERSCALE_ENVIRONMENT, else ${ue})
|
|
38
38
|
--email <email> Email for team invite
|
|
39
39
|
--role <role> Seeded role name or custom role id for team invite
|
|
40
|
-
--blueprint <
|
|
40
|
+
--blueprint <slug> Blueprint for non-interactive start or product create
|
|
41
41
|
--name <name> Product or key name
|
|
42
|
-
--product <id> Product id for key commands and Product-key
|
|
42
|
+
--product <id> Product id for key commands and Product-key actions
|
|
43
|
+
--catalog-revision <id> Tenant catalog revision for HSX composition
|
|
43
44
|
--input <json> JSON input object for call or product run
|
|
44
45
|
--input-file <path> Read call or product run input from a JSON file
|
|
45
|
-
--idempotency-key <key> Idempotency key for a mutation or public
|
|
46
|
+
--idempotency-key <key> Idempotency key for a mutation or public action (default: generated)
|
|
46
47
|
--confirm Confirm compose apply for a person
|
|
47
48
|
--yes Confirm compose apply without a prompt for an agent
|
|
48
|
-
--passkey Print the portal pointer for passkey login
|
|
49
49
|
--json Print machine-readable JSON
|
|
50
50
|
--version Print the CLI version
|
|
51
51
|
--help Print this help
|
|
52
52
|
|
|
53
|
-
Founder
|
|
54
|
-
|
|
55
|
-
|
|
53
|
+
Founder PAT commands: auth, whoami, product create/list/show, compose check/plan/apply,
|
|
54
|
+
key, team, and activity. Product API key commands: product actions/run, ops list,
|
|
55
|
+
and call. The server compiles every compose command against the selected tenant
|
|
56
|
+
catalog revision. The two credential types are not interchangeable. Browser
|
|
57
|
+
login returns through a single-use localhost callback.
|
|
56
58
|
|
|
57
59
|
compose check, plan, and apply exit 2 when the compiler or composer refuses the
|
|
58
60
|
program. Command, credential, request, and server failures exit 1. compose apply
|
|
59
61
|
requires --confirm, or --yes for an agent.
|
|
60
62
|
|
|
61
63
|
Use HYPERSCALE_TOKEN for a founder PAT. Use HYPERSCALE_API_KEY for a Product API
|
|
62
|
-
key. The explicit flag wins over its environment variable.
|
|
64
|
+
key. The explicit flag wins over its environment variable. Founder logins use
|
|
65
|
+
macOS Keychain when available. Set HYPERSCALE_CREDENTIAL_STORE=file to keep the
|
|
66
|
+
founder PAT in the owner-only CLI profile instead and skip Keychain access.
|
|
63
67
|
|
|
64
|
-
|
|
68
|
+
${C}
|
|
69
|
+
Request access at ${O}.
|
|
65
70
|
|
|
66
71
|
Examples:
|
|
72
|
+
hyperscale start
|
|
73
|
+
hyperscale start --blueprint vehicle-escrow-marketplace --json
|
|
67
74
|
hyperscale whoami
|
|
75
|
+
hyperscale auth login
|
|
68
76
|
hyperscale auth login --token hyperscale_pat_...
|
|
69
77
|
hyperscale blueprint list
|
|
70
|
-
hyperscale product create --blueprint
|
|
78
|
+
hyperscale product create --blueprint luxury-goods-consignment-escrow --name "Luxury Consignment"
|
|
71
79
|
hyperscale key create --name "Founder laptop"
|
|
72
|
-
hyperscale product
|
|
73
|
-
hyperscale product
|
|
74
|
-
hyperscale product run
|
|
80
|
+
hyperscale product actions
|
|
81
|
+
hyperscale product actions escrow_order.placeBuyerHold --json
|
|
82
|
+
hyperscale product run escrow_order.placeBuyerHold --input '{"escrowOrderId":"eord_sandbox_..."}'
|
|
75
83
|
hyperscale compose check product.hsx
|
|
76
84
|
hyperscale compose plan product.hsx --json
|
|
77
85
|
hyperscale compose apply product.hsx --yes
|
|
@@ -83,18 +91,37 @@ Examples:
|
|
|
83
91
|
hyperscale call account.list --input-file input.json
|
|
84
92
|
printf '{"limit":5}' | hyperscale call account.list
|
|
85
93
|
hyperscale call account.retrieve --input '{"accountId":"acct_sandbox_..."}'
|
|
86
|
-
`,x=class extends Error{},Oe=class extends x{constructor(t,n){super(t),this.code="check_failed",this.details=n,this.exitCode=2}},or=new Set(["--api-key","--base-url","--blueprint","--environment","--email","--idempotency-key","--input","--input-file","--name","--product","--role","--token"]);function ar(e){let t=[],n={};for(let r=0;r<e.length;r+=1){let o=e[r];if(!o.startsWith("--")){t.push(o);continue}if(or.has(o)){let a=e[r+1];if(a===void 0)throw new x(`${o} needs a value`);n[o]=a,r+=1;continue}if(o==="--help"||o==="--version"||o==="--json"||o==="--confirm"||o==="--yes"||o==="--passkey"||o==="--revoke"){n[o]=!0;continue}throw new x(`Unknown option: ${o}`)}return{flags:n,positional:t}}function ir(e,t){let n=e["--api-key"]??t.HYPERSCALE_API_KEY;if(!n)throw new x("No API key. Set HYPERSCALE_API_KEY, or pass --api-key. Request access at https://hyperscale0.ai/request-access.");let r=e["--environment"]??t.HYPERSCALE_ENVIRONMENT??cn;if(r!=="sandbox"&&r!=="live")throw new x(`Unknown environment: ${r}. Use sandbox or live.`);let o=(e["--base-url"]??t.HYPERSCALE_BASE_URL??Le).replace(/\/+$/,"");return{apiKey:n,baseUrl:o,environment:r}}function Je(e,t,n={}){let r=e["--environment"]??t.HYPERSCALE_ENVIRONMENT??n.environment??cn;if(r!=="sandbox"&&r!=="live")throw new x(`Unknown environment: ${r}. Use sandbox or live.`);let o=(e["--base-url"]??t.HYPERSCALE_BASE_URL??n.baseUrl??Le).replace(/\/+$/,""),a;try{a=new URL(o)}catch{a=null}let l=a?.origin??null;if(!l||l!==o)throw new x(`Invalid API origin: ${o}. Use an origin such as https://hyperscale0.ai.`);let s=["localhost","127.0.0.1","[::1]","::1"].includes(a.hostname);if(a.protocol!=="https:"&&!(a.protocol==="http:"&&s))throw new x(`Refusing cleartext API origin ${o}. Use HTTPS unless the API runs on loopback.`);return{baseUrl:o,environment:r}}function Mn(e){return e.HYPERSCALE_CONFIG_DIR??qe(Qt(),".config","hyperscale")}function Un(e){return qe(Mn(e),tr)}function we(e,t){return qe(Mn(t),`session-${_e(e)}.json`)}async function ln(e,t){let n=we(e,t),r=`${er(n)}.`,o;try{o=await Wt(an(n),{withFileTypes:!0})}catch(a){if(a&&a.code==="ENOENT")return;throw a}for(let a of o){if(!a.isFile()||!a.name.startsWith(r))continue;let l=a.name.slice(r.length);/^\d+\.[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.tmp$/.test(l)&&await Me(qe(an(n),a.name))}}async function sr(e){try{return JSON.parse(await je(e,"utf8"))}catch(t){if(t&&t.code==="ENOENT")return null;throw t instanceof SyntaxError?new x(`${e} is not valid JSON`):t}}async function un(e,t){let n=cr(e);await Vt(n,{mode:448,recursive:!0}),await rn(n,448);let r=`${e}.${process.pid}.${globalThis.crypto.randomUUID()}.tmp`;await Zt(r,t,{flag:"wx",mode:384}),await rn(r,384);try{await Gt(r,e),await rn(e,384)}catch(o){throw await Me(r),o}}function cr(e){return an(e)}async function Me(e){try{await Xt(e)}catch(t){if(!t||t.code!=="ENOENT")throw t}}function dr(e,t){if(!e||typeof e!="object"||Array.isArray(e))throw new x(`${t} does not contain a CLI profile`);let{baseUrl:n,email:r,environment:o,selectedProduct:a}=e;if(typeof n!="string"||typeof r!="string"||o!=="sandbox"&&o!=="live"||!(a===null||typeof a=="string"))throw new x(`${t} does not contain a valid CLI profile`);return{baseUrl:n,email:r,environment:o,selectedProduct:a}}async function Pe(e){let t=Un(e),n=await sr(t);return n===null?null:dr(n,t)}async function Kn(e,t){let n={email:t.email,baseUrl:t.baseUrl,environment:t.environment,selectedProduct:t.selectedProduct??null};await un(Un(e),`${JSON.stringify(n,null,2)}
|
|
87
|
-
`)}
|
|
88
|
-
`)}
|
|
89
|
-
`)
|
|
90
|
-
`),
|
|
91
|
-
|
|
92
|
-
`)
|
|
93
|
-
`)}
|
|
94
|
-
`),{
|
|
95
|
-
|
|
96
|
-
`)
|
|
97
|
-
`)
|
|
98
|
-
`)}
|
|
99
|
-
`)
|
|
100
|
-
`)
|
|
94
|
+
`,we={start:{usage:"start [--blueprint <slug>] [--name <name>] [--json]",summary:"Choose a catalog company, create its Product, and run its first published runnable journey step.",options:["--blueprint <slug> Skip the prompt and choose this catalog Blueprint.","--name <name> Product name. Defaults to the selected Blueprint name.","--json Print one machine document, including the one-time API key under shown_once."],notes:["The command requires an active founder login.","Without --blueprint, start requires an interactive terminal and asks which company to build.","Scripts and agents must pass --blueprint <slug>.","Machine output returns the Product API key only under shown_once.","A Blueprint without a published runnable journey stops after composition and names the next command."],example:"hyperscale start --blueprint vehicle-escrow-marketplace --json"},"auth login":{usage:"auth login [--no-browser] [--token <pat>]",summary:"Sign in through the portal callback or save a founder PAT.",options:["--no-browser Skip the portal callback. Print where to mint a PAT when no token is set.","--token <pat> Founder PAT. Defaults to HYPERSCALE_TOKEN.","--json Print the saved session summary as one JSON document."],notes:["Without a PAT, the CLI opens portal sign-in and accepts one localhost callback.","Headless environments should pass --no-browser and set HYPERSCALE_TOKEN or --token to a portal-minted founder PAT.","Set HYPERSCALE_CREDENTIAL_STORE=file to use the 0600 profile file instead of macOS Keychain."],example:"hyperscale auth login --no-browser"},"auth status":{usage:"auth status [--json]",summary:"Verify and show the active founder PAT and selected Product.",options:["--json Print machine-readable JSON."],example:"hyperscale auth status --json"},"auth logout":{usage:"auth logout [--revoke] [--json]",summary:"Forget the local founder PAT. Optionally revoke it first.",options:["--revoke Revoke the PAT before deleting local state.","--json Print machine-readable JSON."],example:"hyperscale auth logout --revoke"},"blueprint list":{usage:"blueprint list [--json]",summary:"List public Blueprints without authentication.",options:["--json Print the complete collection as JSON."],example:"hyperscale blueprint list"},"blueprint show":{usage:"blueprint show <id> [--json]",summary:"Show one public Blueprint.",options:["--json Print the complete Blueprint as JSON."],example:"hyperscale blueprint show luxury-goods-consignment-escrow"},"product create":{usage:"product create --blueprint <id> --name <name> [--json]",summary:"Create and select a Product. The command refuses a duplicate name.",options:["--blueprint <id> Required Blueprint id.","--name <name> Required Product name.","--json Print the creation summary as JSON."],example:'hyperscale product create --blueprint luxury-goods-consignment-escrow --name "Luxury Consignment"'},"product list":{usage:"product list [--json]",summary:"List Products in the signed-in company.",options:["--json Print the complete collection as JSON."],example:"hyperscale product list"},"product show":{usage:"product show [id] [--json]",summary:"Show a Product summary, or the complete Product document as JSON.",options:["--json Print the complete Product document."],example:"hyperscale product show prd_sandbox_..."},"product select":{usage:"product select <id> [--json]",summary:"Verify a Product and save it as the default for later commands.",options:["--token <pat> Founder PAT. Defaults to HYPERSCALE_TOKEN or the stored login.","--base-url <url> API origin. Defaults to the active founder profile.","--environment <name> sandbox or live. Defaults to the active founder profile.","--json Print the selected Product id as JSON."],notes:["The CLI stores the selection in the active founder profile.","Product show, compose plan/apply, and key commands use it when --product is absent.","Product create and start select the Product they create."],example:"hyperscale product select prd_sandbox_..."},"product actions":{usage:"product actions [operation-id] [--product <id>] [--json]",summary:"List frozen public actions or show one action's full schemas.",options:["--product <id> Product to inspect. Defaults to the selected Product.","--api-key <key> Product API key. Defaults to HYPERSCALE_API_KEY.","--json Print machine-readable JSON."],notes:["Setup operation details include the public input schema used by hyperscale call.","When that schema has no required fields, omit --input or pass {}."],example:"hyperscale product actions escrow_order.placeBuyerHold --json"},"product run":{usage:"product run <operation-id> [--input <json> | --input-file <path>] [--idempotency-key <key>] [--json]",summary:"Run one frozen public action with a Product API key.",options:["--input <json> JSON input object. Stdin is used when piped.","--input-file <path> Read the JSON input object from a file.","--product <id> Product to call. Defaults to the selected Product.","--api-key <key> Product API key. Defaults to HYPERSCALE_API_KEY.","--idempotency-key <key> Send this exact Idempotency-Key header. The default is a generated UUID.","--json Print the key, receipt ids, and output as JSON."],notes:["Reuse an Idempotency-Key only with the same operation and input.",'If a bounded validation value appears as "[Truncated]", run "hyperscale product actions <operation-id>" for the full input schema.'],example:`hyperscale product run escrow_order.placeBuyerHold --input '{"escrowOrderId":"eord_sandbox_..."}' --idempotency-key hold-001`},"compose check":{usage:"compose check <file.hsx> [--catalog-revision <id>] [--json]",summary:"Ask the server to compile and check an HSX program.",options:["--catalog-revision <id> Compile against this immutable tenant catalog revision.","--json Print diagnostics and the verdict as JSON."],example:"hyperscale compose check product.hsx"},"compose plan":{usage:"compose plan <file.hsx> [--product <id>] [--catalog-revision <id>] [--json]",summary:"Diff an HSX program against a Product.",options:["--product <id> Product to compare. Defaults to the selected Product.","--catalog-revision <id> Compile against this immutable tenant catalog revision.","--json Print the plan as JSON."],example:"hyperscale compose plan product.hsx --json"},"compose apply":{usage:"compose apply <file.hsx> (--confirm | --yes) [--product <id>] [--catalog-revision <id>] [--json]",summary:"Recompose a Product from checked HSX.",options:["--confirm Confirm the mutation for a person.","--yes Confirm the mutation without a prompt for an agent.","--product <id> Product to recompose. Defaults to the selected Product.","--catalog-revision <id> Compile and persist against this immutable tenant catalog revision.","--json Print the result as JSON."],example:"hyperscale compose apply product.hsx --yes"},"key create":{usage:"key create [--name <name>] [--product <id>] [--json]",summary:"Create a sandbox Product API key.",options:["--name <name> Key name. Defaults to Founder CLI.","--product <id> Product for the key. Defaults to the selected Product.","--json Print the one-time secret and key metadata as JSON."],example:'hyperscale key create --name "Founder laptop"'},"key list":{usage:"key list [--product <id>] [--json]",summary:"List keys for one Product.",options:["--product <id> Product to inspect. Defaults to the selected Product.","--json Print the collection as JSON."],example:"hyperscale key list --json"},"key revoke":{usage:"key revoke <id> [--product <id>] [--json]",summary:"Revoke one Product API key.",options:["--product <id> Product that owns the key. Defaults to the selected Product.","--json Print the result as JSON."],example:"hyperscale key revoke key_sandbox_..."},"team list":{usage:"team list [--json]",summary:"List company members and pending invitations.",options:["--json Print machine-readable JSON."],example:"hyperscale team list"},"team invite":{usage:"team invite --email <email> --role <role> [--json]",summary:"Invite a company member.",options:["--email <email> Required invitee email.","--role <role> Required seeded role or custom role id.","--json Print the invitation and one-time token as JSON."],example:"hyperscale team invite --email developer@example.com --role developer"},"activity list":{usage:"activity list [--json]",summary:"List company activity with timestamps and resource targets.",options:["--json Print the complete collection as JSON."],example:"hyperscale activity list"},whoami:{usage:"whoami [--json]",summary:"Show the user and company the founder PAT resolves to.",options:["--json Print machine-readable JSON."],example:"hyperscale whoami --json"},"ops list":{usage:"ops list [filter] [--product <id>] [--json]",summary:"List callable operations from the Product machine document.",options:["--product <id> Product to inspect. The Product API key must belong to it.","--api-key <key> Product API key. Defaults to HYPERSCALE_API_KEY.","--json Print matching operations as JSON."],example:"hyperscale ops list account"},call:{usage:"call <operation> [--input <json> | --input-file <path>] [--idempotency-key <key>] [--product <id>]",summary:"Call one operation from the Product machine document.",options:["--input <json> JSON input object. Stdin is used when piped.","--input-file <path> Read the JSON input object from a file.","--product <id> Product to call. The Product API key must belong to it.","--api-key <key> Product API key. Defaults to HYPERSCALE_API_KEY.","--idempotency-key <key> Send this exact Idempotency-Key header for a mutation. The default is a generated UUID."],notes:["Reuse an Idempotency-Key only with the same operation and input."],example:`hyperscale call account.create --input '{"currency":"SAR"}'`}};function st(e){let n=Object.keys(we).sort((o,a)=>a.split(" ").length-o.split(" ").length).find(o=>o.split(" ").every((i,c)=>e[c]===i));if(!n)throw new u(`No help for ${e.join(" ")}. Run "hyperscale --help" to list commands.`);let r=we[n];return[`Usage: hyperscale ${r.usage}`,"",r.summary,"","Options:",...r.options.map(o=>` ${o}`),...r.notes?["","Notes:",...r.notes.map(o=>` ${o}`)]:[],"","Example:",` ${r.example}`,""].join(`
|
|
95
|
+
`)}var u=class extends Error{constructor(t,n={}){super(t),typeof n.code=="string"&&(this.code=n.code),n.details!==void 0&&(this.details=n.details),Number.isInteger(n.exitCode)&&(this.exitCode=n.exitCode),typeof n.fix=="string"&&(this.fix=n.fix)}},T=class extends u{constructor(t,{requestId:n,status:r,code:o,details:a,operationId:i,receiptId:c,traceId:d,structuredError:l}={}){super(t,{code:o,details:a}),this.requestId=n,this.status=r,this.operationId=i??null,this.receiptId=c??null,this.traceId=d??null,this.structuredError=l}};function Q(){return new u(et,{fix:tt})}function Ae(e){let t=e??"<id>";return new u(`This command needs a Product API key. Create one with "hyperscale key create --name 'Founder CLI' --product ${t}", then set HYPERSCALE_API_KEY or pass --api-key.`)}var J=class extends u{constructor(t,n){super(t),this.code="check_failed",this.details=n,this.exitCode=2}},ve=new Set(["--api-key","--base-url","--blueprint","--catalog-revision","--environment","--email","--idempotency-key","--input","--input-file","--name","--product","--role","--token"]);function it(e){let t=[],n={};for(let r=0;r<e.length;r+=1){let o=e[r];if(!o.startsWith("--")){t.push(o);continue}if(ve.has(o)){let a=e[r+1];if(a===void 0)throw new u(`${o} needs a value`);n[o]=a,r+=1;continue}if(o==="--help"||o==="--version"||o==="--json"||o==="--confirm"||o==="--yes"||o==="--no-browser"||o==="--passkey"||o==="--revoke"){n[o]=!0;continue}throw new u(`Unknown option: ${o}`)}return{flags:n,positional:t}}function ge(e,t){let n=e["--api-key"]??t.HYPERSCALE_API_KEY;if(!n)throw Ae();let r=e["--environment"]??t.HYPERSCALE_ENVIRONMENT??ue;if(r!=="sandbox"&&r!=="live")throw new u(`Unknown environment: ${r}. Use sandbox or live.`);let o=(e["--base-url"]??t.HYPERSCALE_BASE_URL??ce).replace(/\/+$/,"");return{apiKey:n,baseUrl:o,environment:r}}function _(e,t,n={}){let r=e["--environment"]??t.HYPERSCALE_ENVIRONMENT??n.environment??ue;if(r!=="sandbox"&&r!=="live")throw new u(`Unknown environment: ${r}. Use sandbox or live.`);let o=(e["--base-url"]??t.HYPERSCALE_BASE_URL??n.baseUrl??ce).replace(/\/+$/,""),a;try{a=new URL(o)}catch{a=null}let i=a?.origin??null;if(!i||i!==o)throw new u(`Invalid API origin: ${o}. Use an origin such as https://hyperscale0.ai.`);let c=["localhost","127.0.0.1","[::1]","::1"].includes(a.hostname);if(a.protocol!=="https:"&&!(a.protocol==="http:"&&c))throw new u(`Refusing cleartext API origin ${o}. Use HTTPS unless the API runs on loopback.`);return{baseUrl:o,environment:r}}function Te(e){return e.HYPERSCALE_CONFIG_DIR??M(Ge(),".config","hyperscale")}function xe(e){return M(Te(e),Ze)}function b(e,t){return M(Te(t),`session-${R(e)}.json`)}function z(e){let t=e.HYPERSCALE_CREDENTIAL_STORE??"auto";if(t==="auto"||t==="file")return t;throw new u(`Unknown HYPERSCALE_CREDENTIAL_STORE value: ${t}. Use auto or file.`)}async function le(e,t){let n=b(e,t),r=`${Xe(n)}.`,o;try{o=await Me(te(n),{withFileTypes:!0})}catch(a){if(a&&a.code==="ENOENT")return;throw a}for(let a of o){if(!a.isFile()||!a.name.startsWith(r))continue;let i=a.name.slice(r.length);/^\d+\.[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\.tmp$/.test(i)&&await j(M(te(n),a.name))}}async function ct(e){try{return JSON.parse(await q(e,"utf8"))}catch(t){if(t&&t.code==="ENOENT")return null;throw t instanceof SyntaxError?new u(`${e} is not valid JSON`):t}}async function N(e,t){let n=ut(e);await qe(n,{mode:448,recursive:!0}),await X(n,448);let r=`${e}.${process.pid}.${globalThis.crypto.randomUUID()}.tmp`;await We(r,t,{flag:"wx",mode:384}),await X(r,384);try{await ze(r,e),await X(e,384)}catch(o){throw await j(r),o}}function ut(e){return te(e)}async function j(e){try{await Ve(e)}catch(t){if(!t||t.code!=="ENOENT")throw t}}function dt(e,t){if(!e||typeof e!="object"||Array.isArray(e))throw new u(`${t} does not contain a CLI profile`);let{baseUrl:n,email:r,environment:o,selectedProduct:a}=e;if(typeof n!="string"||typeof r!="string"||o!=="sandbox"&&o!=="live"||!(a===null||typeof a=="string"))throw new u(`${t} does not contain a valid CLI profile`);return{baseUrl:n,email:r,environment:o,selectedProduct:a}}async function V(e){let t=xe(e),n=await ct(t);return n===null?null:dt(n,t)}async function W(e,t){let n={email:t.email,baseUrl:t.baseUrl,environment:t.environment,selectedProduct:t.selectedProduct??null};await N(xe(e),`${JSON.stringify(n,null,2)}
|
|
96
|
+
`)}function R(e){return Ke("sha256").update(`${e.baseUrl}\0${e.environment}\0${e.email}`).digest("hex")}async function G(e,t){return ne===null?{error:null,status:null,stdout:"",unavailable:!0}:await new Promise(n=>{let r={...process.env};delete r.HYPERSCALE_API_KEY,delete r.HYPERSCALE_TOKEN;let o=Se(ne,e,{env:r,stdio:["pipe","pipe","pipe"]}),a=[],i=!1,c=l=>{i||(i=!0,clearTimeout(d),n(l))},d=setTimeout(()=>{o.kill("SIGKILL"),c({error:null,status:null,stdout:"",unavailable:!0})},nt);o.stdout.on("data",l=>a.push(l)),o.stderr.on("data",()=>{}),o.stdin.on("error",()=>{}),o.once("error",l=>c({error:l,status:null,stdout:"",unavailable:!0})),o.once("close",l=>c({error:null,status:l,stdout:Buffer.concat(a).toString("utf8"),unavailable:!1})),t===void 0?o.stdin.end():o.stdin.end(`${t}
|
|
97
|
+
`)})}async function pe(){return(await G(["show-keychain-info"])).status===0}function Ee(e){try{let t=typeof e=="string"?JSON.parse(e):e;if(t&&typeof t=="object"&&!Array.isArray(t)&&typeof t.token=="string"&&typeof t.tenantId=="string"&&(t.personalAccessTokenId===void 0||typeof t.personalAccessTokenId=="string")&&(t.tokenName===void 0||typeof t.tokenName=="string"))return{token:t.token,tenantId:t.tenantId,...t.personalAccessTokenId?{personalAccessTokenId:t.personalAccessTokenId}:{},...t.tokenName?{tokenName:t.tokenName}:{}}}catch{}return null}async function lt(e,t,n){await le(e,n);let r=R(e);if(z(n)==="auto"&&await pe()){let o=JSON.stringify(t),a=["add-generic-password","-a",r,"-s",de,"-U","-X",Buffer.from(o,"utf8").toString("hex")].join(" ");if((await G(["-i"],a)).status===0)return await j(b(e,n)),"keychain"}return await N(b(e,n),`${JSON.stringify({account:r,activeStore:"file",credential:t})}
|
|
98
|
+
`),"file"}async function pt(e,t){let n=R(e);try{let r=JSON.parse(await q(b(e,t),"utf8"));if(!r||typeof r!="object"||Array.isArray(r)||r.account!==n)return{state:"invalid"};if(r.revoked===!0)return{state:"revoked"};let o=Ee(r.credential);return o?{activeStore:r.activeStore==="file"?"file":null,credential:o,state:"valid"}:{state:"invalid"}}catch(r){return r&&r.code==="ENOENT"?{state:"missing"}:{state:"invalid"}}}async function Ne(e,t){await le(e,t);let n=z(t),r=await pt(e,t);if(r.state==="revoked")return null;if(r.state==="valid"&&(r.activeStore==="file"||n==="file"))return r.credential;if(n==="file")return null;let o=null;if(await pe()){let a=await G(["find-generic-password","-a",R(e),"-s",de,"-w"]);a.status===0&&(o=Ee(a.stdout.trim()))}return o||(r.state==="valid"?r.credential:null)}async function Oe(e,t){await le(e,t);let n=R(e);if(z(t)==="file")return await N(b(e,t),`${JSON.stringify({account:n,revoked:!0})}
|
|
99
|
+
`),{keychainDeleted:!0};if(ne===null)return await j(b(e,t)),{keychainDeleted:!0};if(!await pe())return await N(b(e,t),`${JSON.stringify({account:n,revoked:!0})}
|
|
100
|
+
`),{keychainDeleted:!1};let r=await G(["delete-generic-password","-a",n,"-s",de]);return r.status!==0&&r.status!==44?(await N(b(e,t),`${JSON.stringify({account:n,revoked:!0})}
|
|
101
|
+
`),{keychainDeleted:!1}):(await j(b(e,t)),{keychainDeleted:!0})}function Ce(e,t){return e["--token"]!==void 0?e["--token"]:t.HYPERSCALE_TOKEN||void 0}async function $(e,t,n=!1){let r=await V(t),o=Ce(e,t);if(o!==void 0){if(!o)throw Q();let c=_(e,t,r??{}),d=await A(c,o),l=r?.baseUrl===c.baseUrl&&r.environment===c.environment&&r.email===d.email;return{...c,email:d.email,identity:d,personalAccessTokenId:d.personalAccessTokenId,selectedProduct:l?r.selectedProduct:null,tenantId:d.tenantId,token:o,tokenName:d.name}}if(!r){if(n)return null;throw Q()}let a=_(e,t,r);if(a.baseUrl!==r.baseUrl||a.environment!==r.environment)throw new u(`The active founder login belongs to ${r.baseUrl} (${r.environment}). Log in again to change it.`);let i=await Ne(r,t);if(!i){if(n)return null;throw Q()}return{...r,...i}}function B(e){return e.replace(new RegExp("\\p{Cc}","gu"),t=>`
|
|
102
|
+
\r`.includes(t)?t:"")}function K(e){try{return new URL(e).origin}catch{return null}}function S(e,t){let n=e;for(let r of t)typeof r=="string"&&r.length>0&&(n=n.replaceAll(r,"[redacted]"));return n}async function _e(e,t,n={},r){let o=`${e.baseUrl}${t}`,a=K(e.baseUrl);if(K(o)!==a)throw new u(`The requested path ${t} leaves the ${a} origin; refusing the request.`);try{let i=await fetch(o,{...n,headers:{accept:"application/json",...r?{authorization:`Bearer ${r}`}:{},"x-hyperscale-environment":e.environment,...n.headers},signal:AbortSignal.timeout(re),redirect:"manual"});if(i.status>=300&&i.status<400)throw new u(`${o} redirected, so no credential was sent on. Point --base-url at the origin the API answers on.`);return{response:i,text:B(await i.text())}}catch(i){throw i instanceof u?i:new u(`Could not reach ${o}: ${i.message}`)}}async function g(e,t,n={},r,o=[]){let{response:a,text:i}=await _e(e,t,n,r);if(!a.ok)throw U(a,i,o);try{return JSON.parse(i)}catch{throw new u(`HTTP ${a.status} returned invalid JSON`)}}function P(e,t=globalThis.crypto.randomUUID()){return{body:JSON.stringify(e),headers:{"content-type":"application/json","idempotency-key":t},method:"POST"}}async function mt(){let e=[];for await(let t of process.stdin)e.push(Buffer.from(t));return Buffer.concat(e).toString("utf8")}async function L(e,t,n={},r){let o=`${e.baseUrl}${t}`,a=K(e.baseUrl);if(K(o)!==a)throw new u(`The product document puts ${t} on another origin than the ${a} you configured; refusing to send the key there.`);try{let i=await fetch(o,{...n,headers:{accept:"application/json",authorization:`Bearer ${e.apiKey}`,"x-hyperscale-environment":e.environment,...n.headers},signal:AbortSignal.timeout(re),redirect:"manual"});if(i.status>=300&&i.status<400)throw new u(`${o} redirected, so the key was not sent on. Point --base-url at the origin the API answers on; the usual cause is http:// where it serves https://.`);return{response:i,text:B(await i.text())}}catch(i){throw i instanceof u?i:r&&(i?.name==="TimeoutError"||i?.name==="AbortError")?new u(`product run ${r} timed out after ${re/1e3} seconds.`):new u(`Could not reach ${o}: ${i.message}`)}}async function je(e){let{response:t,text:n}=await L(e,"/v1/product.json");if(!t.ok)throw U(t,n,[e.apiKey]);let r=ft(n);if(!r)throw new Error("The product document is not in the expected format; upgrade the CLI.");let o=r.operations.map(a=>{if(typeof a.summary!="string"||typeof a.description!="string")throw new u(`The product document carries no prose for ${a.operationId}. The server descriptor predates operation prose. Redeploy the platform, then recompose the Product.`);return{description:a.description,idempotency:a.idempotency,method:a.method,name:a.name,operationId:a.operationId,path:a.path,summary:a.summary}});return{compositionId:r.composition.id,operations:o,packageName:r.sdk?r.sdk.packageName.trim():null,title:r.title.trim()}}function ft(e){let t;try{t=JSON.parse(e)}catch{return null}let n=ae(t),r=o=>typeof o=="string";if(!E(n)||n.schemaVersion!==1||!r(n.title)||!E(n.composition)||!r(n.composition.id)||!Array.isArray(n.operations))return null;for(let o of n.operations)if(!E(o)||!r(o.method)||!r(o.path)||!r(o.name)||!r(o.operationId)||!r(o.idempotency))return null;return n.sdk!==void 0&&(!E(n.sdk)||!r(n.sdk.packageName))?null:n}function E(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function ae(e){return typeof e=="string"?B(e):Array.isArray(e)?e.map(ae):E(e)?Object.fromEntries(Object.entries(e).map(([t,n])=>[B(t),ae(n)])):e}function Re(e){let t=e.get("x-trace-id");if(t&&t.trim()!=="")return t.trim();let n=e.get("traceparent");if(n){let r=/^00-([0-9a-fA-F]{32})-[0-9a-fA-F]{16}-[0-9a-fA-F]{2}$/.exec(n.trim());if(r)return r[1]}return null}function ht(e){if(!e||e.trim()==="")return null;try{return JSON.parse(e)}catch{return e}}function yt(e,t=[],n){let r;try{r=JSON.parse(e)}catch{r=null}let o=r&&typeof r=="object"&&r.error&&typeof r.error=="object"?r.error:null,a=typeof o?.code=="string"?o.code:void 0,i=typeof o?.message=="string"?o.message:e.trim(),c=S(i,t),d=a&&typeof o?.message=="string"?`${a}: ${c}`:c,l=o?.details!==void 0?F(o.details,t):void 0,p=r&&typeof r=="object"&&typeof r.requestId=="string"?r.requestId:void 0,m=n?`HTTP ${n}`:"HTTP error";return{code:a,details:l,humanMessage:d,redactedMessage:c,requestId:p,structuredError:{code:a??"http_error",message:c||m,...l!==void 0?{details:l}:{}}}}function U(e,t,n=[]){let r=yt(t,n,e.status),o=e.headers.get("x-request-id")??r.requestId??null,a=e.headers.get("hyperscale-operation-id")??null,i=e.headers.get("hyperscale-receipt-id")??null,c=Re(e.headers),d=r.humanMessage;return new T(`HTTP ${e.status}${d?` \xB7 ${d}`:""}${o?`
|
|
103
|
+
Request id: ${o}`:""}`,{code:r.code,details:r.details,operationId:a,receiptId:i,requestId:o,status:e.status,structuredError:r.structuredError,traceId:c})}function me(e,t){return{authenticated:!0,baseUrl:e.baseUrl,email:t.email,environment:e.environment,expiresAt:t.expiresAt,personalAccessTokenId:t.personalAccessTokenId,role:t.role,scopes:t.scopes,selectedProduct:e.selectedProduct,teamId:t.teamId,tenantId:t.tenantId,tokenName:t.name,userId:t.userId}}function wt(e){if(!e||typeof e!="object"||typeof e.userId!="string"||typeof e.email!="string"||typeof e.tenantId!="string"||typeof e.teamId!="string"||typeof e.role!="string"||typeof e.personalAccessTokenId!="string"||typeof e.name!="string"||!Array.isArray(e.scopes)||e.scopes.some(t=>typeof t!="string")||typeof e.expiresAt!="string"||e.status!=="active")throw new u("personal_access_token.current returned invalid data");return e}async function A(e,t){try{return wt(await g(e,Qe,{},t,[t]))}catch(n){throw!(n instanceof T)||n.status!==401?n:new u(`That founder PAT was not accepted (HTTP 401). ${C}${n.requestId?` Request id: ${n.requestId}.`:""}`,{code:"founder_pat_rejected",fix:C})}}function gt(e,t){return e.HYPERSCALE_CLI_BROWSER?{command:e.HYPERSCALE_CLI_BROWSER,args:[t]}:e.HYPERSCALE_NO_BROWSER==="1"||e.CI==="1"||e.CI==="true"||process.platform==="linux"&&!e.DISPLAY&&!e.WAYLAND_DISPLAY?null:process.platform==="darwin"?{command:"/usr/bin/open",args:[t]}:process.platform==="win32"?{command:"rundll32.exe",args:["url.dll,FileProtocolHandler",t]}:{command:"xdg-open",args:[t]}}async function kt(e,t){let n=gt(e,t);return n?new Promise(r=>{let o=Se(n.command,n.args,{detached:!0,stdio:"ignore"});o.once("error",()=>r(!1)),o.once("spawn",()=>{o.unref(),r(!0)})}):!1}function Z(e){return new Promise(t=>{if(!e.listening){t();return}e.close(()=>t())})}async function $t(e,t){let n=globalThis.crypto.randomUUID(),r=!1,o,a=new Promise((k,y)=>{o={reject:y,resolve:k}}),i=Ye((k,y)=>{let w=new URL(k.url??"/","http://127.0.0.1");if(k.method!=="GET"||w.pathname!=="/callback"){y.writeHead(404,{"content-type":"text/plain; charset=utf-8"}),y.end(`Not found.
|
|
104
|
+
`);return}if(r){y.writeHead(409,{"content-type":"text/plain; charset=utf-8"}),y.end(`Login callback was already received.
|
|
105
|
+
`);return}if(w.searchParams.get("state")!==n){y.writeHead(400,{"content-type":"text/plain; charset=utf-8"}),y.end(`Login state did not match. Return to the terminal.
|
|
106
|
+
`);return}if(w.searchParams.get("error")!==null){r=!0,y.writeHead(200,{"content-type":"text/plain; charset=utf-8"}),y.end(`Login declined. Return to the terminal.
|
|
107
|
+
`),o.reject(new u("Portal login was declined. Run hyperscale auth login to start again.",{code:"auth_callback_denied"}));return}let H=w.searchParams.get("grant"),ye=w.searchParams.get("tenantId");if(!H||!ye){y.writeHead(400,{"content-type":"text/plain; charset=utf-8"}),y.end(`Login callback is missing its grant or tenant.
|
|
108
|
+
`);return}r=!0,y.writeHead(200,{"content-type":"text/plain; charset=utf-8"}),y.end(`Login received. Return to the terminal.
|
|
109
|
+
`),o.resolve({grant:H,tenantId:ye})});await new Promise((k,y)=>{let w=H=>y(H);i.once("error",w),i.listen(0,"127.0.0.1",()=>{i.off("error",w),k()})}),i.once("error",k=>o.reject(k));let c=i.address();if(!c||typeof c=="string")throw await Z(i),new u("Could not bind the localhost login callback");let d=`http://127.0.0.1:${c.port}/callback`,l=new URL("/auth/cli",e.baseUrl);l.searchParams.set("callback",d),l.searchParams.set("state",n);let p=new URL("/signin",e.baseUrl);p.searchParams.set("returnTo",`${l.pathname}${l.search}`);let m=p.toString();if(!await kt(t,m))return await Z(i),null;process.stderr.write(`Opening portal sign-in: ${m}
|
|
110
|
+
`);let I=setTimeout(()=>{o.reject(new u("Portal login timed out. Run hyperscale auth login to start a new callback.",{code:"auth_callback_timeout"}))},ot);try{return await a}finally{clearTimeout(I),await Z(i)}}function ke(e){let t={authenticated:!1,browserOpened:!1,next:["export HYPERSCALE_TOKEN=hyperscale_pat_...","hyperscale auth login --no-browser"],patMintUrl:oe,requestAccessUrl:O};if(e["--json"]){f(t);return}s("No browser detected. Mint a founder PAT in the portal, then run:");for(let n of t.next)s(` ${n}`);s(`PAT desk: ${oe}`),s(`No access yet: ${O}`)}async function $e(e,t,n,r,o){let a=await V(o),i={email:t.email,...e,selectedProduct:a&&a.email===t.email&&a.baseUrl===e.baseUrl&&a.environment===e.environment?a.selectedProduct:null},c=await lt(i,{personalAccessTokenId:t.personalAccessTokenId,token:n,tokenName:t.name,tenantId:t.tenantId},o);try{await W(o,i)}catch(l){throw await Oe(i,o),l}if(c==="file"){let l=z(o)==="file"?"Founder PAT file storage is active.":"macOS Keychain is unavailable.";process.stderr.write(`${l} The founder PAT is in ${b(i,o)} with mode 0600.
|
|
111
|
+
`)}let d=me(i,t);r["--json"]?f(d):s(`Logged in as ${t.email} with PAT ${t.name}.`)}async function It(e,t){let n=_(e,t),r=Ce(e,t);if(r){if(!r.startsWith("hyperscale_pat_"))throw new u("Founder PATs start with hyperscale_pat_. Product API keys belong in HYPERSCALE_API_KEY.");let d=await A(n,r);await $e(n,d,r,e,t);return}if(e["--no-browser"]){ke(e);return}let o=await $t(n,t);if(!o){ke(e);return}let a=await g(n,"/v1/personal-access-token-login-grants/exchange",P({tenantId:o.tenantId,grant:o.grant}),void 0,[o.grant]),i=a?.secret;if(typeof i!="string"||!i.startsWith("hyperscale_pat_")||a?.tenantId!==o.tenantId)throw new u("CLI login grant exchange returned an invalid PAT");let c=await A(n,i);await $e(n,c,i,e,t)}async function bt(e,t){let n=await $(e,t),r=n.identity??await A(n,n.token),o=me(n,r);if(e["--json"]){f(o);return}s(`User: ${r.email}`),s(`Tenant: ${r.tenantId}`),s(`Role: ${r.role}`),s(`Token: ${r.name}`),s(`Scopes: ${r.scopes.join(", ")}`),s(`Expires: ${r.expiresAt}`),s(`API: ${n.baseUrl}`),s(`Environment: ${n.environment}`),s(`Product: ${n.selectedProduct??"not selected"}`)}async function Pt(e,t){let n=await V(t);if(!n){e["--json"]?f({status:"signed_out"}):s("Already logged out.");return}let r=await Ne(n,t);if(e["--revoke"]&&!r)throw new u("The local founder PAT is missing, so the CLI cannot revoke it.");let o=r?.personalAccessTokenId,a=r?.tokenName;if(e["--revoke"]&&r){if(!o||!a){let d=await A(n,r.token);o=d.personalAccessTokenId,a=d.name}await g(n,`/v1/personal-access-tokens/${encodeURIComponent(o)}/revoke`,P({tenantId:r.tenantId,personalAccessTokenId:o}),r.token,[r.token])}let i=await Oe(n,t),c=e["--revoke"]===!0;St(e,{cleanup:i,personalAccessTokenId:o,revoked:c,status:"signed_out",tokenName:a})}function St(e,t){let n=t.cleanup.keychainDeleted?"complete":"tombstoned";if(e["--json"])f({credentialCleanup:n,...t.personalAccessTokenId?{personalAccessTokenId:t.personalAccessTokenId}:{},...t.revoked===void 0?{}:{revoked:t.revoked},status:t.status,...t.tokenName?{tokenName:t.tokenName}:{},...t.revoked===!1?{tokenStillValid:!0}:{}});else{let r=t.tokenName&&t.personalAccessTokenId?`${t.tokenName} (${t.personalAccessTokenId})`:"with unavailable local metadata";t.revoked?s(`Revoked founder PAT ${r} and forgot local state.`):(s(`Forgot local founder PAT ${r}.`),s("The PAT stays valid until expiry; revoke at /desk/security/tokens."))}t.cleanup.keychainDeleted||process.stderr.write(`Keychain cleanup failed. A 0600 profile tombstone blocks the stale founder PAT.
|
|
112
|
+
`)}function v(e,t){if(!e||typeof e!="object"||!Array.isArray(e.items))throw new u(`${t} returned an invalid collection`);return e.items}async function x(e,t,n,r,o,a=[]){let i=[],c=new Set,d,l;for(;;){let I=new URLSearchParams(n);d&&I.set("cursor",d);let k=I.size>0?`?${I}`:"",y=await g(e,`${t}${k}`,{},o,a);l===void 0&&(l=y),i.push(...v(y,r));let w=y.nextCursor;if(typeof w!="string"||w.length===0)break;if(c.has(w))throw new u(`${r} repeated cursor ${w}`);c.add(w),d=w}let{items:p,nextCursor:m,...h}=l;return{...h,items:i}}async function At(e,t){let n=await x(e,"/v1/blueprints",{},"blueprint.list"),r=v(n,"blueprint.list");if(t["--json"]){f(n);return}s("ID Name Summary");for(let o of r)s(`${o.id} ${o.name}${o.summary?` ${o.summary}`:""}`);s("Next:"),s(" hyperscale blueprint show <id>"),s(" hyperscale product create --blueprint <id> --name <name>")}async function vt(e,t,n){if(!n)throw new u("blueprint show needs a Blueprint id");let r=await g(e,`/v1/blueprints/${encodeURIComponent(n)}`),o=Tt(r,e.baseUrl);if(t["--json"]){f(o);return}s(`${o.name} (${o.id})`),s(o.summary),s(o.description),s("Nouns:");for(let a of o.customInstruments??[])s(` ${a.name} (${a.id}): ${a.summary}`);for(let a of o.instruments??[])s(` ${a.title} (${a.id}): ${a.summary}`);s("Verbs:");for(let a of o.verbs??[])s(` ${a.alias} -> ${a.operation}: ${a.summary}`);s("Parties:");for(let a of o.parties??[])s(` ${a.instrumentId}.${a.role} -> ${a.accountField}`);s("Money flows:");for(let a of o.moneyFlows??[]){let i=a.sourceAccount??"action input",c=a.destinationAccount??"action input",d=a.amountPath??"action input";s(` ${a.action} [${a.kind}]: ${i} -> ${c}; amount ${d}`)}s("Fee forms:");for(let a of o.feeForms??[]){let i=a.bps?`${a.bps} bps`:a.amountSar?`SAR ${a.amountSar}`:a.includedQuantity?`${a.includedQuantity} included`:a.kind;s(` ${a.id}: ${i} per ${a.unit}. ${a.summary}`)}o.priceEstimate&&(s("Price estimate:"),s(` monthlySar: SAR ${Number(o.priceEstimate.monthlySar).toLocaleString("en-US")}`),s(` setupSar: SAR ${Number(o.priceEstimate.setupSar).toLocaleString("en-US")}`),s(` complexityScore: ${o.priceEstimate.complexityScore}`)),s("Dials:");for(let a of o.dials??[])s(` ${a.instrumentId}.${a.key} (${a.kind}): ${a.summary}`);s("Journeys:");for(let a of o.journeys??[])s(` ${a.title} (${a.id}): ${a.summary}`),s(` ${a.steps.join(" -> ")}`);o.hsxStructured&&(s("HSX:"),s(` Source:
|
|
113
|
+
${Ie(o.hsxStructured.source," ")}`),o.hsxStructured.document&&s(` Structured document:
|
|
114
|
+
${Ie(JSON.stringify(o.hsxStructured.document,null,2)," ")}`)),s("Terms:");for(let[a,i]of Object.entries(o.terminology))s(` ${a}: ${i.definition}`),s(` ${i.href}`);s("Next:"),s(` hyperscale product create --blueprint ${o.id} --name <name>`)}function Tt(e,t){let n=xt(e?.hsx);return{...e,...n?{hsxStructured:n}:{},terminology:{firedBy:{definition:"Who invokes an action: tenant through the Product surface, operator through a console session, or machine when a due condition arrives.",href:`${t}/glossary#action-caller`},publicIntents:{definition:"The retired name for publicActions. publicActions contains the canonical action IDs frozen into a composed Product.",href:`${t}/glossary#public-actions`},trustFile:{definition:"The evidence attached to a business record for later review, such as inspection, authentication, delivery, or proof-of-work records.",href:`${t}/glossary#trust-file`}}}}function xt(e){if(typeof e!="string"||e.length===0)return;try{let n=JSON.parse(e);if(n&&typeof n=="object"&&!Array.isArray(n))return{document:n,language:"hsx-json",source:e,verdict:"valid"}}catch{}let t=compile(e);return{diagnostics:t.diagnostics,...t.artifacts?{document:t.artifacts.document,frame:t.artifacts.frame}:{},language:"hsx-text",source:e,verdict:t.verdict}}function Ie(e,t){return e.split(`
|
|
115
|
+
`).map(n=>`${t}${n}`).join(`
|
|
116
|
+
`)}function Et(e){return{operationId:e.headers.get("hyperscale-operation-id")??"not returned",receiptId:e.headers.get("hyperscale-receipt-id")??"not returned"}}function Nt(e,t,n=[]){if(!e.ok)throw U(e,t,n);try{return JSON.parse(t)}catch{throw new u(`HTTP ${e.status} returned invalid JSON`)}}function Ot(e,t){s(`${e} operation: ${t.operationId}`),s(`${e} receipt: ${t.receiptId}`)}function Ct(e,t){let n=e instanceof u?e:new u("hyperscale start failed after the Product was created",{code:"start_failed_after_compose"});return n.shownOnce=t,n}function _t(e){if(!e["--blueprint"]&&!(process.stdin.isTTY&&process.stderr.isTTY))throw new u("hyperscale start needs an interactive terminal to choose a company. Pass --blueprint <slug> in scripts and non-interactive environments.",{code:"start_blueprint_required",fix:'Run "hyperscale blueprint list", then pass --blueprint <slug>.'})}function jt(e){return v(e,"blueprint.list").map(t=>{if(typeof t?.id!="string"||t.id.length===0||typeof t?.name!="string"||t.name.length===0)throw new u("blueprint.list returned an invalid start choice");return{id:t.id,name:t.name,summary:typeof t.summary=="string"?t.summary:""}})}async function Rt(e,t){let n=await x(t,"/v1/blueprints",{},"blueprint.list"),r=jt(n);if(r.length===0)throw new u("The Blueprint catalog has no companies to build.");let o=e["--blueprint"];if(o){let m=r.find(({id:h})=>h===o);if(m)return m;throw new u(`Unknown Blueprint: ${o}`,{fix:'Run "hyperscale blueprint list" and pass one listed slug to --blueprint.'})}process.stderr.write(`Which company do you want to build?
|
|
117
|
+
`);for(let[m,h]of r.entries()){let I=h.summary.replace(/\s+/g," ").trim();process.stderr.write(` ${m+1}. ${h.name} (${h.id})${I?`: ${I}`:""}
|
|
118
|
+
`)}let a=Fe({input:process.stdin,output:process.stderr,terminal:!0}),i=new AbortController,c=()=>i.abort();process.stdin.once("end",c),process.stdin.readableEnded&&i.abort();let d;try{try{d=(await a.question("Choose a number or Blueprint slug: ",{signal:i.signal})).trim()}catch(m){throw m?.name!=="AbortError"&&m?.code!=="ABORT_ERR"?m:new u("Start cancelled before a Blueprint was chosen.",{code:"start_cancelled"})}}finally{process.stdin.off("end",c),a.close()}let l=Number(d),p=Number.isInteger(l)?r[l-1]:r.find(({id:m})=>m===d);if(p)return p;throw new u(`No Blueprint matches ${JSON.stringify(d)}.`,{fix:"Run hyperscale start again and choose a listed number or slug."})}async function be(e,t){_t(e);let n={};try{await Lt(e,t,n)}catch(r){throw typeof n.apiKey!="string"?r:Ct(r,n.apiKey)}}async function Lt(e,t,n){let r=await $(e,t),o=await A(r,r.token),a=await Rt(e,r),i=e["--name"]??a.name;e["--json"]||s(`Authenticated: ${o.email}`);let c=await _e(r,"/v1/products/blueprint-compose",P({blueprintId:a.id,name:i,tenantId:r.tenantId}),r.token),d=Nt(c.response,c.text,[r.token]);if(typeof d?.productId!="string"||!rt.test(d.productId)||typeof d?.productBuildId!="string"||d?.blueprintId!==a.id)throw new u("product.blueprint.compose returned an invalid start Product");let l=d?.shown_once;if(typeof l!="string"||l.length===0)throw new u("The composed Product did not return its one-time API key. Choose a new Product name and run hyperscale start again.",{code:"start_api_key_unavailable"});n.apiKey=l;let p=Et(c.response);await W(t,{...r,selectedProduct:d.productId}),e["--json"]||(s(`Product: ${d.productId}`),s(`Blueprint: ${d.blueprintId}`),Ot("Compose",p));let m=[`hyperscale compose plan product.hsx --product ${d.productId}`],h="Composition completed. Run SDK journeys against your Product.",I={blueprintId:d.blueprintId,composeOnly:!0,nextCommands:m,notice:h,productBuildId:d.productBuildId,productId:d.productId,receipts:[{stage:"product.blueprint.compose",...p}],...typeof d.startKeyId=="string"?{startKeyId:d.startKeyId}:{},shown_once:l};if(e["--json"]){f(I);return}s(h),s(`Shown once Product API key: ${l}`),s("Next:");for(let k of m)s(` ${k}`);s(" Run journeys with the Hyperscale SDK using the Product API key above.")}async function Ut(e,t){let n=e["--blueprint"],r=e["--name"];if(!n)throw new u("product create needs --blueprint <id>");if(!r)throw new u("product create needs --name <name>");let o=await $(e,t),a;try{a=await x(o,"/v1/products",{tenantId:o.tenantId},"product.list",o.token,[o.token])}catch(m){if(!(m instanceof T)||m.status!==403)throw m}let i=r.trim().toLocaleLowerCase("en-US"),c=(a?v(a,"product.list"):[]).find(m=>{let h=m?.displayName??m?.name;return typeof h=="string"&&h.trim().toLocaleLowerCase("en-US")===i});if(c){let m=c.productId??c.id??"<id>";throw new u(`A Product named ${JSON.stringify(r.trim())} already exists as ${m}.`,{code:"duplicate_product_name",fix:`Use "hyperscale product select ${m}" or choose another --name.`})}let d=await g(o,"/v1/products/blueprint-compose",P({blueprintId:n,name:r,tenantId:o.tenantId}),o.token,[o.token]);if(typeof d?.productId!="string"||typeof d?.blueprintId!="string"||typeof d?.productBuildId!="string")throw new u("product.blueprint.compose returned an invalid Product");await W(t,{...o,selectedProduct:d.productId});let l=typeof d?.shown_once=="string"&&d.shown_once.length>0?d.shown_once:void 0,p={blueprintId:d.blueprintId,nextSteps:[`hyperscale product show ${d.productId}`,...l?[]:['hyperscale key create --name "Founder CLI"']],productBuildId:d.productBuildId,productId:d.productId,selectedProduct:d.productId,...typeof d.startKeyId=="string"?{startKeyId:d.startKeyId}:{},...l?{shown_once:l}:{}};if(e["--json"]){f(p);return}s(`Product: ${p.productId}`),s(`Blueprint: ${p.blueprintId}`),s(`Build: ${p.productBuildId}`),s(`Selected: ${p.selectedProduct}`),p.shown_once&&s(`Shown once Product API key: ${p.shown_once}`),s("Next:");for(let m of p.nextSteps)s(` ${m}`)}function fe(e){return new URLSearchParams({tenantId:e}).toString()}async function Dt(e,t){let n=await $(e,t),r=await x(n,"/v1/products",{tenantId:n.tenantId},"product.list",n.token,[n.token]),o=v(r,"product.list");if(e["--json"]){f(r);return}if(o.length===0){s('No Products yet. Run "hyperscale blueprint list", then "hyperscale product create --blueprint <id> --name <name>".');return}s("ID Name Status");for(let a of o){let i=a.productId??a.id??"unknown",c=a.displayName??a.name??"unnamed";s(`${i} ${c}${a.status?` ${a.status}`:""}`)}}async function Ht(e,t,n){let r=await $(e,t),o=n??r.selectedProduct;if(!o)throw new u("product show needs an id because no Product is selected. Create a Product first.");let a=await g(r,`/v1/products/${encodeURIComponent(o)}?${fe(r.tenantId)}`,{},r.token,[r.token]);if(e["--json"]){f(a);return}Jt(a,o)}function Jt(e,t){let n=e?.displayName??e?.name??"unnamed",r=e?.status??"unknown",o=e?.blueprint,a=o?.id?`${o.name??o.id}${o.name?` (${o.id})`:""}`:"custom composition",i=e?.cost?.currency??"SAR",c=e?.plan?.monthlySar??e?.cost?.platformMonthlySar,d=e?.plan?.setupSar??e?.cost?.platformSetupSar,l=[...Array.isArray(e?.readiness?.outstandingLiveRequirements)?e.readiness.outstandingLiveRequirements:[],...Array.isArray(e?.readiness?.liveUnavailableCapabilities)?e.readiness.liveUnavailableCapabilities.map(p=>`unavailable:${p}`):[],...Array.isArray(e?.cost?.blockers)?e.cost.blockers.map(p=>p?.code??"pricing"):[]];s(`Name: ${n}`),s(`Product: ${e?.productId??t}`),s(`Status: ${r}`),s(`Blueprint: ${a}`),s(`Monthly: ${c==null?"not returned":`${i} ${c}`}`),s(`Setup: ${d==null?"not returned":`${i} ${d}`}`),s(`Live: ${e?.readiness?.live===!0?"active":"not active"}`),s(`Live blockers: ${l.length>0?l.join(", "):"none"}`);for(let[p,m]of[["openapi","OpenAPI"],["mcp","MCP"],["sdk","SDK"],["graphql","GraphQL"]]){let h=e?.surfaces?.[p];h?.url&&s(`${m}: ${h.url}`)}s("Next:"),s(` hyperscale key create --name "Founder CLI" --product ${e?.productId??t}`)}async function Bt(e,t,n){if(!n)throw new u("product select needs a Product id");let r=await $(e,t),o=await g(r,`/v1/products/${encodeURIComponent(n)}?${fe(r.tenantId)}`,{},r.token,[r.token]);if(o?.productId!==n)throw new u("product.retrieve returned the wrong Product");await W(t,{...r,selectedProduct:n});let a={productId:n,selected:!0};e["--json"]?f(a):s(`Selected Product: ${o.displayName??n} (${n})`)}function Kt(e){return e.map(t=>`${t.path}: error [composer] ${t.code}: ${t.message}`)}async function Yt(e){if(!e)throw new u("compose needs a .hsx file");if(!e.endsWith(".hsx"))throw new u(`compose reads a .hsx file, got ${e}`);let t;try{t=await q(e,"utf8")}catch(n){throw new u(`Could not read ${e}: ${n.message}`)}return{file:e,source:t}}function Ft(e){if(!e||typeof e!="object"||typeof e.ok!="boolean"||!Array.isArray(e.issues))throw new u("composer.check returned an invalid result");return{issues:e.issues.map(n=>{if(!n||typeof n!="object"||typeof n.code!="string"||typeof n.message!="string"||typeof n.path!="string")throw new u("composer.check returned an invalid issue");return{code:n.code,message:n.message,path:n.path}}),ok:e.ok}}async function he(e,t,n,r){let o=await Yt(n),a=await $(e,t),i=r?D(a,e):void 0,c=Ft(await g(a,"/v1/composer/check",P({tenantId:a.tenantId,document:o.source,...e["--catalog-revision"]?{catalogRevisionId:e["--catalog-revision"]}:{}}),a.token,[a.token]));if(!c.ok)throw new J(["composer.check refused the program.",...Kt(c.issues)].join(`
|
|
119
|
+
`),{file:n,issues:c.issues});return{check:c,context:a,productId:i,program:o,catalogRevisionId:e["--catalog-revision"]}}async function qt(e,t,n){let r=await he(e,t,n,!1);if(e["--json"]){f({command:"composer.check",file:n,issues:r.check.issues,ok:!0});return}s(`Check passed: ${n}`)}async function Le(e,t){let n=await g(e.context,"/v1/composer/plan",P({document:e.program.source,tenantId:e.context.tenantId,productId:e.productId,...e.catalogRevisionId?{catalogRevisionId:e.catalogRevisionId}:{}}),e.context.token,[e.context.token]);if(!n||typeof n!="object"||typeof n.summary!="string"||!Array.isArray(n.actions)||!n.pricing||typeof n.pricing!="object")throw new u("composer.plan returned an invalid result");let r=n.actions.filter(o=>!o||typeof o!="object"||o.kind!=="configure_product");if(r.length>0)throw new J([n.summary,...r.map(o=>o&&typeof o=="object"?`${o.kind??"unknown"} ${o.target??"unknown"} ${o.detail??"Composer refused this action."}`:"unknown unknown Composer returned an invalid refusal action.")].join(`
|
|
120
|
+
`),{actions:r,file:t,productId:e.productId});return n}async function Mt(e,t,n){let r=await he(e,t,n,!0),o=await Le(r,n);if(e["--json"]){f({command:"composer.plan",file:n,plan:o,productId:r.productId});return}s(o.summary);for(let a of o.actions)s(`${a.kind} ${a.target} ${a.detail}`);s(`Monthly: SAR ${o.pricing.monthlySar}`),s(`Activation: SAR ${o.pricing.activationSar}`)}async function zt(e,t,n){if(!e["--confirm"]&&!e["--yes"])throw new u("compose apply changes the selected Product. Pass --confirm, or --yes for an agent.");let r=await he(e,t,n,!0);await Le(r,n);let o=await g(r.context,"/v1/products/recompose",P({program:{source:r.program.source},...r.catalogRevisionId?{catalogRevisionId:r.catalogRevisionId}:{},tenantId:r.context.tenantId,productId:r.productId},e["--idempotency-key"]),r.context.token,[r.context.token]);if(!o||typeof o.productBuildId!="string")throw new u("product.recompose returned no new build identity");if(e["--json"]){f({command:"product.recompose",file:n,output:o});return}s(`Product: ${o.productId??r.productId}`),s(`Build: ${o.productBuildId}`),o.buildDigest&&s(`Digest: ${o.buildDigest}`)}function D(e,t){let n=t["--product"]??e.selectedProduct;if(!n)throw new u("No Product selected. Pass --product <id> or create a Product first.");return n}async function Y(e,t,n){let r=await V(t),o=D(r??{},e),a=_(e,t,r??{});if(r&&(a.baseUrl!==r.baseUrl||a.environment!==r.environment))throw new u(`The selected Product belongs to ${r.baseUrl} (${r.environment}). Select a Product at the configured API origin first.`);let i=e["--api-key"]??t.HYPERSCALE_API_KEY;if(!i)throw Ae(o);let c={...a,apiKey:i,productId:o};return await Vt(c,o,n),c}async function Vt(e,t,n){let r=`/v1/products/${encodeURIComponent(t)}/operation-set`,{response:o,text:a}=await L(e,r,{},n);if(o.ok)return;let i;try{i=JSON.parse(a)?.error?.message}catch{i=void 0}throw typeof i=="string"&&i.includes("does not match API key Product")?new u(`${i} Or set HYPERSCALE_API_KEY to a key for ${t}, or pass that key with --api-key.`):U(o,a,[e.apiKey])}async function Ue(e,t){let n=`/v1/products/${encodeURIComponent(e.productId)}/operation-set`,{response:r,text:o}=await L(e,n,{},t);if(!r.ok)throw He(r,o,[e.apiKey]);return Xt(o,r.status)}async function Wt(e,t,n){let r=await Y(e,t),o=await Ue(r);if(n){Gt(o,n,e);return}if(e["--json"]){f(o);return}if(o.status==="legacy"){s("This Product uses a legacy surface. It has no frozen public actions yet."),s(`Build: ${o.productBuildId}`);return}if(o.publicActions.length===0)s("No public actions");else{s("Operation ID Input Kind");for(let a of o.publicActions){let i=a.idempotencyPolicy?.mode==="not_required"?"read-only":"mutation";s(`${a.instrument}.${a.name} ${en(a.inputSchema)} ${i}`)}}if(o.setupOperations.length>0){s("Setup operations (run with hyperscale call)");for(let a of o.setupOperations)s(a.operationName)}if(o.readOperationIds.length>0){s("Reads (run with hyperscale call)");for(let a of o.readOperationIds)s(Zt(a))}s(`Digest: ${o.tenantOperationSetDigest}`),s(`Setup digest: ${o.tenantSetupOperationSetDigest}`),s(`Read digest: ${o.tenantReadOperationSetDigest}`),s(`Build: ${o.productBuildId}`),s(`Surface version: ${o.tenantSurfaceVersion}`)}function Gt(e,t,n){if(e.status==="legacy")throw new u(`This Product uses a legacy surface and has no frozen public action named ${t}. Run "hyperscale product actions" after rebuilding the Product.`);let r=e.publicActions.find(c=>c&&`${c.instrument}.${c.name}`===t),o=Qt(t),a=e.setupOperations.find(c=>c&&(c.operationId===t||c.operationId===o||c.operationName===t));if(a){let{inputSchema:c,operationId:d,operationName:l}=a,p={status:e.status,productBuildId:e.productBuildId,tenantSurfaceVersion:e.tenantSurfaceVersion,tenantSetupOperationSetDigest:e.tenantSetupOperationSetDigest,setupOperationId:d,operationName:l,command:`hyperscale call ${l}`,inputSchema:c};if(n["--json"]){f(p);return}s(`Operation ID: ${d}`),s(`Operation name: ${l}`),s(`Run: hyperscale call ${l}`),s(`Input schema: ${JSON.stringify(c,null,2)}`),(!Array.isArray(c.required)||c.required.length===0)&&s("Input: omit --input or pass {}."),s(`Setup digest: ${e.tenantSetupOperationSetDigest}`),s(`Build: ${e.productBuildId}`),s(`Surface version: ${e.tenantSurfaceVersion}`);return}if(!r)throw new u(`Unknown frozen public action: ${t}. Run "hyperscale product actions" to list exact names.`);let i={status:e.status,productBuildId:e.productBuildId,tenantSurfaceVersion:e.tenantSurfaceVersion,tenantOperationSetDigest:e.tenantOperationSetDigest,publicAction:r};if(n["--json"]){f(i);return}s(`Operation ID: ${r.instrument}.${r.name}`),s(`Instrument: ${r.instrument}`),s(`Input schema: ${JSON.stringify(r.inputSchema,null,2)}`),s(`Output schema: ${JSON.stringify(r.outputSchema,null,2)}`),s(`Actor policy: ${JSON.stringify(r.actorPolicy,null,2)}`),s(`Port policy: ${JSON.stringify(r.portPolicy,null,2)}`),s(`Idempotency policy: ${JSON.stringify(r.idempotencyPolicy,null,2)}`),s(`Receipt policy: ${JSON.stringify(r.receiptPolicy,null,2)}`),s(`Receipt evidence: ${JSON.stringify(r.receiptEvidence,null,2)}`),s(`Digest: ${e.tenantOperationSetDigest}`),s(`Build: ${e.productBuildId}`),s(`Surface version: ${e.tenantSurfaceVersion}`)}function Xt(e,t){let n;try{n=JSON.parse(e)}catch{throw new u(`HTTP ${t} returned invalid JSON`)}if(!n||typeof n!="object"||n.status!=="legacy"&&n.status!=="frozen"||typeof n.productBuildId!="string")throw new u("The Product operation set is not in the expected format. Upgrade the CLI.");if(n.status==="legacy")return n;if(typeof n.tenantSurfaceVersion!="number"||typeof n.tenantOperationSetDigest!="string"||typeof n.tenantReadOperationSetDigest!="string"||typeof n.tenantSetupOperationSetDigest!="string"||!Array.isArray(n.publicActions)||!Array.isArray(n.readOperationIds)||!Array.isArray(n.setupOperationIds)||!Array.isArray(n.setupOperations))throw new u("The Product operation set is not in the expected format. Upgrade the CLI.");return n}function Qt(e){return e.replaceAll(".","_")}function Zt(e){for(let t of["create","list","retrieve"]){let n=`_${t}`;if(e.endsWith(n))return`${e.slice(0,-n.length)}.${t}`}return e}function en(e){if(!e||typeof e!="object")return"input schema unavailable";let t=e.properties&&typeof e.properties=="object"&&!Array.isArray(e.properties)?e.properties:{},n=new Set(Array.isArray(e.required)?e.required.filter(o=>typeof o=="string"):[]),r=Object.entries(t).map(([o,a])=>`${o}${n.has(o)?"":"?"}: ${De(a)}`);return r.length===0?"no input":r.join(", ")}function De(e){return!e||typeof e!="object"?"value":Array.isArray(e.enum)&&e.enum.length>0?e.enum.map(t=>String(t)).join(" | "):e.type==="array"?`${De(e.items)}[]`:typeof e.type=="string"?typeof e.format=="string"?`${e.type} (${e.format})`:e.type:"value"}async function tn(e,t,n){if(!n)throw new u("product run needs a public action");let r=await Y(e,t,n),o=await Ue(r,n);nn(o,n);let a=await Je(e),i=e["--idempotency-key"]??globalThis.crypto.randomUUID(),{response:c,text:d}=await L(r,`/v1/operations/${encodeURIComponent(n)}`,{body:JSON.stringify(a),headers:{"content-type":"application/json","idempotency-key":i},method:"POST"},n);if(!c.ok)throw He(c,d,[r.apiKey],{action:n});let l=c.headers.get("hyperscale-operation-id"),p=c.headers.get("hyperscale-receipt-id");if(e["--json"]){f({idempotencyKey:i,operationId:l,receiptId:p,output:on(d)});return}s(`Operation: ${l??"not returned"}`),s(`Receipt: ${p??"not returned"}`),s(`Idempotency key: ${i}`);let m=Be(d);m&&s(m)}function nn(e,t){if(e.status==="legacy")throw new u(`This Product uses a legacy surface and has no frozen public action named ${t}. Run "hyperscale product actions" after rebuilding the Product.`);let n=e.publicActions.find(o=>o&&`${o.instrument}.${o.name}`===t);if(n)return n;let r=e.publicActions.map(o=>`${o.instrument}.${o.name}`).map(o=>({candidate:o,distance:ie(t,o)})).sort((o,a)=>o.distance-a.distance||o.candidate.localeCompare(a.candidate)).slice(0,3).map(({candidate:o})=>o);throw new u(`Unknown frozen public action: ${t}. Closest valid names: ${r.join(", ")}. Run "hyperscale product actions" to list exact names.`)}function on(e){if(e.trim()==="")return null;try{return JSON.parse(e)}catch{return e}}function He(e,t,n=[],r={}){let o=S(t.trim(),n),a;try{a=JSON.parse(t)}catch{return new u(`HTTP ${e.status}${o?` \xB7 ${o}`:""}`)}if(!a?.error||typeof a.error.message!="string")return new u(`HTTP ${e.status}`);let i=typeof a.error.code=="string"?a.error.code:"user_error",c=i==="user_error"?"":`${i}: `,d=S(`HTTP ${e.status} \xB7 ${c}${a.error.message}`,n),l=rn(a.error.details,n),p;return i==="idempotency_conflict"?p="Reuse the same key only with the same operation and input. Use a new unique key for a different request.":[a.error.message,...l].some(m=>typeof m=="string"&&m.includes("[Truncated]"))&&r.action&&(p=`Run "hyperscale product actions ${r.action}" to read the full input schema and allowed values.`),new u([d,...l].join(`
|
|
121
|
+
`),{code:i,...a.error.details?{details:F(a.error.details,n)}:{},...p?{fix:p}:{}})}function F(e,t){return typeof e=="string"?S(e,t):Array.isArray(e)?e.map(n=>F(n,t)):e&&typeof e=="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[S(n,t),F(r,t)])):e}function rn(e,t){if(!e||typeof e!="object")return[];if(Array.isArray(e.issues))return e.issues.flatMap(r=>{if(!r||typeof r!="object")return[];let a=(Array.isArray(r.path)?r.path.join("."):"input")||"input";return typeof r.message=="string"?[`${a}: ${S(r.message,t)}`]:[]});let n=[];return se(e,"",n,t),n}function se(e,t,n,r){if(Array.isArray(e)){if(e.every(o=>o===null||typeof o!="object")){n.push(`${Pe(t)}: ${S(e.join(", "),r)}`);return}e.forEach((o,a)=>se(o,`${t}[${a}]`,n,r));return}if(e&&typeof e=="object"){for(let[o,a]of Object.entries(e))se(a,t?`${t}.${o}`:o,n,r);return}t&&n.push(`${Pe(t)}: ${S(String(e),r)}`)}function Pe(e){let t=e.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replaceAll("."," ");return t.charAt(0).toUpperCase()+t.slice(1)}async function an(e,t){let n=await $(e,t),r=D(n,e),o=await g(n,"/v1/sandbox-api-keys",P({name:e["--name"]??"Founder CLI",tenantId:n.tenantId,productId:r}),n.token,[n.token]);if(e["--json"]){f(o);return}s(`Key: ${o.apiKeyId??"unknown"}`),s(`Product: ${o.productId??r}`),s(`Status: ${o.status??"unknown"}`),o.secret?(s(`Secret: ${o.secret}`),s("Store it now. Hyperscale will not return it again."),s("Next:"),s(` export HYPERSCALE_API_KEY=${sn(o.secret)}`),s(` hyperscale product actions --product ${r}`)):s("The key already existed, so the one-time secret is unavailable.")}function sn(e){return`'${String(e).replaceAll("'",`'"'"'`)}'`}async function cn(e,t){let n=await $(e,t),r=D(n,e),o=await x(n,"/v1/api-keys",{tenantId:n.tenantId},"api_key.list",n.token,[n.token]),a=v(o,"api_key.list").filter(c=>c.productId===r),i={...o,items:a};if(e["--json"]){f(i);return}for(let c of a)s(`${c.apiKeyId} ${c.name??"unnamed"} ${c.status??"unknown"}`)}async function un(e,t,n){if(!n)throw new u("key revoke needs an API key id");let r=await $(e,t),o=D(r,e),a=await g(r,`/v1/api-keys/${encodeURIComponent(n)}/revoke`,P({tenantId:r.tenantId,productId:o}),r.token,[r.token]);e["--json"]?f(a):s(`Key ${a.apiKeyId??n}: ${a.status??"revoked"}`)}async function dn(e,t){let n=await $(e,t),r=n.identity??await A(n,n.token),o=me(n,r);if(e["--json"]){f(o);return}s(`User: ${r.email}`),s(`Tenant: ${r.tenantId}`),s(`Role: ${r.role}`),s(`Token: ${r.name}`),s(`Expires: ${r.expiresAt}`)}async function ln(e,t,n){let r=await je(e),o=n?n.toLowerCase():null,a=o?r.operations.filter(c=>c.name.toLowerCase().includes(o)||c.path.toLowerCase().includes(o)):r.operations;if(t["--json"]){s(JSON.stringify(a,null,2));return}if(a.length===0){s(n?`No operation matches ${n}`:"No operations");return}let i=Math.max(...a.map(c=>c.name.length));for(let c of a)s(`${c.name.padEnd(i)} ${c.method.padEnd(6)}${c.path}`)}async function pn(e,t){let n=await $(e,t),r=await g(n,`/v1/team/members?${fe(n.tenantId)}`,{},n.token,[n.token]);if(!r||typeof r!="object"||!Array.isArray(r.members)||!Array.isArray(r.invitations))throw new u("team.member.list returned invalid data");if(e["--json"]){f(r);return}for(let o of r.members)s(`${o.email??"unknown"} ${o.role??"unknown"} ${o.status??"unknown"}`);for(let o of r.invitations)s(`${o.email??"unknown"} ${o.role??"unknown"} pending invitation`)}async function mn(e,t){let n=e["--email"],r=e["--role"];if(!n)throw new u("team invite needs --email <email>");if(!r)throw new u("team invite needs --role <role>");let o=await $(e,t),a=await g(o,"/v1/team/members/invite",P({email:n,role:r,tenantId:o.tenantId}),o.token,[o.token]);if(e["--json"]){f(a);return}s(`Invitation: ${a.invitationId??"unknown"}`),s(`Email: ${a.email??n}`),s(`Role: ${a.role??r}`),s(`Expires: ${a.expiresAt??"unknown"}`),a.inviteToken&&(s(`Invite token: ${a.inviteToken}`),s("Share it now. Hyperscale will not return it again."))}async function fn(e,t){let n=await $(e,t),r=await x(n,"/v1/activity",{tenantId:n.tenantId},"activity.list",n.token,[n.token]),o=v(r,"activity.list");if(e["--json"]){f(r);return}s("Time Activity Target Status");for(let a of o){let i=a.operation??a.auditEvent??"activity",c=a.resourceKind&&a.resourceId?`${a.resourceKind}:${a.resourceId}`:a.resourceKind??a.resourceId??"-";s(`${a.occurredAt??"unknown"} ${i} ${c} ${a.status??"recorded"}`)}}function hn(e,t){let n={...t},r=[],o=e.path.replace(/\{([^}]+)\}/g,(a,i)=>{let c=n[i];return c==null?(r.push(i),""):(delete n[i],encodeURIComponent(String(c)))});if(r.length>0)throw new u(`${e.name} needs ${r.join(", ")} in --input`);return{path:o,remaining:n}}function yn(e){let t=new URLSearchParams;for(let[r,o]of Object.entries(e))o!=null&&t.set(r,typeof o=="string"?o:JSON.stringify(o));let n=t.toString();return n?`?${n}`:""}function ie(e,t){let n=Array.from({length:t.length+1},(r,o)=>o);for(let r=1;r<=e.length;r+=1){let o=[r];for(let a=1;a<=t.length;a+=1)o[a]=Math.min(o[a-1]+1,n[a]+1,n[a-1]+(e[r-1]===t[a-1]?0:1));n.splice(0,n.length,...o)}return n[t.length]}function wn(e,t){let n=e.find(a=>a.name===t);if(n)return n;let r=e.filter(a=>a.operationId===t);if(r.length===1)return r[0];if(r.length>1)throw new u(`${t} matches more than one operation. Use one of: ${r.map(a=>a.name).join(", ")}.`);let o=e.map(a=>({candidate:a,distance:Math.min(ie(t,a.name),ie(t,a.operationId))})).sort((a,i)=>a.distance-i.distance||a.candidate.name.localeCompare(i.candidate.name)).slice(0,3).flatMap(({candidate:a})=>[a.name,a.operationId]);throw new u(`${t} is not an operation in the selected Product's machine document. Closest valid names: ${o.join(", ")}.`)}async function gn(e,t,n){if(!n)throw new u("call needs an operation name");let r=await je(e),o=wn(r.operations,n),a=await Je(t),{path:i,remaining:c}=hn(o,a),d={method:o.method},l=i;o.method==="GET"?l+=yn(c):(d.body=JSON.stringify(c),d.headers={"content-type":"application/json",...o.idempotency==="not_required"?{}:{"idempotency-key":t["--idempotency-key"]??globalThis.crypto.randomUUID()}});let{response:p,text:m}=await L(e,l,d);if(p.ok){if(t["--json"]){let h=ht(m),I=p.headers.get("hyperscale-operation-id")??null,k=p.headers.get("hyperscale-receipt-id")??null,y=p.headers.get("x-request-id")??(h&&typeof h=="object"&&typeof h.requestId=="string"?h.requestId:null),w=Re(p.headers);f({status:p.status,data:h,requestId:y,operationId:I,receiptId:k,traceId:w});return}s(Be(m));return}throw U(p,m,[e.apiKey])}async function Je(e){if(e["--input"]!==void 0&&e["--input-file"]!==void 0)throw new u("Use only one of --input and --input-file");if(e["--input"]!==void 0)return ee(e["--input"],"--input");if(e["--input-file"]!==void 0){let t;try{t=await q(e["--input-file"],"utf8")}catch(n){throw new u(`Could not read ${e["--input-file"]}: ${n.message}`)}return ee(t,"--input-file")}if(!process.stdin.isTTY){let t=await mt();if(t.trim()!=="")return ee(t,"stdin")}return{}}function ee(e,t="--input"){if(e===void 0)return{};let n;try{n=JSON.parse(e)}catch(r){throw new u(`${t} is not valid JSON: ${r.message}`)}if(n===null||typeof n!="object"||Array.isArray(n))throw new u(`${t} must be a JSON object`);return n}function Be(e){if(e.trim()==="")return"";try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}function s(e){process.stdout.write(`${e}
|
|
122
|
+
`)}function f(e){s(JSON.stringify(e,null,2))}function kn(e){for(let t=0;t<e.length;t+=1){let n=e[t];if(!n.startsWith("--"))return n;ve.has(n)&&(t+=1)}}function $n(e,t){let n=kn(t)==="call",r=t.includes("--json");if(n&&r&&e instanceof T){f({status:e.status,error:e.structuredError??{code:e.code??"http_error",message:e.message},requestId:e.requestId??null,operationId:e.operationId??null,receiptId:e.receiptId??null,traceId:e.traceId??null});let c=typeof e.message=="string"?e.message:e.stack??String(e);process.stderr.write(`${c}
|
|
123
|
+
`);return}let o=e instanceof u&&typeof e.shownOnce=="string"?e.shownOnce:void 0;if(!r){let c=e instanceof u?e.message:e.stack??String(e),d=e instanceof u&&typeof e.fix=="string"?`
|
|
124
|
+
Fix: ${e.fix}`:"",l=o?`
|
|
125
|
+
Shown once Product API key: ${o}`:"";process.stderr.write(`${c}${d}${l}
|
|
126
|
+
`);return}let a=e instanceof u,i=a&&typeof e.code=="string"?e.code:a?"user_error":"internal_error";process.stderr.write(`${JSON.stringify({error:{code:i,message:a?e.message:"The command failed unexpectedly.",...a&&e.details?{details:e.details}:{},fix:a?e.fix??'Follow the message, or run "hyperscale --help" for command usage.':"Report the failure without including credentials."},...o?{shown_once:o}:{}})}
|
|
127
|
+
`)}async function In(){let{readFileSync:e}=await import("node:fs");return JSON.parse(e(new URL("./package.json",import.meta.url),"utf8")).version}async function bn(e,t){let{flags:n,positional:r}=it(e);if(n["--version"])return s(await In()),0;if(n["--help"]&&r.length>0)return process.stdout.write(st(r)),0;if(r.length===0&&!n["--help"]){if(n["--json"])throw new u('No command. Run "hyperscale --help" to list commands.');return process.stdin.isTTY&&process.stderr.isTTY?(await be(n,t),0):(s('Build your first Product with "hyperscale start".'),s('Run "hyperscale --help" for every command.'),0)}if(n["--help"])return process.stdout.write(at),0;let[o,...a]=r;if(o==="start")return await be(n,t),0;if(o==="auth"){if(a[0]==="login")await It(n,t);else if(a[0]==="status")await bt(n,t);else if(a[0]==="logout")await Pt(n,t);else throw new u('Auth subcommands are "login", "status", and "logout"');return 0}if(o==="blueprint"){let i=_(n,t);if(a[0]==="list")await At(i,n);else if(a[0]==="show")await vt(i,n,a[1]);else throw new u('Blueprint subcommands are "list" and "show"');return 0}if(o==="product"){if(a[0]==="create")await Ut(n,t);else if(a[0]==="list")await Dt(n,t);else if(a[0]==="show")await Ht(n,t,a[1]);else if(a[0]==="select")await Bt(n,t,a[1]);else if(a[0]==="actions")await Wt(n,t,a[1]);else if(a[0]==="run")await tn(n,t,a[1]);else throw new u('Product subcommands are "create", "list", "show", "select", "actions", and "run"');return 0}if(o==="compose"){if(a[0]==="check")await qt(n,t,a[1]);else if(a[0]==="plan")await Mt(n,t,a[1]);else if(a[0]==="apply")await zt(n,t,a[1]);else throw new u('Compose subcommands are "check", "plan", and "apply"');return 0}if(o==="key"){if(a[0]==="create")await an(n,t);else if(a[0]==="list")await cn(n,t);else if(a[0]==="revoke")await un(n,t,a[1]);else throw new u('Key subcommands are "create", "list", and "revoke"');return 0}if(o==="whoami")return await dn(n,t),0;if(o==="team"){if(a[0]==="list")await pn(n,t);else if(a[0]==="invite")await mn(n,t);else throw new u('Team subcommands are "list" and "invite"');return 0}if(o==="activity"){if(a[0]!=="list")throw new u('The only activity subcommand is "list"');return await fn(n,t),0}if(o==="ops"){if(a[0]!=="list")throw new u('The only ops subcommand is "list"');let i=n["--product"]?await Y(n,t):ge(n,t);return await ln(i,n,a[1]),0}if(o==="call"){let i=n["--product"]?await Y(n,t):ge(n,t);return await gn(i,n,a[0]),0}throw new u(`Unknown command: ${o}`)}bn(process.argv.slice(2),process.env).then(e=>{process.exitCode=e},e=>{$n(e,process.argv.slice(2)),process.exitCode=e instanceof u&&Number.isInteger(e.exitCode)?e.exitCode:1});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperscale0/cli",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.10",
|
|
4
4
|
"description": "The Hyperscale founder command line: compose Products, manage keys, and call Product operations.",
|
|
5
5
|
"license": "LicenseRef-Hyperscale-Proprietary",
|
|
6
6
|
"author": "Hyperscale LLC",
|
|
@@ -19,5 +19,6 @@
|
|
|
19
19
|
"homepage": "https://hyperscale0.ai",
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"access": "public"
|
|
22
|
-
}
|
|
22
|
+
},
|
|
23
|
+
"gitHead": "b63bc088b12ddcf09cddc6e6467d749817c14827"
|
|
23
24
|
}
|