@almadar/std 16.180.0 → 16.182.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 (81) hide show
  1. package/behaviors/lolo/infra/atoms/std-calendar-sync.lolo +290 -0
  2. package/behaviors/lolo/infra/atoms/std-notification-center.lolo +290 -0
  3. package/behaviors/lolo/infra/atoms/std-notify-on-event.lolo +238 -40
  4. package/behaviors/lolo/ui/core/atoms/std-esign-flow.lolo +180 -3
  5. package/behaviors/lolo/ui/core/atoms/ui-badge.lolo +1 -9
  6. package/behaviors/lolo/ui/core/atoms/ui-filter-pill.lolo +2 -25
  7. package/behaviors/lolo/ui/core/molecules/ui-calendar-grid.lolo +6 -0
  8. package/behaviors/lolo/ui/core/organisms/ui-detail-panel.lolo +4 -4
  9. package/behaviors/lolo/ui/game/.hand-authored.json +1 -1
  10. package/behaviors/lolo/ui/game/atoms/ui-control-grid.lolo +5 -0
  11. package/behaviors/lolo/ui/game/atoms/ui-game-hud.lolo +5 -0
  12. package/behaviors/lolo/ui/game/atoms/ui-trait-slot.lolo +2 -36
  13. package/behaviors/lolo/ui/game/templates/ui-game-shell.lolo +5 -5
  14. package/behaviors/registry/infra/atoms/std-calendar-sync.orb +1643 -0
  15. package/behaviors/registry/infra/atoms/std-notification-center.orb +1621 -0
  16. package/behaviors/registry/infra/atoms/std-notify-on-event.orb +1734 -169
  17. package/behaviors/registry/ui/core/atoms/std-esign-flow.orb +846 -2
  18. package/behaviors/registry/ui/core/atoms/ui-badge.orb +1 -38
  19. package/behaviors/registry/ui/core/atoms/ui-filter-pill.orb +2 -90
  20. package/behaviors/registry/ui/core/molecules/ui-calendar-grid.orb +9 -0
  21. package/behaviors/registry/ui/core/organisms/ui-detail-panel.orb +4 -2
  22. package/behaviors/registry/ui/game/atoms/ui-control-grid.orb +13 -1
  23. package/behaviors/registry/ui/game/atoms/ui-game-hud.orb +13 -1
  24. package/behaviors/registry/ui/game/atoms/ui-trait-slot.orb +2 -101
  25. package/behaviors/registry/ui/game/templates/ui-game-shell.orb +5 -5
  26. package/canonical-operators.json +21 -1
  27. package/dist/behaviors/exports-reader.js +8303 -3043
  28. package/dist/behaviors/functions/index.d.ts +476 -36
  29. package/dist/behaviors/functions/index.js +18352 -13109
  30. package/dist/behaviors/index.d.ts +1 -1
  31. package/dist/behaviors/index.js +8304 -3044
  32. package/dist/behaviors/query.js +8303 -3043
  33. package/dist/behaviors-embeddings.hash.json +3 -3
  34. package/dist/behaviors-embeddings.json +365 -357
  35. package/dist/behaviors-registry.json +1170 -29
  36. package/dist/index.d.ts +3 -3
  37. package/dist/index.js +8275 -2978
  38. package/dist/knob-embeddings.hash.json +3 -3
  39. package/dist/knob-embeddings.json +1 -1
  40. package/dist/modules/anim.d.ts +1 -1
  41. package/dist/modules/array.d.ts +1 -1
  42. package/dist/modules/async.d.ts +1 -1
  43. package/dist/modules/behavior.d.ts +1 -1
  44. package/dist/modules/browser.d.ts +1 -1
  45. package/dist/modules/browser.js +21 -0
  46. package/dist/modules/composition.d.ts +1 -1
  47. package/dist/modules/contract.d.ts +1 -1
  48. package/dist/modules/core.d.ts +1 -1
  49. package/dist/modules/core.js +18 -2
  50. package/dist/modules/data.d.ts +1 -1
  51. package/dist/modules/ease.d.ts +1 -1
  52. package/dist/modules/format.d.ts +1 -1
  53. package/dist/modules/geo.d.ts +1 -1
  54. package/dist/modules/graph.d.ts +1 -1
  55. package/dist/modules/grid.d.ts +1 -1
  56. package/dist/modules/index.d.ts +1 -1
  57. package/dist/modules/index.js +39 -2
  58. package/dist/modules/integration.d.ts +1 -1
  59. package/dist/modules/llm.d.ts +1 -1
  60. package/dist/modules/math.d.ts +1 -1
  61. package/dist/modules/memory.d.ts +1 -1
  62. package/dist/modules/nn.d.ts +1 -1
  63. package/dist/modules/noise.d.ts +1 -1
  64. package/dist/modules/object.d.ts +1 -1
  65. package/dist/modules/os.d.ts +1 -1
  66. package/dist/modules/path.d.ts +1 -1
  67. package/dist/modules/prob.d.ts +1 -1
  68. package/dist/modules/session.d.ts +1 -1
  69. package/dist/modules/str.d.ts +1 -1
  70. package/dist/modules/tensor.d.ts +1 -1
  71. package/dist/modules/time.d.ts +1 -1
  72. package/dist/modules/trace.d.ts +1 -1
  73. package/dist/modules/train.d.ts +1 -1
  74. package/dist/modules/validate.d.ts +1 -1
  75. package/dist/modules/vector.d.ts +1 -1
  76. package/dist/modules/workspace.d.ts +1 -1
  77. package/dist/registry/factory-signatures.json +1 -1
  78. package/dist/registry.d.ts +1 -1
  79. package/dist/registry.js +39 -2
  80. package/dist/{types-DGJ6Y6nW.d.ts → types-BXWzEjFm.d.ts} +1 -1
  81. package/package.json +3 -3
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "std-notify-on-event — cross-orbital wiring atom. Subscribes to events from another orbital (e.g. CheckoutOrbital emits OrderPlaced, OrderRecordOrbital reacts via this atom) and dispatches a notification. Use when one orbital needs to react to or be notified about events that happen in another orbital — the wiring goes through this atom's `EventOccurred` listener which the molecule renames via traitOverrides.events to the upstream event name. Dispatch gates on `guardOp`: `eq` (default) does string-equality on `triggerStatus` against the upstream event's `status` field, exactly as before; `gt`/`lt`/`gte`/`lte` instead numerically compare `guardField` (read from the event's `data` payload) against `guardValue`, for threshold-crossing asks such as low-stock alerts. Resolves recipient from `recipients` (first entry; multi-recipient fan-out is a future extension), falling back to `fallbackRecipient` when set, or `@user.id` otherwise set `fallbackRecipient` for system/ops alerts (e.g. low-stock, shipping) so the acting user isn't notified in place of the intended audience. Skips dispatch when the recipient is in `suppressionList`. Emits in-app `notify` when `notifyChannel` is `\"in-app\"` (default, unchanged). `\"email\"`/`\"sms\"`/`\"webhook\"` dispatch through call-service at event time (email.send / twilio.sendSMS / webhook.send respectively) and persist a `NotificationRecord` audit row with an honest `dispatched` flag true only once the service call succeeds, false with the failure detail in `error` otherwise. `email` uses `emailSubject` (falls back to `template` when blank); `webhook` requires `webhookUrl` to actually dispatch (`webhookSecret` signs the payload) a blank `webhookUrl` still records the audit row undispatched rather than failing.",
2
+ "description": "std-notify-on-event — cross-orbital wiring atom. Subscribes to events from another orbital (e.g. CheckoutOrbital emits OrderPlaced, OrderRecordOrbital reacts via this atom) and dispatches a notification. Use when one orbital needs to react to or be notified about events that happen in another orbital — the wiring goes through this atom's `EventOccurred` listener which the molecule renames via traitOverrides.events to the upstream event name. Dispatch gates on `guardOp`: `eq` (default) does string-equality on `triggerStatus` against the upstream event's `status` field; `gt`/`lt`/`gte`/`lte` instead numerically compare `guardField` (read from the event's `data` payload) against `guardValue`, for threshold-crossing asks such as low-stock alerts. Resolves recipient from `recipients` (first entry; multi-recipient fan-out is a future extension), falling back to `fallbackRecipient` when set, or `@user.id` otherwise. Skips dispatch when the recipient is in `suppressionList`. Delivery consults std-notification-center data before dispatching: per-user NotificationPreference rows (matched on `userId` = recipient and `eventType` = this listener's `eventKey`, blank = all) can mute (`mode: off`), defer to the digest drain (`mode: digest`), override the channel, or impose per-user quiet hours; the atom-level `quietStartHour`/`quietEndHour` window and the `frequencyCapPerWeek` rolling cap (counted against dispatched NotificationRecord audit rows for the same recipient + channel) suppress likewise. Every suppression persists an honest audit row (`dispatched: false` with the reason in `error`: quiet-hours / digest-deferred / muted-by-preference / frequency-cap / no-push-subscription) which std-notification-center's digest cycle drains later. Channels: `in-app` emits the `notify` toast; `email`/`sms`/`webhook` dispatch through call-service (email.send / twilio.sendSMS / webhook.send); `push` looks up the recipient's PushSubscription row (owned by std-notification-center) and dispatches web-push via push.send (`pushTitle` falls back to `template`; `pushDeepLink`/`pushIcon` optional). The audit row's `dispatched` flag is honest true only once the service call succeeds.",
3
3
  "ledger": {
4
4
  "entries": {
5
5
  "ent_01KXG04FE9SA0FVQV9VJC8915N": {
@@ -10,6 +10,22 @@
10
10
  "owner": "workspace",
11
11
  "renames": []
12
12
  },
13
+ "ent_01M0M65FF6PA66WQD276TVZ489": {
14
+ "bakedName": "NotificationPreference",
15
+ "curName": "NotificationPreference",
16
+ "id": "ent_01M0M65FF6PA66WQD276TVZ489",
17
+ "kind": "entity",
18
+ "owner": "workspace",
19
+ "renames": []
20
+ },
21
+ "ent_01M0M65FF6PZ5Q2FSJKKWJE4NH": {
22
+ "bakedName": "PushSubscription",
23
+ "curName": "PushSubscription",
24
+ "id": "ent_01M0M65FF6PZ5Q2FSJKKWJE4NH",
25
+ "kind": "entity",
26
+ "owner": "workspace",
27
+ "renames": []
28
+ },
13
29
  "evt_01KXG04FE9FBG7H2NH6HKT4ZAR": {
14
30
  "bakedName": "EventOccurred",
15
31
  "curName": "EventOccurred",
@@ -82,6 +98,60 @@
82
98
  "parent": "trt_01KXG04FE9HSGJRHVVCWZJ77YF",
83
99
  "renames": []
84
100
  },
101
+ "evt_01M0M65FF68HQ6K67FGYDE0P4V": {
102
+ "bakedName": "NOTIFY_PREFS_LOADED",
103
+ "curName": "NOTIFY_PREFS_LOADED",
104
+ "id": "evt_01M0M65FF68HQ6K67FGYDE0P4V",
105
+ "kind": "event",
106
+ "owner": "workspace",
107
+ "parent": "trt_01KXG04FE9HSGJRHVVCWZJ77YF",
108
+ "renames": []
109
+ },
110
+ "evt_01M0M65FF6CS2R9V2JQ6EJYGDX": {
111
+ "bakedName": "NOTIFY_LOOKUP_FAILED",
112
+ "curName": "NOTIFY_LOOKUP_FAILED",
113
+ "id": "evt_01M0M65FF6CS2R9V2JQ6EJYGDX",
114
+ "kind": "event",
115
+ "owner": "workspace",
116
+ "parent": "trt_01KXG04FE9HSGJRHVVCWZJ77YF",
117
+ "renames": []
118
+ },
119
+ "evt_01M0M65FF6DKMEW2D2E96T9VTH": {
120
+ "bakedName": "NOTIFY_PUSH_SENT",
121
+ "curName": "NOTIFY_PUSH_SENT",
122
+ "id": "evt_01M0M65FF6DKMEW2D2E96T9VTH",
123
+ "kind": "event",
124
+ "owner": "workspace",
125
+ "parent": "trt_01KXG04FE9HSGJRHVVCWZJ77YF",
126
+ "renames": []
127
+ },
128
+ "evt_01M0M65FF6F8X646FMC2ZYX7HW": {
129
+ "bakedName": "NOTIFY_CAP_LOADED",
130
+ "curName": "NOTIFY_CAP_LOADED",
131
+ "id": "evt_01M0M65FF6F8X646FMC2ZYX7HW",
132
+ "kind": "event",
133
+ "owner": "workspace",
134
+ "parent": "trt_01KXG04FE9HSGJRHVVCWZJ77YF",
135
+ "renames": []
136
+ },
137
+ "evt_01M0M65FF6JAF7JE380C3CWWXM": {
138
+ "bakedName": "NOTIFY_PUSH_FAILED",
139
+ "curName": "NOTIFY_PUSH_FAILED",
140
+ "id": "evt_01M0M65FF6JAF7JE380C3CWWXM",
141
+ "kind": "event",
142
+ "owner": "workspace",
143
+ "parent": "trt_01KXG04FE9HSGJRHVVCWZJ77YF",
144
+ "renames": []
145
+ },
146
+ "evt_01M0M65FF6Z4XVMQTZT0P95WJQ": {
147
+ "bakedName": "NOTIFY_PUSH_SUBS",
148
+ "curName": "NOTIFY_PUSH_SUBS",
149
+ "id": "evt_01M0M65FF6Z4XVMQTZT0P95WJQ",
150
+ "kind": "event",
151
+ "owner": "workspace",
152
+ "parent": "trt_01KXG04FE9HSGJRHVVCWZJ77YF",
153
+ "renames": []
154
+ },
85
155
  "orb_01KXG04FE9P09BNXECH6P7JQ7H": {
86
156
  "bakedName": "NotifyOnEventOrbital",
87
157
  "curName": "NotifyOnEventOrbital",
@@ -112,6 +182,111 @@
112
182
  "name": "std-notify-on-event",
113
183
  "orbitals": [
114
184
  {
185
+ "auxiliaryEntities": [
186
+ {
187
+ "collection": "notificationPreferences",
188
+ "fields": [
189
+ {
190
+ "name": "id",
191
+ "required": true,
192
+ "type": "string"
193
+ },
194
+ {
195
+ "default": "",
196
+ "description": "Owner of this preference row.",
197
+ "name": "userId",
198
+ "synonyms": "user, owner, account",
199
+ "type": "string"
200
+ },
201
+ {
202
+ "default": "",
203
+ "description": "Event key this preference applies to (matches the listener's eventKey); blank = all events.",
204
+ "name": "eventType",
205
+ "synonyms": "event, trigger, subscription",
206
+ "type": "string"
207
+ },
208
+ {
209
+ "default": "instant",
210
+ "description": "Delivery mode: instant, digest, or off.",
211
+ "name": "mode",
212
+ "synonyms": "delivery mode, frequency, cadence",
213
+ "type": "string"
214
+ },
215
+ {
216
+ "default": "",
217
+ "description": "Channel override for this user (in-app/email/sms/push/webhook); blank = the listener's configured channel.",
218
+ "name": "channel",
219
+ "synonyms": "preferred channel, delivery method",
220
+ "type": "string"
221
+ },
222
+ {
223
+ "default": 0.0,
224
+ "description": "Per-user quiet-hours start (hour 0-23); equal to quietEndHour = disabled.",
225
+ "name": "quietStartHour",
226
+ "synonyms": "quiet start, do not disturb from",
227
+ "type": "number"
228
+ },
229
+ {
230
+ "default": 0.0,
231
+ "description": "Per-user quiet-hours end (hour 0-23); equal to quietStartHour = disabled.",
232
+ "name": "quietEndHour",
233
+ "synonyms": "quiet end, do not disturb until",
234
+ "type": "number"
235
+ }
236
+ ],
237
+ "id": "ent_01M0M65FF6PA66WQD276TVZ489",
238
+ "name": "NotificationPreference",
239
+ "persistence": "persistent"
240
+ },
241
+ {
242
+ "collection": "pushSubscriptions",
243
+ "fields": [
244
+ {
245
+ "name": "id",
246
+ "required": true,
247
+ "type": "string"
248
+ },
249
+ {
250
+ "default": "",
251
+ "description": "Owner of this browser push subscription.",
252
+ "name": "userId",
253
+ "synonyms": "user, owner, account",
254
+ "type": "string"
255
+ },
256
+ {
257
+ "default": "",
258
+ "description": "Push service endpoint URL for this subscription.",
259
+ "name": "endpoint",
260
+ "synonyms": "push url, subscription endpoint",
261
+ "type": "string"
262
+ },
263
+ {
264
+ "default": "",
265
+ "description": "Client public key (p256dh) of the subscription.",
266
+ "name": "p256dh",
267
+ "synonyms": "public key",
268
+ "type": "string"
269
+ },
270
+ {
271
+ "default": "",
272
+ "description": "Auth secret of the subscription.",
273
+ "name": "auth",
274
+ "synonyms": "auth secret",
275
+ "type": "string"
276
+ },
277
+ {
278
+ "default": 0.0,
279
+ "description": "When this subscription was captured.",
280
+ "name": "createdAt",
281
+ "synonyms": "subscribed at, created",
282
+ "type": "number"
283
+ }
284
+ ],
285
+ "id": "ent_01M0M65FF6PZ5Q2FSJKKWJE4NH",
286
+ "name": "PushSubscription",
287
+ "persistence": "persistent"
288
+ }
289
+ ],
115
290
  "entity": {
116
291
  "collection": "notifications",
117
292
  "fields": [
@@ -157,7 +332,7 @@
157
332
  },
158
333
  {
159
334
  "default": "",
160
- "description": "Failure detail from the delivery service when dispatched is false (email/sms/webhook channels only).",
335
+ "description": "Failure detail from the delivery service when dispatched is false, or the suppression reason (quiet-hours / digest-deferred / muted-by-preference / frequency-cap / no-push-subscription).",
161
336
  "name": "error",
162
337
  "synonyms": "error message, failure reason, dispatch error",
163
338
  "type": "string"
@@ -168,6 +343,55 @@
168
343
  "name": "recordedAt",
169
344
  "synonyms": "creation time, timestamp, date, when",
170
345
  "type": "number"
346
+ },
347
+ {
348
+ "default": "",
349
+ "description": "Scratch: effective preference mode resolved for the current dispatch (instant/digest/off).",
350
+ "name": "prefMode",
351
+ "synonyms": "resolved mode",
352
+ "type": "string"
353
+ },
354
+ {
355
+ "default": "",
356
+ "description": "Scratch: channel override from the matched preference row; blank = no override.",
357
+ "name": "prefChannel",
358
+ "synonyms": "channel override",
359
+ "type": "string"
360
+ },
361
+ {
362
+ "default": 0.0,
363
+ "description": "Scratch: per-user quiet-hours start (hour 0-23) from the matched preference row.",
364
+ "name": "prefQuietStart",
365
+ "synonyms": "user quiet start",
366
+ "type": "number"
367
+ },
368
+ {
369
+ "default": 0.0,
370
+ "description": "Scratch: per-user quiet-hours end (hour 0-23) from the matched preference row.",
371
+ "name": "prefQuietEnd",
372
+ "synonyms": "user quiet end",
373
+ "type": "number"
374
+ },
375
+ {
376
+ "default": "",
377
+ "description": "Scratch: push endpoint of the recipient's subscription for the current dispatch.",
378
+ "name": "pushEndpoint",
379
+ "synonyms": "subscription endpoint",
380
+ "type": "string"
381
+ },
382
+ {
383
+ "default": "",
384
+ "description": "Scratch: p256dh key of the recipient's push subscription.",
385
+ "name": "pushP256dh",
386
+ "synonyms": "push key",
387
+ "type": "string"
388
+ },
389
+ {
390
+ "default": "",
391
+ "description": "Scratch: auth secret of the recipient's push subscription.",
392
+ "name": "pushAuth",
393
+ "synonyms": "push auth",
394
+ "type": "string"
171
395
  }
172
396
  ],
173
397
  "id": "ent_01KXG04FE9SA0FVQV9VJC8915N",
@@ -201,6 +425,14 @@
201
425
  "tier": "presentation",
202
426
  "type": "string"
203
427
  },
428
+ "eventKey": {
429
+ "default": "",
430
+ "description": "Stable key naming the upstream event this listener is bound to (e.g. 'OrderPlaced'). NotificationPreference rows (std-notification-center) whose eventType equals this key — or is blank — apply to this listener's dispatches.",
431
+ "label": "Event key for preferences",
432
+ "synonyms": "preference key, event name, subscription key, notification topic",
433
+ "tier": "policy",
434
+ "type": "string"
435
+ },
204
436
  "fallbackRecipient": {
205
437
  "default": "",
206
438
  "description": "Recipient used when `recipients` is empty, instead of the acting user. The acting-user fallback (used when this is blank) is intended for personal notifications only — set this to an ops/team address (e.g. 'ops@example.com') for system alerts like low-stock or shipping notices, so the acting user isn't notified in place of the intended audience.",
@@ -211,8 +443,9 @@
211
443
  },
212
444
  "frequencyCapPerWeek": {
213
445
  "default": 0.0,
214
- "description": "Max sends per (channel, recipient) per rolling 7-day window. 0 = uncapped. WIRING DEFERRED: needs stateful history query (gap docs/Almadar_Std_Factories.md).",
446
+ "description": "Max dispatched sends per (channel, recipient) per rolling 7-day window, counted against dispatched NotificationRecord audit rows. 0 = uncapped. Applies to the persisted channels (email/sms/push/webhook); in-app toasts are not audited and not capped. A capped dispatch persists an audit row (`error: frequency-cap`, dispatched:false).",
215
447
  "label": "Frequency cap (per week)",
448
+ "synonyms": "rate limit, cap, max per week, throttle, send limit",
216
449
  "tier": "policy",
217
450
  "type": "number"
218
451
  },
@@ -260,39 +493,58 @@
260
493
  },
261
494
  "notifyChannel": {
262
495
  "default": "in-app",
263
- "description": "Delivery channel. `in-app` (default) emits the in-app `notify` toast — unchanged from prior versions. `email`/`sms`/`webhook` dispatch through call-service at event time (email.send / twilio.sendSMS / webhook.send) and persist a NotificationRecord audit row with an honest `dispatched` flag: true only once the service call succeeds, false plus the failure detail in `error` otherwise. `webhook` requires `webhookUrl` to actually dispatch; a blank `webhookUrl` still records the audit row undispatched rather than failing.",
496
+ "description": "Delivery channel. `in-app` (default) emits the in-app `notify` toast. `email`/`sms`/`webhook` dispatch through call-service at event time (email.send / twilio.sendSMS / webhook.send) and persist a NotificationRecord audit row with an honest `dispatched` flag: true only once the service call succeeds, false plus the failure detail in `error` otherwise. `push` looks up the recipient's PushSubscription row (captured by std-notification-center's subscribe flow) and dispatches web-push via push.send — a recipient with no subscription records the audit row undispatched (`no-push-subscription`). `webhook` requires `webhookUrl` to actually dispatch; a blank `webhookUrl` still records the audit row undispatched rather than failing. A per-user NotificationPreference row with a non-blank `channel` overrides this value for that recipient.",
264
497
  "label": "Channel",
265
- "synonyms": "delivery method, notification channel, send via, dispatch through",
498
+ "synonyms": "delivery method, notification channel, send via, dispatch through, push notification, web push",
266
499
  "tier": "policy",
267
500
  "type": "string",
268
501
  "values": [
269
502
  "in-app",
270
503
  "email",
271
504
  "sms",
505
+ "push",
272
506
  "webhook"
273
507
  ]
274
508
  },
275
- "quietHours": {
276
- "default": {
277
- "end": "",
278
- "start": ""
279
- },
280
- "description": "Local-time window during which dispatch is suppressed. Both start and end required to activate. WIRING DEFERRED: needs @now-aware time comparison primitive (gap — docs/Almadar_Std_Factories.md).",
281
- "label": "Quiet hours",
282
- "properties": {
283
- "end": {
284
- "name": "end",
285
- "required": false,
286
- "type": "string"
287
- },
288
- "start": {
289
- "name": "start",
290
- "required": false,
291
- "type": "string"
292
- }
293
- },
509
+ "pushDeepLink": {
510
+ "default": "",
511
+ "description": "In-app path opened when the recipient clicks the push notification (e.g. '/orders'). Blank = the app root.",
512
+ "label": "Push deep link",
513
+ "synonyms": "click url, open on click, target path, notification link",
514
+ "tier": "presentation",
515
+ "type": "string"
516
+ },
517
+ "pushIcon": {
518
+ "default": "",
519
+ "description": "Icon URL shown on the push notification. Blank = the browser default.",
520
+ "label": "Push icon",
521
+ "synonyms": "notification icon, badge image",
522
+ "tier": "presentation",
523
+ "type": "string"
524
+ },
525
+ "pushTitle": {
526
+ "default": "",
527
+ "description": "Notification title for the push channel. Falls back to `template` when blank. Ignored for other channels.",
528
+ "label": "Push title",
529
+ "synonyms": "notification title, push heading, alert title",
530
+ "tier": "presentation",
531
+ "type": "string"
532
+ },
533
+ "quietEndHour": {
534
+ "default": 0.0,
535
+ "description": "Hour of day (0-23) when the atom-level quiet window closes. Equal to `quietStartHour` = disabled.",
536
+ "label": "Quiet hours end",
537
+ "synonyms": "do not disturb until, silence end, night mode end",
294
538
  "tier": "policy",
295
- "type": "QuietHoursSpec"
539
+ "type": "number"
540
+ },
541
+ "quietStartHour": {
542
+ "default": 0.0,
543
+ "description": "Hour of day (0-23) when the atom-level quiet window opens. Equal to `quietEndHour` = disabled. Dispatches inside the window persist an audit row (`error: quiet-hours`, dispatched:false) which std-notification-center's digest cycle drains later. Per-user quiet hours from NotificationPreference rows apply in addition.",
544
+ "label": "Quiet hours start",
545
+ "synonyms": "quiet hours, do not disturb from, silence start, night mode start",
546
+ "tier": "policy",
547
+ "type": "number"
296
548
  },
297
549
  "recipients": {
298
550
  "default": [],
@@ -381,6 +633,42 @@
381
633
  ],
382
634
  "scope": "external"
383
635
  },
636
+ {
637
+ "description": "NotificationPreference rows loaded; the arm resolves the recipient's effective mode/channel/quiet-hours",
638
+ "event": "NOTIFY_PREFS_LOADED",
639
+ "eventId": "evt_01M0M65FF68HQ6K67FGYDE0P4V",
640
+ "payloadSchema": [
641
+ {
642
+ "name": "data",
643
+ "type": "[PrefRow]"
644
+ }
645
+ ],
646
+ "tier": "secondary"
647
+ },
648
+ {
649
+ "description": "Rolling 7-day NotificationRecord window loaded; the arm enforces frequencyCapPerWeek then dispatches",
650
+ "event": "NOTIFY_CAP_LOADED",
651
+ "eventId": "evt_01M0M65FF6F8X646FMC2ZYX7HW",
652
+ "payloadSchema": [
653
+ {
654
+ "name": "data",
655
+ "type": "[AuditRow]"
656
+ }
657
+ ],
658
+ "tier": "secondary"
659
+ },
660
+ {
661
+ "description": "PushSubscription rows loaded; the arm picks the recipient's subscription and dispatches push.send",
662
+ "event": "NOTIFY_PUSH_SUBS",
663
+ "eventId": "evt_01M0M65FF6Z4XVMQTZT0P95WJQ",
664
+ "payloadSchema": [
665
+ {
666
+ "name": "data",
667
+ "type": "[SubRow]"
668
+ }
669
+ ],
670
+ "tier": "secondary"
671
+ },
384
672
  {
385
673
  "description": "email.send service result, flattened onto the payload by the call-service effect executor",
386
674
  "event": "NOTIFY_EMAIL_SENT",
@@ -478,10 +766,61 @@
478
766
  }
479
767
  ],
480
768
  "tier": "secondary"
769
+ },
770
+ {
771
+ "description": "push.send service result — expired:true means the subscription is gone and should be pruned",
772
+ "event": "NOTIFY_PUSH_SENT",
773
+ "eventId": "evt_01M0M65FF6DKMEW2D2E96T9VTH",
774
+ "payloadSchema": [
775
+ {
776
+ "name": "statusCode",
777
+ "required": true,
778
+ "type": "number"
779
+ },
780
+ {
781
+ "name": "ok",
782
+ "required": true,
783
+ "type": "boolean"
784
+ },
785
+ {
786
+ "name": "expired",
787
+ "required": true,
788
+ "type": "boolean"
789
+ }
790
+ ],
791
+ "tier": "secondary"
792
+ },
793
+ {
794
+ "description": "push.send service call failed — dispatched lands false and error carries the service detail",
795
+ "event": "NOTIFY_PUSH_FAILED",
796
+ "eventId": "evt_01M0M65FF6JAF7JE380C3CWWXM",
797
+ "payloadSchema": [
798
+ {
799
+ "name": "error",
800
+ "required": true,
801
+ "type": "string"
802
+ }
803
+ ],
804
+ "tier": "secondary"
805
+ },
806
+ {
807
+ "description": "A preference / cap-window / subscription fetch failed — dispatched lands false with the fetch error",
808
+ "event": "NOTIFY_LOOKUP_FAILED",
809
+ "eventId": "evt_01M0M65FF6CS2R9V2JQ6EJYGDX",
810
+ "payloadSchema": [
811
+ {
812
+ "name": "error",
813
+ "required": true,
814
+ "type": "string"
815
+ }
816
+ ],
817
+ "tier": "secondary"
481
818
  }
482
819
  ],
