@intelligo-dev/core 1.0.0-beta.1

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 (254) hide show
  1. package/LICENSE +201 -0
  2. package/dist/conversations/errors.d.ts +31 -0
  3. package/dist/conversations/errors.d.ts.map +1 -0
  4. package/dist/conversations/errors.js +25 -0
  5. package/dist/conversations/errors.js.map +1 -0
  6. package/dist/conversations/index.d.ts +13 -0
  7. package/dist/conversations/index.d.ts.map +1 -0
  8. package/dist/conversations/index.js +12 -0
  9. package/dist/conversations/index.js.map +1 -0
  10. package/dist/conversations/service.d.ts +132 -0
  11. package/dist/conversations/service.d.ts.map +1 -0
  12. package/dist/conversations/service.js +347 -0
  13. package/dist/conversations/service.js.map +1 -0
  14. package/dist/conversations/types.d.ts +10 -0
  15. package/dist/conversations/types.d.ts.map +1 -0
  16. package/dist/conversations/types.js +5 -0
  17. package/dist/conversations/types.js.map +1 -0
  18. package/dist/db/client.d.ts +19 -0
  19. package/dist/db/client.d.ts.map +1 -0
  20. package/dist/db/client.js +52 -0
  21. package/dist/db/client.js.map +1 -0
  22. package/dist/db/index.d.ts +4 -0
  23. package/dist/db/index.d.ts.map +1 -0
  24. package/dist/db/index.js +8 -0
  25. package/dist/db/index.js.map +1 -0
  26. package/dist/db/schema/agents.d.ts +400 -0
  27. package/dist/db/schema/agents.d.ts.map +1 -0
  28. package/dist/db/schema/agents.js +39 -0
  29. package/dist/db/schema/agents.js.map +1 -0
  30. package/dist/db/schema/ai.d.ts +2222 -0
  31. package/dist/db/schema/ai.d.ts.map +1 -0
  32. package/dist/db/schema/ai.js +313 -0
  33. package/dist/db/schema/ai.js.map +1 -0
  34. package/dist/db/schema/auth.d.ts +1222 -0
  35. package/dist/db/schema/auth.d.ts.map +1 -0
  36. package/dist/db/schema/auth.js +162 -0
  37. package/dist/db/schema/auth.js.map +1 -0
  38. package/dist/db/schema/billing.d.ts +1199 -0
  39. package/dist/db/schema/billing.d.ts.map +1 -0
  40. package/dist/db/schema/billing.js +150 -0
  41. package/dist/db/schema/billing.js.map +1 -0
  42. package/dist/db/schema/feature-flags.d.ts +143 -0
  43. package/dist/db/schema/feature-flags.d.ts.map +1 -0
  44. package/dist/db/schema/feature-flags.js +25 -0
  45. package/dist/db/schema/feature-flags.js.map +1 -0
  46. package/dist/db/schema/identity.d.ts +1295 -0
  47. package/dist/db/schema/identity.d.ts.map +1 -0
  48. package/dist/db/schema/identity.js +258 -0
  49. package/dist/db/schema/identity.js.map +1 -0
  50. package/dist/db/schema/index.d.ts +16 -0
  51. package/dist/db/schema/index.d.ts.map +1 -0
  52. package/dist/db/schema/index.js +43 -0
  53. package/dist/db/schema/index.js.map +1 -0
  54. package/dist/db/schema/notifications.d.ts +182 -0
  55. package/dist/db/schema/notifications.d.ts.map +1 -0
  56. package/dist/db/schema/notifications.js +38 -0
  57. package/dist/db/schema/notifications.js.map +1 -0
  58. package/dist/db/schema/rag.d.ts +171 -0
  59. package/dist/db/schema/rag.d.ts.map +1 -0
  60. package/dist/db/schema/rag.js +42 -0
  61. package/dist/db/schema/rag.js.map +1 -0
  62. package/dist/db/schema/usage.d.ts +1193 -0
  63. package/dist/db/schema/usage.d.ts.map +1 -0
  64. package/dist/db/schema/usage.js +224 -0
  65. package/dist/db/schema/usage.js.map +1 -0
  66. package/dist/db/validate.d.ts +19 -0
  67. package/dist/db/validate.d.ts.map +1 -0
  68. package/dist/db/validate.js +58 -0
  69. package/dist/db/validate.js.map +1 -0
  70. package/dist/db/workspace-queries.d.ts +75 -0
  71. package/dist/db/workspace-queries.d.ts.map +1 -0
  72. package/dist/db/workspace-queries.js +78 -0
  73. package/dist/db/workspace-queries.js.map +1 -0
  74. package/dist/documents/classifier.d.ts +31 -0
  75. package/dist/documents/classifier.d.ts.map +1 -0
  76. package/dist/documents/classifier.js +41 -0
  77. package/dist/documents/classifier.js.map +1 -0
  78. package/dist/documents/errors.d.ts +32 -0
  79. package/dist/documents/errors.d.ts.map +1 -0
  80. package/dist/documents/errors.js +27 -0
  81. package/dist/documents/errors.js.map +1 -0
  82. package/dist/documents/index.d.ts +14 -0
  83. package/dist/documents/index.d.ts.map +1 -0
  84. package/dist/documents/index.js +13 -0
  85. package/dist/documents/index.js.map +1 -0
  86. package/dist/documents/service.d.ts +54 -0
  87. package/dist/documents/service.d.ts.map +1 -0
  88. package/dist/documents/service.js +146 -0
  89. package/dist/documents/service.js.map +1 -0
  90. package/dist/documents/types.d.ts +27 -0
  91. package/dist/documents/types.d.ts.map +1 -0
  92. package/dist/documents/types.js +5 -0
  93. package/dist/documents/types.js.map +1 -0
  94. package/dist/email/index.d.ts +5 -0
  95. package/dist/email/index.d.ts.map +1 -0
  96. package/dist/email/index.js +5 -0
  97. package/dist/email/index.js.map +1 -0
  98. package/dist/email/provider.d.ts +68 -0
  99. package/dist/email/provider.d.ts.map +1 -0
  100. package/dist/email/provider.js +199 -0
  101. package/dist/email/provider.js.map +1 -0
  102. package/dist/email/send.d.ts +47 -0
  103. package/dist/email/send.d.ts.map +1 -0
  104. package/dist/email/send.js +110 -0
  105. package/dist/email/send.js.map +1 -0
  106. package/dist/email/senders.d.ts +93 -0
  107. package/dist/email/senders.d.ts.map +1 -0
  108. package/dist/email/senders.js +232 -0
  109. package/dist/email/senders.js.map +1 -0
  110. package/dist/email/templates/base-layout.d.ts +7 -0
  111. package/dist/email/templates/base-layout.d.ts.map +1 -0
  112. package/dist/email/templates/base-layout.js +69 -0
  113. package/dist/email/templates/base-layout.js.map +1 -0
  114. package/dist/email/templates/index.d.ts +11 -0
  115. package/dist/email/templates/index.d.ts.map +1 -0
  116. package/dist/email/templates/index.js +17 -0
  117. package/dist/email/templates/index.js.map +1 -0
  118. package/dist/email/templates/password-reset.d.ts +7 -0
  119. package/dist/email/templates/password-reset.d.ts.map +1 -0
  120. package/dist/email/templates/password-reset.js +59 -0
  121. package/dist/email/templates/password-reset.js.map +1 -0
  122. package/dist/email/templates/payment-failed.d.ts +8 -0
  123. package/dist/email/templates/payment-failed.d.ts.map +1 -0
  124. package/dist/email/templates/payment-failed.js +62 -0
  125. package/dist/email/templates/payment-failed.js.map +1 -0
  126. package/dist/email/templates/quota-warning.d.ts +11 -0
  127. package/dist/email/templates/quota-warning.d.ts.map +1 -0
  128. package/dist/email/templates/quota-warning.js +82 -0
  129. package/dist/email/templates/quota-warning.js.map +1 -0
  130. package/dist/email/templates/subscription-confirmed.d.ts +9 -0
  131. package/dist/email/templates/subscription-confirmed.d.ts.map +1 -0
  132. package/dist/email/templates/subscription-confirmed.js +72 -0
  133. package/dist/email/templates/subscription-confirmed.js.map +1 -0
  134. package/dist/email/templates/trial-expiry.d.ts +9 -0
  135. package/dist/email/templates/trial-expiry.d.ts.map +1 -0
  136. package/dist/email/templates/trial-expiry.js +86 -0
  137. package/dist/email/templates/trial-expiry.js.map +1 -0
  138. package/dist/email/templates/trial-warning.d.ts +11 -0
  139. package/dist/email/templates/trial-warning.d.ts.map +1 -0
  140. package/dist/email/templates/trial-warning.js +70 -0
  141. package/dist/email/templates/trial-warning.js.map +1 -0
  142. package/dist/email/templates/verify-email.d.ts +7 -0
  143. package/dist/email/templates/verify-email.d.ts.map +1 -0
  144. package/dist/email/templates/verify-email.js +59 -0
  145. package/dist/email/templates/verify-email.js.map +1 -0
  146. package/dist/email/templates/welcome.d.ts +7 -0
  147. package/dist/email/templates/welcome.d.ts.map +1 -0
  148. package/dist/email/templates/welcome.js +51 -0
  149. package/dist/email/templates/welcome.js.map +1 -0
  150. package/dist/email/templates/workspace-invitation.d.ts +10 -0
  151. package/dist/email/templates/workspace-invitation.d.ts.map +1 -0
  152. package/dist/email/templates/workspace-invitation.js +79 -0
  153. package/dist/email/templates/workspace-invitation.js.map +1 -0
  154. package/dist/env.d.ts +21 -0
  155. package/dist/env.d.ts.map +1 -0
  156. package/dist/env.js +129 -0
  157. package/dist/env.js.map +1 -0
  158. package/dist/identity/audit.d.ts +39 -0
  159. package/dist/identity/audit.d.ts.map +1 -0
  160. package/dist/identity/audit.js +51 -0
  161. package/dist/identity/audit.js.map +1 -0
  162. package/dist/identity/errors.d.ts +32 -0
  163. package/dist/identity/errors.d.ts.map +1 -0
  164. package/dist/identity/errors.js +25 -0
  165. package/dist/identity/errors.js.map +1 -0
  166. package/dist/identity/index.d.ts +16 -0
  167. package/dist/identity/index.d.ts.map +1 -0
  168. package/dist/identity/index.js +15 -0
  169. package/dist/identity/index.js.map +1 -0
  170. package/dist/identity/service.d.ts +70 -0
  171. package/dist/identity/service.d.ts.map +1 -0
  172. package/dist/identity/service.js +179 -0
  173. package/dist/identity/service.js.map +1 -0
  174. package/dist/identity/types.d.ts +27 -0
  175. package/dist/identity/types.d.ts.map +1 -0
  176. package/dist/identity/types.js +5 -0
  177. package/dist/identity/types.js.map +1 -0
  178. package/dist/index.d.ts +3 -0
  179. package/dist/index.d.ts.map +1 -0
  180. package/dist/index.js +11 -0
  181. package/dist/index.js.map +1 -0
  182. package/dist/logger.d.ts +50 -0
  183. package/dist/logger.d.ts.map +1 -0
  184. package/dist/logger.js +183 -0
  185. package/dist/logger.js.map +1 -0
  186. package/dist/notifications/index.d.ts +86 -0
  187. package/dist/notifications/index.d.ts.map +1 -0
  188. package/dist/notifications/index.js +112 -0
  189. package/dist/notifications/index.js.map +1 -0
  190. package/dist/notifications/triggers.d.ts +68 -0
  191. package/dist/notifications/triggers.d.ts.map +1 -0
  192. package/dist/notifications/triggers.js +145 -0
  193. package/dist/notifications/triggers.js.map +1 -0
  194. package/dist/notifications/types.d.ts +19 -0
  195. package/dist/notifications/types.d.ts.map +1 -0
  196. package/dist/notifications/types.js +11 -0
  197. package/dist/notifications/types.js.map +1 -0
  198. package/package.json +101 -0
  199. package/src/db/migrations/0000_sharp_night_nurse.sql +52 -0
  200. package/src/db/migrations/0001_hesitant_vapor.sql +40 -0
  201. package/src/db/migrations/0002_numerous_lady_vermin.sql +235 -0
  202. package/src/db/migrations/0003_mighty_jean_grey.sql +37 -0
  203. package/src/db/migrations/0004_cynical_grandmaster.sql +2 -0
  204. package/src/db/migrations/0005_careful_switch.sql +8 -0
  205. package/src/db/migrations/0006_tense_blue_marvel.sql +16 -0
  206. package/src/db/migrations/0007_next_squadron_sinister.sql +1 -0
  207. package/src/db/migrations/0008_powerful_scream.sql +39 -0
  208. package/src/db/migrations/0009_sad_ink.sql +1 -0
  209. package/src/db/migrations/0010_shocking_omega_flight.sql +2 -0
  210. package/src/db/migrations/0011_ambiguous_otto_octavius.sql +151 -0
  211. package/src/db/migrations/0011_hnsw_vector_index.sql +17 -0
  212. package/src/db/migrations/0012_user_profiles.sql +30 -0
  213. package/src/db/migrations/0013_trending_seasonal_columns.sql +9 -0
  214. package/src/db/migrations/0014_add_product_type_to_agents.sql +6 -0
  215. package/src/db/migrations/0015_new_v1_tables.sql +149 -0
  216. package/src/db/migrations/0016_document_types.sql +30 -0
  217. package/src/db/migrations/0017_document_metadata.sql +2 -0
  218. package/src/db/migrations/0018_identity_graph.sql +200 -0
  219. package/src/db/migrations/0019_db_driven_prompts.sql +20 -0
  220. package/src/db/migrations/0020_pending_extractions.sql +35 -0
  221. package/src/db/migrations/0021_rag_documents.sql +39 -0
  222. package/src/db/migrations/0022_user_quotas_usage_jsonb.sql +70 -0
  223. package/src/db/migrations/0023_user_facts_user_scoped_unique.sql +17 -0
  224. package/src/db/migrations/0024_user_memories_hnsw.sql +23 -0
  225. package/src/db/migrations/0025_audit_trigger_errcode.sql +21 -0
  226. package/src/db/migrations/0026_user_profile_snapshots_composite_pk.sql +17 -0
  227. package/src/db/migrations/0027_billing_settings_mnt_columns.sql +54 -0
  228. package/src/db/migrations/0028_trial_credits_normalized_email.sql +37 -0
  229. package/src/db/migrations/0029_usage_records_conversation_idx.sql +13 -0
  230. package/src/db/migrations/0030_pending_extractions_composite_idx.sql +11 -0
  231. package/src/db/migrations/0031_rag_documents_hnsw.sql +16 -0
  232. package/src/db/migrations/0032_rate_limit_unique_idx.sql +16 -0
  233. package/src/db/migrations/0033_pending_extractions_partial_idx.sql +18 -0
  234. package/src/db/migrations/0034_rate_limit_count.sql +9 -0
  235. package/src/db/migrations/0035_credit_reservations.sql +24 -0
  236. package/src/db/migrations/0036_executions_audit_jobs.sql +96 -0
  237. package/src/db/migrations/0037_rate_limit_minute_bucket.sql +46 -0
  238. package/src/db/migrations/0038_user_quotas_generic_usage.sql +25 -0
  239. package/src/db/migrations/0039_platform_admin_impersonation.sql +27 -0
  240. package/src/db/migrations/0040_ee_audit_chain.sql +23 -0
  241. package/src/db/migrations/README.md +57 -0
  242. package/src/db/migrations/meta/0000_snapshot.json +348 -0
  243. package/src/db/migrations/meta/0001_snapshot.json +631 -0
  244. package/src/db/migrations/meta/0002_snapshot.json +2269 -0
  245. package/src/db/migrations/meta/0003_snapshot.json +2488 -0
  246. package/src/db/migrations/meta/0004_snapshot.json +2500 -0
  247. package/src/db/migrations/meta/0005_snapshot.json +2548 -0
  248. package/src/db/migrations/meta/0006_snapshot.json +2650 -0
  249. package/src/db/migrations/meta/0007_snapshot.json +2657 -0
  250. package/src/db/migrations/meta/0008_snapshot.json +2719 -0
  251. package/src/db/migrations/meta/0009_snapshot.json +2726 -0
  252. package/src/db/migrations/meta/0010_snapshot.json +2739 -0
  253. package/src/db/migrations/meta/0011_snapshot.json +3886 -0
  254. package/src/db/migrations/meta/_journal.json +300 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../../src/db/schema/usage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Usage Tracking Database Schema
