@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,183 @@
1
+ /**
2
+ * Better-Auth's tables. Table and column names must match what its Drizzle
3
+ * adapter expects.
4
+ */
5
+
6
+ import { sql } from "drizzle-orm";
7
+ import {
8
+ pgTable,
9
+ text,
10
+ timestamp,
11
+ boolean,
12
+ index,
13
+ uniqueIndex,
14
+ } from "drizzle-orm/pg-core";
15
+
16
+ export const users = pgTable(
17
+ "users",
18
+ {
19
+ id: text("id").primaryKey(),
20
+ name: text("name").notNull(),
21
+ email: text("email").notNull().unique(),
22
+ emailVerified: boolean("email_verified").notNull().default(false),
23
+ image: text("image"),
24
+ deletedAt: timestamp("deleted_at"), // Soft delete: null = active, timestamp = deleted
25
+ createdAt: timestamp("created_at").notNull().defaultNow(),
26
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
27
+ onboardingCompleted: boolean("onboarding_completed")
28
+ .notNull()
29
+ .default(false),
30
+ onboardingStep: text("onboarding_step"), // Current step if incomplete: "workspace" | "language" | "product"
31
+ preferredLanguage: text("preferred_language").notNull().default("en"), // a locale the app ships, e.g. "en"
32
+ /**
33
+ * Platform role, not a workspace role — "platform-admin" or null. Grants
34
+ * the operational console and impersonation. PLATFORM_ADMIN_EMAILS seeds
35
+ * it: requirePlatformAdmin promotes an allowlisted user on first use.
36
+ */
37
+ role: text("role"),
38
+ /** Required by Better-Auth's admin plugin schema; unused otherwise. */
39
+ banned: boolean("banned").notNull().default(false),
40
+ banReason: text("ban_reason"),
41
+ banExpires: timestamp("ban_expires"),
42
+ },
43
+ (table) => [
44
+ // Finding the platform admins: a handful of rows among many.
45
+ index("users_role_idx")
46
+ .on(table.role)
47
+ .where(sql`${table.role} IS NOT NULL`),
48
+ ]
49
+ );
50
+
51
+ export const sessions = pgTable(
52
+ "sessions",
53
+ {
54
+ id: text("id").primaryKey(),
55
+ userId: text("user_id")
56
+ .notNull()
57
+ .references(() => users.id, { onDelete: "cascade" }),
58
+ token: text("token").notNull().unique(),
59
+ expiresAt: timestamp("expires_at").notNull(),
60
+ ipAddress: text("ip_address"),
61
+ userAgent: text("user_agent"),
62
+ /**
63
+ * Set on a session created by an admin acting as this user, so
64
+ * impersonation stays visible on the session and in the audit trail.
65
+ */
66
+ impersonatedBy: text("impersonated_by"),
67
+ /**
68
+ * The organization plugin's active workspace. Without this column its
69
+ * set-active writes are silently dropped and workspace switching never
70
+ * persists.
71
+ */
72
+ activeOrganizationId: text("active_organization_id"),
73
+ createdAt: timestamp("created_at").notNull().defaultNow(),
74
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
75
+ },
76
+ (table) => [index("sessions_user_id_idx").on(table.userId)]
77
+ );
78
+
79
+ /** OAuth provider connections and password credentials. */
80
+ export const accounts = pgTable(
81
+ "accounts",
82
+ {
83
+ id: text("id").primaryKey(),
84
+ userId: text("user_id")
85
+ .notNull()
86
+ .references(() => users.id, { onDelete: "cascade" }),
87
+ accountId: text("account_id").notNull(),
88
+ providerId: text("provider_id").notNull(),
89
+ accessToken: text("access_token"),
90
+ refreshToken: text("refresh_token"),
91
+ accessTokenExpiresAt: timestamp("access_token_expires_at"),
92
+ refreshTokenExpiresAt: timestamp("refresh_token_expires_at"),
93
+ scope: text("scope"),
94
+ idToken: text("id_token"),
95
+ password: text("password"),
96
+ createdAt: timestamp("created_at").notNull().defaultNow(),
97
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
98
+ },
99
+ (table) => [index("accounts_user_id_idx").on(table.userId)]
100
+ );
101
+
102
+ /** Email verification and password reset tokens. */
103
+ export const verifications = pgTable("verifications", {
104
+ id: text("id").primaryKey(),
105
+ identifier: text("identifier").notNull(),
106
+ value: text("value").notNull(),
107
+ expiresAt: timestamp("expires_at").notNull(),
108
+ createdAt: timestamp("created_at").notNull().defaultNow(),
109
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
110
+ });
111
+
112
+ /** Workspaces, managed by Better-Auth's organization plugin. */
113
+ export const organization = pgTable("organization", {
114
+ id: text("id").primaryKey(),
115
+ name: text("name").notNull(),
116
+ slug: text("slug").unique(),
117
+ logo: text("logo"),
118
+ metadata: text("metadata"),
119
+ createdAt: timestamp("created_at").notNull().defaultNow(),
120
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
121
+ });
122
+
123
+ export const member = pgTable(
124
+ "member",
125
+ {
126
+ id: text("id").primaryKey(),
127
+ organizationId: text("organization_id")
128
+ .notNull()
129
+ .references(() => organization.id, { onDelete: "cascade" }),
130
+ userId: text("user_id")
131
+ .notNull()
132
+ .references(() => users.id, { onDelete: "cascade" }),
133
+ role: text("role").notNull(),
134
+ createdAt: timestamp("created_at").notNull().defaultNow(),
135
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
136
+ },
137
+ (table) => [
138
+ index("member_organization_id_idx").on(table.organizationId),
139
+ index("member_user_id_idx").on(table.userId),
140
+ uniqueIndex("member_organization_user_uniq").on(
141
+ table.organizationId,
142
+ table.userId
143
+ ),
144
+ ]
145
+ );
146
+
147
+ export const invitation = pgTable(
148
+ "invitation",
149
+ {
150
+ id: text("id").primaryKey(),
151
+ organizationId: text("organization_id")
152
+ .notNull()
153
+ .references(() => organization.id, { onDelete: "cascade" }),
154
+ email: text("email").notNull(),
155
+ role: text("role").notNull(),
156
+ status: text("status").notNull(),
157
+ expiresAt: timestamp("expires_at").notNull(),
158
+ inviterId: text("inviter_id").references(() => users.id, {
159
+ onDelete: "set null",
160
+ }),
161
+ createdAt: timestamp("created_at").notNull().defaultNow(),
162
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
163
+ },
164
+ (table) => [
165
+ index("invitation_organization_id_idx").on(table.organizationId),
166
+ index("invitation_email_idx").on(table.email),
167
+ ]
168
+ );
169
+
170
+ export type User = typeof users.$inferSelect;
171
+ export type InsertUser = typeof users.$inferInsert;
172
+ export type Session = typeof sessions.$inferSelect;
173
+ export type InsertSession = typeof sessions.$inferInsert;
174
+ export type Account = typeof accounts.$inferSelect;
175
+ export type InsertAccount = typeof accounts.$inferInsert;
176
+ export type Verification = typeof verifications.$inferSelect;
177
+ export type InsertVerification = typeof verifications.$inferInsert;
178
+ export type Organization = typeof organization.$inferSelect;
179
+ export type InsertOrganization = typeof organization.$inferInsert;
180
+ export type Member = typeof member.$inferSelect;
181
+ export type InsertMember = typeof member.$inferInsert;
182
+ export type Invitation = typeof invitation.$inferSelect;
183
+ export type InsertInvitation = typeof invitation.$inferInsert;
@@ -0,0 +1,209 @@
1
+ /**
2
+ * Plans, subscriptions, credit ledgers, purchases and Stripe events.
3
+ * Amounts in the credit ledgers are micros of their currency.
4
+ */
5
+
6
+ import {
7
+ pgTable,
8
+ text,
9
+ timestamp,
10
+ integer,
11
+ bigint,
12
+ boolean,
13
+ index,
14
+ unique,
15
+ } from "drizzle-orm/pg-core";
16
+ import { organization } from "./auth";
17
+
18
+ /**
19
+ * The registered plan catalogue, copied into rows so a subscription can
20
+ * reference its plan. The catalogue is the source: the rows are written
21
+ * from it at boot, and an edit made here is overwritten by the next one.
22
+ */
23
+ export const plans = pgTable("plans", {
24
+ id: text("id").primaryKey(),
25
+ name: text("name").notNull(),
26
+ slug: text("slug").notNull().unique(),
27
+ description: text("description"),
28
+ /**
29
+ * Whole major units — 29 is twenty-nine of the currency, not cents —
30
+ * rounded from the catalogue's price. 0 for free. The row names no
31
+ * currency; readers take the deployment's billing currency.
32
+ */
33
+ priceMonthly: integer("price_monthly").notNull(),
34
+ /** Whole major units, as `priceMonthly`. 0 when the plan has no yearly price. */
35
+ priceYearly: integer("price_yearly").notNull(),
36
+ stripePriceIdMonthly: text("stripe_price_id_monthly"),
37
+ stripePriceIdYearly: text("stripe_price_id_yearly"),
38
+ features: text("features").notNull(), // JSON string array
39
+ limits: text("limits").notNull(), // JSON string: { tokens, conversations, teamMembers, workspaces, documents }
40
+ isActive: boolean("is_active").notNull().default(true),
41
+ sortOrder: integer("sort_order").notNull().default(0),
42
+ createdAt: timestamp("created_at").notNull().defaultNow(),
43
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
44
+ });
45
+
46
+ /** One subscription per workspace (unique constraint). */
47
+ export const subscriptions = pgTable(
48
+ "subscriptions",
49
+ {
50
+ id: text("id").primaryKey(),
51
+ workspaceId: text("workspace_id")
52
+ .notNull()
53
+ .references(() => organization.id, { onDelete: "cascade" }),
54
+ planId: text("plan_id")
55
+ .notNull()
56
+ .references(() => plans.id, { onDelete: "restrict" }),
57
+ stripeCustomerId: text("stripe_customer_id"),
58
+ stripeSubscriptionId: text("stripe_subscription_id").unique(),
59
+ status: text("status").notNull().default("active"), // active|past_due|canceled|trialing|incomplete
60
+ billingMode: text("billing_mode").notNull().default("subscription"), // subscription|credit
61
+ currentPeriodStart: timestamp("current_period_start"),
62
+ currentPeriodEnd: timestamp("current_period_end"),
63
+ cancelAtPeriodEnd: boolean("cancel_at_period_end").notNull().default(false),
64
+ createdAt: timestamp("created_at").notNull().defaultNow(),
65
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
66
+ },
67
+ (table) => [
68
+ index("subscriptions_workspace_id_idx").on(table.workspaceId),
69
+ unique("subscriptions_workspace_id_unique").on(table.workspaceId),
70
+ ]
71
+ );
72
+
73
+ /** One credit balance per workspace (unique constraint). */
74
+ export const creditBalances = pgTable("credit_balances", {
75
+ id: text("id").primaryKey(),
76
+ workspaceId: text("workspace_id")
77
+ .notNull()
78
+ .unique()
79
+ .references(() => organization.id, { onDelete: "cascade" }),
80
+ /** The balance, in micros of `currency`. */
81
+ balanceMicros: bigint("balance_micros", { mode: "number" })
82
+ .notNull()
83
+ .default(0),
84
+ totalPurchasedMicros: bigint("total_purchased_micros", { mode: "number" })
85
+ .notNull()
86
+ .default(0),
87
+ totalUsedMicros: bigint("total_used_micros", { mode: "number" })
88
+ .notNull()
89
+ .default(0),
90
+ /** What this ledger is denominated in; a write in another is refused. */
91
+ currency: text("currency").notNull().default("USD"),
92
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
93
+ });
94
+
95
+ /**
96
+ * Singleton (id = "default") holding the FX rate and margin, so they change
97
+ * without a deploy. Read per request, cached 60s in-process.
98
+ */
99
+ export const billingSettings = pgTable("billing_settings", {
100
+ id: text("id").primaryKey(),
101
+ /** The deployment's billing currency — every ledger row is in this. */
102
+ currency: text("currency").notNull().default("USD"),
103
+ /** What one USD costs in it, in micros: 1_000_000 is a USD deployment. */
104
+ usdRateMicros: bigint("usd_rate_micros", { mode: "number" })
105
+ .notNull()
106
+ .default(1_000_000),
107
+ /** Margin over provider cost, in basis points of a multiplier: 40_000 = 4×. */
108
+ marginBp: integer("margin_bp").notNull().default(40_000),
109
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
110
+ });
111
+
112
+ /** One-time credit purchases. */
113
+ export const creditPurchases = pgTable(
114
+ "credit_purchases",
115
+ {
116
+ id: text("id").primaryKey(),
117
+ workspaceId: text("workspace_id")
118
+ .notNull()
119
+ .references(() => organization.id, { onDelete: "cascade" }),
120
+ /** What the buyer paid, in minor units of `priceCurrency`. */
121
+ priceMinor: integer("price_minor"),
122
+ priceCurrency: text("price_currency"),
123
+ /**
124
+ * What the workspace was granted, in micros of `grantedCurrency`.
125
+ * Separate from the price on purpose: a pack sold for $5 grants an
126
+ * amount of the billing currency, which is a different unit.
127
+ */
128
+ grantedMicros: bigint("granted_micros", { mode: "number" }),
129
+ grantedCurrency: text("granted_currency"),
130
+ stripePaymentIntentId: text("stripe_payment_intent_id"),
131
+ stripeCheckoutSessionId: text("stripe_checkout_session_id"),
132
+ status: text("status").notNull().default("pending"), // pending|completed|failed
133
+ createdAt: timestamp("created_at").notNull().defaultNow(),
134
+ },
135
+ (table) => [index("credit_purchases_workspace_id_idx").on(table.workspaceId)]
136
+ );
137
+
138
+ /** Every Stripe event, for idempotent webhook processing and audit. */
139
+ export const financeEvents = pgTable("finance_events", {
140
+ id: text("id").primaryKey(),
141
+ workspaceId: text("workspace_id").references(() => organization.id, {
142
+ onDelete: "set null",
143
+ }),
144
+ stripeEventId: text("stripe_event_id").notNull().unique(),
145
+ type: text("type").notNull(), // e.g., "checkout.session.completed", "invoice.paid"
146
+ /** Stripe's own amount, in the minor units of `currency`. */
147
+ amountMinor: integer("amount_minor"),
148
+ currency: text("currency").default("USD"),
149
+ metadata: text("metadata"), // JSON string
150
+ /**
151
+ * When a delivery took the event for processing. A lease: a claim
152
+ * older than the webhook's lease is taken as a delivery that died.
153
+ */
154
+ claimedAt: timestamp("claimed_at"),
155
+ /** Set once the handlers finished; the event is never run again. */
156
+ processedAt: timestamp("processed_at"),
157
+ createdAt: timestamp("created_at").notNull().defaultNow(),
158
+ });
159
+
160
+ /**
161
+ * Closes the admission → settlement race. Admission inserts a reservation
162
+ * for the worst-case estimate inside the same transaction that sums the
163
+ * other active reservations, so concurrent requests cannot all be admitted
164
+ * against the same balance. Settlement closes the reservation; abandoned
165
+ * ones expire via `expires_at`, are ignored by the sum, and are deleted by
166
+ * a cleanup job.
167
+ */
168
+ export const creditReservations = pgTable(
169
+ "credit_reservations",
170
+ {
171
+ id: text("id").primaryKey(),
172
+ workspaceId: text("workspace_id")
173
+ .notNull()
174
+ .references(() => organization.id, { onDelete: "cascade" }),
175
+ /** Correlates admission with settlement. */
176
+ requestId: text("request_id").notNull().unique(),
177
+ /** The hold, in micros of `currency`. */
178
+ estimatedMicros: bigint("estimated_micros", { mode: "number" })
179
+ .notNull()
180
+ .default(0),
181
+ currency: text("currency").notNull().default("USD"),
182
+ status: text("status").notNull().default("active"), // active | settled
183
+ createdAt: timestamp("created_at").notNull().defaultNow(),
184
+ expiresAt: timestamp("expires_at").notNull(),
185
+ settledAt: timestamp("settled_at"),
186
+ },
187
+ (table) => [
188
+ index("credit_reservations_active_idx").on(
189
+ table.workspaceId,
190
+ table.status,
191
+ table.expiresAt
192
+ ),
193
+ ]
194
+ );
195
+
196
+ export type Plan = typeof plans.$inferSelect;
197
+ export type InsertPlan = typeof plans.$inferInsert;
198
+ export type Subscription = typeof subscriptions.$inferSelect;
199
+ export type InsertSubscription = typeof subscriptions.$inferInsert;
200
+ export type CreditBalance = typeof creditBalances.$inferSelect;
201
+ export type InsertCreditBalance = typeof creditBalances.$inferInsert;
202
+ export type CreditPurchase = typeof creditPurchases.$inferSelect;
203
+ export type InsertCreditPurchase = typeof creditPurchases.$inferInsert;
204
+ export type FinanceEvent = typeof financeEvents.$inferSelect;
205
+ export type InsertFinanceEvent = typeof financeEvents.$inferInsert;
206
+ export type BillingSettings = typeof billingSettings.$inferSelect;
207
+ export type InsertBillingSettings = typeof billingSettings.$inferInsert;
208
+ export type CreditReservation = typeof creditReservations.$inferSelect;
209
+ export type InsertCreditReservation = typeof creditReservations.$inferInsert;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Runtime overrides for feature gates: `@intelligo-dev/billing`'s feature
3
+ * check reads a flag by name here before it falls back to the plan's
4
+ * entitlements, so a feature can be switched without a deploy.
5
+ */
6
+
7
+ import { pgTable, text, timestamp, boolean } from "drizzle-orm/pg-core";
8
+
9
+ export const featureFlags = pgTable("feature_flags", {
10
+ id: text("id").primaryKey(),
11
+ name: text("name").notNull().unique(),
12
+ description: text("description"),
13
+ enabledPlans: text("enabled_plans").notNull(), // JSON array string: e.g., '["free","pro","enterprise"]'
14
+ isActive: boolean("is_active").notNull().default(true),
15
+ createdAt: timestamp("created_at").notNull().defaultNow(),
16
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
17
+ });
18
+
19
+ export type FeatureFlag = typeof featureFlags.$inferSelect;
20
+ export type InsertFeatureFlag = typeof featureFlags.$inferInsert;
@@ -0,0 +1,250 @@
1
+ /**
2
+ * The user identity graph: a user's facts, episodic memories and audit
3
+ * trail, synthesized into one profile snapshot an agent session reads in
4
+ * one query.
5
+ *
6
+ * - `user_facts`: the structured source of truth, queryable by category
7
+ * and weighted by confidence and importance.
8
+ * - `user_memories`: unstructured episodic recall via pgvector search.
9
+ * - `user_profile_snapshots`: the cached synthesis, since voice agents
10
+ * cannot rebuild the profile inside a turn's latency budget.
11
+ * - `user_memory_audit`: append-only log of every write, so a user can see
12
+ * where each fact came from.
13
+ */
14
+
15
+ import {
16
+ pgTable,
17
+ primaryKey,
18
+ text,
19
+ timestamp,
20
+ integer,
21
+ index,
22
+ uniqueIndex,
23
+ jsonb,
24
+ doublePrecision,
25
+ } from "drizzle-orm/pg-core";
26
+ import { vector } from "drizzle-orm/pg-core/columns/vector_extension/vector";
27
+ import { organization, users } from "./auth";
28
+
29
+ /**
30
+ * A fact's category, the filter axis for synthesis and display. A closed
31
+ * list on purpose: a new category is a decision, not a free-form string.
32
+ */
33
+ export const USER_FACT_CATEGORIES = [
34
+ "interest",
35
+ "skill",
36
+ "goal",
37
+ "constraint",
38
+ "trait",
39
+ "value",
40
+ "preference",
41
+ "context",
42
+ "background",
43
+ ] as const;
44
+
45
+ export type UserFactCategory = (typeof USER_FACT_CATEGORIES)[number];
46
+
47
+ /**
48
+ * How a fact entered the system. "explicit_user_input" facts are
49
+ * considered ground truth and survive conflict resolution against
50
+ * lower-confidence LLM extractions.
51
+ */
52
+ export const USER_FACT_EXTRACTION_METHODS = [
53
+ "llm_extraction",
54
+ "explicit_user_input",
55
+ "inline_tool",
56
+ "onboarding_form",
57
+ ] as const;
58
+
59
+ export type UserFactExtractionMethod =
60
+ (typeof USER_FACT_EXTRACTION_METHODS)[number];
61
+
62
+ export const userFacts = pgTable(
63
+ "user_facts",
64
+ {
65
+ id: text("id").primaryKey(),
66
+ userId: text("user_id")
67
+ .notNull()
68
+ .references(() => users.id, { onDelete: "cascade" }),
69
+ workspaceId: text("workspace_id")
70
+ .notNull()
71
+ .references(() => organization.id, { onDelete: "cascade" }),
72
+
73
+ category: text("category").$type<UserFactCategory>().notNull(),
74
+ key: text("key").notNull(),
75
+ value: jsonb("value").notNull(),
76
+ confidence: doublePrecision("confidence").notNull(),
77
+ importance: integer("importance").notNull().default(5),
78
+
79
+ sourceProduct: text("source_product"),
80
+ sourceSessionId: text("source_session_id"),
81
+ sourceMessageId: text("source_message_id"),
82
+ extractionMethod:
83
+ text("extraction_method").$type<UserFactExtractionMethod>(),
84
+
85
+ createdAt: timestamp("created_at").notNull().defaultNow(),
86
+ lastConfirmedAt: timestamp("last_confirmed_at"),
87
+ expiresAt: timestamp("expires_at"),
88
+ },
89
+ (table) => [
90
+ index("user_facts_user_idx").on(table.userId),
91
+ index("user_facts_workspace_idx").on(table.workspaceId),
92
+ index("user_facts_category_idx").on(table.workspaceId, table.category),
93
+ // Scoped to (user, workspace, category, key) so members of a shared
94
+ // workspace can hold the same fact key without collision.
95
+ uniqueIndex("user_facts_user_workspace_category_key_uniq").on(
96
+ table.userId,
97
+ table.workspaceId,
98
+ table.category,
99
+ table.key
100
+ ),
101
+ ]
102
+ );
103
+
104
+ export const USER_MEMORY_KINDS = [
105
+ "conversation_summary",
106
+ "event",
107
+ "insight",
108
+ "preference_statement",
109
+ "decision",
110
+ "struggle",
111
+ "success",
112
+ ] as const;
113
+
114
+ export type UserMemoryKind = (typeof USER_MEMORY_KINDS)[number];
115
+
116
+ export const userMemories = pgTable(
117
+ "user_memories",
118
+ {
119
+ id: text("id").primaryKey(),
120
+ userId: text("user_id")
121
+ .notNull()
122
+ .references(() => users.id, { onDelete: "cascade" }),
123
+ workspaceId: text("workspace_id")
124
+ .notNull()
125
+ .references(() => organization.id, { onDelete: "cascade" }),
126
+
127
+ kind: text("kind").$type<UserMemoryKind>().notNull(),
128
+ content: text("content").notNull(),
129
+ embedding: vector({ dimensions: 1536 }),
130
+
131
+ sourceProduct: text("source_product"),
132
+ sourceSessionId: text("source_session_id"),
133
+ sourceMessageIds: text("source_message_ids").array(),
134
+
135
+ importance: integer("importance").notNull().default(5),
136
+ decayFactor: doublePrecision("decay_factor").notNull().default(1.0),
137
+ metadata: jsonb("metadata"),
138
+
139
+ createdAt: timestamp("created_at").notNull().defaultNow(),
140
+ },
141
+ (table) => [
142
+ index("user_memories_user_idx").on(table.userId),
143
+ index("user_memories_workspace_idx").on(table.workspaceId),
144
+ index("user_memories_kind_idx").on(table.workspaceId, table.kind),
145
+ // The pgvector index is created in migration SQL: drizzle-orm cannot
146
+ // express it.
147
+ ]
148
+ );
149
+
150
+ export const SYNTHESIS_TRIGGER_REASONS = [
151
+ "fact_threshold",
152
+ "session_close",
153
+ "daily_cron",
154
+ "manual",
155
+ ] as const;
156
+
157
+ export type SynthesisTriggerReason = (typeof SYNTHESIS_TRIGGER_REASONS)[number];
158
+
159
+ export const userProfileSnapshots = pgTable(
160
+ "user_profile_snapshots",
161
+ {
162
+ userId: text("user_id")
163
+ .notNull()
164
+ .references(() => users.id, { onDelete: "cascade" }),
165
+ workspaceId: text("workspace_id")
166
+ .notNull()
167
+ .references(() => organization.id, { onDelete: "cascade" }),
168
+ version: integer("version").notNull(),
169
+
170
+ summary: text("summary").notNull(),
171
+ summaryEn: text("summary_en"),
172
+ summaryMn: text("summary_mn"),
173
+
174
+ factsDigest: jsonb("facts_digest").notNull(),
175
+ activeGoals: jsonb("active_goals"),
176
+ personalitySignals: jsonb("personality_signals"),
177
+ relationshipNotes: jsonb("relationship_notes"),
178
+
179
+ synthesizedByModel: text("synthesized_by_model"),
180
+ synthesizedAt: timestamp("synthesized_at").notNull().defaultNow(),
181
+ nextSynthesisAt: timestamp("next_synthesis_at"),
182
+ triggerReason: text("trigger_reason").$type<SynthesisTriggerReason>(),
183
+ },
184
+ // One snapshot per user per workspace: a user in two workspaces gets two
185
+ // distinct profiles.
186
+ (table) => [
187
+ primaryKey({ columns: [table.userId, table.workspaceId] }),
188
+ index("user_profile_snapshots_workspace_idx").on(table.workspaceId),
189
+ ]
190
+ );
191
+
192
+ export const AUDIT_TARGET_KINDS = ["fact", "memory", "snapshot"] as const;
193
+ export type AuditTargetKind = (typeof AUDIT_TARGET_KINDS)[number];
194
+
195
+ export const AUDIT_ACTIONS = [
196
+ "create",
197
+ "update",
198
+ "delete",
199
+ "view",
200
+ "export",
201
+ ] as const;
202
+ export type AuditAction = (typeof AUDIT_ACTIONS)[number];
203
+
204
+ export const AUDIT_ACTOR_KINDS = [
205
+ "agent",
206
+ "user",
207
+ "system_job",
208
+ "admin",
209
+ ] as const;
210
+ export type AuditActorKind = (typeof AUDIT_ACTOR_KINDS)[number];
211
+
212
+ export const userMemoryAudit = pgTable(
213
+ "user_memory_audit",
214
+ {
215
+ id: text("id").primaryKey(),
216
+ userId: text("user_id")
217
+ .notNull()
218
+ .references(() => users.id, { onDelete: "cascade" }),
219
+ workspaceId: text("workspace_id")
220
+ .notNull()
221
+ .references(() => organization.id, { onDelete: "cascade" }),
222
+
223
+ targetKind: text("target_kind").$type<AuditTargetKind>().notNull(),
224
+ targetId: text("target_id").notNull(),
225
+ action: text("action").$type<AuditAction>().notNull(),
226
+ actorKind: text("actor_kind").$type<AuditActorKind>().notNull(),
227
+ actorId: text("actor_id"),
228
+
229
+ beforeValue: jsonb("before_value"),
230
+ afterValue: jsonb("after_value"),
231
+ reason: text("reason"),
232
+
233
+ createdAt: timestamp("created_at").notNull().defaultNow(),
234
+ },
235
+ (table) => [
236
+ index("user_memory_audit_user_idx").on(table.userId),
237
+ index("user_memory_audit_workspace_idx").on(table.workspaceId),
238
+ index("user_memory_audit_target_idx").on(table.targetKind, table.targetId),
239
+ ]
240
+ );
241
+
242
+ export type UserFact = typeof userFacts.$inferSelect;
243
+ export type InsertUserFact = typeof userFacts.$inferInsert;
244
+ export type UserMemory = typeof userMemories.$inferSelect;
245
+ export type InsertUserMemory = typeof userMemories.$inferInsert;
246
+ export type UserProfileSnapshot = typeof userProfileSnapshots.$inferSelect;
247
+ export type InsertUserProfileSnapshot =
248
+ typeof userProfileSnapshots.$inferInsert;
249
+ export type UserMemoryAuditRow = typeof userMemoryAudit.$inferSelect;
250
+ export type InsertUserMemoryAudit = typeof userMemoryAudit.$inferInsert;
@@ -0,0 +1,12 @@
1
+ // Better-Auth's tables, including organization, member and invitation.
2
+ // Product code goes through the Better-Auth API rather than querying the
3
+ // organization tables directly, so membership and role rules stay in one
4
+ // place.
5
+ export * from "./auth";
6
+ export * from "./billing";
7
+ export * from "./usage";
8
+ export * from "./notifications";
9
+ export * from "./feature-flags";
10
+ export * from "./ai";
11
+ export * from "./agents";
12
+ export * from "./identity";