483
820
  "entityRefIds": {
484
- "NotificationRecord": "ent_01KXG04FE9SA0FVQV9VJC8915N"
821
+ "NotificationPreference": "ent_01M0M65FF6PA66WQD276TVZ489",
822
+ "NotificationRecord": "ent_01KXG04FE9SA0FVQV9VJC8915N",
823
+ "PushSubscription": "ent_01M0M65FF6PZ5Q2FSJKKWJE4NH"
485
824
  },
486
825
  "id": "trt_01KXG04FE9HSGJRHVVCWZJ77YF",
487
826
  "linkedEntity": "NotificationRecord",
@@ -505,6 +844,107 @@
505
844
  }
506
845
  ]
507
846
  },
847
+ {
848
+ "description": "NotificationPreference rows loaded; the arm resolves the recipient's effective mode/channel/quiet-hours",
849
+ "id": "evt_01M0M65FF68HQ6K67FGYDE0P4V",
850
+ "key": "NOTIFY_PREFS_LOADED",
851
+ "name": "Notify Prefs Loaded",
852
+ "payloadSchema": [
853
+ {
854
+ "name": "data",
855
+ "properties": [
856
+ {
857
+ "name": "userId",
858
+ "type": "string"
859
+ },
860
+ {
861
+ "name": "eventType",
862
+ "type": "string"
863
+ },
864
+ {
865
+ "name": "mode",
866
+ "type": "string"
867
+ },
868
+ {
869
+ "name": "channel",
870
+ "type": "string"
871
+ },
872
+ {
873
+ "name": "quietStartHour",
874
+ "type": "number"
875
+ },
876
+ {
877
+ "name": "quietEndHour",
878
+ "type": "number"
879
+ }
880
+ ],
881
+ "type": "[object]"
882
+ }
883
+ ],
884
+ "tier": "secondary"
885
+ },
886
+ {
887
+ "description": "Rolling 7-day NotificationRecord window loaded; the arm enforces frequencyCapPerWeek then dispatches",
888
+ "id": "evt_01M0M65FF6F8X646FMC2ZYX7HW",
889
+ "key": "NOTIFY_CAP_LOADED",
890
+ "name": "Notify Cap Loaded",
891
+ "payloadSchema": [
892
+ {
893
+ "name": "data",
894
+ "properties": [
895
+ {
896
+ "name": "recipient",
897
+ "type": "string"
898
+ },
899
+ {
900
+ "name": "channel",
901
+ "type": "string"
902
+ },
903
+ {
904
+ "name": "dispatched",
905
+ "type": "boolean"
906
+ },
907
+ {
908
+ "name": "recordedAt",
909
+ "type": "number"
910
+ }
911
+ ],
912
+ "type": "[object]"
913
+ }
914
+ ],
915
+ "tier": "secondary"
916
+ },
917
+ {
918
+ "description": "PushSubscription rows loaded; the arm picks the recipient's subscription and dispatches push.send",
919
+ "id": "evt_01M0M65FF6Z4XVMQTZT0P95WJQ",
920
+ "key": "NOTIFY_PUSH_SUBS",
921
+ "name": "Notify Push Subs",
922
+ "payloadSchema": [
923
+ {
924
+ "name": "data",
925
+ "properties": [
926
+ {
927
+ "name": "userId",
928
+ "type": "string"
929
+ },
930
+ {
931
+ "name": "endpoint",
932
+ "type": "string"
933
+ },
934
+ {
935
+ "name": "p256dh",
936
+ "type": "string"
937
+ },
938
+ {
939
+ "name": "auth",
940
+ "type": "string"
941
+ }
942
+ ],
943
+ "type": "[object]"
944
+ }
945
+ ],
946
+ "tier": "secondary"
947
+ },
508
948
  {
509
949
  "description": "email.send service result, flattened onto the payload by the call-service effect executor",
510
950
  "id": "evt_01M04F6YS147RT3HG7Y6RM5NPR",
@@ -610,27 +1050,79 @@
610
1050
  "tier": "secondary"
611
1051
  },
