@intelligo-dev/core 1.0.0-beta.1 → 1.0.0-beta.13

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 (355) hide show
  1. package/NOTICE +6 -0
  2. package/README.md +102 -0
  3. package/dist/attachments/errors.d.ts +7 -0
  4. package/dist/attachments/errors.d.ts.map +1 -0
  5. package/dist/attachments/errors.js +11 -0
  6. package/dist/attachments/errors.js.map +1 -0
  7. package/dist/attachments/index.d.ts +8 -0
  8. package/dist/attachments/index.d.ts.map +1 -0
  9. package/dist/attachments/index.js +7 -0
  10. package/dist/attachments/index.js.map +1 -0
  11. package/dist/attachments/service.d.ts +45 -0
  12. package/dist/attachments/service.d.ts.map +1 -0
  13. package/dist/attachments/service.js +100 -0
  14. package/dist/attachments/service.js.map +1 -0
  15. package/dist/attachments/types.d.ts +6 -0
  16. package/dist/attachments/types.d.ts.map +1 -0
  17. package/dist/attachments/types.js +2 -0
  18. package/dist/attachments/types.js.map +1 -0
  19. package/dist/conversations/errors.d.ts +2 -8
  20. package/dist/conversations/errors.d.ts.map +1 -1
  21. package/dist/conversations/errors.js +2 -8
  22. package/dist/conversations/errors.js.map +1 -1
  23. package/dist/conversations/index.d.ts +4 -12
  24. package/dist/conversations/index.d.ts.map +1 -1
  25. package/dist/conversations/index.js +2 -11
  26. package/dist/conversations/index.js.map +1 -1
  27. package/dist/conversations/service.d.ts +49 -61
  28. package/dist/conversations/service.d.ts.map +1 -1
  29. package/dist/conversations/service.js +110 -83
  30. package/dist/conversations/service.js.map +1 -1
  31. package/dist/conversations/types.d.ts +1 -4
  32. package/dist/conversations/types.d.ts.map +1 -1
  33. package/dist/conversations/types.js +0 -3
  34. package/dist/conversations/types.js.map +1 -1
  35. package/dist/db/client.d.ts +21 -10
  36. package/dist/db/client.d.ts.map +1 -1
  37. package/dist/db/client.js +43 -18
  38. package/dist/db/client.js.map +1 -1
  39. package/dist/db/index.d.ts +3 -3
  40. package/dist/db/index.d.ts.map +1 -1
  41. package/dist/db/index.js +3 -7
  42. package/dist/db/index.js.map +1 -1
  43. package/dist/db/schema/agents.d.ts +14 -51
  44. package/dist/db/schema/agents.d.ts.map +1 -1
  45. package/dist/db/schema/agents.js +9 -21
  46. package/dist/db/schema/agents.js.map +1 -1
  47. package/dist/db/schema/ai.d.ts +86 -1556
  48. package/dist/db/schema/ai.d.ts.map +1 -1
  49. package/dist/db/schema/ai.js +32 -236
  50. package/dist/db/schema/ai.js.map +1 -1
  51. package/dist/db/schema/auth.d.ts +5 -34
  52. package/dist/db/schema/auth.d.ts.map +1 -1
  53. package/dist/db/schema/auth.js +25 -56
  54. package/dist/db/schema/auth.js.map +1 -1
  55. package/dist/db/schema/billing.d.ts +136 -107
  56. package/dist/db/schema/billing.d.ts.map +1 -1
  57. package/dist/db/schema/billing.js +72 -60
  58. package/dist/db/schema/billing.js.map +1 -1
  59. package/dist/db/schema/feature-flags.d.ts +3 -12
  60. package/dist/db/schema/feature-flags.d.ts.map +1 -1
  61. package/dist/db/schema/feature-flags.js +3 -12
  62. package/dist/db/schema/feature-flags.js.map +1 -1
  63. package/dist/db/schema/identity.d.ts +12 -274
  64. package/dist/db/schema/identity.d.ts.map +1 -1
  65. package/dist/db/schema/identity.js +19 -104
  66. package/dist/db/schema/identity.js.map +1 -1
  67. package/dist/db/schema/index.d.ts +8 -15
  68. package/dist/db/schema/index.d.ts.map +1 -1
  69. package/dist/db/schema/index.js +12 -42
  70. package/dist/db/schema/index.js.map +1 -1
  71. package/dist/db/schema/notifications.d.ts +3 -17
  72. package/dist/db/schema/notifications.d.ts.map +1 -1
  73. package/dist/db/schema/notifications.js +3 -17
  74. package/dist/db/schema/notifications.js.map +1 -1
  75. package/dist/db/schema/usage.d.ts +94 -77
  76. package/dist/db/schema/usage.d.ts.map +1 -1
  77. package/dist/db/schema/usage.js +59 -89
  78. package/dist/db/schema/usage.js.map +1 -1
  79. package/dist/db/validate.d.ts +2 -11
  80. package/dist/db/validate.d.ts.map +1 -1
  81. package/dist/db/validate.js +6 -17
  82. package/dist/db/validate.js.map +1 -1
  83. package/dist/db/workspace-queries.d.ts +5 -29
  84. package/dist/db/workspace-queries.d.ts.map +1 -1
  85. package/dist/db/workspace-queries.js +5 -29
  86. package/dist/db/workspace-queries.js.map +1 -1
  87. package/dist/documents/classifier.d.ts +5 -12
  88. package/dist/documents/classifier.d.ts.map +1 -1
  89. package/dist/documents/classifier.js +16 -16
  90. package/dist/documents/classifier.js.map +1 -1
  91. package/dist/documents/errors.d.ts +2 -10
  92. package/dist/documents/errors.d.ts.map +1 -1
  93. package/dist/documents/errors.js +2 -10
  94. package/dist/documents/errors.js.map +1 -1
  95. package/dist/documents/index.d.ts +4 -13
  96. package/dist/documents/index.d.ts.map +1 -1
  97. package/dist/documents/index.js +3 -12
  98. package/dist/documents/index.js.map +1 -1
  99. package/dist/documents/service.d.ts +19 -26
  100. package/dist/documents/service.d.ts.map +1 -1
  101. package/dist/documents/service.js +44 -38
  102. package/dist/documents/service.js.map +1 -1
  103. package/dist/documents/types.d.ts +6 -10
  104. package/dist/documents/types.d.ts.map +1 -1
  105. package/dist/documents/types.js +0 -3
  106. package/dist/documents/types.js.map +1 -1
  107. package/dist/email/brand.d.ts +17 -0
  108. package/dist/email/brand.d.ts.map +1 -0
  109. package/dist/email/brand.js +9 -0
  110. package/dist/email/brand.js.map +1 -0
  111. package/dist/email/index.d.ts +4 -4
  112. package/dist/email/index.js +4 -4
  113. package/dist/email/provider.d.ts +1 -7
  114. package/dist/email/provider.d.ts.map +1 -1
  115. package/dist/email/provider.js +10 -19
  116. package/dist/email/provider.js.map +1 -1
  117. package/dist/email/send.d.ts +12 -12
  118. package/dist/email/send.d.ts.map +1 -1
  119. package/dist/email/send.js +5 -19
  120. package/dist/email/send.js.map +1 -1
  121. package/dist/email/senders.d.ts +17 -30
  122. package/dist/email/senders.d.ts.map +1 -1
  123. package/dist/email/senders.js +33 -47
  124. package/dist/email/senders.js.map +1 -1
  125. package/dist/email/templates/base-layout.d.ts +1 -1
  126. package/dist/email/templates/base-layout.d.ts.map +1 -1
  127. package/dist/email/templates/base-layout.js +4 -6
  128. package/dist/email/templates/base-layout.js.map +1 -1
  129. package/dist/email/templates/index.d.ts +10 -10
  130. package/dist/email/templates/index.d.ts.map +1 -1
  131. package/dist/email/templates/index.js +10 -16
  132. package/dist/email/templates/index.js.map +1 -1
  133. package/dist/email/templates/password-reset.d.ts +2 -2
  134. package/dist/email/templates/password-reset.d.ts.map +1 -1
  135. package/dist/email/templates/password-reset.js +10 -22
  136. package/dist/email/templates/password-reset.js.map +1 -1
  137. package/dist/email/templates/payment-failed.d.ts +2 -2
  138. package/dist/email/templates/payment-failed.d.ts.map +1 -1
  139. package/dist/email/templates/payment-failed.js +11 -24
  140. package/dist/email/templates/payment-failed.js.map +1 -1
  141. package/dist/email/templates/quota-warning.d.ts +4 -4
  142. package/dist/email/templates/quota-warning.d.ts.map +1 -1
  143. package/dist/email/templates/quota-warning.js +19 -39
  144. package/dist/email/templates/quota-warning.js.map +1 -1
  145. package/dist/email/templates/subscription-confirmed.d.ts +2 -2
  146. package/dist/email/templates/subscription-confirmed.d.ts.map +1 -1
  147. package/dist/email/templates/subscription-confirmed.js +13 -28
  148. package/dist/email/templates/subscription-confirmed.js.map +1 -1
  149. package/dist/email/templates/trial-expiry.d.ts +2 -2
  150. package/dist/email/templates/trial-expiry.d.ts.map +1 -1
  151. package/dist/email/templates/trial-expiry.js +12 -36
  152. package/dist/email/templates/trial-expiry.js.map +1 -1
  153. package/dist/email/templates/trial-warning.d.ts +2 -2
  154. package/dist/email/templates/trial-warning.d.ts.map +1 -1
  155. package/dist/email/templates/trial-warning.js +15 -32
  156. package/dist/email/templates/trial-warning.js.map +1 -1
  157. package/dist/email/templates/verify-email.d.ts +2 -2
  158. package/dist/email/templates/verify-email.d.ts.map +1 -1
  159. package/dist/email/templates/verify-email.js +10 -22
  160. package/dist/email/templates/verify-email.js.map +1 -1
  161. package/dist/email/templates/welcome.d.ts +2 -2
  162. package/dist/email/templates/welcome.d.ts.map +1 -1
  163. package/dist/email/templates/welcome.js +13 -20
  164. package/dist/email/templates/welcome.js.map +1 -1
  165. package/dist/email/templates/workspace-invitation.d.ts +2 -2
  166. package/dist/email/templates/workspace-invitation.d.ts.map +1 -1
  167. package/dist/email/templates/workspace-invitation.js +12 -26
  168. package/dist/email/templates/workspace-invitation.js.map +1 -1
  169. package/dist/env.d.ts +5 -10
  170. package/dist/env.d.ts.map +1 -1
  171. package/dist/env.js +41 -31
  172. package/dist/env.js.map +1 -1
  173. package/dist/identity/audit.d.ts +11 -24
  174. package/dist/identity/audit.d.ts.map +1 -1
  175. package/dist/identity/audit.js +13 -27
  176. package/dist/identity/audit.js.map +1 -1
  177. package/dist/identity/errors.d.ts +4 -12
  178. package/dist/identity/errors.d.ts.map +1 -1
  179. package/dist/identity/errors.js +2 -8
  180. package/dist/identity/errors.js.map +1 -1
  181. package/dist/identity/index.d.ts +5 -13
  182. package/dist/identity/index.d.ts.map +1 -1
  183. package/dist/identity/index.js +4 -12
  184. package/dist/identity/index.js.map +1 -1
  185. package/dist/identity/service.d.ts +13 -47
  186. package/dist/identity/service.d.ts.map +1 -1
  187. package/dist/identity/service.js +31 -78
  188. package/dist/identity/service.js.map +1 -1
  189. package/dist/identity/types.d.ts +1 -4
  190. package/dist/identity/types.d.ts.map +1 -1
  191. package/dist/identity/types.js +0 -3
  192. package/dist/identity/types.js.map +1 -1
  193. package/dist/index.d.ts +1 -2
  194. package/dist/index.d.ts.map +1 -1
  195. package/dist/index.js +3 -10
  196. package/dist/index.js.map +1 -1
  197. package/dist/logger.d.ts +7 -18
  198. package/dist/logger.d.ts.map +1 -1
  199. package/dist/logger.js +45 -49
  200. package/dist/logger.js.map +1 -1
  201. package/dist/money.d.ts +95 -0
  202. package/dist/money.d.ts.map +1 -0
  203. package/dist/money.js +208 -0
  204. package/dist/money.js.map +1 -0
  205. package/dist/notifications/index.d.ts +9 -43
  206. package/dist/notifications/index.d.ts.map +1 -1
  207. package/dist/notifications/index.js +9 -49
  208. package/dist/notifications/index.js.map +1 -1
  209. package/dist/notifications/triggers.d.ts +9 -32
  210. package/dist/notifications/triggers.d.ts.map +1 -1
  211. package/dist/notifications/triggers.js +21 -58
  212. package/dist/notifications/triggers.js.map +1 -1
  213. package/dist/notifications/types.d.ts +1 -10
  214. package/dist/notifications/types.d.ts.map +1 -1
  215. package/dist/notifications/types.js +0 -9
  216. package/dist/notifications/types.js.map +1 -1
  217. package/dist/prompt.d.ts +38 -0
  218. package/dist/prompt.d.ts.map +1 -0
  219. package/dist/prompt.js +118 -0
  220. package/dist/prompt.js.map +1 -0
  221. package/dist/registry.d.ts +32 -0
  222. package/dist/registry.d.ts.map +1 -0
  223. package/dist/registry.js +60 -0
  224. package/dist/registry.js.map +1 -0
  225. package/dist/request-context.d.ts +49 -0
  226. package/dist/request-context.d.ts.map +1 -0
  227. package/dist/request-context.js +100 -0
  228. package/dist/request-context.js.map +1 -0
  229. package/dist/storage/index.d.ts +65 -0
  230. package/dist/storage/index.d.ts.map +1 -0
  231. package/dist/storage/index.js +109 -0
  232. package/dist/storage/index.js.map +1 -0
  233. package/package.json +74 -24
  234. package/src/attachments/errors.ts +18 -0
  235. package/src/attachments/index.ts +22 -0
  236. package/src/attachments/service.ts +178 -0
  237. package/src/attachments/types.ts +6 -0
  238. package/src/conversations/errors.ts +45 -0
  239. package/src/conversations/index.ts +39 -0
  240. package/src/conversations/service.ts +594 -0
  241. package/src/conversations/types.ts +15 -0
  242. package/src/db/client.ts +91 -0
  243. package/src/db/index.ts +3 -0
  244. package/src/db/migrations/0000_baseline.sql +652 -0
  245. package/src/db/migrations/0001_reconcile_chain_built_databases.sql +53 -0
  246. package/src/db/migrations/0002_webhook_claim_lease.sql +1 -0
  247. package/src/db/migrations/README.md +74 -36
  248. package/src/db/migrations/legacy-chain.json +197 -0
  249. package/src/db/migrations/meta/0000_snapshot.json +4182 -157
  250. package/src/db/migrations/meta/0002_snapshot.json +2478 -368
  251. package/src/db/migrations/meta/_journal.json +6 -279
  252. package/src/db/schema/agents.ts +57 -0
  253. package/src/db/schema/ai.ts +174 -0
  254. package/src/db/schema/auth.ts +183 -0
  255. package/src/db/schema/billing.ts +209 -0
  256. package/src/db/schema/feature-flags.ts +20 -0
  257. package/src/db/schema/identity.ts +250 -0
  258. package/src/db/schema/index.ts +12 -0
  259. package/src/db/schema/notifications.ts +31 -0
  260. package/src/db/schema/usage.ts +269 -0
  261. package/src/db/validate.ts +63 -0
  262. package/src/db/workspace-queries.ts +64 -0
  263. package/src/documents/classifier.ts +61 -0
  264. package/src/documents/errors.ts +44 -0
  265. package/src/documents/index.ts +24 -0
  266. package/src/documents/service.ts +256 -0
  267. package/src/documents/types.ts +24 -0
  268. package/src/email/brand.ts +24 -0
  269. package/src/email/index.ts +19 -0
  270. package/src/email/provider.ts +278 -0
  271. package/src/email/send.ts +169 -0
  272. package/src/email/senders.ts +292 -0
  273. package/src/email/templates/base-layout.tsx +145 -0
  274. package/src/email/templates/index.ts +28 -0
  275. package/src/email/templates/password-reset.tsx +72 -0
  276. package/src/email/templates/payment-failed.tsx +77 -0
  277. package/src/email/templates/quota-warning.tsx +118 -0
  278. package/src/email/templates/subscription-confirmed.tsx +91 -0
  279. package/src/email/templates/trial-expiry.tsx +124 -0
  280. package/src/email/templates/trial-warning.tsx +104 -0
  281. package/src/email/templates/verify-email.tsx +72 -0
  282. package/src/email/templates/welcome.tsx +64 -0
  283. package/src/email/templates/workspace-invitation.tsx +105 -0
  284. package/src/env.ts +180 -0
  285. package/src/identity/audit.ts +65 -0
  286. package/src/identity/errors.ts +44 -0
  287. package/src/identity/index.ts +26 -0
  288. package/src/identity/service.ts +202 -0
  289. package/src/identity/types.ts +28 -0
  290. package/src/index.ts +4 -0
  291. package/src/logger.ts +198 -0
  292. package/src/money.ts +270 -0
  293. package/src/notifications/index.ts +108 -0
  294. package/src/notifications/triggers.ts +158 -0
  295. package/src/notifications/types.ts +18 -0
  296. package/src/prompt.ts +142 -0
  297. package/src/registry.ts +75 -0
  298. package/src/request-context.ts +137 -0
  299. package/src/storage/index.ts +153 -0
  300. package/dist/db/schema/rag.d.ts +0 -171
  301. package/dist/db/schema/rag.d.ts.map +0 -1
  302. package/dist/db/schema/rag.js +0 -42
  303. package/dist/db/schema/rag.js.map +0 -1
  304. package/src/db/migrations/0000_sharp_night_nurse.sql +0 -52
  305. package/src/db/migrations/0001_hesitant_vapor.sql +0 -40
  306. package/src/db/migrations/0002_numerous_lady_vermin.sql +0 -235
  307. package/src/db/migrations/0003_mighty_jean_grey.sql +0 -37
  308. package/src/db/migrations/0004_cynical_grandmaster.sql +0 -2
  309. package/src/db/migrations/0005_careful_switch.sql +0 -8
  310. package/src/db/migrations/0006_tense_blue_marvel.sql +0 -16
  311. package/src/db/migrations/0007_next_squadron_sinister.sql +0 -1
  312. package/src/db/migrations/0008_powerful_scream.sql +0 -39
  313. package/src/db/migrations/0009_sad_ink.sql +0 -1
  314. package/src/db/migrations/0010_shocking_omega_flight.sql +0 -2
  315. package/src/db/migrations/0011_ambiguous_otto_octavius.sql +0 -151
  316. package/src/db/migrations/0011_hnsw_vector_index.sql +0 -17
  317. package/src/db/migrations/0012_user_profiles.sql +0 -30
  318. package/src/db/migrations/0013_trending_seasonal_columns.sql +0 -9
  319. package/src/db/migrations/0014_add_product_type_to_agents.sql +0 -6
  320. package/src/db/migrations/0015_new_v1_tables.sql +0 -149
  321. package/src/db/migrations/0016_document_types.sql +0 -30
  322. package/src/db/migrations/0017_document_metadata.sql +0 -2
  323. package/src/db/migrations/0018_identity_graph.sql +0 -200
  324. package/src/db/migrations/0019_db_driven_prompts.sql +0 -20
  325. package/src/db/migrations/0020_pending_extractions.sql +0 -35
  326. package/src/db/migrations/0021_rag_documents.sql +0 -39
  327. package/src/db/migrations/0022_user_quotas_usage_jsonb.sql +0 -70
  328. package/src/db/migrations/0023_user_facts_user_scoped_unique.sql +0 -17
  329. package/src/db/migrations/0024_user_memories_hnsw.sql +0 -23
  330. package/src/db/migrations/0025_audit_trigger_errcode.sql +0 -21
  331. package/src/db/migrations/0026_user_profile_snapshots_composite_pk.sql +0 -17
  332. package/src/db/migrations/0027_billing_settings_mnt_columns.sql +0 -54
  333. package/src/db/migrations/0028_trial_credits_normalized_email.sql +0 -37
  334. package/src/db/migrations/0029_usage_records_conversation_idx.sql +0 -13
  335. package/src/db/migrations/0030_pending_extractions_composite_idx.sql +0 -11
  336. package/src/db/migrations/0031_rag_documents_hnsw.sql +0 -16
  337. package/src/db/migrations/0032_rate_limit_unique_idx.sql +0 -16
  338. package/src/db/migrations/0033_pending_extractions_partial_idx.sql +0 -18
  339. package/src/db/migrations/0034_rate_limit_count.sql +0 -9
  340. package/src/db/migrations/0035_credit_reservations.sql +0 -24
  341. package/src/db/migrations/0036_executions_audit_jobs.sql +0 -96
  342. package/src/db/migrations/0037_rate_limit_minute_bucket.sql +0 -46
  343. package/src/db/migrations/0038_user_quotas_generic_usage.sql +0 -25
  344. package/src/db/migrations/0039_platform_admin_impersonation.sql +0 -27
  345. package/src/db/migrations/0040_ee_audit_chain.sql +0 -23
  346. package/src/db/migrations/meta/0001_snapshot.json +0 -631
  347. package/src/db/migrations/meta/0003_snapshot.json +0 -2488
  348. package/src/db/migrations/meta/0004_snapshot.json +0 -2500
  349. package/src/db/migrations/meta/0005_snapshot.json +0 -2548
  350. package/src/db/migrations/meta/0006_snapshot.json +0 -2650
  351. package/src/db/migrations/meta/0007_snapshot.json +0 -2657
  352. package/src/db/migrations/meta/0008_snapshot.json +0 -2719
  353. package/src/db/migrations/meta/0009_snapshot.json +0 -2726
  354. package/src/db/migrations/meta/0010_snapshot.json +0 -2739
  355. package/src/db/migrations/meta/0011_snapshot.json +0 -3886