3
+ *
4
+ * Tables for tracking per-request token consumption and aggregated monthly usage.
5
+ * Used by the quota enforcement engine to check limits before AI requests
6
+ * and record consumption atomically after completion.
7
+ *
8
+ * Pattern: snake_case columns in PostgreSQL, camelCase TypeScript API (via Drizzle mapping)
9
+ */
10
+ import { pgTable, text, timestamp, integer, real, index, unique, jsonb, } from "drizzle-orm/pg-core";
11
+ import { organization, users } from "./auth";
12
+ /**
13
+ * Usage Records table - Per-request token tracking (QUOTA-05)
14
+ *
15
+ * Every AI request creates one record with input/output/total tokens,
16
+ * the model used, and the agent that handled it. This provides the
17
+ * detailed breakdown for per-model and per-agent reporting (QUOTA-07).
18
+ */
19
+ export const usageRecords = pgTable("usage_records", {
20
+ id: text("id").primaryKey(),
21
+ workspaceId: text("workspace_id")
22
+ .notNull()
23
+ .references(() => organization.id, { onDelete: "cascade" }),
24
+ userId: text("user_id")
25
+ .notNull()
26
+ .references(() => users.id, { onDelete: "cascade" }),
27
+ type: text("type").notNull(), // "ai_tokens", "api_call"
28
+ model: text("model"), // "gpt-4o", "gpt-4o-mini"
29
+ agent: text("agent"), // "career-advisor", "sesh"
30
+ inputTokens: integer("input_tokens").notNull().default(0),
31
+ outputTokens: integer("output_tokens").notNull().default(0),
32
+ totalTokens: integer("total_tokens").notNull().default(0),
33
+ /**
34
+ * Raw provider USD cost snapshot (kept under legacy column name for back-compat).
35
+ * Do NOT use for arithmetic — floating-point accumulation causes sub-cent
36
+ * discrepancies over many records. Use chargedMnt (integer MNT) for all math.
37
+ */
38
+ cost: real("cost").notNull().default(0),
39
+ /** Snapshot of billing margin multiplier applied to this request */
40
+ marginMultiplier: real("margin_multiplier").notNull().default(0),
41
+ /** Snapshot of USD→MNT FX rate used for conversion */
42
+ fxRate: real("fx_rate").notNull().default(0),
43
+ /** Authoritative MNT amount deducted from balance */
44
+ chargedMnt: integer("charged_mnt").notNull().default(0),
45
+ /** Request correlation id for log tracing */
46
+ requestId: text("request_id"),
47
+ /**
48
+ * Owning execution (@intelligo-dev/executions). No FK: the executions
49
+ * table is owned by another package and this column is written by
50
+ * the settlement path, which may run before or after the execution
51
+ * row's terminal update.
52
+ */
53
+ executionId: text("execution_id"),
54
+ /** Conversation/chat id for grouping in usage dashboards */
55
+ conversationId: text("conversation_id"),
56
+ metadata: text("metadata"), // JSON string for additional data
57
+ recordedAt: timestamp("recorded_at").notNull().defaultNow(),
58
+ }, (table) => [
59
+ index("usage_records_workspace_id_idx").on(table.workspaceId),
60
+ index("usage_records_workspace_recorded_at_idx").on(table.workspaceId, table.recordedAt),
61
+ index("usage_records_workspace_type_idx").on(table.workspaceId, table.type),
62
+ index("usage_records_conversation_id_idx").on(table.conversationId),
63
+ index("usage_records_execution_id_idx").on(table.executionId),
64
+ ]);
65
+ /**
66
+ * Monthly Usage table - Aggregated monthly totals for fast quota checks
67
+ *
68
+ * Instead of SUM(totalTokens) on every request, we increment a counter atomically.
69
+ * One row per workspace per billing period. The usage_records table provides
70
+ * the detailed breakdown for reporting; this table provides O(1) quota checks.
71
+ */
72
+ export const monthlyUsage = pgTable("monthly_usage", {
73
+ id: text("id").primaryKey(),
74
+ workspaceId: text("workspace_id")
75
+ .notNull()
76
+ .references(() => organization.id, { onDelete: "cascade" }),
77
+ periodStart: timestamp("period_start").notNull(),
78
+ periodEnd: timestamp("period_end").notNull(),
79
+ tokensUsed: integer("tokens_used").notNull().default(0),
80
+ /** MNT-denominated total charged this period — authoritative for plan quota */
81
+ chargedMnt: integer("charged_mnt").notNull().default(0),
82
+ requestCount: integer("request_count").notNull().default(0),
83
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
84
+ }, (table) => [
85
+ unique("monthly_usage_workspace_period_unique").on(table.workspaceId, table.periodStart),
86
+ index("monthly_usage_workspace_id_idx").on(table.workspaceId),
87
+ ]);
88
+ /**
89
+ * Trial Credits table - One-time trial credit allocation per workspace (TRIAL-01)
90
+ *
91
+ * Each new workspace receives 100K trial tokens on creation.
92
+ * The unique constraint on workspace_id enforces one trial per workspace (TRIAL-07).
93
+ * Trial credits are separate from purchased credits (credit_balances).
94
+ * They act as a fallback when plan quota is exceeded or credit balance is zero.
95
+ *
96
+ * Status flow: active → depleted (credits hit 0) or active → converted (paid plan)
97
+ */
98
+ // Run drizzle-kit push to apply index
99
+ export const trialCredits = pgTable("trial_credits", {
100
+ id: text("id").primaryKey(),
101
+ workspaceId: text("workspace_id")
102
+ .notNull()
103
+ .unique()
104
+ .references(() => organization.id, { onDelete: "cascade" }),
105
+ initialCredits: integer("initial_credits").notNull().default(100000),
106
+ creditsUsed: integer("credits_used").notNull().default(0),
107
+ creditsRemaining: integer("credits_remaining").notNull().default(100000),
108
+ /** MNT-denominated trial grant (replaces token-denominated columns above) */
109
+ initialCreditsMnt: integer("initial_credits_mnt").notNull().default(5000),
110
+ creditsUsedMnt: integer("credits_used_mnt").notNull().default(0),
111
+ creditsRemainingMnt: integer("credits_remaining_mnt")
112
+ .notNull()
113
+ .default(5000),
114
+ status: text("status").notNull().default("active"), // active|depleted|converted|expired
115
+ provisionedAt: timestamp("provisioned_at").notNull().defaultNow(),
116
+ trialEndDate: timestamp("trial_end_date"), // 14 days from provisioning
117
+ depletedAt: timestamp("depleted_at"),
118
+ convertedAt: timestamp("converted_at"),
119
+ createdByIp: text("created_by_ip"),
120
+ createdByEmail: text("created_by_email"),
121
+ /**
122
+ * Canonical form of createdByEmail used by the per-email abuse
123
+ * check. Stored alongside the raw value so `SELECT count(*)`
124
+ * can use an index instead of a full-table scan + JS filter.
125
+ * See packages/billing/src/trial.ts:normalizeEmailForAbuseCheck.
126
+ */
127
+ normalizedEmail: text("normalized_email"),
128
+ }, (table) => [
129
+ index("trial_credits_expiry_idx").on(table.status, table.trialEndDate),
130
+ index("trial_credits_normalized_email_idx").on(table.normalizedEmail),
131
+ ]);
132
+ /**
133
+ * Rate Limit Entries table - Sliding window rate limiting (QUOTA-10)
134
+ *
135
+ * One row per (workspace, endpoint, minute bucket), with a counter.
136
+ * Each request upserts the row and atomically increments `count`, so N
137
+ * concurrent requests observe 1..N and exactly `limit` are admitted.
138
+ *
139
+ * An earlier version used ON CONFLICT DO NOTHING, which admitted
140
+ * exactly ONE request per minute on every plan — the per-plan limit was
141
+ * never consulted. See packages/billing/src/rate-limit.ts.
142
+ *
143
+ * Old buckets are deleted by the billing-maintenance cron.
144
+ *
145
+ * Database-backed rate limiting is the correct choice for <10K users
146
+ * (no Redis dependency, per architecture decisions).
147
+ */
148
+ export const rateLimitEntries = pgTable("rate_limit_entries", {
149
+ id: text("id").primaryKey(),
150
+ workspaceId: text("workspace_id")
151
+ .notNull()
152
+ .references(() => organization.id, { onDelete: "cascade" }),
153
+ endpoint: text("endpoint").notNull().default("chat"),
154
+ requestedAt: timestamp("requested_at").notNull().defaultNow(),
155
+ /** Floored minute bucket for unique constraint enforcement */
156
+ minuteBucket: timestamp("minute_bucket").notNull(),
157
+ /** Requests observed in this bucket — incremented via upsert */
158
+ count: integer("count").notNull().default(1),
159
+ }, (table) => [
160
+ index("rate_limit_entries_window_idx").on(table.workspaceId, table.endpoint, table.requestedAt),
161
+ unique("rate_limit_entries_unique_bucket_idx").on(table.workspaceId, table.endpoint, table.minuteBucket),
162
+ ]);
163
+ /**
164
+ * Notification History table - Tracks sent notifications for deduplication
165
+ *
166
+ * Records each notification sent (quota warnings, trial alerts) with a
167
+ * period-based deduplication key. The unique constraint on
168
+ * (workspaceId, type, periodKey) prevents sending the same notification
169
+ * twice in the same billing period.
170
+ *
171
+ * Phase 14 will update the channel from "console" to "email" and use
172
+ * Resend for actual delivery. For now, notifications are logged to console.
173
+ */
174
+ export const notificationHistory = pgTable("notification_history", {
175
+ id: text("id").primaryKey(),
176
+ workspaceId: text("workspace_id")
177
+ .notNull()
178
+ .references(() => organization.id, { onDelete: "cascade" }),
179
+ type: text("type").notNull(), // "quota_warning_80", "quota_warning_100", "trial_warning_20", "trial_depleted"
180
+ periodKey: text("period_key").notNull(), // "2026-02" for monthly, "trial" for one-time
181
+ sentAt: timestamp("sent_at").notNull().defaultNow(),
182
+ channel: text("channel").notNull().default("console"), // "console" now, "email" in Phase 14
183
+ metadata: text("metadata"), // JSON string for additional context
184
+ }, (table) => [
185
+ unique("notification_history_dedup_unique").on(table.workspaceId, table.type, table.periodKey),
186
+ index("notification_history_workspace_id_idx").on(table.workspaceId),
187
+ ]);
188
+ /**
189
+ * User Quotas table — per-user, per-action usage counters.
190
+ *
191
+ * One row per user (not per period — one-time payment model). Counters
192
+ * live in the `usage` JSONB map and increment atomically in SQL, so a
193
+ * quota check is O(1) with no SUM over usage_records.
194
+ */
195
+ export const userQuotas = pgTable("user_quotas", {
196
+ id: text("id").primaryKey(),
197
+ userId: text("user_id")
198
+ .notNull()
199
+ .unique()
200
+ .references(() => users.id, { onDelete: "cascade" }),
201
+ workspaceId: text("workspace_id")
202
+ .notNull()
203
+ .references(() => organization.id, { onDelete: "cascade" }),
204
+ plan: text("plan").notNull().default("free"), // free | standard | pro
205
+ /**
206
+ * Per-action counter map, keyed by the product's own action slugs
207
+ * (`usage["chat"] = 42`). This is the only counter storage.
208
+ *
209
+ * Three career-specific integer columns — chat_messages_used,
210
+ * assessments_used, reports_used — used to sit beside it, written
211
+ * by every product and read in preference to this map. Migration
212
+ * 0038 backfilled them into the map and dropped them: a public
213
+ * schema naming one vertical's actions meant no other vertical
214
+ * could add a counter without a migration to Intelligo (ADR-0004).
215
+ */
216
+ usage: jsonb("usage").notNull().default({}),
217
+ totalCostUsd: real("total_cost_usd").notNull().default(0),
218
+ createdAt: timestamp("created_at").notNull().defaultNow(),
219
+ updatedAt: timestamp("updated_at").notNull().defaultNow(),
220
+ }, (table) => [
221
+ index("user_quotas_user_id_idx").on(table.userId),
222
+ index("user_quotas_workspace_id_idx").on(table.workspaceId),
223
+ ]);
224
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usage.js","sourceRoot":"","sources":["../../../src/db/schema/usage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Database Connection Validation
3
+ *
4
+ * Validates that the database is connected and tables exist before allowing the app to start.
5
+ */
6
+ export interface DatabaseValidationResult {
7
+ isConnected: boolean;
8
+ tablesExist: boolean;
9
+ error?: string;
10
+ }
11
+ /**
12
+ * Check if database connection is valid and tables exist
13
+ */
14
+ export declare function validateDatabaseConnection(): Promise<DatabaseValidationResult>;
15
+ /**
16
+ * Validate database or throw error (for startup validation)
17
+ */
18
+ export declare function requireDatabaseConnection(): Promise<void>;
19
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/db/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,MAAM,WAAW,wBAAwB;IACvC,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,wBAAwB,CAAC,CA8BpF;AAED;;GAEG;AACH,wBAAsB,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqB/D"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Database Connection Validation
3
+ *
4
+ * Validates that the database is connected and tables exist before allowing the app to start.
5
+ */
6
+ import { db } from "./client";
7
+ import { sql } from "drizzle-orm";
8
+ /**
9
+ * Check if database connection is valid and tables exist
10
+ */
11
+ export async function validateDatabaseConnection() {
12
+ try {
13
+ // Test database connection
14
+ await db.execute(sql `SELECT 1`);
15
+ // Check if auth tables exist
16
+ const result = await db.execute(sql `
17
+ SELECT COUNT(*) as table_count
18
+ FROM information_schema.tables
19
+ WHERE table_schema = 'public'
20
+ AND table_name IN ('users', 'sessions', 'accounts', 'verifications')
21
+ `);
22
+ const tableCount = Number(result.rows[0]?.table_count ?? 0);
23
+ const tablesExist = tableCount === 4;
24
+ return {
25
+ isConnected: true,
26
+ tablesExist,
27
+ error: tablesExist
28
+ ? undefined
29
+ : "Auth tables do not exist. Run 'pnpm --filter @intelligo-dev/core db:push' to create them.",
30
+ };
31
+ }
32
+ catch (error) {
33
+ return {
34
+ isConnected: false,
35
+ tablesExist: false,
36
+ error: error instanceof Error ? error.message : "Unknown database error",
37
+ };
38
+ }
39
+ }
40
+ /**
41
+ * Validate database or throw error (for startup validation)
42
+ */
43
+ export async function requireDatabaseConnection() {
44
+ const result = await validateDatabaseConnection();
45
+ if (!result.isConnected) {
46
+ throw new Error(`❌ Database connection failed: ${result.error}\n\n` +
47
+ `Make sure DATABASE_URL is configured in .env.local\n` +
48
+ `Example: DATABASE_URL=postgres://user:pass@host/db`);
49
+ }
50
+ if (!result.tablesExist) {
51
+ throw new Error(`❌ Database tables do not exist.\n\n` +
52
+ `Run the following commands to set up the database:\n` +
53
+ ` 1. pnpm --filter @intelligo-dev/core db:push\n` +
54
+ ` 2. pnpm --filter @intelligo-dev/core db:seed (optional - creates admin user)`);
55
+ }
56
+ console.log("✓ Database connection validated");
57
+ }
58
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/db/validate.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAC9B,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAQlC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B;IAC9C,IAAI,CAAC;QACH,2BAA2B;QAC3B,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA,UAAU,CAAC,CAAC;QAEhC,6BAA6B;QAC7B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAA;;;;;KAKlC,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,IAAI,CAAC,CAAC,CAAC;QAC5D,MAAM,WAAW,GAAG,UAAU,KAAK,CAAC,CAAC;QAErC,OAAO;YACL,WAAW,EAAE,IAAI;YACjB,WAAW;YACX,KAAK,EAAE,WAAW;gBAChB,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,2FAA2F;SAChG,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,KAAK;YAClB,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,wBAAwB;SACzE,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB;IAC7C,MAAM,MAAM,GAAG,MAAM,0BAA0B,EAAE,CAAC;IAElD,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,iCAAiC,MAAM,CAAC,KAAK,MAAM;YACjD,sDAAsD;YACtD,oDAAoD,CACvD,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,qCAAqC;YACnC,sDAAsD;YACtD,kDAAkD;YAClD,gFAAgF,CACnF,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;AACjD,CAAC"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Workspace-Scoped Query Helpers (WORK-06: Data Isolation)
3
+ *
4
+ * DATA ISOLATION MODEL:
5
+ * - Phase 10 workspace/team operations use Better-Auth organization plugin API exclusively.
6
+ * These APIs provide inherent data isolation — all operations are scoped to the
7
+ * authenticated user's session and active organization. No raw DB queries needed.
8
+ *
9
+ * Better-Auth API isolation guarantees:
10
+ * - auth.api.listOrganizations() — returns ONLY organizations the authenticated user belongs to
11
+ * - auth.api.getFullOrganization() — returns ONLY the active organization (set via session)
12
+ * - auth.api.createInvitation() — requires organizationId from requireWorkspace() (authenticated context)
13
+ * - auth.api.removeMember() — scoped to the organizationId from requireWorkspace()
14
+ * - All other org API methods operate on the authenticated user's session context
15
+ *
16
+ * - Future phases (11+) will add product-specific tables (conversations, knowledge_bases,
17
+ * usage_logs, etc.) that contain a workspaceId column. ALL queries on these tables
18
+ * MUST use the helpers below to enforce workspace-scoped data isolation.
19
+ *
20
+ * USAGE PATTERN (for future phases):
21
+ * import { withWorkspaceFilter } from "@intelligo-dev/core/db/workspace-queries";
22
+ * import { requireWorkspace } from "@intelligo-dev/auth";
23
+ *
24
+ * const { workspace } = await requireWorkspace();
25
+ * const conversations = await db
26
+ * .select()
27
+ * .from(conversationsTable)
28
+ * .where(withWorkspaceFilter(conversationsTable.workspaceId, workspace.id));
29
+ */
30
+ import { type SQL } from "drizzle-orm";
31
+ import type { PgColumn } from "drizzle-orm/pg-core";
32
+ /**
33
+ * Creates a workspace-scoped WHERE condition for any table with a workspaceId column.
34
+ * Use this in all custom Drizzle queries to enforce data isolation (WORK-06).
35
+ *
36
+ * @param workspaceIdColumn - The workspaceId column from the table schema
37
+ * @param workspaceId - The active workspace ID from requireWorkspace()
38
+ * @returns SQL condition: workspaceId = ?
39
+ *
40
+ * @example
41
+ * ```typescript
42
+ * const { workspace } = await requireWorkspace();
43
+ * const conversations = await db
44
+ * .select()
45
+ * .from(conversationsTable)
46
+ * .where(workspaceEq(conversationsTable.workspaceId, workspace.id));
47
+ * ```
48
+ */
49
+ export declare function workspaceEq(workspaceIdColumn: PgColumn, workspaceId: string): SQL;
50
+ /**
51
+ * Combines a workspace scope condition with additional WHERE conditions.
52
+ * Convenience helper to ensure workspaceId is always the first filter.
53
+ *
54
+ * @param workspaceIdColumn - The workspaceId column from the table schema
55
+ * @param workspaceId - The active workspace ID from requireWorkspace()
56
+ * @param additionalConditions - Extra WHERE conditions to AND together
57
+ * @returns Combined SQL condition: workspaceId = ? AND ...
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * const { workspace } = await requireWorkspace();
62
+ * const activeConversations = await db
63
+ * .select()
64
+ * .from(conversationsTable)
65
+ * .where(
66
+ * withWorkspaceFilter(
67
+ * conversationsTable.workspaceId,
68
+ * workspace.id,
69
+ * eq(conversationsTable.status, "active")
70
+ * )
71
+ * );
72
+ * ```
73
+ */
74
+ export declare function withWorkspaceFilter(workspaceIdColumn: PgColumn, workspaceId: string, ...additionalConditions: SQL[]): SQL;
75
+ //# sourceMappingURL=workspace-queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-queries.d.ts","sourceRoot":"","sources":["../../src/db/workspace-queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAW,KAAK,GAAG,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CACzB,iBAAiB,EAAE,QAAQ,EAC3B,WAAW,EAAE,MAAM,GAClB,GAAG,CAEL;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,mBAAmB,CACjC,iBAAiB,EAAE,QAAQ,EAC3B,WAAW,EAAE,MAAM,EACnB,GAAG,oBAAoB,EAAE,GAAG,EAAE,GAC7B,GAAG,CAEL"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Workspace-Scoped Query Helpers (WORK-06: Data Isolation)
3
+ *
4
+ * DATA ISOLATION MODEL:
5
+ * - Phase 10 workspace/team operations use Better-Auth organization plugin API exclusively.
6
+ * These APIs provide inherent data isolation — all operations are scoped to the
7
+ * authenticated user's session and active organization. No raw DB queries needed.
8
+ *
9
+ * Better-Auth API isolation guarantees:
10
+ * - auth.api.listOrganizations() — returns ONLY organizations the authenticated user belongs to
11
+ * - auth.api.getFullOrganization() — returns ONLY the active organization (set via session)
12
+ * - auth.api.createInvitation() — requires organizationId from requireWorkspace() (authenticated context)
13
+ * - auth.api.removeMember() — scoped to the organizationId from requireWorkspace()
14
+ * - All other org API methods operate on the authenticated user's session context
15
+ *
16
+ * - Future phases (11+) will add product-specific tables (conversations, knowledge_bases,
17
+ * usage_logs, etc.) that contain a workspaceId column. ALL queries on these tables
18
+ * MUST use the helpers below to enforce workspace-scoped data isolation.
19
+ *
20
+ * USAGE PATTERN (for future phases):
21
+ * import { withWorkspaceFilter } from "@intelligo-dev/core/db/workspace-queries";
22
+ * import { requireWorkspace } from "@intelligo-dev/auth";
23
+ *
24
+ * const { workspace } = await requireWorkspace();
25
+ * const conversations = await db
26
+ * .select()
27
+ * .from(conversationsTable)
28
+ * .where(withWorkspaceFilter(conversationsTable.workspaceId, workspace.id));
29
+ */
30
+ import { eq, and } from "drizzle-orm";
31
+ /**
32
+ * Creates a workspace-scoped WHERE condition for any table with a workspaceId column.
33
+ * Use this in all custom Drizzle queries to enforce data isolation (WORK-06).
34
+ *
35
+ * @param workspaceIdColumn - The workspaceId column from the table schema
36
+ * @param workspaceId - The active workspace ID from requireWorkspace()
37
+ * @returns SQL condition: workspaceId = ?
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * const { workspace } = await requireWorkspace();
42
+ * const conversations = await db
43
+ * .select()
44
+ * .from(conversationsTable)
45
+ * .where(workspaceEq(conversationsTable.workspaceId, workspace.id));
46
+ * ```
47
+ */
48
+ export function workspaceEq(workspaceIdColumn, workspaceId) {
49
+ return eq(workspaceIdColumn, workspaceId);
50
+ }
51
+ /**
52
+ * Combines a workspace scope condition with additional WHERE conditions.
53
+ * Convenience helper to ensure workspaceId is always the first filter.
54
+ *
55
+ * @param workspaceIdColumn - The workspaceId column from the table schema
56
+ * @param workspaceId - The active workspace ID from requireWorkspace()
57
+ * @param additionalConditions - Extra WHERE conditions to AND together
58
+ * @returns Combined SQL condition: workspaceId = ? AND ...
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * const { workspace } = await requireWorkspace();
63
+ * const activeConversations = await db
64
+ * .select()
65
+ * .from(conversationsTable)
66
+ * .where(
67
+ * withWorkspaceFilter(
68
+ * conversationsTable.workspaceId,
69
+ * workspace.id,
70
+ * eq(conversationsTable.status, "active")
71
+ * )
72
+ * );
73
+ * ```
74
+ */
75
+ export function withWorkspaceFilter(workspaceIdColumn, workspaceId, ...additionalConditions) {
76
+ return and(eq(workspaceIdColumn, workspaceId), ...additionalConditions);
77
+ }
78
+ //# sourceMappingURL=workspace-queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-queries.js","sourceRoot":"","sources":["../../src/db/workspace-queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,EAAE,EAAE,GAAG,EAAY,MAAM,aAAa,CAAC;AAGhD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,WAAW,CACzB,iBAA2B,EAC3B,WAAmB;IAEnB,OAAO,EAAE,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,mBAAmB,CACjC,iBAA2B,EAC3B,WAAmB,EACnB,GAAG,oBAA2B;IAE9B,OAAO,GAAG,CAAC,EAAE,CAAC,iBAAiB,EAAE,WAAW,CAAC,EAAE,GAAG,oBAAoB,CAAE,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Document title classifier registry.
3
+ *
4
+ * Vertical product packages register their title patterns here; the
5
+ * document persistence API (./service.ts) uses the same registry to
6
+ * derive agent labels and the "report" filter. Kept in its own module
7
+ * with zero imports so client-safe code and tests can load it without
8
+ * dragging in the server-only persistence chain (db).
9
+ *
10
+ * Ported from @intelligo-dev/agents/documents/classifier (ADR-0009) —
11
+ * unchanged.
12
+ */
13
+ export type DocumentPatternEntry = {
14
+ /** Stable product slug — same one used across product configs. */
15
+ productSlug: string;
16
+ /** Human-readable agent label rendered in the documents UI. */
17
+ agentLabel: string;
18
+ /** Case-insensitive substring patterns; document matches if its
19
+ * lowercased title contains ANY of these. */
20
+ patterns: string[];
21
+ };
22
+ export declare function registerDocumentPatterns(entry: DocumentPatternEntry): void;
23
+ export declare function classifyDocumentTitle(title: string): {
24
+ productSlug: string | null;
25
+ agentLabel: string;
26
+ };
27
+ /** Returns true when the document looks like it belongs to any registered product. */
28
+ export declare function isProductDocument(title: string, productSlug?: string): boolean;
29
+ export declare function listRegisteredDocumentPatterns(): readonly DocumentPatternEntry[];
30
+ export declare function clearDocumentPatternRegistry(): void;
31
+ //# sourceMappingURL=classifier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifier.d.ts","sourceRoot":"","sources":["../../src/documents/classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,oBAAoB,GAAG;IACjC,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB;kDAC8C;IAC9C,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAIF,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,oBAAoB,GAAG,IAAI,CAE1E;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG;IACpD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACpB,CAQA;AAED,sFAAsF;AACtF,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EACb,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAKT;AAED,wBAAgB,8BAA8B,IAAI,SAAS,oBAAoB,EAAE,CAEhF;AAED,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Document title classifier registry.
3
+ *
4
+ * Vertical product packages register their title patterns here; the
5
+ * document persistence API (./service.ts) uses the same registry to
6
+ * derive agent labels and the "report" filter. Kept in its own module
7
+ * with zero imports so client-safe code and tests can load it without
8
+ * dragging in the server-only persistence chain (db).
9
+ *
10
+ * Ported from @intelligo-dev/agents/documents/classifier (ADR-0009) —
11
+ * unchanged.
12
+ */
13
+ const registry = [];
14
+ export function registerDocumentPatterns(entry) {
15
+ registry.push(entry);
16
+ }
17
+ export function classifyDocumentTitle(title) {
18
+ const lower = title.toLowerCase();
19
+ for (const entry of registry) {
20
+ if (entry.patterns.some((p) => lower.includes(p))) {
21
+ return { productSlug: entry.productSlug, agentLabel: entry.agentLabel };
22
+ }
23
+ }
24
+ return { productSlug: null, agentLabel: "AI Assistant" };
25
+ }
26
+ /** Returns true when the document looks like it belongs to any registered product. */
27
+ export function isProductDocument(title, productSlug) {
28
+ const { productSlug: matched } = classifyDocumentTitle(title);
29
+ if (!matched)
30
+ return false;
31
+ if (productSlug)
32
+ return matched === productSlug;
33
+ return true;
34
+ }
35
+ export function listRegisteredDocumentPatterns() {
36
+ return registry;
37
+ }
38
+ export function clearDocumentPatternRegistry() {
39
+ registry.length = 0;
40
+ }
41
+ //# sourceMappingURL=classifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classifier.js","sourceRoot":"","sources":["../../src/documents/classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAYH,MAAM,QAAQ,GAA2B,EAAE,CAAC;AAE5C,MAAM,UAAU,wBAAwB,CAAC,KAA2B;IAClE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,KAAa;IAIjD,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAClD,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;QAC1E,CAAC;IACH,CAAC;IACD,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;AAC3D,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,iBAAiB,CAC/B,KAAa,EACb,WAAoB;IAEpB,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IAC9D,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAC3B,IAAI,WAAW;QAAE,OAAO,OAAO,KAAK,WAAW,CAAC;IAChD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,8BAA8B;IAC5C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,4BAA4B;IAC1C,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Document service error type.
3
+ *
4
+ * Mirrors `@intelligo-dev/auth`'s `WorkspaceServiceError` exactly (see that
5
+ * file's doc comment for the full rationale): the documents service
6
+ * (./service.ts) throws this for every failure it recognizes rather
7
+ * than returning an ad-hoc `{ success, error }` envelope — that
8
+ * shaping is a transport concern (a Server Action, a route handler)
9
+ * and belongs one layer up, alongside revalidatePath/Sentry/i18n, none
10
+ * of which this package may depend on (core's dependency allowlist is
11
+ * empty — see tests/architecture/dependency-direction.test.ts).
12
+ */
13
+ /**
14
+ * - `not_found` — no document (or no version of it) exists at the
15
+ * given id within the actor's workspace/user scope.
16
+ * - `forbidden` — a document with this id exists but is owned by a
17
+ * different user within the same workspace.
18
+ * - `invalid_input` — a caller-supplied argument failed a basic
19
+ * invariant (e.g. an unparsable or out-of-window delete timestamp).
20
+ * - `database_error` — the underlying insert/update did not return the
21
+ * row it was expected to.
22
+ */
23
+ export type DocumentServiceErrorCode = "not_found" | "forbidden" | "invalid_input" | "database_error";
24
+ export declare class DocumentServiceError extends Error {
25
+ readonly code: DocumentServiceErrorCode;
26
+ readonly cause?: unknown;
27
+ constructor(code: DocumentServiceErrorCode, message: string, options?: {
28
+ cause?: unknown;
29
+ });
30
+ }
31
+ export declare function isDocumentServiceError(error: unknown): error is DocumentServiceError;
32
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/documents/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH;;;;;;;;;GASG;AACH,MAAM,MAAM,wBAAwB,GAChC,WAAW,GACX,WAAW,GACX,eAAe,GACf,gBAAgB,CAAC;AAErB,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,QAAQ,CAAC,IAAI,EAAE,wBAAwB,CAAC;IAIxC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;gBAGvB,IAAI,EAAE,wBAAwB,EAC9B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAUhC;AAED,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,oBAAoB,CAE/B"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Document service error type.
3
+ *
4
+ * Mirrors `@intelligo-dev/auth`'s `WorkspaceServiceError` exactly (see that
5
+ * file's doc comment for the full rationale): the documents service
6
+ * (./service.ts) throws this for every failure it recognizes rather
7
+ * than returning an ad-hoc `{ success, error }` envelope — that
8
+ * shaping is a transport concern (a Server Action, a route handler)
9
+ * and belongs one layer up, alongside revalidatePath/Sentry/i18n, none
10
+ * of which this package may depend on (core's dependency allowlist is
11
+ * empty — see tests/architecture/dependency-direction.test.ts).
12
+ */
13
+ export class DocumentServiceError extends Error {
14
+ constructor(code, message, options) {
15
+ super(message);
16
+ this.name = "DocumentServiceError";
17
+ this.code = code;
18
+ if (options?.cause !== undefined) {
19
+ this.cause = options.cause;
20
+ }
21
+ Object.setPrototypeOf(this, DocumentServiceError.prototype);
22
+ }
23
+ }
24
+ export function isDocumentServiceError(error) {
25
+ return error instanceof DocumentServiceError;
26
+ }
27
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/documents/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAkBH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAO7C,YACE,IAA8B,EAC9B,OAAe,EACf,OAA6B;QAE7B,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,OAAO,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;YAChC,IAA4B,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QACtD,CAAC;QACD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,oBAAoB,CAAC,SAAS,CAAC,CAAC;IAC9D,CAAC;CACF;AAED,MAAM,UAAU,sBAAsB,CACpC,KAAc;IAEd,OAAO,KAAK,YAAY,oBAAoB,CAAC;AAC/C,CAAC"}