612
1052
  {
613
- "id": "evt_01KXG04FE9R85M0QY4RN3YHY2G",
614
- "key": "NotificationDispatched",
615
- "name": "Notification dispatched",
1053
+ "description": "push.send service result — expired:true means the subscription is gone and should be pruned",
1054
+ "id": "evt_01M0M65FF6DKMEW2D2E96T9VTH",
1055
+ "key": "NOTIFY_PUSH_SENT",
1056
+ "name": "Notify Push Sent",
616
1057
  "payloadSchema": [
617
1058
  {
618
- "name": "recipient",
619
- "type": "string"
620
- },
621
- {
622
- "name": "channel",
623
- "type": "string"
1059
+ "name": "statusCode",
1060
+ "required": true,
1061
+ "type": "number"
624
1062
  },
625
1063
  {
626
- "name": "message",
627
- "type": "string"
1064
+ "name": "ok",
1065
+ "required": true,
1066
+ "type": "boolean"
628
1067
  },
629
1068
  {
630
- "name": "severity",
631
- "type": "string"
1069
+ "name": "expired",
1070
+ "required": true,
1071
+ "type": "boolean"
632
1072
  }
633
- ]
1073
+ ],
1074
+ "tier": "secondary"
1075
+ },
1076
+ {
1077
+ "description": "push.send service call failed — dispatched lands false and error carries the service detail",
1078
+ "id": "evt_01M0M65FF6JAF7JE380C3CWWXM",
1079
+ "key": "NOTIFY_PUSH_FAILED",
1080
+ "name": "Notify Push Failed",
1081
+ "payloadSchema": [
1082
+ {
1083
+ "name": "error",
1084
+ "required": true,
1085
+ "type": "string"
1086
+ }
1087
+ ],
1088
+ "tier": "secondary"
1089
+ },
1090
+ {
1091
+ "description": "A preference / cap-window / subscription fetch failed — dispatched lands false with the fetch error",
1092
+ "id": "evt_01M0M65FF6CS2R9V2JQ6EJYGDX",
1093
+ "key": "NOTIFY_LOOKUP_FAILED",
1094
+ "name": "Notify Lookup Failed",
1095
+ "payloadSchema": [
1096
+ {
1097
+ "name": "error",
1098
+ "required": true,
1099
+ "type": "string"
1100
+ }
1101
+ ],
1102
+ "tier": "secondary"
1103
+ },
1104
+ {
1105
+ "id": "evt_01KXG04FE9R85M0QY4RN3YHY2G",
1106
+ "key": "NotificationDispatched",
1107
+ "name": "Notification dispatched",
1108
+ "payloadSchema": [
1109
+ {
1110
+ "name": "recipient",
1111
+ "type": "string"
1112
+ },
1113
+ {
1114
+ "name": "channel",
1115
+ "type": "string"
1116
+ },
1117
+ {
1118
+ "name": "message",
1119
+ "type": "string"
1120
+ },
1121
+ {
1122
+ "name": "severity",
1123
+ "type": "string"
1124
+ }
1125
+ ]
634
1126
  }
