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

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 (356) 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 +339 -105
  56. package/dist/db/schema/billing.d.ts.map +1 -1
  57. package/dist/db/schema/billing.js +99 -58
  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 +6 -13
  182. package/dist/identity/index.d.ts.map +1 -1
  183. package/dist/identity/index.js +5 -12
  184. package/dist/identity/index.js.map +1 -1
  185. package/dist/identity/service.d.ts +29 -47
  186. package/dist/identity/service.d.ts.map +1 -1
  187. package/dist/identity/service.js +107 -79
  188. package/dist/identity/service.js.map +1 -1
  189. package/dist/identity/types.d.ts +28 -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 +6 -8
  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/0003_local_payments.sql +18 -0
  248. package/src/db/migrations/README.md +103 -36
  249. package/src/db/migrations/legacy-chain.json +206 -0
  250. package/src/db/migrations/meta/0000_snapshot.json +4182 -157
  251. package/src/db/migrations/meta/0002_snapshot.json +2478 -368
  252. package/src/db/migrations/meta/0003_snapshot.json +2567 -554
  253. package/src/db/migrations/meta/_journal.json +8 -274
  254. package/src/db/schema/agents.ts +57 -0
  255. package/src/db/schema/ai.ts +174 -0
  256. package/src/db/schema/auth.ts +183 -0
  257. package/src/db/schema/billing.ts +245 -0
  258. package/src/db/schema/feature-flags.ts +20 -0
  259. package/src/db/schema/identity.ts +250 -0
  260. package/src/db/schema/index.ts +12 -0
  261. package/src/db/schema/notifications.ts +31 -0
  262. package/src/db/schema/usage.ts +269 -0
  263. package/src/db/validate.ts +63 -0
  264. package/src/db/workspace-queries.ts +64 -0
  265. package/src/documents/classifier.ts +61 -0
  266. package/src/documents/errors.ts +44 -0
  267. package/src/documents/index.ts +24 -0
  268. package/src/documents/service.ts +256 -0
  269. package/src/documents/types.ts +24 -0
  270. package/src/email/brand.ts +24 -0
  271. package/src/email/index.ts +19 -0
  272. package/src/email/provider.ts +278 -0
  273. package/src/email/send.ts +169 -0
  274. package/src/email/senders.ts +292 -0
  275. package/src/email/templates/base-layout.tsx +145 -0
  276. package/src/email/templates/index.ts +28 -0
  277. package/src/email/templates/password-reset.tsx +72 -0
  278. package/src/email/templates/payment-failed.tsx +77 -0
  279. package/src/email/templates/quota-warning.tsx +118 -0
  280. package/src/email/templates/subscription-confirmed.tsx +91 -0
  281. package/src/email/templates/trial-expiry.tsx +124 -0
  282. package/src/email/templates/trial-warning.tsx +104 -0
  283. package/src/email/templates/verify-email.tsx +72 -0
  284. package/src/email/templates/welcome.tsx +64 -0
  285. package/src/email/templates/workspace-invitation.tsx +105 -0
  286. package/src/env.ts +180 -0
  287. package/src/identity/audit.ts +65 -0
  288. package/src/identity/errors.ts +44 -0
  289. package/src/identity/index.ts +29 -0
  290. package/src/identity/service.ts +303 -0
  291. package/src/identity/types.ts +58 -0
  292. package/src/index.ts +4 -0
  293. package/src/logger.ts +198 -0
  294. package/src/money.ts +270 -0
  295. package/src/notifications/index.ts +112 -0
  296. package/src/notifications/triggers.ts +158 -0
  297. package/src/notifications/types.ts +26 -0
  298. package/src/prompt.ts +142 -0
  299. package/src/registry.ts +75 -0
  300. package/src/request-context.ts +137 -0
  301. package/src/storage/index.ts +153 -0
  302. package/dist/db/schema/rag.d.ts +0 -171
  303. package/dist/db/schema/rag.d.ts.map +0 -1
  304. package/dist/db/schema/rag.js +0 -42
  305. package/dist/db/schema/rag.js.map +0 -1
  306. package/src/db/migrations/0000_sharp_night_nurse.sql +0 -52
  307. package/src/db/migrations/0001_hesitant_vapor.sql +0 -40
  308. package/src/db/migrations/0002_numerous_lady_vermin.sql +0 -235
  309. package/src/db/migrations/0003_mighty_jean_grey.sql +0 -37
  310. package/src/db/migrations/0004_cynical_grandmaster.sql +0 -2
  311. package/src/db/migrations/0005_careful_switch.sql +0 -8
  312. package/src/db/migrations/0006_tense_blue_marvel.sql +0 -16
  313. package/src/db/migrations/0007_next_squadron_sinister.sql +0 -1
  314. package/src/db/migrations/0008_powerful_scream.sql +0 -39
  315. package/src/db/migrations/0009_sad_ink.sql +0 -1
  316. package/src/db/migrations/0010_shocking_omega_flight.sql +0 -2
  317. package/src/db/migrations/0011_ambiguous_otto_octavius.sql +0 -151
  318. package/src/db/migrations/0011_hnsw_vector_index.sql +0 -17
  319. package/src/db/migrations/0012_user_profiles.sql +0 -30
  320. package/src/db/migrations/0013_trending_seasonal_columns.sql +0 -9
  321. package/src/db/migrations/0014_add_product_type_to_agents.sql +0 -6
  322. package/src/db/migrations/0015_new_v1_tables.sql +0 -149
  323. package/src/db/migrations/0016_document_types.sql +0 -30
  324. package/src/db/migrations/0017_document_metadata.sql +0 -2
  325. package/src/db/migrations/0018_identity_graph.sql +0 -200
  326. package/src/db/migrations/0019_db_driven_prompts.sql +0 -20
  327. package/src/db/migrations/0020_pending_extractions.sql +0 -35
  328. package/src/db/migrations/0021_rag_documents.sql +0 -39
  329. package/src/db/migrations/0022_user_quotas_usage_jsonb.sql +0 -70
  330. package/src/db/migrations/0023_user_facts_user_scoped_unique.sql +0 -17
  331. package/src/db/migrations/0024_user_memories_hnsw.sql +0 -23
  332. package/src/db/migrations/0025_audit_trigger_errcode.sql +0 -21
  333. package/src/db/migrations/0026_user_profile_snapshots_composite_pk.sql +0 -17
  334. package/src/db/migrations/0027_billing_settings_mnt_columns.sql +0 -54
  335. package/src/db/migrations/0028_trial_credits_normalized_email.sql +0 -37
  336. package/src/db/migrations/0029_usage_records_conversation_idx.sql +0 -13
  337. package/src/db/migrations/0030_pending_extractions_composite_idx.sql +0 -11
  338. package/src/db/migrations/0031_rag_documents_hnsw.sql +0 -16
  339. package/src/db/migrations/0032_rate_limit_unique_idx.sql +0 -16
  340. package/src/db/migrations/0033_pending_extractions_partial_idx.sql +0 -18
  341. package/src/db/migrations/0034_rate_limit_count.sql +0 -9
  342. package/src/db/migrations/0035_credit_reservations.sql +0 -24
  343. package/src/db/migrations/0036_executions_audit_jobs.sql +0 -96
  344. package/src/db/migrations/0037_rate_limit_minute_bucket.sql +0 -46
  345. package/src/db/migrations/0038_user_quotas_generic_usage.sql +0 -25
  346. package/src/db/migrations/0039_platform_admin_impersonation.sql +0 -27
  347. package/src/db/migrations/0040_ee_audit_chain.sql +0 -23
  348. package/src/db/migrations/meta/0001_snapshot.json +0 -631
  349. package/src/db/migrations/meta/0004_snapshot.json +0 -2500
  350. package/src/db/migrations/meta/0005_snapshot.json +0 -2548
  351. package/src/db/migrations/meta/0006_snapshot.json +0 -2650
  352. package/src/db/migrations/meta/0007_snapshot.json +0 -2657
  353. package/src/db/migrations/meta/0008_snapshot.json +0 -2719
  354. package/src/db/migrations/meta/0009_snapshot.json +0 -2726
  355. package/src/db/migrations/meta/0010_snapshot.json +0 -2739
  356. package/src/db/migrations/meta/0011_snapshot.json +0 -3886
