@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.
Files changed (145) hide show
  1. package/LICENSE +177 -21
  2. package/README.md +16 -13
  3. package/TRADEMARKS.md +49 -0
  4. package/dist/nbt.js +398 -19
  5. package/package.json +5 -4
  6. package/stdlib/auth/README.md +83 -0
  7. package/stdlib/auth/migrations/20260424144652_initial/migration.nbt +48 -0
  8. package/stdlib/auth/migrations/20260424144652_initial/schema_snapshot.nbt +58 -0
  9. package/stdlib/auth/migrations/20260521191014_update_user/migration.nbt +3 -0
  10. package/stdlib/auth/migrations/20260521191014_update_user/schema_snapshot.nbt +59 -0
  11. package/stdlib/auth/schema.nbt +142 -0
  12. package/stdlib/calendar/adapters/gohighlevel/tests/fixtures/v2_calendar_pilot.json +12 -0
  13. package/stdlib/calendar/adapters/gohighlevel/tests/fixtures/webhooks/appointment_changed.json +70 -0
  14. package/stdlib/calendar/adapters/gohighlevel/tests/fixtures/webhooks/appointment_created.json +72 -0
  15. package/stdlib/calendar/migrations/20260501210107_initial/migration.nbt +60 -0
  16. package/stdlib/calendar/migrations/20260501210107_initial/schema_snapshot.nbt +66 -0
  17. package/stdlib/calendar/migrations/20260513151050_schema_update/migration.nbt +17 -0
  18. package/stdlib/calendar/migrations/20260513151050_schema_update/schema_snapshot.nbt +83 -0
  19. package/stdlib/calendar/schema.nbt +86 -0
  20. package/stdlib/chat/migrations/20260429222411_initial/migration.nbt +59 -0
  21. package/stdlib/chat/migrations/20260429222411_initial/schema_snapshot.nbt +71 -0
  22. package/stdlib/chat/migrations/20260430185225_add_messagereaction/migration.nbt +9 -0
  23. package/stdlib/chat/migrations/20260430185225_add_messagereaction/schema_snapshot.nbt +78 -0
  24. package/stdlib/chat/migrations/20260518191152_update_message/migration.nbt +3 -0
  25. package/stdlib/chat/migrations/20260518191152_update_message/schema_snapshot.nbt +81 -0
  26. package/stdlib/chat/schema.nbt +130 -0
  27. package/stdlib/crm/adapters/gohighlevel/README.md +85 -0
  28. package/stdlib/crm/adapters/gohighlevel/tests/README.md +159 -0
  29. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_138fields.json +222 -0
  30. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_140fields.json +219 -0
  31. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_alt.json +212 -0
  32. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_changed.json +102 -0
  33. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_created.json +95 -0
  34. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_full.json +213 -0
  35. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_sparse.json +161 -0
  36. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_update_a.json +197 -0
  37. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/contact_update_b.json +197 -0
  38. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/opportunity_changed.json +85 -0
  39. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/opportunity_created.json +85 -0
  40. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_contact_pilot.json +43 -0
  41. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_contact_with_price_closed.json +7 -0
  42. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_contact_with_price_open.json +7 -0
  43. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_event_appointment_delete.json +1 -0
  44. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_event_calendar_update.json +1 -0
  45. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_event_contact_create.json +1 -0
  46. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_event_opp_status_update.json +1 -0
  47. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_opportunity_pilot.json +16 -0
  48. package/stdlib/crm/adapters/gohighlevel/tests/fixtures/webhooks/v2_pipelines_pilot.json +137 -0
  49. package/stdlib/crm/migrations/20260501210107_initial/migration.nbt +63 -0
  50. package/stdlib/crm/migrations/20260501210107_initial/schema_snapshot.nbt +73 -0
  51. package/stdlib/crm/migrations/20260513151050_schema_update/migration.nbt +13 -0
  52. package/stdlib/crm/migrations/20260513151050_schema_update/schema_snapshot.nbt +86 -0
  53. package/stdlib/crm/schema.nbt +148 -0
  54. package/stdlib/design/migrations/20260501210107_initial/migration.nbt +19 -0
  55. package/stdlib/design/migrations/20260501210107_initial/schema_snapshot.nbt +21 -0
  56. package/stdlib/design/migrations/20260610130000_design_system/migration.nbt +50 -0
  57. package/stdlib/design/migrations/20260610130000_design_system/schema_snapshot.nbt +80 -0
  58. package/stdlib/design/schema.nbt +140 -0
  59. package/stdlib/dns/migrations/20260501210107_initial/migration.nbt +32 -0
  60. package/stdlib/dns/migrations/20260501210107_initial/schema_snapshot.nbt +36 -0
  61. package/stdlib/dns/schema.nbt +68 -0
  62. package/stdlib/email/migrations/20260427235207_initial/migration.nbt +75 -0
  63. package/stdlib/email/migrations/20260427235207_initial/schema_snapshot.nbt +87 -0
  64. package/stdlib/email/schema.nbt +145 -0
  65. package/stdlib/ingest/README.md +29 -0
  66. package/stdlib/ingest/migrations/20260424144652_initial/migration.nbt +18 -0
  67. package/stdlib/ingest/migrations/20260424144652_initial/schema_snapshot.nbt +20 -0
  68. package/stdlib/ingest/migrations/20260429203747_schema_update/migration.nbt +3 -0
  69. package/stdlib/ingest/migrations/20260429203747_schema_update/schema_snapshot.nbt +21 -0
  70. package/stdlib/ingest/schema.nbt +37 -0
  71. package/stdlib/notifications/README.md +118 -0
  72. package/stdlib/notifications/migrations/20260430204408_initial/migration.nbt +42 -0
  73. package/stdlib/notifications/migrations/20260430204408_initial/schema_snapshot.nbt +46 -0
  74. package/stdlib/notifications/schema.nbt +67 -0
  75. package/stdlib/phone/migrations/20260605205722_initial/migration.nbt +50 -0
  76. package/stdlib/phone/migrations/20260605205722_initial/schema_snapshot.nbt +56 -0
  77. package/stdlib/phone/schema.nbt +95 -0
  78. package/stdlib/registry/migrations/20260602181932_initial/migration.nbt +8 -0
  79. package/stdlib/registry/migrations/20260602181932_initial/schema_snapshot.nbt +8 -0
  80. package/stdlib/registry/schema.nbt +20 -0
  81. package/stdlib/workflows/schema.nbt +44 -0
  82. package/vendor/linux-x64/cartridges/auth/migrations/20260424144652_initial/migration.nbt +48 -0
  83. package/vendor/linux-x64/cartridges/auth/migrations/20260424144652_initial/schema_snapshot.nbt +58 -0
  84. package/vendor/linux-x64/cartridges/auth/migrations/20260521191014_update_user/migration.nbt +3 -0
  85. package/vendor/linux-x64/cartridges/auth/migrations/20260521191014_update_user/schema_snapshot.nbt +59 -0
  86. package/vendor/linux-x64/cartridges/auth/schema.nbt +142 -0
  87. package/vendor/linux-x64/cartridges/calendar/migrations/20260501210107_initial/migration.nbt +60 -0
  88. package/vendor/linux-x64/cartridges/calendar/migrations/20260501210107_initial/schema_snapshot.nbt +66 -0
  89. package/vendor/linux-x64/cartridges/calendar/migrations/20260513151050_schema_update/migration.nbt +17 -0
  90. package/vendor/linux-x64/cartridges/calendar/migrations/20260513151050_schema_update/schema_snapshot.nbt +83 -0
  91. package/vendor/linux-x64/cartridges/calendar/schema.nbt +86 -0
  92. package/vendor/linux-x64/cartridges/chat/migrations/20260429222411_initial/migration.nbt +59 -0
  93. package/vendor/linux-x64/cartridges/chat/migrations/20260429222411_initial/schema_snapshot.nbt +71 -0
  94. package/vendor/linux-x64/cartridges/chat/migrations/20260430185225_add_messagereaction/migration.nbt +9 -0
  95. package/vendor/linux-x64/cartridges/chat/migrations/20260430185225_add_messagereaction/schema_snapshot.nbt +78 -0
  96. package/vendor/linux-x64/cartridges/chat/migrations/20260518191152_update_message/migration.nbt +3 -0
  97. package/vendor/linux-x64/cartridges/chat/migrations/20260518191152_update_message/schema_snapshot.nbt +81 -0
  98. package/vendor/linux-x64/cartridges/chat/schema.nbt +130 -0
  99. package/vendor/linux-x64/cartridges/crm/migrations/20260501210107_initial/migration.nbt +63 -0
  100. package/vendor/linux-x64/cartridges/crm/migrations/20260501210107_initial/schema_snapshot.nbt +73 -0
  101. package/vendor/linux-x64/cartridges/crm/migrations/20260513151050_schema_update/migration.nbt +13 -0
  102. package/vendor/linux-x64/cartridges/crm/migrations/20260513151050_schema_update/schema_snapshot.nbt +86 -0
  103. package/vendor/linux-x64/cartridges/crm/schema.nbt +148 -0
  104. package/vendor/linux-x64/cartridges/design/migrations/20260501210107_initial/migration.nbt +19 -0
  105. package/vendor/linux-x64/cartridges/design/migrations/20260501210107_initial/schema_snapshot.nbt +21 -0
  106. package/vendor/linux-x64/cartridges/design/migrations/20260610130000_design_system/migration.nbt +50 -0
  107. package/vendor/linux-x64/cartridges/design/migrations/20260610130000_design_system/schema_snapshot.nbt +80 -0
  108. package/vendor/linux-x64/cartridges/design/schema.nbt +140 -0
  109. package/vendor/linux-x64/cartridges/dns/migrations/20260501210107_initial/migration.nbt +32 -0
  110. package/vendor/linux-x64/cartridges/dns/migrations/20260501210107_initial/schema_snapshot.nbt +36 -0
  111. package/vendor/linux-x64/cartridges/dns/schema.nbt +68 -0
  112. package/vendor/linux-x64/cartridges/email/migrations/20260427235207_initial/migration.nbt +75 -0
  113. package/vendor/linux-x64/cartridges/email/migrations/20260427235207_initial/schema_snapshot.nbt +87 -0
  114. package/vendor/linux-x64/cartridges/email/schema.nbt +145 -0
  115. package/vendor/linux-x64/cartridges/ingest/migrations/20260424144652_initial/migration.nbt +18 -0
  116. package/vendor/linux-x64/cartridges/ingest/migrations/20260424144652_initial/schema_snapshot.nbt +20 -0
  117. package/vendor/linux-x64/cartridges/ingest/migrations/20260429203747_schema_update/migration.nbt +3 -0
  118. package/vendor/linux-x64/cartridges/ingest/migrations/20260429203747_schema_update/schema_snapshot.nbt +21 -0
  119. package/vendor/linux-x64/cartridges/ingest/schema.nbt +37 -0
  120. package/vendor/linux-x64/cartridges/notifications/migrations/20260430204408_initial/migration.nbt +42 -0
  121. package/vendor/linux-x64/cartridges/notifications/migrations/20260430204408_initial/schema_snapshot.nbt +46 -0
  122. package/vendor/linux-x64/cartridges/notifications/schema.nbt +67 -0
  123. package/vendor/linux-x64/cartridges/phone/migrations/20260605205722_initial/migration.nbt +50 -0
  124. package/vendor/linux-x64/cartridges/phone/migrations/20260605205722_initial/schema_snapshot.nbt +56 -0
  125. package/vendor/linux-x64/cartridges/phone/schema.nbt +95 -0
  126. package/vendor/linux-x64/cartridges/registry/migrations/20260602181932_initial/migration.nbt +8 -0
  127. package/vendor/linux-x64/cartridges/registry/migrations/20260602181932_initial/schema_snapshot.nbt +8 -0
  128. package/vendor/linux-x64/cartridges/registry/schema.nbt +20 -0
  129. package/vendor/linux-x64/cartridges/workflows/schema.nbt +44 -0
  130. package/vendor/linux-x64/console +0 -0
  131. package/vendor/linux-x64/nbt +0 -0
  132. package/contracts/audit/.dist/contract.json +0 -56
  133. package/contracts/auth/.dist/contract.json +0 -252
  134. package/contracts/calendar/.dist/contract.json +0 -141
  135. package/contracts/chat/.dist/contract.json +0 -229
  136. package/contracts/crm/.dist/contract.json +0 -239
  137. package/contracts/design/.dist/contract.json +0 -85
  138. package/contracts/dns/.dist/contract.json +0 -123
  139. package/contracts/email/.dist/contract.json +0 -267
  140. package/contracts/embed/.dist/contract.json +0 -137
  141. package/contracts/ingest/.dist/contract.json +0 -86
  142. package/contracts/notifications/.dist/contract.json +0 -133
  143. package/contracts/phone/.dist/contract.json +0 -168
  144. package/contracts/registry/.dist/contract.json +0 -49
  145. package/contracts/workflows/.dist/contract.json +0 -106