635
1127
  ],
636
1128
  "states": [
@@ -692,80 +1184,928 @@
692
1184
  [
693
1185
  "set",
694
1186
  "@entity.dispatched",
1187
+ false
1188
+ ],
1189
+ [
1190
+ "set",
1191
+ "@entity.recordedAt",
1192
+ "@now"
1193
+ ],
1194
+ [
1195
+ "when",
695
1196
  [
696
- "and",
1197
+ "not",
1198
+ [
1199
+ "array/includes",
1200
+ "@config.suppressionList",
1201
+ "@entity.recipient"
1202
+ ]
1203
+ ],
1204
+ [
1205
+ "if",
1206
+ [
1207
+ "and",
1208
+ [
1209
+ "not",
1210
+ [
1211
+ "=",
1212
+ "@config.quietStartHour",
1213
+ "@config.quietEndHour"
1214
+ ]
1215
+ ],
1216
+ [
1217
+ "if",
1218
+ [
1219
+ "<",
1220
+ "@config.quietStartHour",
1221
+ "@config.quietEndHour"
1222
+ ],
1223
+ [
1224
+ "and",
1225
+ [
1226
+ ">=",
1227
+ [
1228
+ "time/hour",
1229
+ "@now"
1230
+ ],
1231
+ "@config.quietStartHour"
1232
+ ],
1233
+ [
1234
+ "<",
1235
+ [
1236
+ "time/hour",
1237
+ "@now"
1238
+ ],
1239
+ "@config.quietEndHour"
1240
+ ]
1241
+ ],
1242
+ [
1243
+ "or",
1244
+ [
1245
+ ">=",
1246
+ [
1247
+ "time/hour",
1248
+ "@now"
1249
+ ],
1250
+ "@config.quietStartHour"
1251
+ ],
1252
+ [
1253
+ "<",
1254
+ [
1255
+ "time/hour",
1256
+ "@now"
1257
+ ],
1258
+ "@config.quietEndHour"
1259
+ ]
1260
+ ]
1261
+ ]
1262
+ ],
1263
+ [
1264
+ "persist",
1265
+ "create",
1266
+ "NotificationRecord",
1267
+ {
1268
+ "channel": "@entity.channel",
1269
+ "dispatched": false,
1270
+ "error": "quiet-hours",
1271
+ "message": "@entity.message",
1272
+ "recipient": "@entity.recipient",
1273
+ "recordedAt": "@now",
1274
+ "severity": "@entity.severity"
1275
+ }
1276
+ ],
1277
+ [
1278
+ "fetch",
1279
+ "NotificationPreference",
1280
+ {
1281
+ "emit": {
1282
+ "failure": "NOTIFY_LOOKUP_FAILED",
1283
+ "success": "NOTIFY_PREFS_LOADED"
1284
+ }
1285
+ }
1286
+ ]
1287
+ ]
1288
+ ],
1289
+ [
1290
+ "emit",
1291
+ "NotificationDispatched",
1292
+ {
1293
+ "channel": "@entity.channel",
1294
+ "message": "@entity.message",
1295
+ "recipient": "@entity.recipient",
1296
+ "severity": "@entity.severity"
1297
+ }
1298
+ ]
1299
+ ],
1300
+ "event": "EventOccurred",
1301
+ "eventId": "evt_01KXG04FE9FBG7H2NH6HKT4ZAR",
1302
+ "from": "idle",
1303
+ "guard": [
1304
+ "if",
1305
+ [
1306
+ "=",
1307
+ "@config.guardOp",
1308
+ "eq"
1309
+ ],
1310
+ [
1311
+ "or",
1312
+ [
1313
+ "=",
1314
+ "@config.triggerStatus",
1315
+ ""
1316
+ ],
1317
+ [
1318
+ "=",
1319
+ "@payload.status",
1320
+ "@config.triggerStatus"
1321
+ ]
1322
+ ],
1323
+ [
1324
+ "if",
1325
+ [
1326
+ "=",
1327
+ "@config.guardOp",
1328
+ "gt"
1329
+ ],
1330
+ [
1331
+ ">",
1332
+ [
1333
+ "object/get",
1334
+ "@payload.data",
1335
+ "@config.guardField"
1336
+ ],
1337
+ "@config.guardValue"
1338
+ ],
1339
+ [
1340
+ "if",
697
1341
  [
698
1342
  "=",
699
- "@config.notifyChannel",
700
- "in-app"
1343
+ "@config.guardOp",
1344
+ "lt"
701
1345
  ],
702
1346
  [
703
- "not",
1347
+ "<",
704
1348
  [
705
- "array/includes",
706
- "@config.suppressionList",
707
- "@entity.recipient"
1349
+ "object/get",
1350
+ "@payload.data",
1351
+ "@config.guardField"
1352
+ ],
1353
+ "@config.guardValue"
1354
+ ],
1355
+ [
1356
+ "if",
1357
+ [
1358
+ "=",
1359
+ "@config.guardOp",
1360
+ "gte"
1361
+ ],
1362
+ [
1363
+ ">=",
1364
+ [
1365
+ "object/get",
1366
+ "@payload.data",
1367
+ "@config.guardField"
1368
+ ],
1369
+ "@config.guardValue"
1370
+ ],
1371
+ [
1372
+ "<=",
1373
+ [
1374
+ "object/get",
1375
+ "@payload.data",
1376
+ "@config.guardField"
1377
+ ],
1378
+ "@config.guardValue"
708
1379
  ]
709
1380
  ]
710
1381
  ]
1382
+ ]
1383
+ ],
1384
+ "to": "idle"
1385
+ },
1386
+ {
1387
+ "effects": [
1388
+ [
1389
+ "set",
1390
+ "@entity.prefMode",
1391
+ [
1392
+ "if",
1393
+ [
1394
+ "=",
1395
+ [
1396
+ "array/len",
1397
+ [
1398
+ "array/filter",
1399
+ "@payload.data",
1400
+ [
1401
+ "fn",
1402
+ "p",
1403
+ [
1404
+ "and",
1405
+ [
1406
+ "=",
1407
+ [
1408
+ "object/get",
1409
+ "@p",
1410
+ "userId"
1411
+ ],
1412
+ "@entity.recipient"
1413
+ ],
1414
+ [
1415
+ "or",
1416
+ [
1417
+ "=",
1418
+ [
1419
+ "object/get",
1420
+ "@p",
1421
+ "eventType"
1422
+ ],
1423
+ ""
1424
+ ],
1425
+ [
1426
+ "=",
1427
+ [
1428
+ "object/get",
1429
+ "@p",
1430
+ "eventType"
1431
+ ],
1432
+ "@config.eventKey"
1433
+ ]
1434
+ ]
1435
+ ]
1436
+ ]
1437
+ ]
1438
+ ],
1439
+ 0.0
1440
+ ],
1441
+ "instant",
1442
+ [
1443
+ "object/get",
1444
+ [
1445
+ "array/first",
1446
+ [
1447
+ "array/filter",
1448
+ "@payload.data",
1449
+ [
1450
+ "fn",
1451
+ "p",
1452
+ [
1453
+ "and",
1454
+ [
1455
+ "=",
1456
+ [
1457
+ "object/get",
1458
+ "@p",
1459
+ "userId"
1460
+ ],
1461
+ "@entity.recipient"
1462
+ ],
1463
+ [
1464
+ "or",
1465
+ [
1466
+ "=",
1467
+ [
1468
+ "object/get",
1469
+ "@p",
1470
+ "eventType"
1471
+ ],
1472
+ ""
1473
+ ],
1474
+ [
1475
+ "=",
1476
+ [
1477
+ "object/get",
1478
+ "@p",
1479
+ "eventType"
1480
+ ],
1481
+ "@config.eventKey"
1482
+ ]
1483
+ ]
1484
+ ]
1485
+ ]
1486
+ ]
1487
+ ],
1488
+ "mode"
1489
+ ]
1490
+ ]
711
1491
  ],
712
1492
  [
713
1493
  "set",
714
- "@entity.recordedAt",
715
- 0.0
1494
+ "@entity.prefChannel",
1495
+ [
1496
+ "if",
1497
+ [
1498
+ "=",
1499
+ [
1500
+ "array/len",
1501
+ [
1502
+ "array/filter",
1503
+ "@payload.data",
1504
+ [
1505
+ "fn",
1506
+ "p",
1507
+ [
1508
+ "and",
1509
+ [
1510
+ "=",
1511
+ [
1512
+ "object/get",
1513
+ "@p",
1514
+ "userId"
1515
+ ],
1516
+ "@entity.recipient"
1517
+ ],
1518
+ [
1519
+ "or",
1520
+ [
1521
+ "=",
1522
+ [
1523
+ "object/get",
1524
+ "@p",
1525
+ "eventType"
1526
+ ],
1527
+ ""
1528
+ ],
1529
+ [
1530
+ "=",
1531
+ [
1532
+ "object/get",
1533
+ "@p",
1534
+ "eventType"
1535
+ ],
1536
+ "@config.eventKey"
1537
+ ]
1538
+ ]
1539
+ ]
1540
+ ]
1541
+ ]
1542
+ ],
1543
+ 0.0
1544
+ ],
1545
+ "",
1546
+ [
1547
+ "object/get",
1548
+ [
1549
+ "array/first",
1550
+ [
1551
+ "array/filter",
1552
+ "@payload.data",
1553
+ [
1554
+ "fn",
1555
+ "p",
1556
+ [
1557
+ "and",
1558
+ [
1559
+ "=",
1560
+ [
1561
+ "object/get",
1562
+ "@p",
1563
+ "userId"
1564
+ ],
1565
+ "@entity.recipient"
1566
+ ],
1567
+ [
1568
+ "or",
1569
+ [
1570
+ "=",
1571
+ [
1572
+ "object/get",
1573
+ "@p",
1574
+ "eventType"
1575
+ ],
1576
+ ""
1577
+ ],
1578
+ [
1579
+ "=",
1580
+ [
1581
+ "object/get",
1582
+ "@p",
1583
+ "eventType"
1584
+ ],
1585
+ "@config.eventKey"
1586
+ ]
1587
+ ]
1588
+ ]
1589
+ ]
1590
+ ]
1591
+ ],
1592
+ "channel"
1593
+ ]
1594
+ ]
716
1595
  ],
717
1596
  [
718
- "when",
1597
+ "set",
1598
+ "@entity.prefQuietStart",
719
1599
  [
720
- "not",
1600
+ "if",
721
1601
  [
722
- "array/includes",
723
- "@config.suppressionList",
724
- "@entity.recipient"
1602
+ "=",
1603
+ [
1604
+ "array/len",
1605
+ [
1606
+ "array/filter",
1607
+ "@payload.data",
1608
+ [
1609
+ "fn",
1610
+ "p",
1611
+ [
1612
+ "and",
1613
+ [
1614
+ "=",
1615
+ [
1616
+ "object/get",
1617
+ "@p",
1618
+ "userId"
1619
+ ],
1620
+ "@entity.recipient"
1621
+ ],
1622
+ [
1623
+ "or",
1624
+ [
1625
+ "=",
1626
+ [
1627
+ "object/get",
1628
+ "@p",
1629
+ "eventType"
1630
+ ],
1631
+ ""
1632
+ ],
1633
+ [
1634
+ "=",
1635
+ [
1636
+ "object/get",
1637
+ "@p",
1638
+ "eventType"
1639
+ ],
1640
+ "@config.eventKey"
1641
+ ]
1642
+ ]
1643
+ ]
1644
+ ]
1645
+ ]
1646
+ ],
1647
+ 0.0
1648
+ ],
1649
+ 0.0,
1650
+ [
1651
+ "object/get",
1652
+ [
1653
+ "array/first",
1654
+ [
1655
+ "array/filter",
1656
+ "@payload.data",
1657
+ [
1658
+ "fn",
1659
+ "p",
1660
+ [
1661
+ "and",
1662
+ [
1663
+ "=",
1664
+ [
1665
+ "object/get",
1666
+ "@p",
1667
+ "userId"
1668
+ ],
1669
+ "@entity.recipient"
1670
+ ],
1671
+ [
1672
+ "or",
1673
+ [
1674
+ "=",
1675
+ [
1676
+ "object/get",
1677
+ "@p",
1678
+ "eventType"
1679
+ ],
1680
+ ""
1681
+ ],
1682
+ [
1683
+ "=",
1684
+ [
1685
+ "object/get",
1686
+ "@p",
1687
+ "eventType"
1688
+ ],
1689
+ "@config.eventKey"
1690
+ ]
1691
+ ]
1692
+ ]
1693
+ ]
1694
+ ]
1695
+ ],
1696
+ "quietStartHour"
725
1697
  ]
1698
+ ]
1699
+ ],
1700
+ [
1701
+ "set",
1702
+ "@entity.prefQuietEnd",
1703
+ [
1704
+ "if",
1705
+ [
1706
+ "=",
1707
+ [
1708
+ "array/len",
1709
+ [
1710
+ "array/filter",
1711
+ "@payload.data",
1712
+ [
1713
+ "fn",
1714
+ "p",
1715
+ [
1716
+ "and",
1717
+ [
1718
+ "=",
1719
+ [
1720
+ "object/get",
1721
+ "@p",
1722
+ "userId"
1723
+ ],
1724
+ "@entity.recipient"
1725
+ ],
1726
+ [
1727
+ "or",
1728
+ [
1729
+ "=",
1730
+ [
1731
+ "object/get",
1732
+ "@p",
1733
+ "eventType"
1734
+ ],
1735
+ ""
1736
+ ],
1737
+ [
1738
+ "=",
1739
+ [
1740
+ "object/get",
1741
+ "@p",
1742
+ "eventType"
1743
+ ],
1744
+ "@config.eventKey"
1745
+ ]
1746
+ ]
1747
+ ]
1748
+ ]
1749
+ ]
1750
+ ],
1751
+ 0.0
1752
+ ],
1753
+ 0.0,
1754
+ [
1755
+ "object/get",
1756
+ [
1757
+ "array/first",
1758
+ [
1759
+ "array/filter",
1760
+ "@payload.data",
1761
+ [
1762
+ "fn",
1763
+ "p",
1764
+ [
1765
+ "and",
1766
+ [
1767
+ "=",
1768
+ [
1769
+ "object/get",
1770
+ "@p",
1771
+ "userId"
1772
+ ],
1773
+ "@entity.recipient"
1774
+ ],
1775
+ [
1776
+ "or",
1777
+ [
1778
+ "=",
1779
+ [
1780
+ "object/get",
1781
+ "@p",
1782
+ "eventType"
1783
+ ],
1784
+ ""
1785
+ ],
1786
+ [
1787
+ "=",
1788
+ [
1789
+ "object/get",
1790
+ "@p",
1791
+ "eventType"
1792
+ ],
1793
+ "@config.eventKey"
1794
+ ]
1795
+ ]
1796
+ ]
1797
+ ]
1798
+ ]
1799
+ ],
1800
+ "quietEndHour"
1801
+ ]
1802
+ ]
1803
+ ],
1804
+ [
1805
+ "set",
1806
+ "@entity.channel",
1807
+ [
1808
+ "if",
1809
+ [
1810
+ "=",
1811
+ "@entity.prefChannel",
1812
+ ""
1813
+ ],
1814
+ "@entity.channel",
1815
+ "@entity.prefChannel"
1816
+ ]
1817
+ ],
1818
+ [
1819
+ "if",
1820
+ [
1821
+ "=",
1822
+ "@entity.prefMode",
1823
+ "off"
1824
+ ],
1825
+ [
1826
+ "persist",
1827
+ "create",
1828
+ "NotificationRecord",
1829
+ {
1830
+ "channel": "@entity.channel",
1831
+ "dispatched": false,
1832
+ "error": "muted-by-preference",
1833
+ "message": "@entity.message",
1834
+ "recipient": "@entity.recipient",
1835
+ "recordedAt": "@now",
1836
+ "severity": "@entity.severity"
1837
+ }
1838
+ ],
1839
+ [
1840
+ "if",
1841
+ [
1842
+ "=",
1843
+ "@entity.prefMode",
1844
+ "digest"
1845
+ ],
1846
+ [
1847
+ "persist",
1848
+ "create",
1849
+ "NotificationRecord",
1850
+ {
1851
+ "channel": "@entity.channel",
1852
+ "dispatched": false,
1853
+ "error": "digest-deferred",
1854
+ "message": "@entity.message",
1855
+ "recipient": "@entity.recipient",
1856
+ "recordedAt": "@now",
1857
+ "severity": "@entity.severity"
1858
+ }
1859
+ ],
1860
+ [
1861
+ "if",
1862
+ [
1863
+ "and",
1864
+ [
1865
+ "not",
1866
+ [
1867
+ "=",
1868
+ "@entity.prefQuietStart",
1869
+ "@entity.prefQuietEnd"
1870
+ ]
1871
+ ],
1872
+ [
1873
+ "if",
1874
+ [
1875
+ "<",
1876
+ "@entity.prefQuietStart",
1877
+ "@entity.prefQuietEnd"
1878
+ ],
1879
+ [
1880
+ "and",
1881
+ [
1882
+ ">=",
1883
+ [
1884
+ "time/hour",
1885
+ "@now"
1886
+ ],
1887
+ "@entity.prefQuietStart"
1888
+ ],
1889
+ [
1890
+ "<",
1891
+ [
1892
+ "time/hour",
1893
+ "@now"
1894
+ ],
1895
+ "@entity.prefQuietEnd"
1896
+ ]
1897
+ ],
1898
+ [
1899
+ "or",
1900
+ [
1901
+ ">=",
1902
+ [
1903
+ "time/hour",
1904
+ "@now"
1905
+ ],
1906
+ "@entity.prefQuietStart"
1907
+ ],
1908
+ [
1909
+ "<",
1910
+ [
1911
+ "time/hour",
1912
+ "@now"
1913
+ ],
1914
+ "@entity.prefQuietEnd"
1915
+ ]
1916
+ ]
1917
+ ]
1918
+ ],
1919
+ [
1920
+ "persist",
1921
+ "create",
1922
+ "NotificationRecord",
1923
+ {
1924
+ "channel": "@entity.channel",
1925
+ "dispatched": false,
1926
+ "error": "quiet-hours",
1927
+ "message": "@entity.message",
1928
+ "recipient": "@entity.recipient",
1929
+ "recordedAt": "@now",
1930
+ "severity": "@entity.severity"
1931
+ }
1932
+ ],
1933
+ [
1934
+ "if",
1935
+ [
1936
+ "=",
1937
+ "@entity.channel",
1938
+ "in-app"
1939
+ ],
1940
+ [
1941
+ "do",
1942
+ [
1943
+ "set",
1944
+ "@entity.dispatched",
1945
+ true
1946
+ ],
1947
+ [
1948
+ "notify",
1949
+ "@config.severity",
1950
+ "@config.template"
1951
+ ]
1952
+ ],
1953
+ [
1954
+ "fetch",
1955
+ "NotificationRecord",
1956
+ {
1957
+ "emit": {
1958
+ "failure": "NOTIFY_LOOKUP_FAILED",
1959
+ "success": "NOTIFY_CAP_LOADED"
1960
+ },
1961
+ "filter": [
1962
+ ">",
1963
+ [
1964
+ "object/get",
1965
+ "@entity",
1966
+ "recordedAt"
1967
+ ],
1968
+ [
1969
+ "-",
1970
+ "@now",
1971
+ 604800000.0
1972
+ ]
1973
+ ]
1974
+ }
1975
+ ]
1976
+ ]
1977
+ ]
1978
+ ]
1979
+ ]
1980
+ ],
1981
+ "event": "NOTIFY_PREFS_LOADED",
1982
+ "eventId": "evt_01M0M65FF68HQ6K67FGYDE0P4V",
1983
+ "from": "idle",
1984
+ "to": "idle"
1985
+ },
1986
+ {
1987
+ "effects": [
1988
+ [
1989
+ "if",
1990
+ [
1991
+ "and",
1992
+ [
1993
+ ">",
1994
+ "@config.frequencyCapPerWeek",
1995
+ 0.0
1996
+ ],
1997
+ [
1998
+ ">=",
1999
+ [
2000
+ "array/len",
2001
+ [
2002
+ "array/filter",
2003
+ "@payload.data",
2004
+ [
2005
+ "fn",
2006
+ "r",
2007
+ [
2008
+ "and",
2009
+ [
2010
+ "=",
2011
+ [
2012
+ "object/get",
2013
+ "@r",
2014
+ "recipient"
2015
+ ],
2016
+ "@entity.recipient"
2017
+ ],
2018
+ [
2019
+ "=",
2020
+ [
2021
+ "object/get",
2022
+ "@r",
2023
+ "channel"
2024
+ ],
2025
+ "@entity.channel"
2026
+ ],
2027
+ [
2028
+ "=",
2029
+ [
2030
+ "object/get",
2031
+ "@r",
2032
+ "dispatched"
2033
+ ],
2034
+ true
2035
+ ]
2036
+ ]
2037
+ ]
2038
+ ]
2039
+ ],
2040
+ "@config.frequencyCapPerWeek"
2041
+ ]
2042
+ ],
2043
+ [
2044
+ "persist",
2045
+ "create",
2046
+ "NotificationRecord",
2047
+ {
2048
+ "channel": "@entity.channel",
2049
+ "dispatched": false,
2050
+ "error": "frequency-cap",
2051
+ "message": "@entity.message",
2052
+ "recipient": "@entity.recipient",
2053
+ "recordedAt": "@now",
2054
+ "severity": "@entity.severity"
2055
+ }
726
2056
  ],
727
2057
  [
728
2058
  "if",
729
2059
  [
730
2060
  "=",
731
- "@config.notifyChannel",
732
- "in-app"
2061
+ "@entity.channel",
2062
+ "email"
733
2063
  ],
734
2064
  [
735
- "notify",
736
- "@config.severity",
737
- "@config.template"
2065
+ "call-service",
2066
+ "email",
2067
+ "send",
2068
+ {
2069
+ "body": "@entity.message",
2070
+ "from": "",
2071
+ "subject": [
2072
+ "if",
2073
+ [
2074
+ "=",
2075
+ "@config.emailSubject",
2076
+ ""
2077
+ ],
2078
+ "@entity.message",
2079
+ "@config.emailSubject"
2080
+ ],
2081
+ "to": "@entity.recipient"
2082
+ },
2083
+ {
2084
+ "emit": {
2085
+ "failure": "NOTIFY_EMAIL_FAILED",
2086
+ "success": "NOTIFY_EMAIL_SENT"
2087
+ }
2088
+ }
738
2089
  ],
739
2090
  [
740
2091
  "if",
741
2092
  [
742
2093
  "=",
743
- "@config.notifyChannel",
744
- "email"
2094
+ "@entity.channel",
2095
+ "sms"
745
2096
  ],
746
2097
  [
747
2098
  "call-service",
748
- "email",
749
- "send",
2099
+ "twilio",
2100
+ "sendSMS",
750
2101
  {
751
- "body": "@config.template",
752
- "from": "",
753
- "subject": [
754
- "if",
755
- [
756
- "=",
757
- "@config.emailSubject",
758
- ""
759
- ],
760
- "@config.template",
761
- "@config.emailSubject"
762
- ],
2102
+ "body": "@entity.message",
763
2103
  "to": "@entity.recipient"
764
2104
  },
765
2105
  {
766
2106
  "emit": {
767
- "failure": "NOTIFY_EMAIL_FAILED",
768
- "success": "NOTIFY_EMAIL_SENT"
2107
+ "failure": "NOTIFY_SMS_FAILED",
2108
+ "success": "NOTIFY_SMS_SENT"
769
2109
  }
770
2110
  }
771
2111
  ],
@@ -773,21 +2113,16 @@
773
2113
  "if",
774
2114
  [
775
2115
  "=",
776
- "@config.notifyChannel",
777
- "sms"
2116
+ "@entity.channel",
2117
+ "push"
778
2118
  ],
779
2119
  [
780
- "call-service",
781
- "twilio",
782
- "sendSMS",
783
- {
784
- "body": "@config.template",
785
- "to": "@entity.recipient"
786
- },
2120
+ "fetch",
2121
+ "PushSubscription",
787
2122
  {
788
2123
  "emit": {
789
- "failure": "NOTIFY_SMS_FAILED",
790
- "success": "NOTIFY_SMS_SENT"
2124
+ "failure": "NOTIFY_LOOKUP_FAILED",
2125
+ "success": "NOTIFY_PUSH_SUBS"
791
2126
  }
792
2127
  }
793
2128
  ],
@@ -806,11 +2141,11 @@
806
2141
  "webhook",
807
2142
  "send",
808
2143
  {
809
- "event": "@config.template",
2144
+ "event": "@entity.message",
810
2145
  "payload": {
811
- "message": "@config.template",
2146
+ "message": "@entity.message",
812
2147
  "recipient": "@entity.recipient",
813
- "severity": "@config.severity"
2148
+ "severity": "@entity.severity"
814
2149
  },
815
2150
  "secret": "@config.webhookSecret",
816
2151
  "url": "@config.webhookUrl"
@@ -827,114 +2162,254 @@
827
2162
  "create",
828
2163
  "NotificationRecord",
829
2164
  {
830
- "channel": "@config.notifyChannel",
2165
+ "channel": "@entity.channel",
831
2166
  "dispatched": false,
832
- "message": "@config.template",
2167
+ "message": "@entity.message",
833
2168
  "recipient": "@entity.recipient",
834
- "recordedAt": 0.0,
835
- "severity": "@config.severity"
2169
+ "recordedAt": "@now",
2170
+ "severity": "@entity.severity"
836
2171
  }
837
2172
  ]
838
2173
  ]
839
2174
  ]
840
2175
  ]
841
2176
  ]
842
- ],
843
- [
844
- "emit",
845
- "NotificationDispatched",
846
- {
847
- "channel": "@config.notifyChannel",
848
- "message": "@config.template",
849
- "recipient": "@entity.recipient",
850
- "severity": "@config.severity"
851
- }
852
2177
  ]