@@ -1,69 +1,49 @@
1
1
  /**
2
- * Notification Trigger Functions
3
- *
4
- * These functions create BOTH in-app notifications (via createNotification)
5
- * AND send emails (via email senders). They are the integration points that
6
- * connect application events to the notification + email infrastructure.
7
- *
8
- * Design:
9
- * - In-app notifications are awaited (fast DB inserts)
10
- * - Email sends are fire-and-forget (non-blocking, errors logged)
11
- * - These do NOT handle deduplication -- that's handled by notification_history
12
- * table from Phase 12's checkNotificationTriggers()
13
- *
14
- * Usage:
15
- * - Quota/trial triggers are called by Phase 12 notification system
16
- * - Payment failed trigger is called by billing email triggers
17
- * - Team member joined trigger is called by server actions
2
+ * Each trigger creates an in-app notification (awaited) and sends an email
3
+ * (fire-and-forget, errors logged). Deduplication is the caller's job.
18
4
  */
19
- import { createNotification } from "./index";
20
- import { sendQuotaWarningEmail, sendTrialWarningEmail, sendPaymentFailedEmail, } from "../email/senders";
21
- // ---------------------------------------------------------------------------
22
- // Quota Notifications (QUOTA-08, QUOTA-09)
23
- // ---------------------------------------------------------------------------
5
+ import { createNotification } from "./index.js";
6
+ import { sendQuotaWarningEmail, sendTrialWarningEmail, sendPaymentFailedEmail, } from "../email/senders.js";
7
+ import { formatMoney } from "../money.js";
8
+ /** The locale the framework's own notification and email copy is written in. */
9
+ const COPY_LOCALE = "en";
24
10
  /**
25
- * Trigger a quota warning or exceeded notification.
26
- * Creates an in-app notification and sends an email.
11
+ * The plan allowance is money, not tokens: `used` and `allowance` are
12
+ * amounts in the deployment's billing currency, and the copy prints
13
+ * them as such.
27
14
  */