@@ -0,0 +1,105 @@
1
+ import { Button, Section, Text } from "@react-email/components";
2
+ import * as React from "react";
3
+ import { BaseLayout } from "./base-layout";
4
+
5
+ export interface WorkspaceInvitationEmailProps {
6
+ inviterName: string;
7
+ workspaceName: string;
8
+ role: string;
9
+ acceptUrl: string;
10
+ declineUrl: string;
11
+ }
12
+
13
+ export function WorkspaceInvitationEmail({
14
+ inviterName,
15
+ workspaceName,
16
+ role,
17
+ acceptUrl,
18
+ declineUrl,
19
+ }: WorkspaceInvitationEmailProps) {
20
+ const text = {
21
+ preview: `${inviterName} invited you to join ${workspaceName}`,
22
+ heading: "You're invited!",
23
+ body: "has invited you to join the workspace",
24
+ as: "as a",
25
+ invitedYou: "",
26
+ acceptButton: "Accept Invitation",
27
+ declineButton: "Decline",
28
+ note: "This invitation expires in 7 days.",
29
+ };
30
+
31
+ return (
32
+ <BaseLayout preview={text.preview}>
33
+ <Text style={headingStyle}>{text.heading}</Text>
34
+ <Text style={bodyTextStyle}>
35
+ <strong>{inviterName}</strong> {text.body}{" "}
36
+ <strong>&lsquo;{workspaceName}&rsquo;</strong> {text.as}{" "}
37
+ <strong>{role}</strong>
38
+ {text.invitedYou ? ` ${text.invitedYou}` : ""}.
39
+ </Text>
40
+ <Section style={buttonGroupStyle}>
41
+ <Button href={acceptUrl} style={acceptButtonStyle}>
42
+ {text.acceptButton}
43
+ </Button>
44
+ <Button href={declineUrl} style={declineButtonStyle}>
45
+ {text.declineButton}
46
+ </Button>
47
+ </Section>
48
+ <Text style={noteStyle}>{text.note}</Text>
49
+ </BaseLayout>
50
+ );
51
+ }
52
+
53
+ const headingStyle: React.CSSProperties = {
54
+ color: "#18181b",
55
+ fontSize: "22px",
56
+ fontWeight: 700,
57
+ lineHeight: "30px",
58
+ margin: "0 0 16px",
59
+ };
60
+
61
+ const bodyTextStyle: React.CSSProperties = {
62
+ color: "#18181b",
63
+ fontSize: "15px",
64
+ lineHeight: "24px",
65
+ margin: "0 0 12px",
66
+ };
67
+
68
+ const buttonGroupStyle: React.CSSProperties = {
69
+ marginTop: "8px",
70
+ };
71
+
72
+ const acceptButtonStyle: React.CSSProperties = {
73
+ backgroundColor: "#7c3aed",
74
+ borderRadius: "6px",
75
+ color: "#ffffff",
76
+ display: "inline-block",
77
+ fontSize: "15px",
78
+ fontWeight: 600,
79
+ lineHeight: "100%",
80
+ padding: "12px 24px",
81
+ textDecoration: "none",
82
+ textAlign: "center" as const,
83
+ marginRight: "12px",
84
+ };
85
+
86
+ const declineButtonStyle: React.CSSProperties = {
87
+ backgroundColor: "transparent",
88
+ border: "1px solid #d4d4d8",
89
+ borderRadius: "6px",
90
+ color: "#71717a",
91
+ display: "inline-block",
92
+ fontSize: "15px",
93
+ fontWeight: 600,
94
+ lineHeight: "100%",
95
+ padding: "12px 24px",
96
+ textDecoration: "none",
97
+ textAlign: "center" as const,
98
+ };
99
+
100
+ const noteStyle: React.CSSProperties = {
101
+ color: "#71717a",
102
+ fontSize: "13px",
103
+ lineHeight: "20px",
104
+ marginTop: "20px",
105
+ };
package/src/env.ts ADDED
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Startup validation of environment variables: a missing required variable
3
+ * throws immediately instead of when its feature is first used. Some are
4
+ * optional in development (STRIPE_*, RESEND_API_KEY).
5
+ */
6
+
7
+ type EnvVar = {
8
+ name: string;
9
+ required: boolean;
10
+ description: string;
11
+ /** Optional minimum length — used for secret strength checks */
12
+ minLength?: number;
13
+ };
14
+
15
+ // Only variables the framework itself reads. A model provider's key is
16
+ // absent on purpose: which provider a deployment calls is the product's
17
+ // choice, and its SDK reports a missing key on the first request.
18
+ const ENV_VARS: EnvVar[] = [
19
+ {
20
+ name: "DATABASE_URL",
21
+ required: true,
22
+ description: "PostgreSQL connection string",
23
+ },
24
+ {
25
+ name: "BETTER_AUTH_SECRET",
26
+ required: true,
27
+ description:
28
+ "Better-Auth session encryption key (AUTH_SECRET is accepted as a legacy alias)",
29
+ minLength: 32,
30
+ },
31
+ {
32
+ name: "NEXT_PUBLIC_APP_URL",
33
+ required: true,
34
+ description: "Application base URL for auth and redirects",
35
+ },
36
+ {
37
+ name: "STRIPE_SECRET_KEY",
38
+ required: false,
39
+ description: "Stripe API key (billing features)",
40
+ },
41
+ {
42
+ name: "STRIPE_WEBHOOK_SECRET",
43
+ required: false,
44
+ description: "Stripe webhook signature secret",
45
+ },
46
+ {
47
+ name: "RESEND_API_KEY",
48
+ required: false,
49
+ description: "Resend API key (email features)",
50
+ },
51
+ {
52
+ name: "LOOPS_API_KEY",
53
+ required: false,
54
+ description:
55
+ "Loops API key (email features; templates mapped via LOOPS_TRANSACTIONAL_ID_*)",
56
+ },
57
+ {
58
+ name: "EMAIL_PROVIDER",
59
+ required: false,
60
+ description: "Explicit email provider selection (resend | loops | console)",
61
+ },
62
+ // Cron endpoints gate on a Bearer header equal to CRON_SECRET. Optional
63
+ // in development; production should set at least 32 characters.
64
+ {
65
+ name: "CRON_SECRET",
66
+ required: false,
67
+ description: "Shared secret for /api/cron/* Bearer auth",
68
+ minLength: 32,
69
+ },
70
+ ];
71
+
72
+ export function validateEnv(): {
73
+ valid: boolean;
74
+ errors: string[];
75
+ warnings: string[];
76
+ } {
77
+ const errors: string[] = [];
78
+ const warnings: string[] = [];
79
+
80
+ for (const envVar of ENV_VARS) {
81
+ let value = process.env[envVar.name];
82
+ // Better-Auth reads BETTER_AUTH_SECRET then AUTH_SECRET; the CLI, the
83
+ // scaffold and this validator use the former.
84
+ if (
85
+ envVar.name === "BETTER_AUTH_SECRET" &&
86
+ !value &&
87
+ process.env.AUTH_SECRET
88
+ ) {
89
+ value = process.env.AUTH_SECRET;
90
+ warnings.push(
91
+ "AUTH_SECRET is set but BETTER_AUTH_SECRET is not — rename it; AUTH_SECRET is a legacy alias"
92
+ );
93
+ }
94
+ if (!value || value.trim() === "") {
95
+ if (envVar.required) {
96
+ errors.push(
97
+ `Missing required env var: ${envVar.name} — ${envVar.description}`
98
+ );
99
+ } else {
100
+ warnings.push(
101
+ `Missing optional env var: ${envVar.name} — ${envVar.description}`
102
+ );
103
+ }
104
+ continue;
105
+ }
106
+ if (envVar.minLength && value.length < envVar.minLength) {
107
+ const msg = `${envVar.name} is shorter than ${envVar.minLength} chars — too weak for ${envVar.description}`;
108
+ if (envVar.required) {
109
+ errors.push(msg);
110
+ } else {
111
+ warnings.push(msg);
112
+ }
113
+ }
114
+ }
115
+
116
+ // Resend rejects a send without a sender on a verified domain, and the
117
+ // framework has no domain of its own to fall back on. Loops takes the
118
+ // sender from each template, so only Resend is checked.
119
+ const emailProvider = process.env.EMAIL_PROVIDER?.toLowerCase();
120
+ const sendsThroughResend =
121
+ Boolean(process.env.RESEND_API_KEY?.trim()) &&
122
+ emailProvider !== "loops" &&
123
+ emailProvider !== "console";
124
+ if (sendsThroughResend && !process.env.EMAIL_FROM?.trim()) {
125
+ warnings.push(
126
+ 'RESEND_API_KEY is set but EMAIL_FROM is not — every email fails until EMAIL_FROM names a sender on a domain verified with Resend, e.g. "Acme <noreply@acme.com>"'
127
+ );
128
+ }
129
+
130
+ // Production safety checks
131
+ if (process.env.NODE_ENV === "production") {
132
+ const appUrl = process.env.NEXT_PUBLIC_APP_URL?.trim();
133
+ if (appUrl && !appUrl.startsWith("https://")) {
134
+ warnings.push(
135
+ `NEXT_PUBLIC_APP_URL is ${appUrl}, not an https URL — auth callbacks, email links and secure cookies are built from it`
136
+ );
137
+ }
138
+ if (!process.env.RESEND_API_KEY && !process.env.LOOPS_API_KEY) {
139
+ warnings.push(
140
+ "No email provider (RESEND_API_KEY or LOOPS_API_KEY) — sign-ups are not email-verified and emails only reach the server console"
141
+ );
142
+ }
143
+ if (process.env.STRIPE_SECRET_KEY?.startsWith("sk_test_")) {
144
+ warnings.push(
145
+ "STRIPE_SECRET_KEY is a test key in production environment"
146
+ );
147
+ }
148
+ if (!process.env.CRON_SECRET || process.env.CRON_SECRET.length < 32) {
149
+ // A warning, not an error: the framework ships no cron route of its
150
+ // own, and the maintenance route refuses to serve without it.
151
+ warnings.push(
152
+ "CRON_SECRET unset or shorter than 32 chars — required by any /api/cron/* route you mount"
153
+ );
154
+ }
155
+ }
156
+
157
+ return { valid: errors.length === 0, errors, warnings };
158
+ }
159
+
160
+ /**
161
+ * Call during app initialization. Throws on missing required variables;
162
+ * logs warnings for optional ones.
163
+ */
164
+ export function assertEnv(): void {
165
+ const { valid, errors, warnings } = validateEnv();
166
+
167
+ for (const warning of warnings) {
168
+ console.warn(`[Env] ${warning}`);
169
+ }
170
+
171
+ if (!valid) {
172
+ console.error("[Env] Missing required environment variables:");
173
+ for (const error of errors) {
174
+ console.error(` - ${error}`);
175
+ }
176
+ throw new Error(
177
+ `Missing ${errors.length} required environment variable(s). See logs above.`
178
+ );
179
+ }
180
+ }
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Writes `user_memory_audit` rows. Core may not import
3
+ * `@intelligo-dev/audit` (only audit -> core is allowed), so the write lives
4
+ * here and audit exports only the event contract. Internal to identity; not
5
+ * re-exported.
6
+ */
7
+
8
+ import { db } from "../db";
9
+ import { userMemoryAudit } from "../db/schema";
10
+ import type {
11
+ AuditTargetKind,
12
+ AuditAction,
13
+ AuditActorKind,
14
+ UserMemoryAuditRow,
15
+ } from "../db/schema";
16
+ import { IdentityServiceError } from "./errors";
17
+
18
+ export type RecordMemoryAuditInput = {
19
+ userId: string;
20
+ workspaceId: string;
21
+ targetKind: AuditTargetKind;
22
+ targetId: string;
23
+ action: AuditAction;
24
+ actorKind: AuditActorKind;
25
+ actorId?: string;
26
+ beforeValue?: unknown;
27
+ afterValue?: unknown;
28
+ reason?: string;
29
+ };
30
+
31
+ /**
32
+ * `writer` is the transaction of the mutation being audited, so the
33
+ * change and its record commit or fail together.
34
+ */
35
+ export async function recordMemoryAudit(
36
+ input: RecordMemoryAuditInput,
37
+ writer: Pick<typeof db, "insert"> = db
38
+ ): Promise<UserMemoryAuditRow> {
39
+ const [row] = await writer
40
+ .insert(userMemoryAudit)
41
+ .values({
42
+ id: crypto.randomUUID(),
43
+ userId: input.userId,
44
+ workspaceId: input.workspaceId,
45
+ targetKind: input.targetKind,
46
+ targetId: input.targetId,
47
+ action: input.action,
48
+ actorKind: input.actorKind,
49
+ actorId: input.actorId,
50
+ beforeValue: input.beforeValue,
51
+ afterValue: input.afterValue,
52
+ reason: input.reason,
53
+ createdAt: new Date(),
54
+ })
55
+ .returning();
56
+
57
+ if (!row) {
58
+ throw new IdentityServiceError(
59
+ "database_error",
60
+ "Failed to record memory audit event"
61
+ );
62
+ }
63
+
64
+ return row;
65
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Thrown by the identity service for every failure it recognizes. Shaping
3
+ * it into a transport envelope is the caller's job.
4
+ */
5
+
6
+ /**
7
+ * - `not_found` — no fact exists at the given id within the actor's
8
+ * workspace/user scope. Covers both "no such fact" and "a fact that
9
+ * belongs to a different user in the same workspace" — deliberately
10
+ * indistinguishable, so an id never reveals whose data exists behind it.
11
+ * - `invalid_input` — a caller-supplied argument failed a basic
12
+ * invariant (e.g. an empty fact id).
13
+ * - `database_error` — the underlying insert did not return the row it
14
+ * was expected to.
15
+ */
16
+ export type IdentityServiceErrorCode =
17
+ "not_found" | "invalid_input" | "database_error";
18
+
19
+ export class IdentityServiceError extends Error {
20
+ readonly code: IdentityServiceErrorCode;
21
+ // The ES2020 target predates `Error.cause`; declared so `err.cause`
22
+ // type-checks for callers.
23
+ readonly cause?: unknown;
24
+
25
+ constructor(
26
+ code: IdentityServiceErrorCode,
27
+ message: string,
28
+ options?: { cause?: unknown }
29
+ ) {
30
+ super(message);
31
+ this.name = "IdentityServiceError";
32
+ this.code = code;
33
+ if (options?.cause !== undefined) {
34
+ (this as { cause?: unknown }).cause = options.cause;
35
+ }
36
+ Object.setPrototypeOf(this, IdentityServiceError.prototype);
37
+ }
38
+ }
39
+
40
+ export function isIdentityServiceError(
41
+ error: unknown
42
+ ): error is IdentityServiceError {
43
+ return error instanceof IdentityServiceError;
44
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Privacy-facing reads and mutations over the user identity graph: fact
3
+ * listing and deletion, full-identity export, and the memory-audit trail.
4
+ */
5
+
6
+ export {
7
+ listFacts,
8
+ deleteFact,
9
+ exportIdentity,
10
+ getAuditTrail,
11
+ } from "./service";
12
+
13
+ export {
14
+ IdentityServiceError,
15
+ isIdentityServiceError,
16
+ type IdentityServiceErrorCode,
17
+ } from "./errors";
18
+
19
+ export type {
20
+ IdentityActor,
21
+ IdentityExport,
22
+ UserFact,
23
+ UserMemory,
24
+ UserProfileSnapshot,
25
+ UserMemoryAuditRow,
26
+ } from "./types";
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Server-only reads and mutations over the user identity graph: fact
3
+ * listing and deletion, a full data export, and the memory-audit trail.
4
+ *
5
+ * `deleteFact` does not touch the cached profile snapshot; profile synthesis
6
+ * is the product's AI code, so a caller that owns it re-triggers it.
7
+ *
8
+ * Callers pass a resolved actor (workspaceId, userId); core cannot depend on
9
+ * `@intelligo-dev/auth`. Every query filters by both ids. Every mutation
10
+ * writes a `user_memory_audit` row. Failures throw `IdentityServiceError`.
11
+ */
12
+
13
+ import { and, desc, eq } from "drizzle-orm";
14
+ import { db } from "../db";
15
+ import {
16
+ userFacts,
17
+ userMemories,
18
+ userProfileSnapshots,
19
+ userMemoryAudit,
20
+ } from "../db/schema";
21
+ import type { UserFact, UserMemoryAuditRow } from "../db/schema";
22
+ import { recordMemoryAudit } from "./audit";
23
+ import { IdentityServiceError } from "./errors";
24
+ import type { IdentityActor, IdentityExport } from "./types";
25
+
26
+ /**
27
+ * Returns the fact if the actor owns it. Throws
28
+ * IdentityServiceError("not_found") otherwise — another user's fact is
29
+ * indistinguishable from a missing one.
30
+ */
31
+ async function verifyFact(
32
+ actor: IdentityActor,
33
+ factId: string
34
+ ): Promise<UserFact> {
35
+ const [fact] = await db
36
+ .select()
37
+ .from(userFacts)
38
+ .where(eq(userFacts.id, factId))
39
+ .limit(1);
40
+
41
+ if (
42
+ !fact ||
43
+ fact.userId !== actor.userId ||
44
+ fact.workspaceId !== actor.workspaceId
45
+ ) {
46
+ throw new IdentityServiceError("not_found", "Fact not found");
47
+ }
48
+
49
+ return fact;
50
+ }
51
+
52
+ /** List the actor's facts, most important and most confident first. */
53
+ export async function listFacts(actor: IdentityActor): Promise<UserFact[]> {
54
+ return db
55
+ .select()
56
+ .from(userFacts)
57
+ .where(
58
+ and(
59
+ eq(userFacts.userId, actor.userId),
60
+ eq(userFacts.workspaceId, actor.workspaceId)
61
+ )
62
+ )
63
+ .orderBy(desc(userFacts.importance), desc(userFacts.confidence));
64
+ }
65
+
66
+ const MAX_AUDIT_LIMIT = 200;
67
+
68
+ /**
69
+ * Read the actor's memory-audit trail, most recent first. Optionally
70
+ * scoped to a single target (e.g. one fact's history).
71
+ */
72
+ export async function getAuditTrail(
73
+ actor: IdentityActor,
74
+ options?: { limit?: number; targetId?: string }
75
+ ): Promise<UserMemoryAuditRow[]> {
76
+ const limit = Math.min(
77
+ Math.max(1, options?.limit ?? MAX_AUDIT_LIMIT),
78
+ MAX_AUDIT_LIMIT
79
+ );
80
+
81
+ const baseClause = and(
82
+ eq(userMemoryAudit.userId, actor.userId),
83
+ eq(userMemoryAudit.workspaceId, actor.workspaceId)
84
+ );
85
+
86
+ return db
87
+ .select()
88
+ .from(userMemoryAudit)
89
+ .where(
90
+ options?.targetId
91
+ ? and(baseClause, eq(userMemoryAudit.targetId, options.targetId))
92
+ : baseClause
93
+ )
94
+ .orderBy(desc(userMemoryAudit.createdAt))
95
+ .limit(limit);
96
+ }
97
+
98
+ /**
99
+ * Delete a fact and record the deletion in the audit trail. Throws
100
+ * `invalid_input` for an empty id and `not_found` for anything outside
101
+ * the actor's scope. Does not re-trigger profile synthesis.
102
+ */
103
+ export async function deleteFact(
104
+ actor: IdentityActor,
105
+ factId: string
106
+ ): Promise<void> {
107
+ if (!factId || factId.trim().length === 0) {
108
+ throw new IdentityServiceError("invalid_input", "factId is required");
109
+ }
110
+
111
+ const existing = await verifyFact(actor, factId);
112
+
113
+ await db.transaction(async (tx) => {
114
+ await tx.delete(userFacts).where(eq(userFacts.id, factId));
115
+ await recordMemoryAudit(
116
+ {
117
+ userId: actor.userId,
118
+ workspaceId: actor.workspaceId,
119
+ targetKind: "fact",
120
+ targetId: factId,
121
+ action: "delete",
122
+ actorKind: "user",
123
+ actorId: actor.userId,
124
+ beforeValue: existing,
125
+ reason: "user requested deletion",
126
+ },
127
+ tx
128
+ );
129
+ });
130
+ }
131
+
132
+ /**
133
+ * The actor's full identity graph — facts, memories, latest profile
134
+ * snapshot and audit trail — for a "download my data" flow. Records its own
135
+ * audit row (action "export").
136
+ */
137
+ export async function exportIdentity(
138
+ actor: IdentityActor
139
+ ): Promise<IdentityExport> {
140
+ // Recorded before the reads so the export's own audit row is part of
141
+ // the export — the trail a user downloads should show that download.
142
+ await recordMemoryAudit({
143
+ userId: actor.userId,
144
+ workspaceId: actor.workspaceId,
145
+ targetKind: "snapshot",
146
+ targetId: actor.userId,
147
+ action: "export",
148
+ actorKind: "user",
149
+ actorId: actor.userId,
150
+ reason: "user requested data export",
151
+ });
152
+
153
+ const [facts, memories, snapshotRows, audit] = await Promise.all([
154
+ db
155
+ .select()
156
+ .from(userFacts)
157
+ .where(
158
+ and(
159
+ eq(userFacts.userId, actor.userId),
160
+ eq(userFacts.workspaceId, actor.workspaceId)
161
+ )
162
+ ),
163
+ db
164
+ .select()
165
+ .from(userMemories)
166
+ .where(
167
+ and(
168
+ eq(userMemories.userId, actor.userId),
169
+ eq(userMemories.workspaceId, actor.workspaceId)
170
+ )
171
+ ),
172
+ db
173
+ .select()
174
+ .from(userProfileSnapshots)
175
+ .where(
176
+ and(
177
+ eq(userProfileSnapshots.userId, actor.userId),
178
+ eq(userProfileSnapshots.workspaceId, actor.workspaceId)
179
+ )
180
+ )
181
+ .limit(1),
182
+ db
183
+ .select()
184
+ .from(userMemoryAudit)
185
+ .where(
186
+ and(
187
+ eq(userMemoryAudit.userId, actor.userId),
188
+ eq(userMemoryAudit.workspaceId, actor.workspaceId)
189
+ )
190
+ )
191
+ .orderBy(desc(userMemoryAudit.createdAt)),
192
+ ]);
193
+
194
+ return {
195
+ exportedAt: new Date().toISOString(),
196
+ user: { id: actor.userId, workspaceId: actor.workspaceId },
197
+ facts,
198
+ memories,
199
+ snapshot: snapshotRows[0] ?? null,
200
+ audit,
201
+ };
202
+ }
@@ -0,0 +1,28 @@
1
+ import type {
2
+ UserFact,
3
+ UserMemory,
4
+ UserProfileSnapshot,
5
+ UserMemoryAuditRow,
6
+ } from "../db/schema";
7
+
8
+ export type { UserFact, UserMemory, UserProfileSnapshot, UserMemoryAuditRow };
9
+
10
+ /** Resolved actor identity — every query is scoped to this pair. */
11
+ export type IdentityActor = {
12
+ workspaceId: string;
13
+ userId: string;
14
+ };
15
+
16
+ /**
17
+ * Full identity dump for a GDPR-style "download my data" flow: every
18
+ * fact and memory the actor owns, their latest synthesized profile
19
+ * snapshot (if one exists), and their complete memory-audit trail.
20
+ */
21
+ export type IdentityExport = {
22
+ exportedAt: string;
23
+ user: { id: string; workspaceId: string };
24
+ facts: UserFact[];
25
+ memories: UserMemory[];
26
+ snapshot: UserProfileSnapshot | null;
27
+ audit: UserMemoryAuditRow[];
28
+ };
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./db";
2
+
3
+ // Everything else is a subpath import: @intelligo-dev/core/email,
4
+ // /notifications, /conversations, /documents, /identity, /logger, /env.