853
2178
  ],
854
- "event": "EventOccurred",
855
- "eventId": "evt_01KXG04FE9FBG7H2NH6HKT4ZAR",
2179
+ "event": "NOTIFY_CAP_LOADED",
2180
+ "eventId": "evt_01M0M65FF6F8X646FMC2ZYX7HW",
856
2181
  "from": "idle",
857
- "guard": [
858
- "if",
859
- [
860
- "=",
861
- "@config.guardOp",
862
- "eq"
863
- ],
2182
+ "to": "idle"
2183
+ },
2184
+ {
2185
+ "effects": [
864
2186
  [
865
- "or",
866
- [
867
- "=",
868
- "@config.triggerStatus",
869
- ""
870
- ],
2187
+ "set",
2188
+ "@entity.pushEndpoint",
871
2189
  [
872
- "=",
873
- "@payload.status",
874
- "@config.triggerStatus"
2190
+ "if",
2191
+ [
2192
+ "=",
2193
+ [
2194
+ "array/len",
2195
+ [
2196
+ "array/filter",
2197
+ "@payload.data",
2198
+ [
2199
+ "fn",
2200
+ "s",
2201
+ [
2202
+ "=",
2203
+ [
2204
+ "object/get",
2205
+ "@s",
2206
+ "userId"
2207
+ ],
2208
+ "@entity.recipient"
2209
+ ]
2210
+ ]
2211
+ ]
2212
+ ],
2213
+ 0.0
2214
+ ],
2215
+ "",
2216
+ [
2217
+ "object/get",
2218
+ [
2219
+ "array/first",
2220
+ [
2221
+ "array/filter",
2222
+ "@payload.data",
2223
+ [
2224
+ "fn",
2225
+ "s",
2226
+ [
2227
+ "=",
2228
+ [
2229
+ "object/get",
2230
+ "@s",
2231
+ "userId"
2232
+ ],
2233
+ "@entity.recipient"
2234
+ ]
2235
+ ]
2236
+ ]
2237
+ ],
2238
+ "endpoint"
2239
+ ]
875
2240
  ]
876
2241
  ],
877
2242
  [
878
- "if",
879
- [
880
- "=",
881
- "@config.guardOp",
882
- "gt"
883
- ],
884
- [
885
- ">",
886
- [
887
- "object/get",
888
- "@payload.data",
889
- "@config.guardField"
890
- ],
891
- "@config.guardValue"
892
- ],
2243
+ "set",
2244
+ "@entity.pushP256dh",
893
2245
  [
894
2246
  "if",
895
2247
  [
896
2248
  "=",
897
- "@config.guardOp",
898
- "lt"
899
- ],
900
- [
901
- "<",
902
2249
  [
903
- "object/get",
904
- "@payload.data",
905
- "@config.guardField"
2250
+ "array/len",
2251
+ [
2252
+ "array/filter",
2253
+ "@payload.data",
2254
+ [
2255
+ "fn",
2256
+ "s",
2257
+ [
2258
+ "=",
2259
+ [
2260
+ "object/get",
2261
+ "@s",
2262
+ "userId"
2263
+ ],
2264
+ "@entity.recipient"
2265
+ ]
2266
+ ]
2267
+ ]
906
2268
  ],
907
- "@config.guardValue"
2269
+ 0.0
908
2270
  ],
2271
+ "",
909
2272
  [
910
- "if",
2273
+ "object/get",
911
2274
  [
912
- "=",
913
- "@config.guardOp",
914
- "gte"
2275
+ "array/first",
2276
+ [
2277
+ "array/filter",
2278
+ "@payload.data",
2279
+ [
2280
+ "fn",
2281
+ "s",
2282
+ [
2283
+ "=",
2284
+ [
2285
+ "object/get",
2286
+ "@s",
2287
+ "userId"
2288
+ ],
2289
+ "@entity.recipient"
2290
+ ]
2291
+ ]
2292
+ ]
915
2293
  ],
2294
+ "p256dh"
2295
+ ]
2296
+ ]
2297
+ ],
2298
+ [
2299
+ "set",
2300
+ "@entity.pushAuth",
2301
+ [
2302
+ "if",
2303
+ [
2304
+ "=",
916
2305
  [
917
- ">=",
2306
+ "array/len",
918
2307
  [
919
- "object/get",
2308
+ "array/filter",
920
2309
  "@payload.data",
921
- "@config.guardField"
922
- ],
923
- "@config.guardValue"
2310
+ [
2311
+ "fn",
2312
+ "s",
2313
+ [
2314
+ "=",
2315
+ [
2316
+ "object/get",
2317
+ "@s",
2318
+ "userId"
2319
+ ],
2320
+ "@entity.recipient"
2321
+ ]
2322
+ ]
2323
+ ]
924
2324
  ],
2325
+ 0.0
2326
+ ],
2327
+ "",
2328
+ [
2329
+ "object/get",
925
2330
  [
926
- "<=",
2331
+ "array/first",
927
2332
  [
928
- "object/get",
2333
+ "array/filter",
929
2334
  "@payload.data",
930
- "@config.guardField"
931
- ],
932
- "@config.guardValue"
933
- ]
2335
+ [
2336
+ "fn",
2337
+ "s",
2338
+ [
2339
+ "=",
2340
+ [
2341
+ "object/get",
2342
+ "@s",
2343
+ "userId"
2344
+ ],
2345
+ "@entity.recipient"
2346
+ ]
2347
+ ]
2348
+ ]
2349
+ ],
2350
+ "auth"
934
2351
  ]
935
2352
  ]
