@hyperscale0/udl 1.0.0-beta.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/CHANGELOG.md +78 -25
  2. package/README.md +37 -99
  3. package/conformance/README.md +44 -41
  4. package/conformance/evolution/action-contract.expected.json +10 -0
  5. package/conformance/evolution/action-contract.live.udl +44 -0
  6. package/conformance/evolution/action-contract.next.udl +45 -0
  7. package/conformance/evolution/product-identity.expected.json +10 -0
  8. package/conformance/evolution/product-identity.live.udl +55 -0
  9. package/conformance/evolution/product-identity.next.udl +55 -0
  10. package/conformance/evolution/version-required.expected.json +10 -0
  11. package/conformance/evolution/version-required.live.udl +55 -0
  12. package/conformance/evolution/version-required.next.udl +58 -0
  13. package/conformance/invalid/action-without-transition.expected.json +10 -0
  14. package/conformance/invalid/{verb-without-transition.udl → action-without-transition.udl} +7 -2
  15. package/conformance/invalid/agent-description-too-long.expected.json +10 -0
  16. package/conformance/invalid/agent-description-too-long.udl +57 -0
  17. package/conformance/invalid/blank-title.expected.json +1 -1
  18. package/conformance/invalid/blank-title.udl +6 -2
  19. package/conformance/invalid/composition-dial-duplicate-key.expected.json +10 -0
  20. package/conformance/invalid/composition-dial-duplicate-key.udl +73 -0
  21. package/conformance/invalid/depth-budget.expected.json +1 -1
  22. package/conformance/invalid/duplicate-subject.expected.json +10 -0
  23. package/conformance/invalid/duplicate-subject.udl +230 -0
  24. package/conformance/invalid/forged-effects.expected.json +10 -0
  25. package/conformance/invalid/forged-effects.udl +76 -0
  26. package/conformance/invalid/format-version.expected.json +1 -1
  27. package/conformance/invalid/format-version.udl +6 -2
  28. package/conformance/invalid/instrument-id-not-snake-case.expected.json +10 -0
  29. package/conformance/invalid/{noun-id-not-snake-case.udl → instrument-id-not-snake-case.udl} +6 -2
  30. package/conformance/invalid/invalid-aggregate-gate-shape.expected.json +10 -0
  31. package/conformance/invalid/invalid-aggregate-gate-shape.udl +1819 -0
  32. package/conformance/invalid/invalid-check-duration.expected.json +10 -0
  33. package/conformance/invalid/invalid-check-duration.udl +219 -0
  34. package/conformance/invalid/invalid-dial-anchor.expected.json +10 -0
  35. package/conformance/invalid/invalid-dial-anchor.udl +219 -0
  36. package/conformance/invalid/invalid-exception-parent-ref.expected.json +10 -0
  37. package/conformance/invalid/invalid-exception-parent-ref.udl +2487 -0
  38. package/conformance/invalid/invalid-exposure-shape.expected.json +10 -0
  39. package/conformance/invalid/invalid-exposure-shape.udl +1819 -0
  40. package/conformance/invalid/invalid-remainder.expected.json +10 -0
  41. package/conformance/invalid/invalid-remainder.udl +220 -0
  42. package/conformance/invalid/invalid-schema-keyword.expected.json +10 -0
  43. package/conformance/invalid/invalid-schema-keyword.udl +220 -0
  44. package/conformance/invalid/invalid-utf8.expected.json +1 -1
  45. package/conformance/invalid/malformed-json.expected.json +1 -1
  46. package/conformance/invalid/missing-create-action.expected.json +10 -0
  47. package/conformance/invalid/{missing-create-verb.udl → missing-create-action.udl} +5 -2
  48. package/conformance/invalid/missing-exception-amount-field.expected.json +10 -0
  49. package/conformance/invalid/missing-exception-amount-field.udl +2487 -0
  50. package/conformance/invalid/missing-exception-contract.expected.json +14 -0
  51. package/conformance/invalid/missing-exception-contract.udl +2523 -0
  52. package/conformance/invalid/missing-exception-reason-field.expected.json +10 -0
  53. package/conformance/invalid/missing-exception-reason-field.udl +2487 -0
  54. package/conformance/invalid/not-an-object.expected.json +1 -1
  55. package/conformance/invalid/payout-reconcile-not-a-bank-debit.expected.json +10 -0
  56. package/conformance/invalid/payout-reconcile-not-a-bank-debit.udl +259 -0
  57. package/conformance/invalid/quote-freeze-set-incomplete.expected.json +10 -0
  58. package/conformance/invalid/quote-freeze-set-incomplete.udl +261 -0
  59. package/conformance/invalid/quote-named-reference-gate.expected.json +10 -0
  60. package/conformance/invalid/quote-named-reference-gate.udl +50 -0
  61. package/conformance/invalid/reconcile-named-reference-gate.expected.json +10 -0
  62. package/conformance/invalid/reconcile-named-reference-gate.udl +50 -0
  63. package/conformance/invalid/unknown-key.expected.json +1 -1
  64. package/conformance/invalid/unknown-key.udl +6 -2
  65. package/conformance/invalid/unknown-reference-gate-field.expected.json +10 -0
  66. package/conformance/invalid/unknown-reference-gate-field.udl +1819 -0
  67. package/conformance/invalid/unknown-required-field.expected.json +10 -0
  68. package/conformance/invalid/unknown-required-field.udl +220 -0
  69. package/conformance/invalid/unreachable-state.expected.json +2 -2
  70. package/conformance/invalid/unreachable-state.udl +6 -2
  71. package/conformance/invalid/wrong-exception-amount-field.expected.json +10 -0
  72. package/conformance/invalid/wrong-exception-amount-field.udl +2487 -0
  73. package/conformance/invalid/wrong-exception-reason-field.expected.json +10 -0
  74. package/conformance/invalid/wrong-exception-reason-field.udl +2487 -0
  75. package/conformance/valid/agent-description.expected.json +6 -0
  76. package/conformance/valid/agent-description.udl +66 -0
  77. package/conformance/valid/cards.expected.json +1 -0
  78. package/conformance/valid/cards.udl +843 -356
  79. package/conformance/valid/commerce-escrow.expected.json +1 -0
  80. package/conformance/valid/commerce-escrow.udl +792 -291
  81. package/conformance/valid/compiled-crowdfunding.expected.json +6 -0
  82. package/conformance/valid/compiled-crowdfunding.udl +1843 -0
  83. package/conformance/valid/compiled-watch-club.expected.json +6 -0
  84. package/conformance/valid/compiled-watch-club.udl +2486 -0
  85. package/conformance/valid/complete-contract.expected.json +6 -0
  86. package/conformance/valid/complete-contract.udl +218 -0
  87. package/conformance/valid/effect-signatures.expected.json +6 -0
  88. package/conformance/valid/effect-signatures.udl +75 -0
  89. package/conformance/valid/hand-edited.expected.json +1 -0
  90. package/conformance/valid/hand-edited.udl +1 -1
  91. package/conformance/valid/insured-car-marketplace.expected.json +1 -0
  92. package/conformance/valid/insured-car-marketplace.udl +534 -315
  93. package/conformance/valid/insured-travel.expected.json +2 -1
  94. package/conformance/valid/insured-travel.udl +1489 -641
  95. package/conformance/valid/minimal.expected.json +1 -0
  96. package/conformance/valid/minimal.udl +18 -14
  97. package/conformance/valid/protection.expected.json +1 -0
  98. package/conformance/valid/protection.udl +719 -304
  99. package/conformance/valid/string-escaping.expected.json +6 -0
  100. package/conformance/valid/string-escaping.udl +54 -0
  101. package/dist/canonical.d.ts +2 -0
  102. package/dist/canonical.d.ts.map +1 -1
  103. package/dist/canonical.js +7 -0
  104. package/dist/canonical.js.map +1 -1
  105. package/dist/check-profiles.d.ts +57 -0
  106. package/dist/check-profiles.d.ts.map +1 -0
  107. package/dist/check-profiles.js +62 -0
  108. package/dist/check-profiles.js.map +1 -0
  109. package/dist/cli.js +48 -4
  110. package/dist/cli.js.map +1 -1
  111. package/dist/diagnostics.d.ts +168 -0
  112. package/dist/diagnostics.d.ts.map +1 -0
  113. package/dist/diagnostics.js +164 -0
  114. package/dist/diagnostics.js.map +1 -0
  115. package/dist/effects.d.ts +41 -0
  116. package/dist/effects.d.ts.map +1 -0
  117. package/dist/effects.js +110 -0
  118. package/dist/effects.js.map +1 -0
  119. package/dist/evolution.d.ts +51 -18
  120. package/dist/evolution.d.ts.map +1 -1
  121. package/dist/evolution.js +244 -102
  122. package/dist/evolution.js.map +1 -1
  123. package/dist/finance.d.ts +17 -13
  124. package/dist/finance.d.ts.map +1 -1
  125. package/dist/finance.js +165 -109
  126. package/dist/finance.js.map +1 -1
  127. package/dist/index.d.ts +12 -8
  128. package/dist/index.d.ts.map +1 -1
  129. package/dist/index.js +8 -5
  130. package/dist/index.js.map +1 -1
  131. package/dist/limits.d.ts +2 -2
  132. package/dist/limits.d.ts.map +1 -1
  133. package/dist/limits.js +4 -3
  134. package/dist/limits.js.map +1 -1
  135. package/dist/parser.d.ts.map +1 -1
  136. package/dist/parser.js +6 -16
  137. package/dist/parser.js.map +1 -1
  138. package/dist/schema.d.ts +2059 -135
  139. package/dist/schema.d.ts.map +1 -1
  140. package/dist/schema.js +759 -73
  141. package/dist/schema.js.map +1 -1
  142. package/dist/validation.d.ts +22 -9
  143. package/dist/validation.d.ts.map +1 -1
  144. package/dist/validation.js +1463 -457
  145. package/dist/validation.js.map +1 -1
  146. package/docs/README.md +14 -0
  147. package/docs/guide/01-a-document.md +37 -0
  148. package/docs/guide/02-money-steps.md +23 -0
  149. package/docs/guide/03-laws.md +18 -0
  150. package/docs/guide/04-fees-and-remainder.md +15 -0
  151. package/docs/guide/05-checks-updates-dials.md +7 -0
  152. package/docs/guide/06-effects.md +11 -0
  153. package/docs/guide/07-evolution.md +11 -0
  154. package/docs/guide/08-implementing.md +13 -0
  155. package/docs/llms-full.txt +1241 -0
  156. package/docs/llms.txt +14 -0
  157. package/docs/reference/canonical.md +16 -0
  158. package/docs/reference/clauses.md +986 -0
  159. package/docs/reference/cli.md +22 -0
  160. package/docs/reference/diagnostics.md +32 -0
  161. package/package.json +6 -2
  162. package/skills/udl/SKILL.md +28 -0
  163. package/spec/README.md +82 -51
  164. package/spec/udl.schema.json +1191 -119
  165. package/src/canonical.ts +11 -0
  166. package/src/check-profiles.ts +80 -0
  167. package/src/cli.ts +49 -3
  168. package/src/diagnostics.ts +221 -0
  169. package/src/effects.ts +163 -0
  170. package/src/evolution.ts +375 -125
  171. package/src/finance.ts +255 -160
  172. package/src/index.ts +50 -14
  173. package/src/limits.ts +4 -3
  174. package/src/parser.ts +15 -18
  175. package/src/schema.ts +855 -81
  176. package/src/validation.ts +2666 -560
  177. package/conformance/invalid/missing-create-verb.expected.json +0 -10
  178. package/conformance/invalid/noun-id-not-snake-case.expected.json +0 -10
  179. package/conformance/invalid/verb-without-transition.expected.json +0 -10