28
15
  export async function triggerQuotaNotification(params) {
29
16
  const upgradeUrl = `${process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000"}/settings/billing`;
30
- // Create in-app notification (awaited -- fast DB insert)
17
+ const used = formatMoney(params.used, COPY_LOCALE);
18
+ const allowance = formatMoney(params.allowance, COPY_LOCALE);
31
19
  await createNotification({
32
20
  userId: params.userId,
33
21
  workspaceId: params.workspaceId,
34
22
  type: params.isExceeded ? "quota_warning_100" : "quota_warning_80",
35
- title: params.isExceeded ? "Quota Exceeded" : "Quota Warning",
23
+ title: params.isExceeded ? "Allowance Used Up" : "Allowance Warning",
36
24
  message: params.isExceeded
37
- ? `Your workspace "${params.workspaceName}" has used all ${params.tokensLimit.toLocaleString()} tokens this month. Upgrade your plan for more tokens.`
38
- : `Your workspace "${params.workspaceName}" has used ${params.percentageUsed}% of its monthly token quota.`,
25
+ ? `Your workspace "${params.workspaceName}" has used all of its ${allowance} monthly allowance. Upgrade your plan for more.`
26
+ : `Your workspace "${params.workspaceName}" has used ${used} of its ${allowance} monthly allowance (${params.percentageUsed}%).`,
39
27
  metadata: {
40
28
  workspaceName: params.workspaceName,
41
29
  percentageUsed: params.percentageUsed,
42
- tokensUsed: params.tokensUsed,
43
- tokensLimit: params.tokensLimit,
30
+ usedMicros: params.used.amount,
31
+ allowanceMicros: params.allowance.amount,
32
+ currency: params.allowance.currency,
44
33
  },
45
34
  });
46
- // Send email (fire-and-forget -- non-blocking)
47
35
  sendQuotaWarningEmail({
48
36
  to: params.userEmail,
49
37
  workspaceName: params.workspaceName,
50
38
  percentageUsed: params.percentageUsed,
51
- tokensUsed: params.tokensUsed,
52
- tokensLimit: params.tokensLimit,
39
+ used: params.used,
40
+ allowance: params.allowance,
53
41
  upgradeUrl,
54
42
  isExceeded: params.isExceeded,
55
43
  }).catch((err) => console.error("[Email] Failed to send quota warning:", err));
56
44
  }