2353
+ ],
2354
+ [
2355
+ "if",
2356
+ [
2357
+ "=",
2358
+ "@entity.pushEndpoint",
2359
+ ""
2360
+ ],
2361
+ [
2362
+ "persist",
2363
+ "create",
2364
+ "NotificationRecord",
2365
+ {
2366
+ "channel": "@entity.channel",
2367
+ "dispatched": false,
2368
+ "error": "no-push-subscription",
2369
+ "message": "@entity.message",
2370
+ "recipient": "@entity.recipient",
2371
+ "recordedAt": "@now",
2372
+ "severity": "@entity.severity"
2373
+ }
2374
+ ],
2375
+ [
2376
+ "call-service",
2377
+ "push",
2378
+ "send",
2379
+ {
2380
+ "body": "@entity.message",
2381
+ "icon": "@config.pushIcon",
2382
+ "subscription": {
2383
+ "endpoint": "@entity.pushEndpoint",
2384
+ "keys": {
2385
+ "auth": "@entity.pushAuth",
2386
+ "p256dh": "@entity.pushP256dh"
2387
+ }
2388
+ },
2389
+ "title": [
2390
+ "if",
2391
+ [
2392
+ "=",
2393
+ "@config.pushTitle",
2394
+ ""
2395
+ ],
2396
+ "@entity.message",
2397
+ "@config.pushTitle"
2398
+ ],
2399
+ "url": "@config.pushDeepLink"
2400
+ },
2401
+ {
2402
+ "emit": {
2403
+ "failure": "NOTIFY_PUSH_FAILED",
2404
+ "success": "NOTIFY_PUSH_SENT"
2405
+ }
2406
+ }
2407
+ ]
936
2408
  ]
