@nbt-dev/nbt 0.0.1 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +177 -21
- package/README.md +16 -13
- package/TRADEMARKS.md +49 -0
- package/dist/nbt.js +398 -19
- package/package.json +5 -4
- package/stdlib/auth/README.md +83 -0
- package/stdlib/auth/migrations/20260424144652_initial/migration.nbt +48 -0
- package/stdlib/auth/migrations/20260424144652_initial/schema_snapshot.nbt +58 -0
- package/stdlib/auth/migrations/20260521191014_update_user/migration.nbt +3 -0
- package/stdlib/auth/migrations/20260521191014_update_user/schema_snapshot.nbt +59 -0
- package/stdlib/auth/schema.nbt +142 -0
- package/stdlib/calendar/adapters/gohighlevel/tests/fixtures/v2_calendar_pilot.json +12 -0
- package/stdlib/calendar/adapters/gohighlevel/tests/fixtures/webhooks/appointment_changed.json +70 -0
- package/stdlib/calendar/adapters/gohighlevel/tests/fixtures/webhooks/appointment_created.json +72 -0
- package/stdlib/calendar/migrations/20260501210107_initial/migration.nbt +60 -0
- package/stdlib/calendar/migrations/20260501210107_initial/schema_snapshot.nbt +66 -0
- package/stdlib/calendar/migrations/20260513151050_schema_update/migration.nbt +17 -0
- package/stdlib/calendar/migrations/20260513151050_schema_update/schema_snapshot.nbt +83 -0
- package/stdlib/calendar/schema.nbt +86 -0
- package/stdlib/chat/migrations/20260429222411_initial/migration.nbt +59 -0
- package/stdlib/chat/migrations/20260429222411_initial/schema_snapshot.nbt +71 -0
- package/stdlib/chat/migrations/20260430185225_add_messagereaction/migration.nbt +9 -0
- package/stdlib/chat/migrations/20260430185225_add_messagereaction/schema_snapshot.nbt +78 -0
- package/stdlib/chat/migrations/20260518191152_update_message/migration.nbt +3 -0
- package/stdlib/chat/migrations/20260518191152_update_message/schema_snapshot.nbt +81 -0
- package/stdlib/chat/schema.nbt +130 -0
- package/stdlib/crm/adapters/gohighlevel/README.md +85 -0
- package/stdlib/crm/adapters/gohighlevel/tests/README.md +159 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_138fields.json +222 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_140fields.json +219 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_alt.json +212 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_changed.json +102 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_created.json +95 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_full.json +213 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_sparse.json +161 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_update_a.json +197 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_update_b.json +197 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/opportunity_changed.json +85 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/opportunity_created.json +85 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_contact_pilot.json +43 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_contact_with_price_closed.json +7 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_contact_with_price_open.json +7 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_event_appointment_delete.json +1 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_event_calendar_update.json +1 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_event_contact_create.json +1 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_event_opp_status_update.json +1 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_opportunity_pilot.json +16 -0
- package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_pipelines_pilot.json +137 -0
- package/stdlib/crm/migrations/20260501210107_initial/migration.nbt +63 -0
- package/stdlib/crm/migrations/20260501210107_initial/schema_snapshot.nbt +73 -0
- package/stdlib/crm/migrations/20260513151050_schema_update/migration.nbt +13 -0
- package/stdlib/crm/migrations/20260513151050_schema_update/schema_snapshot.nbt +86 -0
- package/stdlib/crm/schema.nbt +148 -0
- package/stdlib/design/migrations/20260501210107_initial/migration.nbt +19 -0
- package/stdlib/design/migrations/20260501210107_initial/schema_snapshot.nbt +21 -0
- package/stdlib/design/migrations/20260610130000_design_system/migration.nbt +50 -0
- package/stdlib/design/migrations/20260610130000_design_system/schema_snapshot.nbt +80 -0
- package/stdlib/design/schema.nbt +140 -0
- package/stdlib/dns/migrations/20260501210107_initial/migration.nbt +32 -0
- package/stdlib/dns/migrations/20260501210107_initial/schema_snapshot.nbt +36 -0
- package/stdlib/dns/schema.nbt +68 -0
- package/stdlib/email/migrations/20260427235207_initial/migration.nbt +75 -0
- package/stdlib/email/migrations/20260427235207_initial/schema_snapshot.nbt +87 -0
- package/stdlib/email/schema.nbt +145 -0
- package/stdlib/ingest/README.md +29 -0
- package/stdlib/ingest/migrations/20260424144652_initial/migration.nbt +18 -0
- package/stdlib/ingest/migrations/20260424144652_initial/schema_snapshot.nbt +20 -0
- package/stdlib/ingest/migrations/20260429203747_schema_update/migration.nbt +3 -0
- package/stdlib/ingest/migrations/20260429203747_schema_update/schema_snapshot.nbt +21 -0
- package/stdlib/ingest/schema.nbt +37 -0
- package/stdlib/notifications/README.md +118 -0
- package/stdlib/notifications/migrations/20260430204408_initial/migration.nbt +42 -0
- package/stdlib/notifications/migrations/20260430204408_initial/schema_snapshot.nbt +46 -0
- package/stdlib/notifications/schema.nbt +67 -0
- package/stdlib/phone/migrations/20260605205722_initial/migration.nbt +50 -0
- package/stdlib/phone/migrations/20260605205722_initial/schema_snapshot.nbt +56 -0
- package/stdlib/phone/schema.nbt +95 -0
- package/stdlib/registry/migrations/20260602181932_initial/migration.nbt +8 -0
- package/stdlib/registry/migrations/20260602181932_initial/schema_snapshot.nbt +8 -0
- package/stdlib/registry/schema.nbt +20 -0
- package/stdlib/workflows/schema.nbt +44 -0
- package/vendor/linux-x64/cartridges/auth/migrations/20260424144652_initial/migration.nbt +48 -0
- package/vendor/linux-x64/cartridges/auth/migrations/20260424144652_initial/schema_snapshot.nbt +58 -0
- package/vendor/linux-x64/cartridges/auth/migrations/20260521191014_update_user/migration.nbt +3 -0
- package/vendor/linux-x64/cartridges/auth/migrations/20260521191014_update_user/schema_snapshot.nbt +59 -0
- package/vendor/linux-x64/cartridges/auth/schema.nbt +142 -0
- package/vendor/linux-x64/cartridges/calendar/migrations/20260501210107_initial/migration.nbt +60 -0
- package/vendor/linux-x64/cartridges/calendar/migrations/20260501210107_initial/schema_snapshot.nbt +66 -0
- package/vendor/linux-x64/cartridges/calendar/migrations/20260513151050_schema_update/migration.nbt +17 -0
- package/vendor/linux-x64/cartridges/calendar/migrations/20260513151050_schema_update/schema_snapshot.nbt +83 -0
- package/vendor/linux-x64/cartridges/calendar/schema.nbt +86 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260429222411_initial/migration.nbt +59 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260429222411_initial/schema_snapshot.nbt +71 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260430185225_add_messagereaction/migration.nbt +9 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260430185225_add_messagereaction/schema_snapshot.nbt +78 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260518191152_update_message/migration.nbt +3 -0
- package/vendor/linux-x64/cartridges/chat/migrations/20260518191152_update_message/schema_snapshot.nbt +81 -0
- package/vendor/linux-x64/cartridges/chat/schema.nbt +130 -0
- package/vendor/linux-x64/cartridges/crm/migrations/20260501210107_initial/migration.nbt +63 -0
- package/vendor/linux-x64/cartridges/crm/migrations/20260501210107_initial/schema_snapshot.nbt +73 -0
- package/vendor/linux-x64/cartridges/crm/migrations/20260513151050_schema_update/migration.nbt +13 -0
- package/vendor/linux-x64/cartridges/crm/migrations/20260513151050_schema_update/schema_snapshot.nbt +86 -0
- package/vendor/linux-x64/cartridges/crm/schema.nbt +148 -0
- package/vendor/linux-x64/cartridges/design/migrations/20260501210107_initial/migration.nbt +19 -0
- package/vendor/linux-x64/cartridges/design/migrations/20260501210107_initial/schema_snapshot.nbt +21 -0
- package/vendor/linux-x64/cartridges/design/migrations/20260610130000_design_system/migration.nbt +50 -0
- package/vendor/linux-x64/cartridges/design/migrations/20260610130000_design_system/schema_snapshot.nbt +80 -0
- package/vendor/linux-x64/cartridges/design/schema.nbt +140 -0
- package/vendor/linux-x64/cartridges/dns/migrations/20260501210107_initial/migration.nbt +32 -0
- package/vendor/linux-x64/cartridges/dns/migrations/20260501210107_initial/schema_snapshot.nbt +36 -0
- package/vendor/linux-x64/cartridges/dns/schema.nbt +68 -0
- package/vendor/linux-x64/cartridges/email/migrations/20260427235207_initial/migration.nbt +75 -0
- package/vendor/linux-x64/cartridges/email/migrations/20260427235207_initial/schema_snapshot.nbt +87 -0
- package/vendor/linux-x64/cartridges/email/schema.nbt +145 -0
- package/vendor/linux-x64/cartridges/ingest/migrations/20260424144652_initial/migration.nbt +18 -0
- package/vendor/linux-x64/cartridges/ingest/migrations/20260424144652_initial/schema_snapshot.nbt +20 -0
- package/vendor/linux-x64/cartridges/ingest/migrations/20260429203747_schema_update/migration.nbt +3 -0
- package/vendor/linux-x64/cartridges/ingest/migrations/20260429203747_schema_update/schema_snapshot.nbt +21 -0
- package/vendor/linux-x64/cartridges/ingest/schema.nbt +37 -0
- package/vendor/linux-x64/cartridges/notifications/migrations/20260430204408_initial/migration.nbt +42 -0
- package/vendor/linux-x64/cartridges/notifications/migrations/20260430204408_initial/schema_snapshot.nbt +46 -0
- package/vendor/linux-x64/cartridges/notifications/schema.nbt +67 -0
- package/vendor/linux-x64/cartridges/phone/migrations/20260605205722_initial/migration.nbt +50 -0
- package/vendor/linux-x64/cartridges/phone/migrations/20260605205722_initial/schema_snapshot.nbt +56 -0
- package/vendor/linux-x64/cartridges/phone/schema.nbt +95 -0
- package/vendor/linux-x64/cartridges/registry/migrations/20260602181932_initial/migration.nbt +8 -0
- package/vendor/linux-x64/cartridges/registry/migrations/20260602181932_initial/schema_snapshot.nbt +8 -0
- package/vendor/linux-x64/cartridges/registry/schema.nbt +20 -0
- package/vendor/linux-x64/cartridges/workflows/schema.nbt +44 -0
- package/vendor/linux-x64/console +0 -0
- package/vendor/linux-x64/nbt +0 -0
- package/contracts/audit/.dist/contract.json +0 -56
- package/contracts/auth/.dist/contract.json +0 -252
- package/contracts/calendar/.dist/contract.json +0 -141
- package/contracts/chat/.dist/contract.json +0 -229
- package/contracts/crm/.dist/contract.json +0 -239
- package/contracts/design/.dist/contract.json +0 -85
- package/contracts/dns/.dist/contract.json +0 -123
- package/contracts/email/.dist/contract.json +0 -267
- package/contracts/embed/.dist/contract.json +0 -137
- package/contracts/ingest/.dist/contract.json +0 -86
- package/contracts/notifications/.dist/contract.json +0 -133
- package/contracts/phone/.dist/contract.json +0 -168
- package/contracts/registry/.dist/contract.json +0 -49
- package/contracts/workflows/.dist/contract.json +0 -106
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Behavior (the former main.nbt actions) lives in native/runtime.jai over the
|
|
2
|
+
# generated ORM — see
|
|
3
|
+
# ingest_register_extra_routes. All routes stay auth-gated by the daemon
|
|
4
|
+
# middleware (no @public_route), matching the pre-migration manifest.
|
|
5
|
+
|
|
6
|
+
entity Endpoint {
|
|
7
|
+
id: ulid
|
|
8
|
+
createdAt: DateTime @default(now())
|
|
9
|
+
updatedAt: DateTime @updatedAt
|
|
10
|
+
name: string
|
|
11
|
+
slug: string
|
|
12
|
+
status: string
|
|
13
|
+
secret: string
|
|
14
|
+
payloadCount: u64
|
|
15
|
+
errorCount: u64
|
|
16
|
+
|
|
17
|
+
# Legacy field retained for stored rows. Previously named a downstream
|
|
18
|
+
# dispatch target; no dispatch fires today (the webhook just stores the
|
|
19
|
+
# payload and acks 200).
|
|
20
|
+
systemId?: string
|
|
21
|
+
|
|
22
|
+
@@unique([slug])
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
entity Payload {
|
|
26
|
+
id: ulid
|
|
27
|
+
createdAt: DateTime @default(now())
|
|
28
|
+
updatedAt: DateTime @updatedAt
|
|
29
|
+
endpointId: string
|
|
30
|
+
headers: string
|
|
31
|
+
body: document @scope(endpointId)
|
|
32
|
+
status: string
|
|
33
|
+
sourceIp: string
|
|
34
|
+
errorMessage: string
|
|
35
|
+
|
|
36
|
+
@@index([endpointId])
|
|
37
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Notifications cartridge
|
|
2
|
+
|
|
3
|
+
Durable notification state for console-backed applications.
|
|
4
|
+
|
|
5
|
+
This cartridge owns the notification record, browser push subscription state,
|
|
6
|
+
and delivery bookkeeping. The portal UI accesses this cartridge through normal
|
|
7
|
+
console routes. Browser-specific work such as permission prompts and service
|
|
8
|
+
worker registration still happens in the portal, but the resulting subscription
|
|
9
|
+
and all user-visible notification state live here.
|
|
10
|
+
|
|
11
|
+
## Goals
|
|
12
|
+
|
|
13
|
+
- Give every cartridge a single place to emit user notifications.
|
|
14
|
+
- Keep in-app notifications, read state, and delivery attempts durable in the
|
|
15
|
+
console.
|
|
16
|
+
- Support the browser Notifications API when the portal is open.
|
|
17
|
+
- Support Web Push when the portal is closed by storing `PushSubscription`
|
|
18
|
+
records in the console.
|
|
19
|
+
- Keep delivery channels generic enough for later email, SMS, Slack, and mobile
|
|
20
|
+
push.
|
|
21
|
+
|
|
22
|
+
## Non-goals for the first pass
|
|
23
|
+
|
|
24
|
+
- No direct dependency on a browser API from the console process.
|
|
25
|
+
- No provider-specific Web Push implementation in the schema. VAPID signing and
|
|
26
|
+
push HTTP delivery can be implemented by a console native helper or a portal
|
|
27
|
+
worker, but both operate against this cartridge's state.
|
|
28
|
+
- No cross-cartridge notification preferences yet. Preferences should be added
|
|
29
|
+
after at least two real notification sources exist.
|
|
30
|
+
|
|
31
|
+
## Model
|
|
32
|
+
|
|
33
|
+
`Notification` is the user-visible record. It contains title/body/url plus
|
|
34
|
+
source metadata so chat, systems, agents, CRM, and other cartridges can emit
|
|
35
|
+
without knowing how delivery works.
|
|
36
|
+
|
|
37
|
+
`NotificationDelivery` is an outbox row. It records intended channel delivery,
|
|
38
|
+
attempts, status, and provider response. For browser push, delivery rows point
|
|
39
|
+
at a notification and are fulfilled using the user's active
|
|
40
|
+
`BrowserPushSubscription` rows.
|
|
41
|
+
|
|
42
|
+
`BrowserPushSubscription` stores the browser-provided Push API subscription for
|
|
43
|
+
one signed-in user/device/browser. The portal registers the service worker,
|
|
44
|
+
calls `pushManager.subscribe`, and upserts the resulting endpoint and keys here.
|
|
45
|
+
|
|
46
|
+
## Initial API
|
|
47
|
+
|
|
48
|
+
- `Notification.emit`
|
|
49
|
+
- Service-only action.
|
|
50
|
+
- Creates a `Notification`.
|
|
51
|
+
- Creates a pending `browser_push` delivery row by default.
|
|
52
|
+
- Later: publish a realtime event over the multiplayer hub.
|
|
53
|
+
- `Notification.listMine`
|
|
54
|
+
- User action.
|
|
55
|
+
- Lists current user's notifications, optionally unread only.
|
|
56
|
+
- `Notification.markRead`
|
|
57
|
+
- User action.
|
|
58
|
+
- Marks one notification read if it belongs to the current user.
|
|
59
|
+
- `Notification.markAllRead`
|
|
60
|
+
- User action.
|
|
61
|
+
- Marks all current user's unread notifications read, optionally scoped to a
|
|
62
|
+
project.
|
|
63
|
+
- `BrowserPushSubscription.upsertMine`
|
|
64
|
+
- User action.
|
|
65
|
+
- Stores or refreshes the current browser/device push subscription.
|
|
66
|
+
- `BrowserPushSubscription.removeMine`
|
|
67
|
+
- User action.
|
|
68
|
+
- Disables one current-user subscription, usually during logout or explicit
|
|
69
|
+
notification opt-out.
|
|
70
|
+
- `NotificationDelivery.recordAttempt`
|
|
71
|
+
- Service-only action.
|
|
72
|
+
- Updates delivery state after a sender attempts Web Push delivery.
|
|
73
|
+
|
|
74
|
+
## Portal integration plan
|
|
75
|
+
|
|
76
|
+
1. Add `public/sw.js` in the portal.
|
|
77
|
+
- Handles `push`.
|
|
78
|
+
- Calls `self.registration.showNotification`.
|
|
79
|
+
- Handles `notificationclick` by focusing or opening the notification URL.
|
|
80
|
+
2. Add a small portal notification client.
|
|
81
|
+
- Registers the service worker.
|
|
82
|
+
- Requests `Notification` permission from a user gesture.
|
|
83
|
+
- Calls `registration.pushManager.subscribe`.
|
|
84
|
+
- Sends `endpoint`, `p256dh`, `auth`, `expirationTime`, and user agent to
|
|
85
|
+
`BrowserPushSubscription.upsertMine`.
|
|
86
|
+
3. Replace the top-bar Bell placeholder with notification state from
|
|
87
|
+
`Notification.listMine`.
|
|
88
|
+
4. Subscribe to realtime notification events when the portal is open.
|
|
89
|
+
- Use browser `new Notification(...)` only after permission is granted.
|
|
90
|
+
- Also update the Bell dropdown from the same event.
|
|
91
|
+
5. Add a delivery worker.
|
|
92
|
+
- Reads pending `browser_push` deliveries.
|
|
93
|
+
- Loads active subscriptions for the notification user.
|
|
94
|
+
- Sends Web Push using VAPID.
|
|
95
|
+
- Calls `NotificationDelivery.recordAttempt`.
|
|
96
|
+
- Disables expired subscriptions after HTTP 404/410 from the push service.
|
|
97
|
+
|
|
98
|
+
## Console integration plan
|
|
99
|
+
|
|
100
|
+
1. Add this cartridge to the bundled core cartridge list.
|
|
101
|
+
2. Generate and commit the initial migration.
|
|
102
|
+
3. Add a tiny cross-cartridge helper or service route for emitting
|
|
103
|
+
notifications so other cartridges do not hand-roll HTTP calls.
|
|
104
|
+
4. Update chat to emit through this cartridge after its current per-user inbox
|
|
105
|
+
fanout. Chat's existing inbox event remains useful for live unread updates;
|
|
106
|
+
notifications become the durable user-facing record.
|
|
107
|
+
5. Add multiplayer fanout for `Notification.emit` so an open portal sees new
|
|
108
|
+
notifications immediately.
|
|
109
|
+
|
|
110
|
+
## Delivery ownership
|
|
111
|
+
|
|
112
|
+
The cartridge owns state. The delivery executor may be either:
|
|
113
|
+
|
|
114
|
+
- a console native helper, preferred once VAPID/web-push support exists in Jai,
|
|
115
|
+
or
|
|
116
|
+
- a portal worker that reads/writes this cartridge through service-auth routes.
|
|
117
|
+
|
|
118
|
+
Both shapes keep the portal as a browser client, not the source of truth.
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
migration initial {
|
|
2
|
+
add_entity Notification
|
|
3
|
+
add_field Notification userId string default("")
|
|
4
|
+
add_field Notification projectId string default("")
|
|
5
|
+
add_field Notification sourceCart string default("")
|
|
6
|
+
add_field Notification sourceId string default("")
|
|
7
|
+
add_field Notification kind string default("")
|
|
8
|
+
add_field Notification title string default("")
|
|
9
|
+
add_field Notification body string default("")
|
|
10
|
+
add_field Notification url string default("")
|
|
11
|
+
add_field Notification payloadJson string default("")
|
|
12
|
+
add_field Notification readAt DateTime default(0)
|
|
13
|
+
add_field Notification archivedAt DateTime default(0)
|
|
14
|
+
add_index Notification [userId]
|
|
15
|
+
add_index Notification [projectId]
|
|
16
|
+
add_index Notification [sourceCart, sourceId]
|
|
17
|
+
add_entity NotificationDelivery
|
|
18
|
+
add_field NotificationDelivery notificationId string default("")
|
|
19
|
+
add_field NotificationDelivery userId string default("")
|
|
20
|
+
add_field NotificationDelivery channel string default("")
|
|
21
|
+
add_field NotificationDelivery status string default("")
|
|
22
|
+
add_field NotificationDelivery attempts u32 default(0)
|
|
23
|
+
add_field NotificationDelivery lastError string default("")
|
|
24
|
+
add_field NotificationDelivery providerMessageId string default("")
|
|
25
|
+
add_field NotificationDelivery lastAttemptAt DateTime default(0)
|
|
26
|
+
add_field NotificationDelivery sentAt DateTime default(0)
|
|
27
|
+
add_index NotificationDelivery [notificationId]
|
|
28
|
+
add_index NotificationDelivery [userId]
|
|
29
|
+
add_index NotificationDelivery [channel, status]
|
|
30
|
+
add_entity BrowserPushSubscription
|
|
31
|
+
add_field BrowserPushSubscription userId string default("")
|
|
32
|
+
add_field BrowserPushSubscription endpoint string default("")
|
|
33
|
+
add_field BrowserPushSubscription p256dh string default("")
|
|
34
|
+
add_field BrowserPushSubscription auth string default("")
|
|
35
|
+
add_field BrowserPushSubscription expirationTimeMs u64 default(0)
|
|
36
|
+
add_field BrowserPushSubscription userAgent string default("")
|
|
37
|
+
add_field BrowserPushSubscription deviceLabel string default("")
|
|
38
|
+
add_field BrowserPushSubscription lastSeenAt DateTime default(0)
|
|
39
|
+
add_field BrowserPushSubscription disabledAt DateTime default(0)
|
|
40
|
+
add_index BrowserPushSubscription [userId]
|
|
41
|
+
add_unique BrowserPushSubscription [endpoint]
|
|
42
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
entity Notification {
|
|
2
|
+
userId: string
|
|
3
|
+
projectId?: string
|
|
4
|
+
sourceCart?: string
|
|
5
|
+
sourceId?: string
|
|
6
|
+
kind: string
|
|
7
|
+
title: string
|
|
8
|
+
body?: string
|
|
9
|
+
url?: string
|
|
10
|
+
payloadJson?: string
|
|
11
|
+
readAt?: DateTime
|
|
12
|
+
archivedAt?: DateTime
|
|
13
|
+
@@index([userId])
|
|
14
|
+
@@index([projectId])
|
|
15
|
+
@@index([sourceCart, sourceId])
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
entity NotificationDelivery {
|
|
19
|
+
notificationId: string
|
|
20
|
+
userId: string
|
|
21
|
+
channel: string
|
|
22
|
+
status: string
|
|
23
|
+
attempts: u32
|
|
24
|
+
lastError?: string
|
|
25
|
+
providerMessageId?: string
|
|
26
|
+
lastAttemptAt?: DateTime
|
|
27
|
+
sentAt?: DateTime
|
|
28
|
+
@@index([notificationId])
|
|
29
|
+
@@index([userId])
|
|
30
|
+
@@index([channel, status])
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
entity BrowserPushSubscription {
|
|
34
|
+
userId: string
|
|
35
|
+
endpoint: string
|
|
36
|
+
p256dh: string
|
|
37
|
+
auth: string
|
|
38
|
+
expirationTimeMs?: u64
|
|
39
|
+
userAgent?: string
|
|
40
|
+
deviceLabel?: string
|
|
41
|
+
lastSeenAt: DateTime
|
|
42
|
+
disabledAt?: DateTime
|
|
43
|
+
@@unique([endpoint])
|
|
44
|
+
@@index([userId])
|
|
45
|
+
}
|
|
46
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Notifications cartridge — durable user notification state plus browser push
|
|
2
|
+
# subscriptions. The portal owns browser permission prompts and service worker
|
|
3
|
+
# registration; this cartridge owns the resulting state.
|
|
4
|
+
#
|
|
5
|
+
# Behavior (the former main.nbt actions) lives in native/runtime.jai as regular
|
|
6
|
+
# Jai over the generated ORM — see notifications_register_extra_routes.
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
entity Notification {
|
|
10
|
+
id: ulid
|
|
11
|
+
createdAt: DateTime @default(now())
|
|
12
|
+
updatedAt: DateTime @updatedAt
|
|
13
|
+
userId: string
|
|
14
|
+
projectId?: string
|
|
15
|
+
sourceCart?: string
|
|
16
|
+
sourceId?: string
|
|
17
|
+
kind: string
|
|
18
|
+
|
|
19
|
+
title: string
|
|
20
|
+
body?: string
|
|
21
|
+
url?: string
|
|
22
|
+
payloadJson?: string
|
|
23
|
+
|
|
24
|
+
readAt?: DateTime
|
|
25
|
+
archivedAt?: DateTime
|
|
26
|
+
|
|
27
|
+
@@index([userId])
|
|
28
|
+
@@index([projectId])
|
|
29
|
+
@@index([sourceCart, sourceId])
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
entity NotificationDelivery {
|
|
33
|
+
id: ulid
|
|
34
|
+
createdAt: DateTime @default(now())
|
|
35
|
+
updatedAt: DateTime @updatedAt
|
|
36
|
+
notificationId: string
|
|
37
|
+
userId: string
|
|
38
|
+
channel: string # "browser_push", later "email", "sms", etc.
|
|
39
|
+
status: string # "pending" | "sent" | "failed" | "skipped"
|
|
40
|
+
attempts: u32
|
|
41
|
+
lastError?: string
|
|
42
|
+
providerMessageId?: string
|
|
43
|
+
lastAttemptAt?: DateTime
|
|
44
|
+
sentAt?: DateTime
|
|
45
|
+
|
|
46
|
+
@@index([notificationId])
|
|
47
|
+
@@index([userId])
|
|
48
|
+
@@index([channel, status])
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
entity BrowserPushSubscription {
|
|
52
|
+
id: ulid
|
|
53
|
+
createdAt: DateTime @default(now())
|
|
54
|
+
updatedAt: DateTime @updatedAt
|
|
55
|
+
userId: string
|
|
56
|
+
endpoint: string
|
|
57
|
+
p256dh: string
|
|
58
|
+
auth: string
|
|
59
|
+
expirationTimeMs?: u64
|
|
60
|
+
userAgent?: string
|
|
61
|
+
deviceLabel?: string
|
|
62
|
+
lastSeenAt: DateTime @default(now())
|
|
63
|
+
disabledAt?: DateTime
|
|
64
|
+
|
|
65
|
+
@@unique([endpoint])
|
|
66
|
+
@@index([userId])
|
|
67
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
migration initial {
|
|
2
|
+
add_entity TwilioAccount
|
|
3
|
+
add_field TwilioAccount name string default("")
|
|
4
|
+
add_field TwilioAccount subAccountSid string default("")
|
|
5
|
+
add_field TwilioAccount authToken string default("")
|
|
6
|
+
add_field TwilioAccount publicUrlBase string default("")
|
|
7
|
+
add_field TwilioAccount status string default("")
|
|
8
|
+
add_field TwilioAccount retentionDays s32 default(0)
|
|
9
|
+
add_index TwilioAccount [subAccountSid]
|
|
10
|
+
add_unique TwilioAccount [name]
|
|
11
|
+
add_entity PhoneNumber
|
|
12
|
+
add_field PhoneNumber accountId string default("")
|
|
13
|
+
add_field PhoneNumber phoneNumber string default("")
|
|
14
|
+
add_field PhoneNumber numberSid string default("")
|
|
15
|
+
add_field PhoneNumber friendlyName string default("")
|
|
16
|
+
add_field PhoneNumber capabilities string default("")
|
|
17
|
+
add_index PhoneNumber [accountId]
|
|
18
|
+
add_index PhoneNumber [numberSid]
|
|
19
|
+
add_unique PhoneNumber [phoneNumber]
|
|
20
|
+
add_entity SmsMessage
|
|
21
|
+
add_field SmsMessage accountId string default("")
|
|
22
|
+
add_field SmsMessage numberId string default("")
|
|
23
|
+
add_field SmsMessage direction string default("")
|
|
24
|
+
add_field SmsMessage fromE164 string default("")
|
|
25
|
+
add_field SmsMessage toE164 string default("")
|
|
26
|
+
add_field SmsMessage body string default("")
|
|
27
|
+
add_field SmsMessage twilioSid string default("")
|
|
28
|
+
add_field SmsMessage status string default("")
|
|
29
|
+
add_field SmsMessage errorCode s32 default(0)
|
|
30
|
+
add_field SmsMessage errorMessage string default("")
|
|
31
|
+
add_field SmsMessage priceMicros s64 default(0)
|
|
32
|
+
add_field SmsMessage priceCurrency string default("")
|
|
33
|
+
add_field SmsMessage numSegments s32 default(0)
|
|
34
|
+
add_field SmsMessage numMedia s32 default(0)
|
|
35
|
+
add_field SmsMessage mediaUrls string default("")
|
|
36
|
+
add_field SmsMessage senderUserId string default("")
|
|
37
|
+
add_field SmsMessage dateSentMs u64 default(0)
|
|
38
|
+
add_field SmsMessage dateDeliveredMs u64 default(0)
|
|
39
|
+
add_index SmsMessage [accountId]
|
|
40
|
+
add_index SmsMessage [numberId]
|
|
41
|
+
add_index SmsMessage [twilioSid]
|
|
42
|
+
add_entity PhoneUsageDaily
|
|
43
|
+
add_field PhoneUsageDaily accountId string default("")
|
|
44
|
+
add_field PhoneUsageDaily date string default("")
|
|
45
|
+
add_field PhoneUsageDaily smsCount s64 default(0)
|
|
46
|
+
add_field PhoneUsageDaily smsSegmentsTotal s64 default(0)
|
|
47
|
+
add_field PhoneUsageDaily smsPriceMicros s64 default(0)
|
|
48
|
+
add_index PhoneUsageDaily [accountId]
|
|
49
|
+
add_unique PhoneUsageDaily [accountId, date]
|
|
50
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
entity TwilioAccount {
|
|
2
|
+
name: string
|
|
3
|
+
subAccountSid: string
|
|
4
|
+
authToken: string
|
|
5
|
+
publicUrlBase: string
|
|
6
|
+
status: string
|
|
7
|
+
retentionDays: s32
|
|
8
|
+
@@unique([name])
|
|
9
|
+
@@index([subAccountSid])
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
entity PhoneNumber {
|
|
13
|
+
accountId: string
|
|
14
|
+
phoneNumber: string
|
|
15
|
+
numberSid: string
|
|
16
|
+
friendlyName: string
|
|
17
|
+
capabilities: string
|
|
18
|
+
@@index([accountId])
|
|
19
|
+
@@unique([phoneNumber])
|
|
20
|
+
@@index([numberSid])
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
entity SmsMessage {
|
|
24
|
+
accountId: string
|
|
25
|
+
numberId: string
|
|
26
|
+
direction: string
|
|
27
|
+
fromE164: string
|
|
28
|
+
toE164: string
|
|
29
|
+
body: string
|
|
30
|
+
twilioSid: string
|
|
31
|
+
status: string
|
|
32
|
+
errorCode: s32
|
|
33
|
+
errorMessage: string
|
|
34
|
+
priceMicros: s64
|
|
35
|
+
priceCurrency: string
|
|
36
|
+
numSegments: s32
|
|
37
|
+
numMedia: s32
|
|
38
|
+
mediaUrls: string
|
|
39
|
+
senderUserId: string
|
|
40
|
+
dateSentMs: u64
|
|
41
|
+
dateDeliveredMs: u64
|
|
42
|
+
@@index([accountId])
|
|
43
|
+
@@index([numberId])
|
|
44
|
+
@@index([twilioSid])
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
entity PhoneUsageDaily {
|
|
48
|
+
accountId: string
|
|
49
|
+
date: string
|
|
50
|
+
smsCount: s64
|
|
51
|
+
smsSegmentsTotal: s64
|
|
52
|
+
smsPriceMicros: s64
|
|
53
|
+
@@unique([accountId, date])
|
|
54
|
+
@@index([accountId])
|
|
55
|
+
}
|
|
56
|
+
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Phone cartridge — Twilio number management, SMS, click-to-call.
|
|
2
|
+
#
|
|
3
|
+
# Per-tenant model (see modules/twilio/module.jai for the rationale):
|
|
4
|
+
# - One master Twilio account owned by the platform (SID + auth token in
|
|
5
|
+
# env: TWILIO_MASTER_SID, TWILIO_MASTER_TOKEN).
|
|
6
|
+
# - Each tenant gets a TwilioAccount row with its own subaccount SID and
|
|
7
|
+
# auth token. All per-tenant API calls authenticate as the subaccount.
|
|
8
|
+
# - Webhooks are configured to URLs under the tenant's public base
|
|
9
|
+
# (TwilioAccount.publicUrlBase), which the gateway routes back to this
|
|
10
|
+
# cart. Signature verification uses the subaccount's auth token.
|
|
11
|
+
|
|
12
|
+
# Behavior (the former jai{} helper blocks + actions) lives in
|
|
13
|
+
# native/runtime.jai over the generated ORM — see phone_register_extra_routes,
|
|
14
|
+
# which registers the HTTP routes.
|
|
15
|
+
|
|
16
|
+
# Auth policy for the hand-written routes (formerly @public actions). The
|
|
17
|
+
# handlers live in native/runtime.jai; these keep the daemon's public-route
|
|
18
|
+
# manifest correct so the /api/* auth gate is bypassed for Twilio webhooks.
|
|
19
|
+
@public_route "/api/phone/webhook/sms"
|
|
20
|
+
@public_route "/api/phone/webhook/status"
|
|
21
|
+
|
|
22
|
+
entity TwilioAccount {
|
|
23
|
+
id: ulid
|
|
24
|
+
createdAt: DateTime @default(now())
|
|
25
|
+
updatedAt: DateTime @updatedAt
|
|
26
|
+
name: string # operator-facing label
|
|
27
|
+
subAccountSid: string # AC... — populated by provision()
|
|
28
|
+
authToken: string # subaccount auth token (TODO: encrypt at rest)
|
|
29
|
+
publicUrlBase: string # e.g. "https://acme.console.app"
|
|
30
|
+
status: string # PENDING | ACTIVE | SUSPENDED | CLOSED
|
|
31
|
+
retentionDays: s32 # 0 = keep message bodies forever; N = null body after N days
|
|
32
|
+
|
|
33
|
+
@@unique([name])
|
|
34
|
+
@@index([subAccountSid])
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
entity PhoneNumber {
|
|
38
|
+
id: ulid
|
|
39
|
+
createdAt: DateTime @default(now())
|
|
40
|
+
updatedAt: DateTime @updatedAt
|
|
41
|
+
accountId: string # FK TwilioAccount.id
|
|
42
|
+
phoneNumber: string # E.164 "+15551234567"
|
|
43
|
+
numberSid: string # PN...
|
|
44
|
+
friendlyName: string
|
|
45
|
+
capabilities: string # "sms"
|
|
46
|
+
|
|
47
|
+
@@index([accountId])
|
|
48
|
+
@@unique([phoneNumber])
|
|
49
|
+
@@index([numberSid])
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
entity SmsMessage {
|
|
53
|
+
id: ulid
|
|
54
|
+
createdAt: DateTime @default(now())
|
|
55
|
+
updatedAt: DateTime @updatedAt
|
|
56
|
+
accountId: string
|
|
57
|
+
numberId: string # FK PhoneNumber.id (empty on inbound if not matched)
|
|
58
|
+
direction: string # inbound | outbound
|
|
59
|
+
fromE164: string
|
|
60
|
+
toE164: string
|
|
61
|
+
body: string # nulled after retentionDays if TwilioAccount configured
|
|
62
|
+
twilioSid: string # SM...
|
|
63
|
+
status: string # queued | sent | delivered | failed | received
|
|
64
|
+
errorCode: s32
|
|
65
|
+
errorMessage: string # human-readable sibling of errorCode
|
|
66
|
+
priceMicros: s64 # negative = charged (Twilio convention); 0 until status callback
|
|
67
|
+
priceCurrency: string # "USD" / "CAD"
|
|
68
|
+
numSegments: s32
|
|
69
|
+
numMedia: s32
|
|
70
|
+
mediaUrls: string # JSON array of MMS media URLs
|
|
71
|
+
senderUserId: string # who triggered the send (empty for inbound)
|
|
72
|
+
dateSentMs: u64 # Twilio canonical timestamp (ms since epoch)
|
|
73
|
+
dateDeliveredMs: u64
|
|
74
|
+
|
|
75
|
+
@@index([accountId])
|
|
76
|
+
@@index([numberId])
|
|
77
|
+
@@index([twilioSid])
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# Per-tenant per-day usage rollup. Written by the nightly rollup workflow;
|
|
81
|
+
# read by the portal to generate invoices.
|
|
82
|
+
entity PhoneUsageDaily {
|
|
83
|
+
id: ulid
|
|
84
|
+
createdAt: DateTime @default(now())
|
|
85
|
+
updatedAt: DateTime @updatedAt
|
|
86
|
+
accountId: string
|
|
87
|
+
date: string # "YYYY-MM-DD" in UTC
|
|
88
|
+
smsCount: s64
|
|
89
|
+
smsSegmentsTotal: s64
|
|
90
|
+
smsPriceMicros: s64
|
|
91
|
+
|
|
92
|
+
@@unique([accountId, date])
|
|
93
|
+
@@index([accountId])
|
|
94
|
+
}
|
|
95
|
+
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
migration initial {
|
|
2
|
+
add_entity InstalledCartridge
|
|
3
|
+
add_field InstalledCartridge tier string default("")
|
|
4
|
+
add_field InstalledCartridge source string default("")
|
|
5
|
+
add_field InstalledCartridge schemaChecksum string default("")
|
|
6
|
+
add_field InstalledCartridge installedAt u64 default(0)
|
|
7
|
+
add_field InstalledCartridge status string default("")
|
|
8
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Installed-cartridge registry — the single source of truth for which tier-2
|
|
2
|
+
# (bundled) and customer cartridges are installed on this instance.
|
|
3
|
+
#
|
|
4
|
+
# Lives in replicated storage, so the install set is HA-safe and survives
|
|
5
|
+
# restarts: on boot the console re-activates every InstalledCartridge row.
|
|
6
|
+
#
|
|
7
|
+
# The console daemon is the SINGLE WRITER (cartridge_registry.jai writes rows
|
|
8
|
+
# through THIS cart's generated serializer — same code, no format drift). The
|
|
9
|
+
# generated CRUD routes are read-mostly, for the portal/client. The row id is
|
|
10
|
+
# the cartridge name.
|
|
11
|
+
entity InstalledCartridge {
|
|
12
|
+
id: string @id # the cartridge name (slug), NOT a ulid
|
|
13
|
+
createdAt: DateTime @default(now())
|
|
14
|
+
updatedAt: DateTime @updatedAt
|
|
15
|
+
tier: string # "bundled" | "customer"
|
|
16
|
+
source: string # "bundled" | "customer"
|
|
17
|
+
schemaChecksum: string # checksum of the installed schema (drift detection)
|
|
18
|
+
installedAt: u64 # ms epoch
|
|
19
|
+
status: string # "installed" | "failed"
|
|
20
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
|
|
2
|
+
# Question: How do we tie in cartridge metadata and workflow side effects into all this?
|
|
3
|
+
|
|
4
|
+
enum WorkerStatus {
|
|
5
|
+
WAITING
|
|
6
|
+
RUNNING
|
|
7
|
+
TERMINATED
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
entity Worker {
|
|
11
|
+
id: ulid
|
|
12
|
+
createdAt: DateTime @default(now())
|
|
13
|
+
updatedAt: DateTime @updatedAt
|
|
14
|
+
source: blob
|
|
15
|
+
contentHash: string
|
|
16
|
+
queue?: string
|
|
17
|
+
# TODO: We need some sort of termination options like a restart policy
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
# Stub — flesh out execution lifecycle fields later.
|
|
21
|
+
entity WorkflowExecution {
|
|
22
|
+
id: ulid
|
|
23
|
+
createdAt: DateTime @default(now())
|
|
24
|
+
updatedAt: DateTime @updatedAt
|
|
25
|
+
status: string
|
|
26
|
+
events: WorkflowExecutionEvent[]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
# Do we want this to be a string?
|
|
30
|
+
enum WorkflowExecutionEventKind {
|
|
31
|
+
WORKFLOW_EXECUTION_STARTED
|
|
32
|
+
WORKFLOW_STEP_SCHEDULED
|
|
33
|
+
WORKFLOW_STEP_STARTED
|
|
34
|
+
WORKFLOW_STEP_COMPLETED
|
|
35
|
+
WORKFLOW_EXECUTION_COMPLETED
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
entity WorkflowExecutionEvent {
|
|
39
|
+
id: ulid
|
|
40
|
+
createdAt: DateTime @default(now())
|
|
41
|
+
updatedAt: DateTime @updatedAt
|
|
42
|
+
execution: WorkflowExecution @relation(onDelete: Cascade) # events are owned by their execution
|
|
43
|
+
kind: WorkflowExecutionEventKind
|
|
44
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
migration initial {
|
|
2
|
+
add_entity User
|
|
3
|
+
add_field User name string default("")
|
|
4
|
+
add_field User username string default("")
|
|
5
|
+
add_field User email string default("")
|
|
6
|
+
add_field User emailVerified bool default(false)
|
|
7
|
+
add_field User externalId string default("")
|
|
8
|
+
add_field User capsVersion u32 default(0)
|
|
9
|
+
add_index User [email]
|
|
10
|
+
add_index User [externalId]
|
|
11
|
+
add_entity UserRole
|
|
12
|
+
add_field UserRole userId string default("")
|
|
13
|
+
add_field UserRole cart string default("")
|
|
14
|
+
add_field UserRole role string default("")
|
|
15
|
+
add_index UserRole [userId]
|
|
16
|
+
add_entity Session
|
|
17
|
+
add_field Session userId string default("")
|
|
18
|
+
add_field Session token string default("")
|
|
19
|
+
add_field Session expiresAt DateTime default(0)
|
|
20
|
+
add_field Session ipAddress string default("")
|
|
21
|
+
add_field Session userAgent string default("")
|
|
22
|
+
add_index Session [token]
|
|
23
|
+
add_index Session [userId]
|
|
24
|
+
add_entity Account
|
|
25
|
+
add_field Account userId string default("")
|
|
26
|
+
add_field Account providerId string default("")
|
|
27
|
+
add_field Account password string default("")
|
|
28
|
+
add_field Account accessToken string default("")
|
|
29
|
+
add_field Account refreshToken string default("")
|
|
30
|
+
add_field Account idToken string default("")
|
|
31
|
+
add_field Account accessTokenExpiresAt DateTime default(0)
|
|
32
|
+
add_field Account refreshTokenExpiresAt DateTime default(0)
|
|
33
|
+
add_field Account scope string default("")
|
|
34
|
+
add_index Account [userId]
|
|
35
|
+
add_entity Verification
|
|
36
|
+
add_field Verification identifier string default("")
|
|
37
|
+
add_field Verification value string default("")
|
|
38
|
+
add_field Verification expiresAt DateTime default(0)
|
|
39
|
+
add_index Verification [identifier]
|
|
40
|
+
add_entity ApiKey
|
|
41
|
+
add_field ApiKey name string default("")
|
|
42
|
+
add_field ApiKey projectId string default("")
|
|
43
|
+
add_field ApiKey start string default("")
|
|
44
|
+
add_field ApiKey prefix string default("")
|
|
45
|
+
add_field ApiKey key string default("")
|
|
46
|
+
add_field ApiKey permissions string default("")
|
|
47
|
+
add_field ApiKey roles string default("")
|
|
48
|
+
}
|