@@ -0,0 +1,87 @@
1
+ entity MailDomain {
2
+ hostname: string
3
+ isDefault: bool
4
+ domainId: string
5
+ sendgridParseId: string
6
+ sendgridDomainAuthId: string
7
+ verificationToken: string
8
+ verificationState: string
9
+ dkimState: string
10
+ spfState: string
11
+ createdAt: u64
12
+ verifiedAt: u64
13
+ @@unique([hostname])
14
+ }
15
+
16
+ entity Inbox {
17
+ name: string
18
+ ownerType: string
19
+ ownerRef: string
20
+ createdAt: u64
21
+ @@index([ownerType, ownerRef])
22
+ }
23
+
24
+ entity MailAddress {
25
+ mailDomainId: string
26
+ localPart: string
27
+ inboxId: string
28
+ enabled: bool
29
+ @@unique([mailDomainId, localPart])
30
+ @@index([mailDomainId])
31
+ @@index([inboxId])
32
+ }
33
+
34
+ entity Email {
35
+ inboxId: string
36
+ direction: string
37
+ messageId: string
38
+ sendgridMessageId: string
39
+ inReplyTo: string
40
+ referencesJson: string
41
+ fromAddr: string
42
+ fromName: string
43
+ toAddrsJson: string
44
+ ccAddrsJson: string
45
+ bccAddrsJson: string
46
+ subject: string
47
+ textBody: string
48
+ htmlBody: string
49
+ headersRaw: string
50
+ spamScore: string
51
+ receivedAt: u64
52
+ sentAt: u64
53
+ status: string
54
+ @@index([inboxId, receivedAt])
55
+ @@index([sendgridMessageId])
56
+ @@index([messageId])
57
+ }
58
+
59
+ entity EmailAttachment {
60
+ emailId: string
61
+ filename: string
62
+ contentType: string
63
+ sizeBytes: u64
64
+ contentB64: string
65
+ contentId: string
66
+ @@index([emailId])
67
+ }
68
+
69
+ entity EmailTemplate {
70
+ name: string
71
+ subjectTmpl: string
72
+ textTmpl: string
73
+ htmlTmpl: string
74
+ @@unique([name])
75
+ }
76
+
77
+ entity EmailEvent {
78
+ emailId: string
79
+ sendgridMessageId: string
80
+ type: string
81
+ timestamp: u64
82
+ reason: string
83
+ rawJson: string
84
+ @@index([emailId])
85
+ @@index([sendgridMessageId])
86
+ }
87
+
@@ -0,0 +1,145 @@
1
+ # Email cartridge — transactional send + synthetic inboxes.
2
+ #
3
+ # Provider: SendGrid (modules/sendgrid). Nothing in the user-facing surface
4
+ # mentions SendGrid; the cart is branded "Email".
5
+ #
6
+ # Per-console model:
7
+ # - Every console auto-provisions `<console>.nbt.dev` as the default mail
8
+ # domain on first boot (via MailDomain.ensure_default — hit once after
9
+ # deploy). Users can create inboxes + addresses under it with no DNS
10
+ # work.
11
+ # - Custom domains (acme.com) go through the Domains cart: user connects
12
+ # Cloudflare, runs MailDomain.register → we write MX + DKIM CNAMEs,
13
+ # register with SendGrid Inbound Parse + Domain Authentication, poll
14
+ # until everything is green.
15
+ #
16
+ # Ops prerequisites (one-time, see plans/squishy-puzzling-spindle.md):
17
+ # - SENDGRID_API_KEY in console env.
18
+ # - SENDGRID_EVENT_PUBKEY in console env (base64 SPKI for event webhook verification).
19
+ # - `*.nbt.dev MX 10 mx.sendgrid.net` at zone level.
20
+ # - SendGrid Inbound Parse wildcard entry + per-console entries (latter are
21
+ # created programmatically by MailDomain.ensure_default).
22
+
23
+ # Behavior (the former main.nbt actions) lives in native/runtime.jai over the
24
+ # generated ORM — see email_register_extra_routes. These imports trigger the
25
+ # #load of the native files into the cart module scope.
26
+ import crypto from "crypto"
27
+
28
+ # Auth policy for the hand-written routes (formerly @public actions). The
29
+ # handlers live in native/runtime.jai; these keep the daemon's public-route
30
+ # manifest correct so the /api/* auth gate is bypassed for SendGrid webhooks.
31
+ @public_route "/api/email/inbound"
32
+ @public_route "/api/email/events"
33
+
34
+ entity MailDomain {
35
+ id: ulid
36
+ createdAt: DateTime @default(now())
37
+ updatedAt: DateTime @updatedAt
38
+ hostname: string # "acme.nbt.dev" or "acme.com"
39
+ isDefault: bool # true for built-in <console>.nbt.dev
40
+ domainId: string # FK domains cart Domain (empty for default)
41
+ sendgridParseId: string # returned by sendgrid_create_inbound_parse (string id, may be hostname)
42
+ sendgridDomainAuthId: string # returned by sendgrid_create_domain_auth (numeric id as string)
43
+ verificationToken: string # TXT verify token (custom domains only)
44
+ verificationState: string # "pending" | "verified" | "failed"
45
+ dkimState: string # "pending" | "published" | "verified" | "failed"
46
+ spfState: string
47
+ verifiedAt: u64
48
+
49
+ @@unique([hostname])
50
+ }
51
+
52
+ entity Inbox {
53
+ id: ulid
54
+ createdAt: DateTime @default(now())
55
+ updatedAt: DateTime @updatedAt
56
+ name: string
57
+ ownerType: string # "user" | "project" | "system"
58
+ ownerRef: string # id in the owning scope (empty for system)
59
+
60
+ @@index([ownerType, ownerRef])
61
+ }
62
+
63
+ entity MailAddress {
64
+ id: ulid
65
+ createdAt: DateTime @default(now())
66
+ updatedAt: DateTime @updatedAt
67
+ mailDomainId: string
68
+ localPart: string # "sales" or "*" for catch-all
69
+ inboxId: string
70
+ enabled: bool
71
+
72
+ @@unique([mailDomainId, localPart])
73
+ @@index([mailDomainId])
74
+ @@index([inboxId])
75
+ }
76
+
77
+ entity Email {
78
+ id: ulid
79
+ createdAt: DateTime @default(now())
80
+ updatedAt: DateTime @updatedAt
81
+ inboxId: string
82
+ direction: string # "inbound" | "outbound"
83
+ messageId: string # RFC 5322 Message-ID (outbound: we generate; inbound: from headers)
84
+ sendgridMessageId: string # SendGrid's X-Message-Id (outbound) or sg_message_id (inbound/event)
85
+ inReplyTo: string
86
+ referencesJson: string # JSON array of Message-IDs
87
+ fromAddr: string
88
+ fromName: string
89
+ toAddrsJson: string # JSON array
90
+ ccAddrsJson: string
91
+ bccAddrsJson: string
92
+ subject: string
93
+ textBody: string
94
+ htmlBody: string
95
+ headersRaw: string # full headers blob for inbound (empty for outbound)
96
+ spamScore: string # as returned by SendGrid, "" if not scored
97
+ receivedAt: u64
98
+ sentAt: u64
99
+ status: string # inbound: "received" | outbound: "queued" | "sent" | "delivered" | "bounced" | "dropped"
100
+
101
+ @@index([inboxId, receivedAt])
102
+ @@index([sendgridMessageId])
103
+ @@index([messageId])
104
+ }
105
+
106
+ entity EmailAttachment {
107
+ id: ulid
108
+ createdAt: DateTime @default(now())
109
+ updatedAt: DateTime @updatedAt
110
+ emailId: string
111
+ filename: string
112
+ contentType: string
113
+ sizeBytes: u64
114
+ contentB64: string # base64-encoded file bytes — simple for Phase 1; replace with docstore/blob ref later
115
+ contentId: string # for inline images
116
+
117
+ @@index([emailId])
118
+ }
119
+
120
+ entity EmailTemplate {
121
+ id: ulid
122
+ createdAt: DateTime @default(now())
123
+ updatedAt: DateTime @updatedAt
124
+ name: string
125
+ subjectTmpl: string
126
+ textTmpl: string
127
+ htmlTmpl: string
128
+
129
+ @@unique([name])
130
+ }
131
+
132
+ entity EmailEvent {
133
+ id: ulid
134
+ createdAt: DateTime @default(now())
135
+ updatedAt: DateTime @updatedAt
136
+ emailId: string
137
+ sendgridMessageId: string
138
+ type: string # delivered | bounced | opened | clicked | dropped | deferred | spamreport | unsubscribe | processed
139
+ timestamp: u64 # seconds since epoch (as SendGrid emits)
140
+ reason: string
141
+ rawJson: string # entire event JSON slice for debugging
142
+
143
+ @@index([emailId])
144
+ @@index([sendgridMessageId])
145
+ }
@@ -0,0 +1,18 @@
1
+ migration initial {
2
+ add_entity Endpoint
3
+ add_field Endpoint name string default("")
4
+ add_field Endpoint slug string default("")
5
+ add_field Endpoint status string default("")
6
+ add_field Endpoint secret string default("")
7
+ add_field Endpoint payloadCount u64 default(0)
8
+ add_field Endpoint errorCount u64 default(0)
9
+ add_unique Endpoint [slug]
10
+ add_entity Payload
11
+ add_field Payload endpointId string default("")
12
+ add_field Payload headers string default("")
13
+ add_field Payload body document default(0)
14
+ add_field Payload status string default("")
15
+ add_field Payload sourceIp string default("")
16
+ add_field Payload errorMessage string default("")
17
+ add_index Payload [endpointId]
18
+ }
@@ -0,0 +1,20 @@
1
+ entity Endpoint {
2
+ name: string
3
+ slug: string
4
+ status: string
5
+ secret: string
6
+ payloadCount: u64
7
+ errorCount: u64
8
+ @@unique([slug])
9
+ }
10
+
11
+ entity Payload {
12
+ endpointId: string
13
+ headers: string
14
+ body: document
15
+ status: string
16
+ sourceIp: string
17
+ errorMessage: string
18
+ @@index([endpointId])
19
+ }
20
+
@@ -0,0 +1,3 @@
1
+ migration schema_update {
2
+ add_field Endpoint systemId string default("")
3
+ }
@@ -0,0 +1,21 @@
1
+ entity Endpoint {
2
+ name: string
3
+ slug: string
4
+ status: string
5
+ secret: string
6
+ payloadCount: u64
7
+ errorCount: u64
8
+ systemId?: string
9
+ @@unique([slug])
10
+ }
11
+
12
+ entity Payload {
13
+ endpointId: string
14
+ headers: string
15
+ body: document
16
+ status: string
17
+ sourceIp: string
18
+ errorMessage: string
19
+ @@index([endpointId])
20
+ }
21
+
@@ -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,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
+