937
2409
  ],
2410
+ "event": "NOTIFY_PUSH_SUBS",
2411
+ "eventId": "evt_01M0M65FF6Z4XVMQTZT0P95WJQ",
2412
+ "from": "idle",
938
2413
  "to": "idle"
939
2414
  },
940
2415
  {
@@ -953,7 +2428,7 @@
953
2428
  "dispatched": true,
954
2429
  "message": "@entity.message",
955
2430
  "recipient": "@entity.recipient",
956
- "recordedAt": 0.0,
2431
+ "recordedAt": "@now",
957
2432
  "severity": "@entity.severity"
958
2433
  }
959
2434
  ]
@@ -985,7 +2460,7 @@
985
2460
  "error": "@entity.error",
986
2461
  "message": "@entity.message",
987
2462
  "recipient": "@entity.recipient",
988
- "recordedAt": 0.0,
2463
+ "recordedAt": "@now",
989
2464
  "severity": "@entity.severity"
990
2465
  }
991
2466
  ]
@@ -1011,7 +2486,7 @@
1011
2486
  "dispatched": true,
1012
2487
  "message": "@entity.message",
1013
2488
  "recipient": "@entity.recipient",
1014
- "recordedAt": 0.0,
2489
+ "recordedAt": "@now",
1015
2490
  "severity": "@entity.severity"