57
- // ---------------------------------------------------------------------------
58
- // Trial Notifications (TRIAL-04, TRIAL-05)
59
- // ---------------------------------------------------------------------------
60
- /**
61
- * Trigger a trial credits warning or depleted notification.
62
- * Creates an in-app notification and sends an email.
63
- */
64
45
  export async function triggerTrialNotification(params) {
65
46
  const upgradeUrl = `${process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000"}/settings/billing`;
66
- // Create in-app notification (awaited -- fast DB insert)
67
47
  await createNotification({
68
48
  userId: params.userId,
69
49
  workspaceId: params.workspaceId,
@@ -81,7 +61,6 @@ export async function triggerTrialNotification(params) {
81
61
  percentageRemaining: params.percentageRemaining,
82
62
  },
83
63
  });
84
- // Send email (fire-and-forget -- non-blocking)
85
64
  sendTrialWarningEmail({
86
65
  to: params.userEmail,
87
66
  workspaceName: params.workspaceName,
@@ -92,16 +71,8 @@ export async function triggerTrialNotification(params) {
92
71
  isDepleted: params.isDepleted,
93
72
  }).catch((err) => console.error("[Email] Failed to send trial warning:", err));
94
73
  }
95
- // ---------------------------------------------------------------------------
96
- // Payment Failed Notification
97
- // ---------------------------------------------------------------------------
98
- /**
99
- * Trigger a payment failed notification.
100
- * Creates an in-app notification and sends an email.
101
- */
102
74
  export async function triggerPaymentFailedNotification(params) {
103
75
  const updatePaymentUrl = `${process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000"}/settings/billing`;
104
- // Create in-app notification (awaited -- fast DB insert)
105
76
  await createNotification({
106
77
  userId: params.userId,
107
78
  workspaceId: params.workspaceId,
@@ -113,7 +84,6 @@ export async function triggerPaymentFailedNotification(params) {
113
84
  amount: params.amount,
114
85
  },
115
86
  });
116
- // Send email (fire-and-forget -- non-blocking)
117
87
  sendPaymentFailedEmail({
118
88
  to: params.userEmail,
119
89
  workspaceName: params.workspaceName,
@@ -121,15 +91,8 @@ export async function triggerPaymentFailedNotification(params) {
121
91
  updatePaymentUrl,
122
92
  }).catch((err) => console.error("[Email] Failed to send payment failed:", err));
123
93
  }
124
- // ---------------------------------------------------------------------------
125
- // Team Member Joined Notification
126
- // ---------------------------------------------------------------------------
127
- /**
128
- * Trigger a team member joined notification.
129
- * Creates an in-app notification ONLY (no email for this event).
130
- */
94
+ /** In-app only: this event sends no email. */
131
95
  export async function triggerTeamMemberJoinedNotification(params) {
132
- // Create in-app notification only (no email for team member joined events)
133
96
  await createNotification({
134
97
  userId: params.userId,
135
98
  workspaceId: params.workspaceId,
@@ -1 +1 @@
1
- {"version":3,"file":"triggers.js","sourceRoot":"","sources":["../../src/notifications/triggers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"triggers.js","sourceRoot":"","sources":["../../src/notifications/triggers.ts"],"names":[],"mappings":"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"}
@@ -1,13 +1,11 @@
1
+ /** The notification types the framework itself creates. */
2
+ export type BuiltInNotificationType = "quota_warning_80" | "quota_warning_100" | "trial_warning_20" | "trial_depleted" | "payment_failed" | "team_member_joined" | "subscription_confirmed" | "workspace_invitation";
1
3
  /**
2
- * Notification Type Definitions (NOTIF-07)
3
- *
4
- * Types covering all notification events:
5
- * - Quota/usage warnings (80%, 100%)
6
- * - Trial credit alerts (20% remaining, depleted)
7
- * - Payment events (failed, confirmed)
8
- * - Team events (member joined, invitation)
4
+ * A notification's `type`: one of the built-in types, or any string a
5
+ * product defines for its own notifications. `(string & {})` keeps the
6
+ * built-in names offered by autocompletion.
9
7
  */
10
- export type NotificationType = "quota_warning_80" | "quota_warning_100" | "trial_warning_20" | "trial_depleted" | "payment_failed" | "team_member_joined" | "subscription_confirmed" | "workspace_invitation" | "referral_signup" | "referral_upgrade";
8
+ export type NotificationType = BuiltInNotificationType | (string & {});
11
9
  export interface CreateNotificationParams {
12
10
  userId: string;
13
11
  workspaceId?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/notifications/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,gBAAgB,GACxB,kBAAkB,GAClB,mBAAmB,GACnB,kBAAkB,GAClB,gBAAgB,GAChB,gBAAgB,GAChB,oBAAoB,GACpB,wBAAwB,GACxB,sBAAsB,GACtB,iBAAiB,GACjB,kBAAkB,CAAC;AAEvB,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/notifications/types.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,MAAM,MAAM,uBAAuB,GAC/B,kBAAkB,GAClB,mBAAmB,GACnB,kBAAkB,GAClB,gBAAgB,GAChB,gBAAgB,GAChB,oBAAoB,GACpB,wBAAwB,GACxB,sBAAsB,CAAC;AAE3B;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,uBAAuB,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAEvE,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC"}
@@ -1,11 +1,2 @@
1
- /**
2
- * Notification Type Definitions (NOTIF-07)
3
- *
4
- * Types covering all notification events:
5
- * - Quota/usage warnings (80%, 100%)
6
- * - Trial credit alerts (20% remaining, depleted)
7
- * - Payment events (failed, confirmed)
8
- * - Team events (member joined, invitation)
9
- */
10
1
  export {};
11
2
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/notifications/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/notifications/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Prompt-injection sanitisation for user-authored text that reaches a
3
+ * system prompt (a stored summary, a profile field, a quoted web page).
4
+ * Strips role markers, override phrases and obfuscated separators, and
5
+ * reports which patterns it saw so a transport can log the attempt.
6
+ *
7
+ * Dependency-free, so any package that assembles a prompt can use it.
8
+ *
9
+ * Returns an empty string when more than half of the original was
10
+ * injection patterns: feeding the remaining fragments to the model is
11
+ * worse than dropping them.
12
+ */
13
+ export type InjectionPattern = {
14
+ name: string;
15
+ pattern: RegExp;
16
+ };
17
+ /**
18
+ * What is stripped. Exported so a product can extend the list for its
19
+ * own model or language without re-implementing the sweep.
20
+ */
21
+ export declare const INJECTION_PATTERNS: readonly InjectionPattern[];
22
+ export type InjectionReport = {
23
+ isInjection: boolean;
24
+ /** Names of the patterns that matched, for a log line. */
25
+ patterns: string[];
26
+ };
27
+ /**
28
+ * Which patterns the text carries, without changing it. Zero-width
29
+ * characters are both removed and replaced by spaces before matching,
30
+ * so neither obfuscation hides a marker.
31
+ */
32
+ export declare function detectPromptInjection(text: string, patterns?: readonly InjectionPattern[]): InjectionReport;
33
+ /**
34
+ * The text with every pattern replaced by a space and whitespace
35
+ * collapsed — or an empty string when the text was mostly patterns.
36
+ */
37
+ export declare function sanitizeForSystemPrompt(text: string, patterns?: readonly InjectionPattern[]): string;
38
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAYH,MAAM,MAAM,gBAAgB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,gBAAgB,EAuCzD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,EAAE,OAAO,CAAC;IACrB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,SAAS,gBAAgB,EAAuB,GACzD,eAAe,CAiBjB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,SAAS,gBAAgB,EAAuB,GACzD,MAAM,CA+BR"}
package/dist/prompt.js ADDED
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Prompt-injection sanitisation for user-authored text that reaches a
3
+ * system prompt (a stored summary, a profile field, a quoted web page).
4
+ * Strips role markers, override phrases and obfuscated separators, and
5
+ * reports which patterns it saw so a transport can log the attempt.
6
+ *
7
+ * Dependency-free, so any package that assembles a prompt can use it.
8
+ *
9
+ * Returns an empty string when more than half of the original was
10
+ * injection patterns: feeding the remaining fragments to the model is
11
+ * worse than dropping them.
12
+ */
13
+ const ZERO_WIDTH_CHARS = /[\u200B\u200C\u200D\u200E\u200F\uFEFF\u00AD\u2060\u2061\u2062\u2063\u2064]/g;
14
+ function normalizeText(text) {
15
+ return {
16
+ withSpaces: text.replace(ZERO_WIDTH_CHARS, " ").normalize("NFKC"),
17
+ stripped: text.replace(ZERO_WIDTH_CHARS, "").normalize("NFKC"),
18
+ };
19
+ }
20
+ /**
21
+ * What is stripped. Exported so a product can extend the list for its
22
+ * own model or language without re-implementing the sweep.
23
+ */
24
+ export const INJECTION_PATTERNS = [
25
+ { name: "[SYSTEM]", pattern: /\[SYSTEM\]/gi },
26
+ { name: "<<SYS>>", pattern: /<<SYS>>/gi },
27
+ { name: "<|system|>", pattern: /<\|system\|>/gi },
28
+ { name: "<|im_start|>", pattern: /<\|im_start\|>/gi },
29
+ { name: "<|im_end|>", pattern: /<\|im_end\|>/gi },
30
+ { name: "system: prefix", pattern: /^(SYSTEM|System|system)\s*:\s*/gm },
31
+ {
32
+ name: "ignore previous instructions",
33
+ pattern: /ignore\s+(?:all\s+)?previous\s+instructions?/gi,
34
+ },
35
+ { name: "disregard above", pattern: /disregard\s+(?:everything\s+)?above/gi },
36
+ { name: "forget everything", pattern: /forget\s+(?:all|everything)/gi },
37
+ {
38
+ name: "override instructions",
39
+ pattern: /override\s+(?:your\s+)?instructions?/gi,
40
+ },
41
+ {
42
+ name: "new instructions",
43
+ pattern: /(?:your\s+)?new\s+instructions?\s+(?:are|follow)/gi,
44
+ },
45
+ { name: "you are now", pattern: /you\s+are\s+now\s+/gi },
46
+ { name: "act as", pattern: /\bact\s+as\s+(?:a\s+|an\s+)?/gi },
47
+ { name: "pretend to be", pattern: /pretend\s+to\s+be\s+/gi },
48
+ { name: "roleplay as", pattern: /roleplay\s+as\s+/gi },
49
+ { name: "play the role", pattern: /play\s+(?:the\s+)?role\s+of\s+/gi },
50
+ { name: "separator ---", pattern: /\n{0,2}-{3,}\n{0,2}/g },
51
+ { name: "separator ===", pattern: /\n{0,2}={3,}\n{0,2}/g },
52
+ { name: "separator ###", pattern: /\n{0,2}#{3,}\n{0,2}/g },
53
+ { name: "script tag", pattern: /<script[\s>]/gi },
54
+ { name: "base64 data", pattern: /data:[^;]+;base64,/gi },
55
+ {
56
+ name: "do not follow",
57
+ pattern: /do\s+not\s+follow\s+(?:your\s+)?(?:previous\s+)?instructions?/gi,
58
+ },
59
+ {
60
+ name: "new system prompt",
61
+ pattern: /(?:new|updated?)\s+system\s+prompt/gi,
62
+ },
63
+ ];
64
+ /**
65
+ * Which patterns the text carries, without changing it. Zero-width
66
+ * characters are both removed and replaced by spaces before matching,
67
+ * so neither obfuscation hides a marker.
68
+ */
69
+ export function detectPromptInjection(text, patterns = INJECTION_PATTERNS) {
70
+ // Stryker disable next-line all: a fast path, not behaviour. Empty or
71
+ // blank text matches no pattern, so every mutant of this guard —
72
+ // dropping it, inverting it, swapping the operator — returns the same
73
+ // report the loop below would have built.
74
+ if (!text || text.trim().length === 0) {
75
+ return { isInjection: false, patterns: [] };
76
+ }
77
+ const { withSpaces, stripped } = normalizeText(text);
78
+ const matched = [];
79
+ for (const { name, pattern } of patterns) {
80
+ // Fresh instances: a global RegExp carries lastIndex between tests.
81
+ const a = new RegExp(pattern.source, pattern.flags);
82
+ const b = new RegExp(pattern.source, pattern.flags);
83
+ if (a.test(withSpaces) || b.test(stripped))
84
+ matched.push(name);
85
+ }
86
+ return { isInjection: matched.length > 0, patterns: matched };
87
+ }
88
+ /**
89
+ * The text with every pattern replaced by a space and whitespace
90
+ * collapsed — or an empty string when the text was mostly patterns.
91
+ */
92
+ export function sanitizeForSystemPrompt(text, patterns = INJECTION_PATTERNS) {
93
+ if (!text || text.trim().length === 0)
94
+ return text;
95
+ const originalLength = text.length;
96
+ const { withSpaces, stripped } = normalizeText(text);
97
+ // Detection reads both forms; so does this. A marker split by a
98
+ // zero-width character ("ig\u200Bnore") only exists once the
99
+ // character is removed, and cleaning the spaced form would pass it on.
100
+ const hiddenByZeroWidth = patterns.some(({ pattern }) => new RegExp(pattern.source, pattern.flags).test(stripped) &&
101
+ !new RegExp(pattern.source, pattern.flags).test(withSpaces));
102
+ let sanitized = hiddenByZeroWidth ? stripped : withSpaces;
103
+ for (const { pattern } of patterns) {
104
+ sanitized = sanitized.replace(new RegExp(pattern.source, pattern.flags), " ");
105
+ }
106
+ sanitized = sanitized
107
+ // A pattern replaced between two newlines leaves a whitespace-only
108
+ // line behind; drop those before collapsing blank lines.
109
+ .replace(/\n[ \t]+\n/g, "\n\n")
110
+ .replace(/\n{3,}/g, "\n\n")
111
+ .replace(/ {2,}/g, " ")
112
+ .trim();
113
+ const removed = originalLength - sanitized.length;
114
+ if (removed / originalLength > 0.5)
115
+ return "";
116
+ return sanitized;
117
+ }
118
+ //# sourceMappingURL=prompt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../src/prompt.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Registries that survive a bundler duplicating the module they live in.
3
+ *
4
+ * Next.js's server build can instantiate a package twice, so a module-scope
5
+ * `Map` written by the composition root may not be the one a page reads —
6
+ * and the failure is quiet (registries look empty, checks fall through to
7
+ * their defaults). Keying storage off `Symbol.for()` puts the map in the
8
+ * realm's global symbol registry, which every copy of the module shares.
9
+ *
10
+ * `globalThis` is per process: Node and Edge runtimes each still need the
11
+ * composition root to run.
12
+ */
13
+ /**
14
+ * A `Map` shared by every copy of the module that asks for the same key.
15
+ * Use it wherever a registry is written by the composition root and read by
16
+ * request-time code:
17
+ *
18
+ * const plans = createRegistry<PlanMap>("billing/plans");
19
+ *
20
+ * `key` must be unique across the framework (`"<package>/<registry>"`). The
21
+ * value type is not checked across copies.
22
+ */
23
+ export declare function createRegistry<T>(key: string): Map<string, T>;
24
+ /**
25
+ * A single shared value, for registries that are not maps: a module-scope
26
+ * `let` has the same duplication problem a `Map` does.
27
+ */
28
+ export declare function createRegistryRef<T>(key: string, initial: T): {
29
+ get(): T;
30
+ set(value: T): void;
31
+ };
32
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAWH;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAwB7D;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,GACT;IAAE,GAAG,IAAI,CAAC,CAAC;IAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAA;CAAE,CASnC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Registries that survive a bundler duplicating the module they live in.
3
+ *
4
+ * Next.js's server build can instantiate a package twice, so a module-scope
5
+ * `Map` written by the composition root may not be the one a page reads —
6
+ * and the failure is quiet (registries look empty, checks fall through to
7
+ * their defaults). Keying storage off `Symbol.for()` puts the map in the
8
+ * realm's global symbol registry, which every copy of the module shares.
9
+ *
10
+ * `globalThis` is per process: Node and Edge runtimes each still need the
11
+ * composition root to run.
12
+ */
13
+ const seen = new Set();
14
+ /**
15
+ * A `Map` shared by every copy of the module that asks for the same key.
16
+ * Use it wherever a registry is written by the composition root and read by
17
+ * request-time code:
18
+ *
19
+ * const plans = createRegistry<PlanMap>("billing/plans");
20
+ *
21
+ * `key` must be unique across the framework (`"<package>/<registry>"`). The
22
+ * value type is not checked across copies.
23
+ */
24
+ export function createRegistry(key) {
25
+ const symbol = Symbol.for(`@intelligo-dev/registry/${key}`);
26
+ const globals = globalThis;
27
+ const existing = globals[symbol];
28
+ if (existing) {
29
+ // A second copy reaching the same slot is not an error. Warn once per
30
+ // key anyway: every other module-scope value in that file is
31
+ // duplicated too, and those fail silently.
32
+ if (existing.origin !== import.meta.url && !seen.has(key)) {
33
+ seen.add(key);
34
+ console.warn(`[intelligo] registry "${key}" is being read from a second module ` +
35
+ `instance (${import.meta.url}, first seen from ${existing.origin}). ` +
36
+ `The registry itself is shared, so this is safe — but any other ` +
37
+ `module-scope state in that file is now duplicated.`);
38
+ }
39
+ return existing.map;
40
+ }
41
+ const map = new Map();
42
+ globals[symbol] = { map, origin: import.meta.url };
43
+ return map;
44
+ }
45
+ /**
46
+ * A single shared value, for registries that are not maps: a module-scope
47
+ * `let` has the same duplication problem a `Map` does.
48
+ */
49
+ export function createRegistryRef(key, initial) {
50
+ const box = createRegistry(`ref/${key}`);
51
+ if (!box.has("value"))
52
+ box.set("value", initial);
53
+ return {
54
+ get: () => box.get("value"),
55
+ set: (value) => {
56
+ box.set("value", value);
57
+ },
58
+ };
59
+ }
60
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;AAE/B;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAI,GAAW;IAC3C,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,UAA4D,CAAC;IAE7E,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,QAAQ,EAAE,CAAC;QACb,sEAAsE;QACtE,6DAA6D;QAC7D,2CAA2C;QAC3C,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACd,OAAO,CAAC,IAAI,CACV,yBAAyB,GAAG,uCAAuC;gBACjE,aAAa,MAAM,CAAC,IAAI,CAAC,GAAG,qBAAqB,QAAQ,CAAC,MAAM,KAAK;gBACrE,iEAAiE;gBACjE,oDAAoD,CACvD,CAAC;QACJ,CAAC;QACD,OAAO,QAAQ,CAAC,GAAG,CAAC;IACtB,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,GAAG,EAAa,CAAC;IACjC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IACnD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC/B,GAAW,EACX,OAAU;IAEV,MAAM,GAAG,GAAG,cAAc,CAAI,OAAO,GAAG,EAAE,CAAC,CAAC;IAC5C,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC;QAAE,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACjD,OAAO;QACL,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAM;QAChC,GAAG,EAAE,CAAC,KAAQ,EAAE,EAAE;YAChB,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC1B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Where request-scoped context comes from. The framework asks for headers
3
+ * through `getRequestHeaders()`; the application binds the source once,
4
+ * from its composition root, so no package outside `@intelligo-dev/next`
5
+ * depends on Next:
6
+ *
7
+ * import { setRequestContextSource } from "@intelligo-dev/core/request-context";
8
+ * import { nextRequestContext } from "@intelligo-dev/next";
9
+ *
10
+ * setRequestContextSource(nextRequestContext);
11
+ *
12
+ * An unbound source throws rather than guessing at the request, which is how
13
+ * a session gets read from the wrong one.
14
+ */
15
+ /**
16
+ * Produces the current request's headers.
17
+ *
18
+ * Async because Next's accessor is, and sync sources satisfy it too —
19
+ * `getRequestHeaders` awaits either.
20
+ */
21
+ export type RequestContextSource = () => Headers | Promise<Headers>;
22
+ export declare class RequestContextUnavailableError extends Error {
23
+ readonly code = "request_context_unavailable";
24
+ constructor();
25
+ }
26
+ export declare function setRequestContextSource(next: RequestContextSource): void;
27
+ /** Forget the bound source. For tests composing a fresh root. */
28
+ export declare function clearRequestContextSource(): void;
29
+ export declare function hasRequestContextSource(): boolean;
30
+ /**
31
+ * The current request's headers.
32
+ *
33
+ * @throws {RequestContextUnavailableError} when nothing is bound.
34
+ */
35
+ export declare function getRequestHeaders(): Promise<Headers>;
36
+ /**
37
+ * Validates a client-sent time zone. The value comes from the browser and
38
+ * reaches SQL (`AT TIME ZONE`) and `Intl`, so anything this runtime does not
39
+ * know as a zone, or no value at all, becomes `UTC`.
40
+ */
41
+ export declare function resolveTimeZone(value: string | null | undefined): string;
42
+ /**
43
+ * Runs `fn` with these headers, whatever the ambient source says — for a
44
+ * background job, a script acting as a user, or an integration test.
45
+ * Only `fn` and the work it starts see them; a concurrent request keeps
46
+ * its own. Nesting works: the innermost call wins.
47
+ */
48
+ export declare function withRequestHeaders<T>(headers: Headers, fn: () => Promise<T> | T): Promise<T>;
49
+ //# sourceMappingURL=request-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../src/request-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpE,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,QAAQ,CAAC,IAAI,iCAAiC;;CAU/C;AA6CD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,oBAAoB,GAAG,IAAI,CAExE;AAED,iEAAiE;AACjE,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAED,wBAAgB,uBAAuB,IAAI,OAAO,CAEjD;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAO1D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CASxE;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GACvB,OAAO,CAAC,CAAC,CAAC,CAGZ"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Where request-scoped context comes from. The framework asks for headers
3
+ * through `getRequestHeaders()`; the application binds the source once,
4
+ * from its composition root, so no package outside `@intelligo-dev/next`
5
+ * depends on Next:
6
+ *
7
+ * import { setRequestContextSource } from "@intelligo-dev/core/request-context";
8
+ * import { nextRequestContext } from "@intelligo-dev/next";
9
+ *
10
+ * setRequestContextSource(nextRequestContext);
11
+ *
12
+ * An unbound source throws rather than guessing at the request, which is how
13
+ * a session gets read from the wrong one.
14
+ */
15
+ import { createRegistryRef } from "./registry.js";
16
+ export class RequestContextUnavailableError extends Error {
17
+ constructor() {
18
+ super("No request context source is bound. Call setRequestContextSource() " +
19
+ "from your composition root — `nextRequestContext` from " +
20
+ "@intelligo-dev/next in a Next.js app — or wrap the call in " +
21
+ "withRequestHeaders() outside a request.");
22
+ this.code = "request_context_unavailable";
23
+ this.name = "RequestContextUnavailableError";
24
+ }
25
+ }
26
+ /**
27
+ * Held in the cross-instance registry, not a module variable: a bundler that
28
+ * duplicates this module would otherwise give the composition root one copy
29
+ * and the request path another.
30
+ */
31
+ const source = createRegistryRef("core/request-context-source", undefined);
32
+ const scope = createRegistryRef("core/request-headers-scope", undefined);
33
+ /**
34
+ * The runtime's `AsyncLocalStorage`: the global one Next.js and edge
35
+ * runtimes provide, or Node's own, loaded only when there is none — a
36
+ * script, a worker or a test.
37
+ */
38
+ async function headerScope() {
39
+ const existing = scope.get();
40
+ if (existing)
41
+ return existing;
42
+ const Storage = globalThis
43
+ .AsyncLocalStorage ??
44
+ (await import("node:async_hooks")).AsyncLocalStorage;
45
+ const created = new Storage();
46
+ scope.set(created);
47
+ return created;
48
+ }
49
+ export function setRequestContextSource(next) {
50
+ source.set(next);
51
+ }
52
+ /** Forget the bound source. For tests composing a fresh root. */
53
+ export function clearRequestContextSource() {
54
+ source.set(undefined);
55
+ }
56
+ export function hasRequestContextSource() {
57
+ return source.get() !== undefined || scope.get()?.getStore() !== undefined;
58
+ }
59
+ /**
60
+ * The current request's headers.
61
+ *
62
+ * @throws {RequestContextUnavailableError} when nothing is bound.
63
+ */
64
+ export async function getRequestHeaders() {
65
+ const explicit = scope.get()?.getStore();
66
+ if (explicit)
67
+ return explicit;
68
+ const resolve = source.get();
69
+ if (!resolve)
70
+ throw new RequestContextUnavailableError();
71
+ return await resolve();
72
+ }
73
+ /**
74
+ * Validates a client-sent time zone. The value comes from the browser and
75
+ * reaches SQL (`AT TIME ZONE`) and `Intl`, so anything this runtime does not
76
+ * know as a zone, or no value at all, becomes `UTC`.
77
+ */
78
+ export function resolveTimeZone(value) {
79
+ if (!value)
80
+ return "UTC";
81
+ try {
82
+ // Throws RangeError for anything that is not a zone it knows.
83
+ new Intl.DateTimeFormat("en-US", { timeZone: value });
84
+ return value;
85
+ }
86
+ catch {
87
+ return "UTC";
88
+ }
89
+ }
90
+ /**
91
+ * Runs `fn` with these headers, whatever the ambient source says — for a
92
+ * background job, a script acting as a user, or an integration test.
93
+ * Only `fn` and the work it starts see them; a concurrent request keeps
94
+ * its own. Nesting works: the innermost call wins.
95
+ */
96
+ export async function withRequestHeaders(headers, fn) {
97
+ const storage = await headerScope();
98
+ return await storage.run(headers, async () => await fn());
99
+ }
100
+ //# sourceMappingURL=request-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-context.js","sourceRoot":"","sources":["../src/request-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAU/C,MAAM,OAAO,8BAA+B,SAAQ,KAAK;IAEvD;QACE,KAAK,CACH,qEAAqE;YACnE,yDAAyD;YACzD,6DAA6D;YAC7D,yCAAyC,CAC5C,CAAC;QAPK,SAAI,GAAG,6BAA6B,CAAC;QAQ5C,IAAI,CAAC,IAAI,GAAG,gCAAgC,CAAC;IAC/C,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,MAAM,GAAG,iBAAiB,CAC9B,6BAA6B,EAC7B,SAAS,CACV,CAAC;AAaF,MAAM,KAAK,GAAG,iBAAiB,CAC7B,4BAA4B,EAC5B,SAAS,CACV,CAAC;AAEF;;;;GAIG;AACH,KAAK,UAAU,WAAW;IACxB,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,OAAO,GACV,UAA4D;SAC1D,iBAAiB;QACpB,CAAC,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC,CAAC,iBAAiB,CAAC;IACvD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAiB,CAAC;IAC7C,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACnB,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,IAA0B;IAChE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,yBAAyB;IACvC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,UAAU,uBAAuB;IACrC,OAAO,MAAM,CAAC,GAAG,EAAE,KAAK,SAAS,IAAI,KAAK,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,KAAK,SAAS,CAAC;AAC7E,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,CAAC;IACzC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,8BAA8B,EAAE,CAAC;IACzD,OAAO,MAAM,OAAO,EAAE,CAAC;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAAgC;IAC9D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,CAAC;QACH,8DAA8D;QAC9D,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACtD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAgB,EAChB,EAAwB;IAExB,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;IACpC,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC5D,CAAC"}