@@ -1,229 +1,46 @@
1
1
  {
2
- "nouns": [
2
+ "instruments": [
3
3
  {
4
- "aggregateInvariants": [
5
- {
6
- "childField": "claimAmount",
7
- "childNounId": "claim",
8
- "childRefField": "policyId",
9
- "childStatuses": [
10
- "filed",
11
- "assessed",
12
- "approved",
13
- "paid"
14
- ],
15
- "parentField": "coverageLimit"
16
- }
4
+ "actionOrder": [
5
+ "create",
6
+ "bind",
7
+ "activate",
8
+ "preview",
9
+ "cancel",
10
+ "withdraw",
11
+ "endorse",
12
+ "expire"
17
13
  ],
18
- "description": "A policy quotes protection over one subject, binds after a carrier decision, activates at its declared start, and expires at term. Premium remains refundable while bound but not active; activation pays the insurer and opens the policy to claims.",
19
- "fields": {
20
- "coverageLimit": {
21
- "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
22
- "pattern": "^[1-9][0-9]{0,17}$",
23
- "type": "string"
24
- },
25
- "currency": {
26
- "description": "ISO 4217 currency code",
27
- "maxLength": 3,
28
- "minLength": 3,
29
- "pattern": "^[A-Z]{3}$",
30
- "type": "string"
31
- },
32
- "expiresAt": {
33
- "format": "hyperscale-date-time",
34
- "type": "string"
35
- },
36
- "insurerAccountId": {
37
- "description": "Hyperscale account ID",
38
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
39
- "type": "string",
40
- "x-hyperscale-reference-filter": {
41
- "column": "role",
42
- "values": [
43
- "customer_balance"
44
- ]
45
- }
46
- },
47
- "perilSchedule": {
48
- "items": {
49
- "additionalProperties": false,
50
- "properties": {
51
- "deductibleBps": {
52
- "maximum": 10000,
53
- "minimum": 0,
54
- "type": "integer"
55
- },
56
- "limitAmount": {
57
- "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
58
- "pattern": "^[1-9][0-9]{0,17}$",
59
- "type": "string"
60
- },
61
- "peril": {
62
- "pattern": "^[a-z][a-z0-9_]{1,79}$",
63
- "type": "string"
64
- },
65
- "waitingPeriodDays": {
66
- "maximum": 3650,
67
- "minimum": 0,
68
- "type": "integer"
69
- }
70
- },
71
- "required": [
72
- "peril",
73
- "limitAmount",
74
- "deductibleBps",
75
- "waitingPeriodDays"
76
- ],
77
- "type": "object"
78
- },
79
- "maxItems": 24,
80
- "minItems": 1,
81
- "type": "array"
82
- },
83
- "policyholderAccountId": {
84
- "description": "Hyperscale account ID",
85
- "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
86
- "type": "string",
87
- "x-hyperscale-reference-filter": {
88
- "column": "role",
89
- "values": [
90
- "customer_balance"
91
- ]
92
- }
93
- },
94
- "premiumAmount": {
95
- "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
96
- "pattern": "^[1-9][0-9]{0,17}$",
97
- "type": "string"
98
- },
99
- "renewalOfPolicyId": {
100
- "description": "Prior policy this quote renews; the prior term must be active or already expired",
101
- "pattern": "^pol_(sandbox|live)_[a-z0-9]{8,64}$",
102
- "type": "string"
103
- },
104
- "startsAt": {
105
- "format": "hyperscale-date-time",
106
- "type": "string"
107
- },
108
- "termsSummary": {
109
- "maxLength": 1000,
110
- "minLength": 1,
111
- "type": "string"
112
- }
113
- },
114
- "id": "policy",
115
- "idPrefix": "pol",
116
- "lifecycle": {
117
- "initial": "quoted",
118
- "states": [
119
- "quoted",
120
- "bound",
121
- "active",
122
- "cancel_quoted",
123
- "canceled",
124
- "expired"
125
- ],
126
- "transitions": {
127
- "activate": {
128
- "from": [
129
- "bound"
130
- ],
131
- "to": "active"
132
- },
133
- "bind": {
134
- "from": [
135
- "quoted"
136
- ],
137
- "to": "bound"
138
- },
139
- "cancel": {
140
- "from": [
141
- "cancel_quoted"
142
- ],
143
- "to": "canceled"
144
- },
145
- "endorse": {
146
- "from": [
147
- "active"
148
- ],
149
- "to": "active"
150
- },
151
- "expire": {
152
- "from": [
153
- "active"
154
- ],
155
- "to": "expired"
156
- },
157
- "preview": {
158
- "from": [
159
- "bound"
160
- ],
161
- "to": "cancel_quoted"
162
- },
163
- "withdraw": {
164
- "from": [
165
- "quoted"
166
- ],
167
- "to": "canceled"
168
- }
169
- }
170
- },
171
- "parties": {
172
- "beneficiary": "insurerAccountId",
173
- "payer": "policyholderAccountId"
174
- },
175
- "required": [
176
- "policyholderAccountId",
177
- "insurerAccountId",
178
- "premiumAmount",
179
- "coverageLimit",
180
- "currency",
181
- "startsAt",
182
- "expiresAt",
183
- "perilSchedule"
184
- ],
185
- "subject": {
186
- "kinds": [
187
- "policy_risk",
188
- "flight_itinerary",
189
- "lodging_stay",
190
- "vehicle",
191
- "pet",
192
- "traveler_party",
193
- "employee_census"
194
- ]
195
- },
196
- "summary": "Carrier-backed protection over one declared-value subject.",
197
- "title": "Policy",
198
- "unwind": {
199
- "confirm": "cancel",
200
- "penalty": [
201
- {
202
- "bps": 0
203
- }
204
- ],
205
- "quote": "preview",
206
- "refundDestinationField": "policyholderAccountId",
207
- "refundableField": "premiumAmount"
208
- },
209
- "update": {
210
- "fields": [
211
- "startsAt",
212
- "expiresAt",
213
- "perilSchedule",
214
- "termsSummary"
215
- ],
216
- "states": [
217
- "quoted"
218
- ]
219
- },
220
- "verbs": {
14
+ "actions": {
221
15
  "activate": {
222
16
  "description": "Starts cover at the declared time and pays the held premium to the insurer under the machine principal.",
223
17
  "due": {
224
18
  "field": "startsAt"
225
19
  },
226
20
  "earnable": true,
21
+ "effects": {
22
+ "moves": [
23
+ {
24
+ "signature": "moves.transfer.internal",
25
+ "source": "moves[0]"
26
+ }
27
+ ],
28
+ "schedules": [
29
+ {
30
+ "signature": "schedules.due",
31
+ "source": "due"
32
+ }
33
+ ]
34
+ },
35
+ "examples": [
36
+ {
37
+ "input": {
38
+ "policyId": "pol_sandbox_protection001",
39
+ "tenantId": "ten_sandbox_protection01"
40
+ },
41
+ "name": "activate_cover_at_start"
42
+ }
43
+ ],
227
44
  "moves": [
228
45
  {
229
46
  "bind": {
@@ -239,13 +56,13 @@
239
56
  "from": "instance",
240
57
  "path": "fields.insurerAccountId"
241
58
  },
242
- "sourceAccountId": {
59
+ "productId": {
243
60
  "from": "instance",
244
- "path": "refs.premiumReserveAccountId"
61
+ "path": "productId"
245
62
  },
246
- "workspaceId": {
63
+ "sourceAccountId": {
247
64
  "from": "instance",
248
- "path": "workspaceId"
65
+ "path": "refs.premiumReserveAccountId"
249
66
  }
250
67
  },
251
68
  "capture": {
@@ -259,13 +76,37 @@
259
76
  "summary": "Activate a policy"
260
77
  },
261
78
  "bind": {
79
+ "agentDescription": "Ask the carrier to accept the risk under a 15 second deadline, where a timeout declines, then move the full premium from the policyholder into the policy's premium reserve. Only a quoted policy binds. Cover is not live yet. Activation happens at startsAt. This moves the policyholder's money.",
262
80
  "decision": {
263
81
  "capability": "insurance_carrier",
264
82
  "deadlineMs": 15000,
265
83
  "onTimeout": "decline"
266
84
  },
267
85
  "description": "Asks the carrier to accept the risk, then moves the premium into its dedicated reserve until cover starts.",
86
+ "effects": {
87
+ "decides": [
88
+ {
89
+ "signature": "decides.insurance_carrier",
90
+ "source": "decision"
91
+ }
92
+ ],
93
+ "moves": [
94
+ {
95
+ "signature": "moves.transfer.internal",
96
+ "source": "moves[0]"
97
+ }
98
+ ]
99
+ },
268
100
  "eventName": "policy.bound",
101
+ "examples": [
102
+ {
103
+ "input": {
104
+ "policyId": "pol_sandbox_protection001",
105
+ "tenantId": "ten_sandbox_protection01"
106
+ },
107
+ "name": "bind_carrier_accepted_risk"
108
+ }
109
+ ],
269
110
  "moves": [
270
111
  {
271
112
  "bind": {
@@ -281,13 +122,13 @@
281
122
  "from": "instance",
282
123
  "path": "refs.premiumReserveAccountId"
283
124
  },
284
- "sourceAccountId": {
125
+ "productId": {
285
126
  "from": "instance",
286
- "path": "fields.policyholderAccountId"
127
+ "path": "productId"
287
128
  },
288
- "workspaceId": {
129
+ "sourceAccountId": {
289
130
  "from": "instance",
290
- "path": "workspaceId"
131
+ "path": "fields.policyholderAccountId"
291
132
  }
292
133
  },
293
134
  "capture": {
@@ -301,7 +142,26 @@
301
142
  "summary": "Bind a policy"
302
143
  },
303
144
  "cancel": {
145
+ "agentDescription": "Confirm the previewed cancellation and return the entire reserved premium to the policyholder. It requires preview first and only works before cover activates. This moves money and does not reverse. An active policy has no cancellation path and runs to its expiry.",
146
+ "commit": "preview",
304
147
  "description": "Confirms the previewed cancellation and returns the entire reserved premium to the policyholder before cover starts.",
148
+ "effects": {
149
+ "moves": [
150
+ {
151
+ "signature": "moves.transfer.internal",
152
+ "source": "moves[0]"
153
+ }
154
+ ]
155
+ },
156
+ "examples": [
157
+ {
158
+ "input": {
159
+ "policyId": "pol_sandbox_protection001",
160
+ "tenantId": "ten_sandbox_protection01"
161
+ },
162
+ "name": "confirm_pre_activation_cancel"
163
+ }
164
+ ],
305
165
  "moves": [
306
166
  {
307
167
  "bind": {
@@ -317,13 +177,13 @@
317
177
  "from": "instance",
318
178
  "path": "fields.policyholderAccountId"
319
179
  },
320
- "sourceAccountId": {
180
+ "productId": {
321
181
  "from": "instance",
322
- "path": "refs.premiumReserveAccountId"
182
+ "path": "productId"
323
183
  },
324
- "workspaceId": {
184
+ "sourceAccountId": {
325
185
  "from": "instance",
326
- "path": "workspaceId"
186
+ "path": "refs.premiumReserveAccountId"
327
187
  }
328
188
  },
329
189
  "capture": {
@@ -337,7 +197,16 @@
337
197
  "summary": "Cancel a policy"
338
198
  },
339
199
  "create": {
200
+ "agentDescription": "Open a quote against one declared-value subject with its premium, coverage limit, peril schedule, and term, and provision the premium reserve. No premium moves. A renewal may name the prior policy only while that prior term is active or already expired.",
340
201
  "description": "Creates a quote against one declared-value risk and provisions the premium reserve. No premium moves until the carrier binds.",
202
+ "effects": {
203
+ "reads": [
204
+ {
205
+ "signature": "reads.requires_refs",
206
+ "source": "requiresRefs"
207
+ }
208
+ ]
209
+ },
341
210
  "eventName": "policy.quoted",
342
211
  "examples": [
343
212
  {
@@ -362,8 +231,10 @@
362
231
  ],
363
232
  "policyholderAccountId": "acct_sandbox_holder00001",
364
233
  "premiumAmount": "12500",
234
+ "productId": "prd_sandbox_protection01",
365
235
  "startsAt": "2026-08-01T00:00:00.000Z",
366
236
  "subject": "sbj_sandbox_protection001",
237
+ "tenantId": "ten_sandbox_protection01",
367
238
  "termsSummary": "Annual cover for accidental damage and theft."
368
239
  },
369
240
  "name": "quote_asset_protection"
@@ -389,19 +260,19 @@
389
260
  },
390
261
  "owner.id": {
391
262
  "from": "instance",
392
- "path": "workspaceId"
263
+ "path": "productId"
393
264
  },
394
265
  "owner.type": {
395
266
  "from": "const",
396
- "value": "workspace"
267
+ "value": "product"
268
+ },
269
+ "productId": {
270
+ "from": "instance",
271
+ "path": "productId"
397
272
  },
398
273
  "role": {
399
274
  "from": "const",
400
- "value": "workspace_escrow"
401
- },
402
- "workspaceId": {
403
- "from": "instance",
404
- "path": "workspaceId"
275
+ "value": "product_escrow"
405
276
  }
406
277
  },
407
278
  "capture": {
@@ -413,16 +284,27 @@
413
284
  "summary": "Quote a policy"
414
285
  },
415
286
  "endorse": {
287
+ "agentDescription": "Rewrite the peril schedule, terms summary, or expiry on active cover. The carrier approves under a 15 second deadline and a timeout declines. No premium moves, because mid-term repricing is not modeled. A change that should reprice the cover needs a new policy.",
416
288
  "decision": {
417
289
  "capability": "insurance_carrier",
418
290
  "deadlineMs": 15000,
419
291
  "onTimeout": "decline"
420
292
  },
421
293
  "description": "Applies a carrier-approved mid-term change to active cover: the peril schedule, terms summary, or expiry may be rewritten. No premium moves; mid-term premium adjustment is not modeled.",
294
+ "effects": {
295
+ "decides": [
296
+ {
297
+ "signature": "decides.insurance_carrier",
298
+ "source": "decision"
299
+ }
300
+ ]
301
+ },
422
302
  "examples": [
423
303
  {
424
304
  "input": {
425
305
  "expiresAt": "2027-11-01T00:00:00.000Z",
306
+ "policyId": "pol_sandbox_protection001",
307
+ "tenantId": "ten_sandbox_protection01",
426
308
  "termsSummary": "Extended cover incl. water damage."
427
309
  },
428
310
  "name": "endorse_extend_active_cover"
@@ -481,13 +363,35 @@
481
363
  },
482
364
  "moves": [],
483
365
  "steps": [],
484
- "summary": "Endorse a policy"
366
+ "summary": "Endorse a policy",
367
+ "updates": [
368
+ "perilSchedule",
369
+ "termsSummary",
370
+ "expiresAt"
371
+ ]
485
372
  },
486
373
  "expire": {
487
374
  "description": "Ends active cover at term under the machine principal. Earned premium remains with the insurer.",
488
375
  "due": {
489
376
  "field": "expiresAt"
490
377
  },
378
+ "effects": {
379
+ "schedules": [
380
+ {
381
+ "signature": "schedules.due",
382
+ "source": "due"
383
+ }
384
+ ]
385
+ },
386
+ "examples": [
387
+ {
388
+ "input": {
389
+ "policyId": "pol_sandbox_protection001",
390
+ "tenantId": "ten_sandbox_protection01"
391
+ },
392
+ "name": "expire_cover_at_term"
393
+ }
394
+ ],
491
395
  "moves": [],
492
396
  "requiresDrainedAccount": {
493
397
  "path": "refs.premiumReserveAccountId"
@@ -496,14 +400,66 @@
496
400
  "summary": "Expire a policy"
497
401
  },
498
402
  "preview": {
403
+ "agentDescription": "Price the cancellation refund while the policy is bound and cover has not started. No money moves. Under the declared schedule the refund is the whole premium. Required before cancel, which is the call that actually returns the money.",
499
404
  "description": "Quotes the full premium refund while cover is bound but not active. No money moves until cancellation is confirmed.",
405
+ "effects": {
406
+ "holds": [
407
+ {
408
+ "signature": "holds.quote",
409
+ "source": "quote"
410
+ }
411
+ ],
412
+ "schedules": [
413
+ {
414
+ "signature": "schedules.expiry",
415
+ "source": "quote"
416
+ }
417
+ ]
418
+ },
419
+ "examples": [
420
+ {
421
+ "input": {
422
+ "policyId": "pol_sandbox_protection001",
423
+ "tenantId": "ten_sandbox_protection01"
424
+ },
425
+ "name": "preview_pre_activation_cancel"
426
+ }
427
+ ],
500
428
  "moves": [],
429
+ "quote": {
430
+ "baseField": "premiumAmount",
431
+ "chargeRef": "unwindPenalty",
432
+ "charges": [
433
+ {
434
+ "bps": 0
435
+ }
436
+ ],
437
+ "expires": {
438
+ "offset": "PT15M"
439
+ },
440
+ "fixes": [
441
+ "policyholderAccountId",
442
+ "premiumAmount"
443
+ ],
444
+ "netDestinationField": "policyholderAccountId",
445
+ "netRef": "unwindRefund"
446
+ },
501
447
  "steps": [],
502
448
  "summary": "Preview policy cancellation"
503
449
  },
504
450
  "withdraw": {
451
+ "agentDescription": "Drop a quote the carrier never bound. Only a quoted policy withdraws, no premium has moved, and the premium reserve must be empty. No preview is needed because there is nothing to refund.",
505
452
  "description": "Closes an unbound quote. No premium moved, so no cancellation preview is required.",
506
453
  "eventName": "policy.withdrawn",
454
+ "examples": [
455
+ {
456
+ "input": {
457
+ "policyId": "pol_sandbox_protection001",
458
+ "tenantId": "ten_sandbox_protection01"
459
+ },
460
+ "name": "withdraw_unbound_quote"
461
+ }
462
+ ],
507
463
  "moves": [],
508
464
  "requiresDrainedAccount": {
509
465
  "path": "refs.premiumReserveAccountId"
@@ -511,17 +467,45 @@
511
467
  "steps": [],
512
468
  "summary": "Withdraw a policy quote"
513
469
  }
514
- }
515
- },
516
- {
517
- "description": "A claim is filed against an active policy, assessed, approved or denied, and paid from the insurer account through a held transfer. Approval can be reversed before payment, releasing the insurer's hold without moving settled money.",
470
+ },
471
+ "agentDescription": "Reach for policy when the caller quotes carrier-backed cover over one declared-value subject and drives it through bind, endorsement, and expiry. Between bind and activation the premium sits in a per-policy reserve and is fully refundable. Once cover activates the premium is the insurer's. Claims are a separate instrument.",
472
+ "aggregateInvariants": [
473
+ {
474
+ "childField": "claimAmount",
475
+ "childInstrumentId": "claim",
476
+ "childRefField": "policyId",
477
+ "childStatuses": [
478
+ "filed",
479
+ "assessed",
480
+ "approved",
481
+ "paid"
482
+ ],
483
+ "parentField": "coverageLimit"
484
+ }
485
+ ],
486
+ "callerParkedStates": {
487
+ "cancel_quoted": "a quoted cancellation moves money only when the caller confirms it",
488
+ "quoted": "binding or withdrawing a quote is the policyholder's decision"
489
+ },
490
+ "description": "A policy quotes protection over one subject, binds after a carrier decision, activates at its declared start, and expires at term. Premium remains refundable while bound but not active; activation pays the insurer and opens the policy to claims.",
518
491
  "fields": {
519
- "claimAmount": {
492
+ "coverageLimit": {
520
493
  "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
521
494
  "pattern": "^[1-9][0-9]{0,17}$",
522
495
  "type": "string"
523
496
  },
524
- "claimantAccountId": {
497
+ "currency": {
498
+ "description": "ISO 4217 currency code",
499
+ "maxLength": 3,
500
+ "minLength": 3,
501
+ "pattern": "^[A-Z]{3}$",
502
+ "type": "string"
503
+ },
504
+ "expiresAt": {
505
+ "format": "hyperscale-date-time",
506
+ "type": "string"
507
+ },
508
+ "insurerAccountId": {
525
509
  "description": "Hyperscale account ID",
526
510
  "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
527
511
  "type": "string",
@@ -532,19 +516,43 @@
532
516
  ]
533
517
  }
534
518
  },
535
- "currency": {
536
- "description": "ISO 4217 currency code",
537
- "maxLength": 3,
538
- "minLength": 3,
539
- "pattern": "^[A-Z]{3}$",
540
- "type": "string"
541
- },
542
- "evidenceSummary": {
543
- "maxLength": 2000,
544
- "minLength": 1,
545
- "type": "string"
519
+ "perilSchedule": {
520
+ "items": {
521
+ "additionalProperties": false,
522
+ "properties": {
523
+ "deductibleBps": {
524
+ "maximum": 10000,
525
+ "minimum": 0,
526
+ "type": "integer"
527
+ },
528
+ "limitAmount": {
529
+ "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
530
+ "pattern": "^[1-9][0-9]{0,17}$",
531
+ "type": "string"
532
+ },
533
+ "peril": {
534
+ "pattern": "^[a-z][a-z0-9_]{1,79}$",
535
+ "type": "string"
536
+ },
537
+ "waitingPeriodDays": {
538
+ "maximum": 3650,
539
+ "minimum": 0,
540
+ "type": "integer"
541
+ }
542
+ },
543
+ "required": [
544
+ "peril",
545
+ "limitAmount",
546
+ "deductibleBps",
547
+ "waitingPeriodDays"
548
+ ],
549
+ "type": "object"
550
+ },
551
+ "maxItems": 24,
552
+ "minItems": 1,
553
+ "type": "array"
546
554
  },
547
- "insurerAccountId": {
555
+ "policyholderAccountId": {
548
556
  "description": "Hyperscale account ID",
549
557
  "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
550
558
  "type": "string",
@@ -555,83 +563,100 @@
555
563
  ]
556
564
  }
557
565
  },
558
- "occurredAt": {
559
- "format": "hyperscale-date-time",
566
+ "premiumAmount": {
567
+ "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
568
+ "pattern": "^[1-9][0-9]{0,17}$",
560
569
  "type": "string"
561
570
  },
562
- "peril": {
563
- "pattern": "^[a-z][a-z0-9_]{1,79}$",
571
+ "renewalOfPolicyId": {
572
+ "description": "Prior policy this quote renews; the prior term must be active or already expired",
573
+ "pattern": "^pol_(sandbox|live)_[a-z0-9]{8,64}$",
564
574
  "type": "string"
565
575
  },
566
- "policyId": {
567
- "description": "Active policy this claim is made against",
568
- "pattern": "^pol_(sandbox|live)_[a-z0-9]{8,64}$",
576
+ "startsAt": {
577
+ "format": "hyperscale-date-time",
578
+ "type": "string"
579
+ },
580
+ "termsSummary": {
581
+ "maxLength": 1000,
582
+ "minLength": 1,
569
583
  "type": "string"
570
584
  }
571
585
  },
572
- "id": "claim",
573
- "idPrefix": "clm",
586
+ "id": "policy",
587
+ "idPrefix": "pol",
574
588
  "lifecycle": {
575
- "initial": "filed",
589
+ "initial": "quoted",
576
590
  "states": [
577
- "filed",
578
- "assessed",
579
- "approved",
580
- "paid",
581
- "denied"
591
+ "quoted",
592
+ "bound",
593
+ "active",
594
+ "cancel_quoted",
595
+ "canceled",
596
+ "expired"
582
597
  ],
583
598
  "transitions": {
584
- "approve": {
599
+ "activate": {
585
600
  "from": [
586
- "assessed"
601
+ "bound"
587
602
  ],
588
- "to": "approved"
603
+ "to": "active"
589
604
  },
590
- "assess": {
605
+ "bind": {
591
606
  "from": [
592
- "filed"
607
+ "quoted"
593
608
  ],
594
- "to": "assessed"
609
+ "to": "bound"
595
610
  },
596
- "attest": {
611
+ "cancel": {
597
612
  "from": [
598
- "assessed"
613
+ "cancel_quoted"
599
614
  ],
600
- "to": "approved"
615
+ "to": "canceled"
601
616
  },
602
- "deny": {
617
+ "endorse": {
603
618
  "from": [
604
- "filed",
605
- "assessed"
619
+ "active"
606
620
  ],
607
- "to": "denied"
621
+ "to": "active"
608
622
  },
609
- "pay": {
623
+ "expire": {
610
624
  "from": [
611
- "approved"
625
+ "active"
612
626
  ],
613
- "to": "paid"
627
+ "to": "expired"
614
628
  },
615
- "reverse": {
629
+ "preview": {
616
630
  "from": [
617
- "approved"
631
+ "bound"
618
632
  ],
619
- "to": "denied"
633
+ "to": "cancel_quoted"
634
+ },
635
+ "withdraw": {
636
+ "from": [
637
+ "quoted"
638
+ ],
639
+ "to": "canceled"
620
640
  }
621
641
  }
622
642
  },
643
+ "nav": [
644
+ "Blueprints",
645
+ "Policies"
646
+ ],
623
647
  "parties": {
624
- "beneficiary": "claimantAccountId",
625
- "payer": "insurerAccountId"
648
+ "beneficiary": "insurerAccountId",
649
+ "payer": "policyholderAccountId"
626
650
  },
627
651
  "required": [
628
- "policyId",
629
- "claimantAccountId",
652
+ "policyholderAccountId",
630
653
  "insurerAccountId",
631
- "claimAmount",
654
+ "premiumAmount",
655
+ "coverageLimit",
632
656
  "currency",
633
- "peril",
634
- "occurredAt"
657
+ "startsAt",
658
+ "expiresAt",
659
+ "perilSchedule"
635
660
  ],
636
661
  "subject": {
637
662
  "kinds": [
@@ -639,30 +664,99 @@
639
664
  "flight_itinerary",
640
665
  "lodging_stay",
641
666
  "vehicle",
667
+ "merchandise",
642
668
  "pet",
643
669
  "traveler_party",
644
670
  "employee_census"
645
671
  ]
646
672
  },
647
- "summary": "Demand against active protection for one covered peril.",
648
- "title": "Claim",
673
+ "summary": "Carrier-backed protection over one declared-value subject.",
674
+ "templateId": "insurance",
675
+ "title": "Policy",
649
676
  "update": {
677
+ "examples": [
678
+ {
679
+ "input": {
680
+ "perilSchedule": [
681
+ {
682
+ "deductibleBps": 500,
683
+ "limitAmount": "200000",
684
+ "peril": "accidental_damage",
685
+ "waitingPeriodDays": 0
686
+ },
687
+ {
688
+ "deductibleBps": 250,
689
+ "limitAmount": "200000",
690
+ "peril": "theft",
691
+ "waitingPeriodDays": 7
692
+ }
693
+ ],
694
+ "policyId": "pol_sandbox_protection001",
695
+ "tenantId": "ten_sandbox_protection01",
696
+ "termsSummary": "Covers accidental damage and theft."
697
+ },
698
+ "name": "refine_quoted_cover"
699
+ }
700
+ ],
650
701
  "fields": [
651
- "evidenceSummary"
702
+ "startsAt",
703
+ "expiresAt",
704
+ "perilSchedule",
705
+ "termsSummary"
652
706
  ],
653
707
  "states": [
654
- "filed",
655
- "assessed"
708
+ "quoted"
656
709
  ]
657
- },
658
- "verbs": {
710
+ }
711
+ },
712
+ {
713
+ "actionOrder": [
714
+ "create",
715
+ "assess",
716
+ "approve",
717
+ "attest",
718
+ "pay",
719
+ "deny",
720
+ "reverse"
721
+ ],
722
+ "actions": {
659
723
  "approve": {
724
+ "agentDescription": "Ask the claims adjuster for a verdict and hold the claim amount from the insurer account for the claimant. Only an assessed claim can approve, and an adjuster that misses the deadline declines by default. The hold reserves money without settling it. Pay posts it, reverse voids it.",
660
725
  "decision": {
661
726
  "capability": "insurance_claims_adjuster",
662
727
  "deadlineMs": 15000,
663
728
  "onTimeout": "decline"
664
729
  },
665
730
  "description": "Asks the claims adjuster to approve the assessed demand, then holds the immutable claim amount from the insurer for the claimant. For a carrier that exposes an adjudication API: the verdict is the provider's, taken just in time under a deadline.",
731
+ "effects": {
732
+ "decides": [
733
+ {
734
+ "signature": "decides.insurance_claims_adjuster",
735
+ "source": "decision"
736
+ }
737
+ ],
738
+ "holds": [
739
+ {
740
+ "signature": "holds.reserve",
741
+ "source": "moves[0]"
742
+ }
743
+ ],
744
+ "moves": [
745
+ {
746
+ "signature": "moves.transfer.internal",
747
+ "source": "moves[0]"
748
+ }
749
+ ]
750
+ },
751
+ "examples": [
752
+ {
753
+ "input": {
754
+ "claimId": "clm_sandbox_protection001",
755
+ "tenantId": "ten_sandbox_protection01"
756
+ },
757
+ "name": "approve_assessed_claim"
758
+ }
759
+ ],
666
760
  "moves": [
667
761
  {
668
762
  "bind": {
@@ -694,13 +788,54 @@
694
788
  "summary": "Approve a claim"
695
789
  },
696
790
  "assess": {
791
+ "agentDescription": "Mark the filed evidence ready for an approval decision. Only a filed claim can assess and no money moves. A claim filed validly during cover stays alive even if the policy term later expires.",
697
792
  "description": "Marks filed evidence ready for an approval decision. A claim validly filed during cover continues even if the policy term later expires.",
793
+ "examples": [
794
+ {
795
+ "input": {
796
+ "claimId": "clm_sandbox_protection001",
797
+ "tenantId": "ten_sandbox_protection01"
798
+ },
799
+ "name": "complete_claim_assessment"
800
+ }
801
+ ],
698
802
  "moves": [],
699
803
  "steps": [],
700
804
  "summary": "Assess a claim"
701
805
  },
702
806
  "attest": {
807
+ "agentDescription": "Record an approval the insurer already made outside the platform and hold the claim amount from the insurer for the claimant. Only an assessed claim can attest, and the caller must assert the insurer as the acting party. Use this where the carrier has no adjudication API. Where one exists, approve calls it.",
703
808
  "description": "Records the insurer's own approval of the assessed demand, taken outside the platform, and holds the immutable claim amount from the insurer for the claimant. The insurer must be asserted as the acting party. Use this where the carrier exposes no adjudication API; where one exists, approve calls it instead.",
809
+ "effects": {
810
+ "decides": [
811
+ {
812
+ "signature": "decides.tenant_port",
813
+ "source": "port"
814
+ }
815
+ ],
816
+ "holds": [
817
+ {
818
+ "signature": "holds.reserve",
819
+ "source": "moves[0]"
820
+ }
821
+ ],
822
+ "moves": [
823
+ {
824
+ "signature": "moves.transfer.internal",
825
+ "source": "moves[0]"
826
+ }
827
+ ]
828
+ },
829
+ "examples": [
830
+ {
831
+ "input": {
832
+ "actorAccountId": "acct_sandbox_insurer0001",
833
+ "claimId": "clm_sandbox_protection001",
834
+ "tenantId": "ten_sandbox_protection01"
835
+ },
836
+ "name": "attest_insurer_approval"
837
+ }
838
+ ],
704
839
  "moves": [
705
840
  {
706
841
  "bind": {
@@ -737,7 +872,16 @@
737
872
  "summary": "Attest an out-of-band claim approval"
738
873
  },
739
874
  "create": {
875
+ "agentDescription": "File a demand against a policy. The policy must be active, and the filed amount is reserved against its aggregate coverage limit. The caller supplies the peril, the moment it occurred, the claim amount, and both accounts. No money moves at filing.",
740
876
  "description": "Records a demand against an active policy and reserves its filed amount against the policy's aggregate coverage limit.",
877
+ "effects": {
878
+ "reads": [
879
+ {
880
+ "signature": "reads.requires_refs",
881
+ "source": "requiresRefs"
882
+ }
883
+ ]
884
+ },
741
885
  "eventName": "claim.filed",
742
886
  "examples": [
743
887
  {
@@ -750,7 +894,9 @@
750
894
  "occurredAt": "2026-10-14T11:30:00.000Z",
751
895
  "peril": "accidental_damage",
752
896
  "policyId": "pol_sandbox_protection001",
753
- "subject": "sbj_sandbox_protection001"
897
+ "productId": "prd_sandbox_protection01",
898
+ "subject": "sbj_sandbox_protection001",
899
+ "tenantId": "ten_sandbox_protection01"
754
900
  },
755
901
  "name": "file_accidental_damage_claim"
756
902
  }
@@ -768,15 +914,43 @@
768
914
  "summary": "File a claim"
769
915
  },
770
916
  "deny": {
917
+ "agentDescription": "Close a filed or assessed demand with no payout. Only a claim with no hold behind it can deny, so an approved claim goes through reverse instead. No money moves.",
771
918
  "description": "Closes a filed or assessed demand before any payout hold exists.",
772
919
  "eventName": "claim.denied",
920
+ "examples": [
921
+ {
922
+ "input": {
923
+ "claimId": "clm_sandbox_protection001",
924
+ "tenantId": "ten_sandbox_protection01"
925
+ },
926
+ "name": "deny_unapproved_claim"
927
+ }
928
+ ],
773
929
  "moves": [],
774
930
  "steps": [],
775
931
  "summary": "Deny a claim"
776
932
  },
777
933
  "pay": {
934
+ "agentDescription": "Post the approved hold so the claim amount settles into the claimant account. Only an approved claim can pay. This settles money and is terminal.",
778
935
  "description": "Posts the approved hold and settles the claim amount into the claimant account.",
936
+ "effects": {
937
+ "moves": [
938
+ {
939
+ "signature": "moves.transfer.internal",
940
+ "source": "moves[0]"
941
+ }
942
+ ]
943
+ },
779
944
  "eventName": "claim.paid",
945
+ "examples": [
946
+ {
947
+ "input": {
948
+ "claimId": "clm_sandbox_protection001",
949
+ "tenantId": "ten_sandbox_protection01"
950
+ },
951
+ "name": "pay_approved_claim"
952
+ }
953
+ ],
780
954
  "moves": [
781
955
  {
782
956
  "bind": {
@@ -793,7 +967,25 @@
793
967
  "summary": "Pay a claim"
794
968
  },
795
969
  "reverse": {
970
+ "agentDescription": "Void an approved payout hold before payment and close the claim as denied. Only an approved claim can reverse. The insurer's held funds are released and no settled money is clawed back.",
796
971
  "description": "Voids an approved payout hold before payment and closes the claim denied. No settled money is reversed.",
972
+ "effects": {
973
+ "moves": [
974
+ {
975
+ "signature": "moves.transfer.internal",
976
+ "source": "moves[0]"
977
+ }
978
+ ]
979
+ },
980
+ "examples": [
981
+ {
982
+ "input": {
983
+ "claimId": "clm_sandbox_protection001",
984
+ "tenantId": "ten_sandbox_protection01"
985
+ },
986
+ "name": "reverse_approved_claim"
987
+ }
988
+ ],
797
989
  "moves": [
798
990
  {
799
991
  "bind": {
@@ -813,6 +1005,179 @@
813
1005
  "steps": [],
814
1006
  "summary": "Reverse claim approval"
815
1007
  }
1008
+ },
1009
+ "agentDescription": "Reach for claim when a policyholder demands payment for a covered peril under an active policy. Filing reserves the amount against the policy's coverage limit. Use approve where the carrier exposes an adjudication API and attest where the insurer decides out of band. Premium collection and cover dates live on policy.",
1010
+ "callerParkedStates": {
1011
+ "approved": "paying or reversing an approved claim is the operator's deliberate money movement",
1012
+ "assessed": "approval or denial is an adjuster's judgment, whether the adjuster answers over an API or out of band",
1013
+ "filed": "assessment is an adjuster's judgment"
1014
+ },
1015
+ "description": "A claim is filed against an active policy, assessed, approved or denied, and paid from the insurer account through a held transfer. Approval can be reversed before payment, releasing the insurer's hold without moving settled money.",
1016
+ "dials": [
1017
+ {
1018
+ "action": "approve",
1019
+ "key": "adjuster_decision_deadline_ms",
1020
+ "kind": "decision_deadline_ms",
1021
+ "minMs": 1000,
1022
+ "summary": "How long approve waits for the claims adjuster's decision before the timeout default declines.",
1023
+ "title": "Adjuster decision deadline"
1024
+ }
1025
+ ],
1026
+ "fields": {
1027
+ "claimAmount": {
1028
+ "description": "Positive minor-unit integer amount serialized as a string (at most 18 digits)",
1029
+ "pattern": "^[1-9][0-9]{0,17}$",
1030
+ "type": "string"
1031
+ },
1032
+ "claimantAccountId": {
1033
+ "description": "Hyperscale account ID",
1034
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1035
+ "type": "string",
1036
+ "x-hyperscale-reference-filter": {
1037
+ "column": "role",
1038
+ "values": [
1039
+ "customer_balance"
1040
+ ]
1041
+ }
1042
+ },
1043
+ "currency": {
1044
+ "description": "ISO 4217 currency code",
1045
+ "maxLength": 3,
1046
+ "minLength": 3,
1047
+ "pattern": "^[A-Z]{3}$",
1048
+ "type": "string"
1049
+ },
1050
+ "evidenceSummary": {
1051
+ "maxLength": 2000,
1052
+ "minLength": 1,
1053
+ "type": "string"
1054
+ },
1055
+ "insurerAccountId": {
1056
+ "description": "Hyperscale account ID",
1057
+ "pattern": "^acct_(sandbox|live)_[a-z0-9]{8,64}$",
1058
+ "type": "string",
1059
+ "x-hyperscale-reference-filter": {
1060
+ "column": "role",
1061
+ "values": [
1062
+ "customer_balance"
1063
+ ]
1064
+ }
1065
+ },
1066
+ "occurredAt": {
1067
+ "format": "hyperscale-date-time",
1068
+ "type": "string"
1069
+ },
1070
+ "peril": {
1071
+ "pattern": "^[a-z][a-z0-9_]{1,79}$",
1072
+ "type": "string"
1073
+ },
1074
+ "policyId": {
1075
+ "description": "Active policy this claim is made against",
1076
+ "pattern": "^pol_(sandbox|live)_[a-z0-9]{8,64}$",
1077
+ "type": "string"
1078
+ }
1079
+ },
1080
+ "id": "claim",
1081
+ "idPrefix": "clm",
1082
+ "lifecycle": {
1083
+ "initial": "filed",
1084
+ "states": [
1085
+ "filed",
1086
+ "assessed",
1087
+ "approved",
1088
+ "paid",
1089
+ "denied"
1090
+ ],
1091
+ "transitions": {
1092
+ "approve": {
1093
+ "from": [
1094
+ "assessed"
1095
+ ],
1096
+ "to": "approved"
1097
+ },
1098
+ "assess": {
1099
+ "from": [
1100
+ "filed"
1101
+ ],
1102
+ "to": "assessed"
1103
+ },
1104
+ "attest": {
1105
+ "from": [
1106
+ "assessed"
1107
+ ],
1108
+ "to": "approved"
1109
+ },
1110
+ "deny": {
1111
+ "from": [
1112
+ "filed",
1113
+ "assessed"
1114
+ ],
1115
+ "to": "denied"
1116
+ },
1117
+ "pay": {
1118
+ "from": [
1119
+ "approved"
1120
+ ],
1121
+ "to": "paid"
1122
+ },
1123
+ "reverse": {
1124
+ "from": [
1125
+ "approved"
1126
+ ],
1127
+ "to": "denied"
1128
+ }
1129
+ }
1130
+ },
1131
+ "nav": [
1132
+ "Blueprints",
1133
+ "Claims"
1134
+ ],
1135
+ "parties": {
1136
+ "beneficiary": "claimantAccountId",
1137
+ "payer": "insurerAccountId"
1138
+ },
1139
+ "required": [
1140
+ "policyId",
1141
+ "claimantAccountId",
1142
+ "insurerAccountId",
1143
+ "claimAmount",
1144
+ "currency",
1145
+ "peril",
1146
+ "occurredAt"
1147
+ ],
1148
+ "subject": {
1149
+ "kinds": [
1150
+ "policy_risk",
1151
+ "flight_itinerary",
1152
+ "lodging_stay",
1153
+ "vehicle",
1154
+ "merchandise",
1155
+ "pet",
1156
+ "traveler_party",
1157
+ "employee_census"
1158
+ ]
1159
+ },
1160
+ "summary": "Demand against active protection for one covered peril.",
1161
+ "templateId": "insurance",
1162
+ "title": "Claim",
1163
+ "update": {
1164
+ "examples": [
1165
+ {
1166
+ "input": {
1167
+ "claimId": "clm_sandbox_protection001",
1168
+ "evidenceSummary": "Damage assessment confirms the covered accidental event.",
1169
+ "tenantId": "ten_sandbox_protection01"
1170
+ },
1171
+ "name": "add_claim_evidence_summary"
1172
+ }
1173
+ ],
1174
+ "fields": [
1175
+ "evidenceSummary"
1176
+ ],
1177
+ "states": [
1178
+ "filed",
1179
+ "assessed"
1180
+ ]
816
1181
  }
817
1182
  }
818
1183
  ],
@@ -861,6 +1226,56 @@
861
1226
  "title": "Vehicle",
862
1227
  "version": 1
863
1228
  },
1229
+ {
1230
+ "declaredValue": "required",
1231
+ "kind": "merchandise",
1232
+ "schema": {
1233
+ "additionalProperties": false,
1234
+ "properties": {
1235
+ "brand": {
1236
+ "maxLength": 60,
1237
+ "minLength": 1,
1238
+ "type": "string"
1239
+ },
1240
+ "category": {
1241
+ "maxLength": 60,
1242
+ "minLength": 1,
1243
+ "type": "string"
1244
+ },
1245
+ "condition": {
1246
+ "enum": [
1247
+ "new",
1248
+ "excellent",
1249
+ "good",
1250
+ "fair",
1251
+ "poor"
1252
+ ],
1253
+ "type": "string"
1254
+ },
1255
+ "model": {
1256
+ "maxLength": 60,
1257
+ "minLength": 1,
1258
+ "type": "string"
1259
+ },
1260
+ "serialNumber": {
1261
+ "maxLength": 80,
1262
+ "minLength": 1,
1263
+ "type": "string"
1264
+ },
1265
+ "yearOfManufacture": {
1266
+ "pattern": "^\\d{4}$",
1267
+ "type": "string"
1268
+ }
1269
+ },
1270
+ "required": [
1271
+ "category",
1272
+ "condition"
1273
+ ],
1274
+ "type": "object"
1275
+ },
1276
+ "title": "Merchandise",
1277
+ "version": 1
1278
+ },
864
1279
  {
865
1280
  "declaredValue": "required",
866
1281
  "kind": "policy_risk",