1016
2491
  }
1017
2492
  ]
@@ -1043,7 +2518,7 @@
1043
2518
  "error": "@entity.error",
1044
2519
  "message": "@entity.message",
1045
2520
  "recipient": "@entity.recipient",
1046
- "recordedAt": 0.0,
2521
+ "recordedAt": "@now",
1047
2522
  "severity": "@entity.severity"
1048
2523
  }
1049
2524
  ]
@@ -1069,7 +2544,7 @@
1069
2544
  "dispatched": true,
1070
2545
  "message": "@entity.message",
1071
2546
  "recipient": "@entity.recipient",
1072
- "recordedAt": 0.0,
2547
+ "recordedAt": "@now",
1073
2548
  "severity": "@entity.severity"
1074
2549
  }
1075
2550
  ]
@@ -1101,7 +2576,7 @@
1101
2576
  "error": "@entity.error",
1102
2577
  "message": "@entity.message",
1103
2578
  "recipient": "@entity.recipient",
1104
- "recordedAt": 0.0,
2579
+ "recordedAt": "@now",
1105
2580
  "severity": "@entity.severity"
1106
2581
  }
1107
2582
  ]
@@ -1110,6 +2585,96 @@
1110
2585
  "eventId": "evt_01M04F6YS1THM7EMY3BAB7CSCV",
1111
2586
  "from": "idle",
1112
2587
  "to": "idle"
2588
+ },
2589
+ {
2590
+ "effects": [
2591
+ [
2592
+ "set",
2593
+ "@entity.dispatched",
2594
+ true
2595
+ ],
2596
+ [
2597
+ "persist",
2598
+ "create",
2599
+ "NotificationRecord",
2600
+ {
2601
+ "channel": "@entity.channel",
2602
+ "dispatched": true,
2603
+ "message": "@entity.message",
2604
+ "recipient": "@entity.recipient",
2605
+ "recordedAt": "@now",
2606
+ "severity": "@entity.severity"
2607
+ }
2608
+ ]
2609
+ ],
2610
+ "event": "NOTIFY_PUSH_SENT",
2611
+ "eventId": "evt_01M0M65FF6DKMEW2D2E96T9VTH",
2612
+ "from": "idle",
2613
+ "to": "idle"
2614
+ },
2615
+ {
2616
+ "effects": [
2617
+ [
2618
+ "set",
2619
+ "@entity.dispatched",
2620
+ false
2621
+ ],
2622
+ [
2623
+ "set",
2624
+ "@entity.error",
2625
+ "@payload.error"
2626
+ ],
2627
+ [
2628
+ "persist",
2629
+ "create",
2630
+ "NotificationRecord",
2631
+ {
2632
+ "channel": "@entity.channel",
2633
+ "dispatched": false,
2634
+ "error": "@entity.error",
2635
+ "message": "@entity.message",
2636
+ "recipient": "@entity.recipient",
2637
+ "recordedAt": "@now",
2638
+ "severity": "@entity.severity"
2639
+ }
2640
+ ]
2641
+ ],
2642
+ "event": "NOTIFY_PUSH_FAILED",
2643
+ "eventId": "evt_01M0M65FF6JAF7JE380C3CWWXM",
2644
+ "from": "idle",
2645
+ "to": "idle"
2646
+ },
2647
+ {
2648
+ "effects": [
2649
+ [
2650
+ "set",
2651
+ "@entity.dispatched",
2652
+ false
2653
+ ],
2654
+ [
2655
+ "set",
2656
+ "@entity.error",
2657
+ "@payload.error"
2658
+ ],
2659
+ [
2660
+ "persist",
2661
+ "create",
2662
+ "NotificationRecord",
2663
+ {
2664
+ "channel": "@entity.channel",
2665
+ "dispatched": false,
2666
+ "error": "@entity.error",
2667
+ "message": "@entity.message",
2668
+ "recipient": "@entity.recipient",
2669
+ "recordedAt": "@now",
2670
+ "severity": "@entity.severity"
2671
+ }
2672
+ ]
2673
+ ],
2674
+ "event": "NOTIFY_LOOKUP_FAILED",
2675
+ "eventId": "evt_01M0M65FF6CS2R9V2JQ6EJYGDX",
2676
+ "from": "idle",
2677
+ "to": "idle"
1113
2678
  }
1114
2679
  ]
1115
2680
  }
@@ -1118,5 +2683,5 @@
1118
2683
  }
1119
2684
  ],
1120
2685
  "schemaVersion": 1,
1121
- "version": "1.5.0"
2686
+ "version": "2.0.0"
1122
2687
  }