opensentinel 3.6.1 → 3.7.0

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 (197) hide show
  1. package/README.md +12 -0
  2. package/dist/{agent-manager-7N7REQZQ.js → agent-manager-JZ4IM7XI.js} +8 -8
  3. package/dist/{agent-processor-I23VWQY3.js → agent-processor-DDDHC2SO.js} +22 -21
  4. package/dist/{agent-processor-I23VWQY3.js.map → agent-processor-DDDHC2SO.js.map} +1 -1
  5. package/dist/{alerting-4I37GG4U.js → alerting-LK7VVYTX.js} +4 -4
  6. package/dist/alerting-LK7VVYTX.js.map +1 -0
  7. package/dist/analyzer-OTWE3ARE.js +22 -0
  8. package/dist/{archiver-XLRIIXPY.js → archiver-FPGKRP6P.js} +16 -85
  9. package/dist/archiver-FPGKRP6P.js.map +1 -0
  10. package/dist/{audit-logger-AU3TMWKI.js → audit-logger-CI4WZQPD.js} +5 -5
  11. package/dist/bot-VDHBGUVI.js +47 -0
  12. package/dist/{brain-SLA474EU.js → brain-6QTXN4QP.js} +18 -17
  13. package/dist/{chunk-AR34B6XR.js → chunk-2I5QHYG6.js} +3 -3
  14. package/dist/chunk-2I5QHYG6.js.map +1 -0
  15. package/dist/chunk-3AWAWRWB.js +143 -0
  16. package/dist/chunk-3AWAWRWB.js.map +1 -0
  17. package/dist/{chunk-PUNIMPMY.js → chunk-4KIHDIXZ.js} +13 -2
  18. package/dist/chunk-4KIHDIXZ.js.map +1 -0
  19. package/dist/{chunk-GUKKW7JI.js → chunk-4WH6MFEW.js} +2 -2
  20. package/dist/chunk-4WH6MFEW.js.map +1 -0
  21. package/dist/{chunk-M7YLQHFP.js → chunk-56UJS2LA.js} +6 -6
  22. package/dist/{chunk-S4NJJS5C.js → chunk-5BTVJR7R.js} +3 -3
  23. package/dist/{chunk-HKOPRRDJ.js → chunk-5JJTLWOR.js} +3 -3
  24. package/dist/chunk-5JJTLWOR.js.map +1 -0
  25. package/dist/chunk-66SAOZPU.js +236 -0
  26. package/dist/chunk-66SAOZPU.js.map +1 -0
  27. package/dist/chunk-6HGMRR4J.js +113 -0
  28. package/dist/chunk-6HGMRR4J.js.map +1 -0
  29. package/dist/{chunk-BMOUYXLX.js → chunk-6ZNCY2GI.js} +5 -5
  30. package/dist/chunk-7BNFELEK.js +31 -0
  31. package/dist/chunk-7BNFELEK.js.map +1 -0
  32. package/dist/{chunk-KABG5PG3.js → chunk-BBN4VCNK.js} +4 -4
  33. package/dist/chunk-BBN4VCNK.js.map +1 -0
  34. package/dist/{chunk-4YJRBMMA.js → chunk-BNZHWAZC.js} +2 -2
  35. package/dist/{chunk-TAAZB5KN.js → chunk-CWT6CAE5.js} +2 -2
  36. package/dist/{chunk-UWUIJTT4.js → chunk-CZTMGHUC.js} +1 -1
  37. package/dist/chunk-CZTMGHUC.js.map +1 -0
  38. package/dist/chunk-DTISLIMB.js +89 -0
  39. package/dist/chunk-DTISLIMB.js.map +1 -0
  40. package/dist/{chunk-VKMFUIVA.js → chunk-GBVJTRXS.js} +2 -2
  41. package/dist/{chunk-MFK34XSY.js → chunk-GJETKBOY.js} +15 -15
  42. package/dist/chunk-GJETKBOY.js.map +1 -0
  43. package/dist/{chunk-HTF2GIQC.js → chunk-GW6V4D43.js} +2 -2
  44. package/dist/chunk-GW6V4D43.js.map +1 -0
  45. package/dist/{chunk-2RGPWU77.js → chunk-HJSEEFO3.js} +2 -2
  46. package/dist/{chunk-JOA5A3G3.js → chunk-HQZQFEAX.js} +5 -5
  47. package/dist/{chunk-45YXODSB.js → chunk-J4JW73TT.js} +2 -2
  48. package/dist/{chunk-KT7NLIXP.js → chunk-JHYYFPKX.js} +2 -2
  49. package/dist/{chunk-XMCVRVTF.js → chunk-P64EV4YY.js} +1 -1
  50. package/dist/chunk-P64EV4YY.js.map +1 -0
  51. package/dist/chunk-PBOCSGNL.js +84 -0
  52. package/dist/chunk-PBOCSGNL.js.map +1 -0
  53. package/dist/{chunk-H3BOLSTS.js → chunk-PD3CTDO6.js} +2 -2
  54. package/dist/{chunk-6UZPE35A.js → chunk-QPY3WRVM.js} +10 -87
  55. package/dist/chunk-QPY3WRVM.js.map +1 -0
  56. package/dist/{chunk-AD6YEH6U.js → chunk-S2EOIVF4.js} +590 -91
  57. package/dist/chunk-S2EOIVF4.js.map +1 -0
  58. package/dist/chunk-SDLOMKCW.js +213 -0
  59. package/dist/chunk-SDLOMKCW.js.map +1 -0
  60. package/dist/{chunk-7MZN73J2.js → chunk-TKBVW7ZJ.js} +4 -4
  61. package/dist/{chunk-A24GPVLY.js → chunk-V3OKHQUX.js} +5 -5
  62. package/dist/{chunk-NMSHVO5O.js → chunk-WMDVOWN6.js} +4 -4
  63. package/dist/{chunk-643M3AP5.js → chunk-WMFYI7XC.js} +7 -7
  64. package/dist/{chunk-6LTLIYAQ.js → chunk-YEDEAX6Y.js} +3 -3
  65. package/dist/{chunk-NYVBXUGD.js → chunk-ZIBRVA3Y.js} +60 -1
  66. package/dist/chunk-ZIBRVA3Y.js.map +1 -0
  67. package/dist/{chunk-6JY4HNUH.js → chunk-ZMML6T63.js} +361 -24
  68. package/dist/chunk-ZMML6T63.js.map +1 -0
  69. package/dist/{chunk-FFV2SXFD.js → chunk-ZVHG4KF2.js} +4 -4
  70. package/dist/cli.js.map +1 -1
  71. package/dist/commands/setup.js +1 -1
  72. package/dist/commands/start.js +2 -2
  73. package/dist/commands/status.js +1 -1
  74. package/dist/commands/stop.js +1 -1
  75. package/dist/commands/utils.js +1 -1
  76. package/dist/{cost-tracker-EMOIOYH7.js → cost-tracker-KZQSTSE2.js} +2 -2
  77. package/dist/{db-LRIOKQBO.js → db-I7MNG6CL.js} +10 -4
  78. package/dist/{discord-NKR3X4AV.js → discord-6UQHCN27.js} +24 -23
  79. package/dist/{documents-EYIYLZK2.js → documents-PFHSK7SZ.js} +19 -19
  80. package/dist/{email-EAQNULVD.js → email-6OIN4SYL.js} +22 -21
  81. package/dist/email-6OIN4SYL.js.map +1 -0
  82. package/dist/{enhanced-retrieval-OGHT6TS5.js → enhanced-retrieval-JWX2HWU4.js} +7 -6
  83. package/dist/{enhanced-retrieval-OGHT6TS5.js.map → enhanced-retrieval-JWX2HWU4.js.map} +1 -1
  84. package/dist/enrichment-pipeline-7FE5R5ZI.js +14 -0
  85. package/dist/{entity-resolution-4X4JU43O.js → entity-resolution-7Z6STVXX.js} +5 -5
  86. package/dist/{env-CHOFICED.js → env-GN5VHI43.js} +2 -2
  87. package/dist/{error-tracker-SVQSDQDW.js → error-tracker-64DEH3D7.js} +6 -6
  88. package/dist/{github-KGNILDWJ.js → github-DUWSXCNP.js} +4 -4
  89. package/dist/graph-client-NB475AK5.js +17 -0
  90. package/dist/{imessage-V2XNDDHT.js → imessage-DSGSGUZS.js} +19 -18
  91. package/dist/{inbox-summarizer-DKKRYXDR.js → inbox-summarizer-F2KAU72V.js} +19 -18
  92. package/dist/{incident-response-ZTIKUWEO.js → incident-response-E3UGMX5G.js} +5 -5
  93. package/dist/incident-response-E3UGMX5G.js.map +1 -0
  94. package/dist/{knowledge-base-J7PJ7MZ3.js → knowledge-base-5SMMOGQJ.js} +5 -5
  95. package/dist/lib.d.ts +21 -0
  96. package/dist/lib.js +64 -57
  97. package/dist/lib.js.map +1 -1
  98. package/dist/{matrix-XHTR53VQ.js → matrix-WYGEOZL5.js} +18 -17
  99. package/dist/{matrix-XHTR53VQ.js.map → matrix-WYGEOZL5.js.map} +1 -1
  100. package/dist/{mcp-3C2TN67D.js → mcp-DJ2QDA6A.js} +2 -2
  101. package/dist/{metrics-VJDWQWU7.js → metrics-BH3ZLGEV.js} +5 -5
  102. package/dist/{multi-user-S56GUD6L.js → multi-user-XAEMB244.js} +4 -4
  103. package/dist/oauth-UPJYFOVU.js +34 -0
  104. package/dist/{ocr-LGUIPKVZ.js → ocr-UONKTQU7.js} +4 -4
  105. package/dist/{presentations-HXTAMGHT.js → presentations-UOET2FVZ.js} +2 -2
  106. package/dist/{providers-H6YIC3MG.js → providers-2YQ6E3IF.js} +3 -3
  107. package/dist/{scheduler-CA5UNHZV.js → scheduler-6PLLAQI7.js} +21 -20
  108. package/dist/{schema-ALJ67YVG.js → schema-ETY7L2VA.js} +8 -2
  109. package/dist/sharepoint-V5P4Q62L.js +30 -0
  110. package/dist/{signal-X7IQJGRQ.js → signal-7D5EPGVL.js} +19 -18
  111. package/dist/{slack-P2LFUJUQ.js → slack-KSS6YK5Z.js} +23 -22
  112. package/dist/slack-KSS6YK5Z.js.map +1 -0
  113. package/dist/{sms-4VME2HUL.js → sms-CSUCC7HL.js} +3 -3
  114. package/dist/sms-CSUCC7HL.js.map +1 -0
  115. package/dist/{src-S5KX4YEV.js → src-GO7GGW7O.js} +48 -41
  116. package/dist/{src-S5KX4YEV.js.map → src-GO7GGW7O.js.map} +1 -1
  117. package/dist/token-store-SEWRX6RE.js +20 -0
  118. package/dist/token-store-SEWRX6RE.js.map +1 -0
  119. package/dist/{tools-FGPN522P.js → tools-PJZ6RI4P.js} +18 -17
  120. package/dist/tools-PJZ6RI4P.js.map +1 -0
  121. package/dist/{whatsapp-KRPQ4YUX.js → whatsapp-DWXK25V2.js} +19 -18
  122. package/dist/whatsapp-DWXK25V2.js.map +1 -0
  123. package/dist/{word-document-D6N2C47N.js → word-document-AV3YB4L2.js} +2 -2
  124. package/dist/{workflow-store-ZYAYE5P6.js → workflow-store-5Y56GUP7.js} +4 -4
  125. package/drizzle/0002_mushy_master_mold.sql +139 -139
  126. package/drizzle/0003_overjoyed_rhodey.sql +46 -0
  127. package/drizzle/meta/0002_snapshot.json +3636 -3636
  128. package/drizzle/meta/0003_snapshot.json +3946 -0
  129. package/drizzle/meta/_journal.json +7 -0
  130. package/package.json +110 -110
  131. package/dist/alerting-4I37GG4U.js.map +0 -1
  132. package/dist/archiver-XLRIIXPY.js.map +0 -1
  133. package/dist/bot-MU2TJQ3Y.js +0 -46
  134. package/dist/chunk-6JY4HNUH.js.map +0 -1
  135. package/dist/chunk-6UZPE35A.js.map +0 -1
  136. package/dist/chunk-AD6YEH6U.js.map +0 -1
  137. package/dist/chunk-AR34B6XR.js.map +0 -1
  138. package/dist/chunk-GUKKW7JI.js.map +0 -1
  139. package/dist/chunk-HKOPRRDJ.js.map +0 -1
  140. package/dist/chunk-HTF2GIQC.js.map +0 -1
  141. package/dist/chunk-KABG5PG3.js.map +0 -1
  142. package/dist/chunk-MFK34XSY.js.map +0 -1
  143. package/dist/chunk-NYVBXUGD.js.map +0 -1
  144. package/dist/chunk-PUNIMPMY.js.map +0 -1
  145. package/dist/chunk-UWUIJTT4.js.map +0 -1
  146. package/dist/chunk-XMCVRVTF.js.map +0 -1
  147. package/dist/email-EAQNULVD.js.map +0 -1
  148. package/dist/enrichment-pipeline-CMUVBDC7.js +0 -14
  149. package/dist/incident-response-ZTIKUWEO.js.map +0 -1
  150. /package/dist/{agent-manager-7N7REQZQ.js.map → agent-manager-JZ4IM7XI.js.map} +0 -0
  151. /package/dist/{audit-logger-AU3TMWKI.js.map → analyzer-OTWE3ARE.js.map} +0 -0
  152. /package/dist/{bot-MU2TJQ3Y.js.map → audit-logger-CI4WZQPD.js.map} +0 -0
  153. /package/dist/{brain-SLA474EU.js.map → bot-VDHBGUVI.js.map} +0 -0
  154. /package/dist/{cost-tracker-EMOIOYH7.js.map → brain-6QTXN4QP.js.map} +0 -0
  155. /package/dist/{chunk-M7YLQHFP.js.map → chunk-56UJS2LA.js.map} +0 -0
  156. /package/dist/{chunk-S4NJJS5C.js.map → chunk-5BTVJR7R.js.map} +0 -0
  157. /package/dist/{chunk-BMOUYXLX.js.map → chunk-6ZNCY2GI.js.map} +0 -0
  158. /package/dist/{chunk-4YJRBMMA.js.map → chunk-BNZHWAZC.js.map} +0 -0
  159. /package/dist/{chunk-TAAZB5KN.js.map → chunk-CWT6CAE5.js.map} +0 -0
  160. /package/dist/{chunk-VKMFUIVA.js.map → chunk-GBVJTRXS.js.map} +0 -0
  161. /package/dist/{chunk-2RGPWU77.js.map → chunk-HJSEEFO3.js.map} +0 -0
  162. /package/dist/{chunk-JOA5A3G3.js.map → chunk-HQZQFEAX.js.map} +0 -0
  163. /package/dist/{chunk-45YXODSB.js.map → chunk-J4JW73TT.js.map} +0 -0
  164. /package/dist/{chunk-KT7NLIXP.js.map → chunk-JHYYFPKX.js.map} +0 -0
  165. /package/dist/{chunk-H3BOLSTS.js.map → chunk-PD3CTDO6.js.map} +0 -0
  166. /package/dist/{chunk-7MZN73J2.js.map → chunk-TKBVW7ZJ.js.map} +0 -0
  167. /package/dist/{chunk-A24GPVLY.js.map → chunk-V3OKHQUX.js.map} +0 -0
  168. /package/dist/{chunk-NMSHVO5O.js.map → chunk-WMDVOWN6.js.map} +0 -0
  169. /package/dist/{chunk-643M3AP5.js.map → chunk-WMFYI7XC.js.map} +0 -0
  170. /package/dist/{chunk-6LTLIYAQ.js.map → chunk-YEDEAX6Y.js.map} +0 -0
  171. /package/dist/{chunk-FFV2SXFD.js.map → chunk-ZVHG4KF2.js.map} +0 -0
  172. /package/dist/{db-LRIOKQBO.js.map → cost-tracker-KZQSTSE2.js.map} +0 -0
  173. /package/dist/{discord-NKR3X4AV.js.map → db-I7MNG6CL.js.map} +0 -0
  174. /package/dist/{enrichment-pipeline-CMUVBDC7.js.map → discord-6UQHCN27.js.map} +0 -0
  175. /package/dist/{documents-EYIYLZK2.js.map → documents-PFHSK7SZ.js.map} +0 -0
  176. /package/dist/{entity-resolution-4X4JU43O.js.map → enrichment-pipeline-7FE5R5ZI.js.map} +0 -0
  177. /package/dist/{env-CHOFICED.js.map → entity-resolution-7Z6STVXX.js.map} +0 -0
  178. /package/dist/{error-tracker-SVQSDQDW.js.map → env-GN5VHI43.js.map} +0 -0
  179. /package/dist/{imessage-V2XNDDHT.js.map → error-tracker-64DEH3D7.js.map} +0 -0
  180. /package/dist/{github-KGNILDWJ.js.map → github-DUWSXCNP.js.map} +0 -0
  181. /package/dist/{inbox-summarizer-DKKRYXDR.js.map → graph-client-NB475AK5.js.map} +0 -0
  182. /package/dist/{knowledge-base-J7PJ7MZ3.js.map → imessage-DSGSGUZS.js.map} +0 -0
  183. /package/dist/{mcp-3C2TN67D.js.map → inbox-summarizer-F2KAU72V.js.map} +0 -0
  184. /package/dist/{metrics-VJDWQWU7.js.map → knowledge-base-5SMMOGQJ.js.map} +0 -0
  185. /package/dist/{ocr-LGUIPKVZ.js.map → mcp-DJ2QDA6A.js.map} +0 -0
  186. /package/dist/{providers-H6YIC3MG.js.map → metrics-BH3ZLGEV.js.map} +0 -0
  187. /package/dist/{multi-user-S56GUD6L.js.map → multi-user-XAEMB244.js.map} +0 -0
  188. /package/dist/{scheduler-CA5UNHZV.js.map → oauth-UPJYFOVU.js.map} +0 -0
  189. /package/dist/{schema-ALJ67YVG.js.map → ocr-UONKTQU7.js.map} +0 -0
  190. /package/dist/{presentations-HXTAMGHT.js.map → presentations-UOET2FVZ.js.map} +0 -0
  191. /package/dist/{signal-X7IQJGRQ.js.map → providers-2YQ6E3IF.js.map} +0 -0
  192. /package/dist/{slack-P2LFUJUQ.js.map → scheduler-6PLLAQI7.js.map} +0 -0
  193. /package/dist/{sms-4VME2HUL.js.map → schema-ETY7L2VA.js.map} +0 -0
  194. /package/dist/{tools-FGPN522P.js.map → sharepoint-V5P4Q62L.js.map} +0 -0
  195. /package/dist/{whatsapp-KRPQ4YUX.js.map → signal-7D5EPGVL.js.map} +0 -0
  196. /package/dist/{word-document-D6N2C47N.js.map → word-document-AV3YB4L2.js.map} +0 -0
  197. /package/dist/{workflow-store-ZYAYE5P6.js.map → workflow-store-5Y56GUP7.js.map} +0 -0
@@ -0,0 +1,213 @@
1
+ import {
2
+ createLogger
3
+ } from "./chunk-7BNFELEK.js";
4
+ import {
5
+ providerRegistry
6
+ } from "./chunk-GW6V4D43.js";
7
+ import {
8
+ db
9
+ } from "./chunk-5BTVJR7R.js";
10
+ import {
11
+ m365AnalysisResults
12
+ } from "./chunk-ZIBRVA3Y.js";
13
+
14
+ // src/integrations/m365/analyzer.ts
15
+ import { eq, desc } from "drizzle-orm";
16
+ var log = createLogger("m365:analyzer");
17
+ var SYSTEM_PROMPT = `You are a security analyst reviewing an email for phishing, business-email-compromise, and credential-harvesting risk.
18
+
19
+ Return STRICT JSON with this exact shape:
20
+ {
21
+ "riskScore": <integer 0-100>,
22
+ "category": <"Safe" | "Suspicious" | "Phishing">,
23
+ "explanation": [<short strings, each one signal>],
24
+ "recommendedActions": [<short strings, each one actionable step>]
25
+ }
26
+
27
+ Scoring guidance:
28
+ - 0-34 Safe: typical business mail, known-good sender patterns, no red flags.
29
+ - 35-69 Suspicious: one or more soft signals (urgency, consumer sender for business content, lookalike domain).
30
+ - 70-100 Phishing: credential harvest, wire-transfer / gift-card fraud, brand impersonation, malicious link patterns.
31
+
32
+ Be specific in explanations \u2014 name the signal, not a category. Return JSON only, no prose.`;
33
+ async function analyzeEmail(input) {
34
+ const started = Date.now();
35
+ const provider = safeGetProvider();
36
+ if (!provider) {
37
+ const result = heuristicAnalyze(input);
38
+ return { ...result, latencyMs: Date.now() - started };
39
+ }
40
+ const userContent = JSON.stringify({
41
+ subject: input.subject,
42
+ sender: input.sender,
43
+ body: truncate(input.body ?? "", 8e3),
44
+ headers: input.headers ?? {}
45
+ });
46
+ try {
47
+ const caps = provider.getCapabilities();
48
+ const model = caps?.defaultModel || (typeof provider.defaultModel === "string" ? provider.defaultModel : "claude-sonnet-4-6");
49
+ const response = await provider.createMessage({
50
+ model,
51
+ max_tokens: 800,
52
+ system: SYSTEM_PROMPT,
53
+ messages: [{ role: "user", content: userContent }]
54
+ });
55
+ const text = extractText(response);
56
+ const parsed = parseJsonResponse(text);
57
+ if (!parsed) throw new Error("LLM returned unparseable JSON");
58
+ const result = {
59
+ riskScore: clampScore(parsed.riskScore),
60
+ category: normaliseCategory(parsed.category, clampScore(parsed.riskScore)),
61
+ explanation: Array.isArray(parsed.explanation) ? parsed.explanation.map(String) : [],
62
+ recommendedActions: Array.isArray(parsed.recommendedActions) ? parsed.recommendedActions.map(String) : [],
63
+ engine: "llm",
64
+ model,
65
+ latencyMs: Date.now() - started
66
+ };
67
+ return result;
68
+ } catch (err) {
69
+ log.warn("LLM analysis failed, falling back to heuristic", {
70
+ error: err instanceof Error ? err.message : String(err)
71
+ });
72
+ const result = heuristicAnalyze(input);
73
+ return { ...result, latencyMs: Date.now() - started };
74
+ }
75
+ }
76
+ async function persistAnalysis(opts) {
77
+ const inserted = await db.insert(m365AnalysisResults).values({
78
+ userKey: opts.userKey,
79
+ inputType: opts.inputType ?? "email",
80
+ inputId: opts.inputId ?? null,
81
+ subject: opts.input.subject,
82
+ sender: opts.input.sender,
83
+ riskScore: opts.result.riskScore,
84
+ category: opts.result.category,
85
+ explanation: opts.result.explanation,
86
+ recommendedActions: opts.result.recommendedActions,
87
+ engine: opts.result.engine,
88
+ model: opts.result.model ?? null,
89
+ latencyMs: opts.result.latencyMs
90
+ }).returning({ id: m365AnalysisResults.id });
91
+ return inserted[0].id;
92
+ }
93
+ async function listAnalyses(userKey, limit = 50) {
94
+ return db.select().from(m365AnalysisResults).where(eq(m365AnalysisResults.userKey, userKey)).orderBy(desc(m365AnalysisResults.createdAt)).limit(limit);
95
+ }
96
+ var KNOWN_BRANDS = [
97
+ "paypal.com",
98
+ "microsoft.com",
99
+ "apple.com",
100
+ "amazon.com",
101
+ "google.com",
102
+ "netflix.com",
103
+ "chase.com",
104
+ "bankofamerica.com"
105
+ ];
106
+ function heuristicAnalyze(input) {
107
+ const explanation = [];
108
+ let score = 0;
109
+ const sender = input.sender.toLowerCase();
110
+ const body = (input.body ?? "").toLowerCase();
111
+ const subject = input.subject.toLowerCase();
112
+ const combined = `${body} ${subject}`;
113
+ if (/(urgent|immediately|act now|wire transfer|gift card|verify your account|password expires)/i.test(combined)) {
114
+ score += 25;
115
+ explanation.push("Urgency or credential-harvest phrasing detected.");
116
+ }
117
+ if (/(click here|tap here|verify account|reset your password|confirm identity|login to continue|restore access|regain access)/i.test(combined)) {
118
+ score += 20;
119
+ explanation.push("Common social-engineering phrases detected.");
120
+ }
121
+ if (/(account (has been )?(suspended|terminated|locked|disabled|compromised))/i.test(combined)) {
122
+ score += 20;
123
+ explanation.push("Account-status fear phrasing detected.");
124
+ }
125
+ for (const brand of KNOWN_BRANDS) {
126
+ const brandName = brand.split(".")[0];
127
+ if (sender.includes(brandName) && !sender.endsWith(`@${brand}`) && !sender.endsWith(`.${brand}`)) {
128
+ score += 50;
129
+ explanation.push(`Possible impersonation of ${brand} \u2014 sender domain does not match.`);
130
+ break;
131
+ }
132
+ }
133
+ if (/@(gmail|outlook|hotmail|yahoo|proton)\.com$/.test(sender) && /(invoice|wire|payment|urgent)/i.test(combined)) {
134
+ score += 15;
135
+ explanation.push("Consumer mailbox is requesting business payment action.");
136
+ }
137
+ const linkCount = (body.match(/https?:\/\/[^\s)<]+/g) || []).length;
138
+ if (linkCount > 10) {
139
+ score += 10;
140
+ explanation.push(`High link density (${linkCount} URLs).`);
141
+ }
142
+ score = Math.min(100, score);
143
+ const category = normaliseCategory(void 0, score);
144
+ const recommendedActions = category === "Phishing" ? [
145
+ "Do not click links or open attachments.",
146
+ "Report to your security team or phishing@ mailbox.",
147
+ "Verify sender via a trusted out-of-band channel."
148
+ ] : category === "Suspicious" ? [
149
+ "Verify sender identity through a known channel before acting.",
150
+ "Inspect link destinations before clicking."
151
+ ] : ["No high-risk signals detected \u2014 proceed with normal vigilance."];
152
+ return {
153
+ riskScore: score,
154
+ category,
155
+ explanation: explanation.length ? explanation : ["No major high-risk indicators detected."],
156
+ recommendedActions,
157
+ engine: "heuristic",
158
+ latencyMs: 0
159
+ };
160
+ }
161
+ function safeGetProvider() {
162
+ try {
163
+ return providerRegistry.getDefault();
164
+ } catch {
165
+ return null;
166
+ }
167
+ }
168
+ function truncate(s, n) {
169
+ return s.length > n ? s.slice(0, n) + "...[truncated]" : s;
170
+ }
171
+ function clampScore(x) {
172
+ const n = Number(x);
173
+ if (!Number.isFinite(n)) return 0;
174
+ return Math.max(0, Math.min(100, Math.round(n)));
175
+ }
176
+ function normaliseCategory(raw, score) {
177
+ const v = typeof raw === "string" ? raw.toLowerCase() : "";
178
+ if (v.includes("phish")) return "Phishing";
179
+ if (v.includes("suspic")) return "Suspicious";
180
+ if (v.includes("safe")) return "Safe";
181
+ if (score >= 70) return "Phishing";
182
+ if (score >= 35) return "Suspicious";
183
+ return "Safe";
184
+ }
185
+ function extractText(response) {
186
+ const r = response;
187
+ if (!r) return "";
188
+ if (typeof r.content === "string") return r.content;
189
+ if (Array.isArray(r.content)) {
190
+ return r.content.map((b) => typeof b === "string" ? b : b?.text ?? "").join("");
191
+ }
192
+ if (typeof r.text === "string") return r.text;
193
+ return "";
194
+ }
195
+ function parseJsonResponse(text) {
196
+ if (!text) return null;
197
+ const match = text.match(/\{[\s\S]*\}/);
198
+ if (!match) return null;
199
+ try {
200
+ return JSON.parse(match[0]);
201
+ } catch {
202
+ return null;
203
+ }
204
+ }
205
+
206
+ export {
207
+ analyzeEmail,
208
+ persistAnalysis,
209
+ listAnalyses,
210
+ heuristicAnalyze,
211
+ parseJsonResponse
212
+ };
213
+ //# sourceMappingURL=chunk-SDLOMKCW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/integrations/m365/analyzer.ts"],"sourcesContent":["/**\n * Email risk analysis — LLM first, with a deterministic heuristic fallback.\n *\n * Uses the default LLM provider from providerRegistry (typically Anthropic) to\n * produce structured { riskScore, category, explanation, recommendedActions }.\n * Falls back to regex heuristics when no provider is registered — useful for\n * tests and self-hosted deployments without an LLM key.\n */\n\nimport { db, m365AnalysisResults } from \"../../db\";\nimport { providerRegistry } from \"../../core/providers\";\nimport { eq, desc } from \"drizzle-orm\";\nimport { createLogger } from \"../../core/logger\";\n\nconst log = createLogger(\"m365:analyzer\");\n\nexport interface AnalysisInput {\n subject: string;\n sender: string;\n body?: string;\n headers?: Record<string, string>;\n}\n\nexport type AnalysisCategory = \"Safe\" | \"Suspicious\" | \"Phishing\" | \"Error\";\n\nexport interface AnalysisResult {\n riskScore: number; // 0-100\n category: AnalysisCategory;\n explanation: string[];\n recommendedActions: string[];\n engine: \"llm\" | \"heuristic\";\n model?: string;\n latencyMs: number;\n}\n\nconst SYSTEM_PROMPT = `You are a security analyst reviewing an email for phishing, business-email-compromise, and credential-harvesting risk.\n\nReturn STRICT JSON with this exact shape:\n{\n \"riskScore\": <integer 0-100>,\n \"category\": <\"Safe\" | \"Suspicious\" | \"Phishing\">,\n \"explanation\": [<short strings, each one signal>],\n \"recommendedActions\": [<short strings, each one actionable step>]\n}\n\nScoring guidance:\n- 0-34 Safe: typical business mail, known-good sender patterns, no red flags.\n- 35-69 Suspicious: one or more soft signals (urgency, consumer sender for business content, lookalike domain).\n- 70-100 Phishing: credential harvest, wire-transfer / gift-card fraud, brand impersonation, malicious link patterns.\n\nBe specific in explanations — name the signal, not a category. Return JSON only, no prose.`;\n\nexport async function analyzeEmail(input: AnalysisInput): Promise<AnalysisResult> {\n const started = Date.now();\n const provider = safeGetProvider();\n\n if (!provider) {\n const result = heuristicAnalyze(input);\n return { ...result, latencyMs: Date.now() - started };\n }\n\n const userContent = JSON.stringify({\n subject: input.subject,\n sender: input.sender,\n body: truncate(input.body ?? \"\", 8000),\n headers: input.headers ?? {},\n });\n\n try {\n const caps = provider.getCapabilities();\n const model =\n (caps as any)?.defaultModel ||\n (typeof (provider as any).defaultModel === \"string\" ? (provider as any).defaultModel : \"claude-sonnet-4-6\");\n\n const response = await provider.createMessage({\n model,\n max_tokens: 800,\n system: SYSTEM_PROMPT,\n messages: [{ role: \"user\", content: userContent }],\n });\n\n const text = extractText(response);\n const parsed = parseJsonResponse(text);\n if (!parsed) throw new Error(\"LLM returned unparseable JSON\");\n\n const result: AnalysisResult = {\n riskScore: clampScore(parsed.riskScore),\n category: normaliseCategory(parsed.category, clampScore(parsed.riskScore)),\n explanation: Array.isArray(parsed.explanation) ? parsed.explanation.map(String) : [],\n recommendedActions: Array.isArray(parsed.recommendedActions)\n ? parsed.recommendedActions.map(String)\n : [],\n engine: \"llm\",\n model,\n latencyMs: Date.now() - started,\n };\n return result;\n } catch (err) {\n log.warn(\"LLM analysis failed, falling back to heuristic\", {\n error: err instanceof Error ? err.message : String(err),\n });\n const result = heuristicAnalyze(input);\n return { ...result, latencyMs: Date.now() - started };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Persistence\n// ---------------------------------------------------------------------------\n\nexport interface PersistOpts {\n userKey: string;\n input: AnalysisInput;\n inputId?: string;\n inputType?: \"email\" | \"file\" | \"document\";\n result: AnalysisResult;\n}\n\nexport async function persistAnalysis(opts: PersistOpts): Promise<string> {\n const inserted = await db\n .insert(m365AnalysisResults)\n .values({\n userKey: opts.userKey,\n inputType: opts.inputType ?? \"email\",\n inputId: opts.inputId ?? null,\n subject: opts.input.subject,\n sender: opts.input.sender,\n riskScore: opts.result.riskScore,\n category: opts.result.category,\n explanation: opts.result.explanation,\n recommendedActions: opts.result.recommendedActions,\n engine: opts.result.engine,\n model: opts.result.model ?? null,\n latencyMs: opts.result.latencyMs,\n })\n .returning({ id: m365AnalysisResults.id });\n return inserted[0].id;\n}\n\nexport async function listAnalyses(userKey: string, limit = 50) {\n return db\n .select()\n .from(m365AnalysisResults)\n .where(eq(m365AnalysisResults.userKey, userKey))\n .orderBy(desc(m365AnalysisResults.createdAt))\n .limit(limit);\n}\n\n// ---------------------------------------------------------------------------\n// Heuristic fallback\n// ---------------------------------------------------------------------------\n\nconst KNOWN_BRANDS = [\n \"paypal.com\",\n \"microsoft.com\",\n \"apple.com\",\n \"amazon.com\",\n \"google.com\",\n \"netflix.com\",\n \"chase.com\",\n \"bankofamerica.com\",\n];\n\nexport function heuristicAnalyze(input: AnalysisInput): AnalysisResult {\n const explanation: string[] = [];\n let score = 0;\n\n const sender = input.sender.toLowerCase();\n const body = (input.body ?? \"\").toLowerCase();\n const subject = input.subject.toLowerCase();\n const combined = `${body} ${subject}`;\n\n if (/(urgent|immediately|act now|wire transfer|gift card|verify your account|password expires)/i.test(combined)) {\n score += 25;\n explanation.push(\"Urgency or credential-harvest phrasing detected.\");\n }\n\n if (/(click here|tap here|verify account|reset your password|confirm identity|login to continue|restore access|regain access)/i.test(combined)) {\n score += 20;\n explanation.push(\"Common social-engineering phrases detected.\");\n }\n\n if (/(account (has been )?(suspended|terminated|locked|disabled|compromised))/i.test(combined)) {\n score += 20;\n explanation.push(\"Account-status fear phrasing detected.\");\n }\n\n for (const brand of KNOWN_BRANDS) {\n const brandName = brand.split(\".\")[0];\n if (sender.includes(brandName) && !sender.endsWith(`@${brand}`) && !sender.endsWith(`.${brand}`)) {\n score += 50;\n explanation.push(`Possible impersonation of ${brand} — sender domain does not match.`);\n break;\n }\n }\n\n if (/@(gmail|outlook|hotmail|yahoo|proton)\\.com$/.test(sender) && /(invoice|wire|payment|urgent)/i.test(combined)) {\n score += 15;\n explanation.push(\"Consumer mailbox is requesting business payment action.\");\n }\n\n const linkCount = (body.match(/https?:\\/\\/[^\\s)<]+/g) || []).length;\n if (linkCount > 10) {\n score += 10;\n explanation.push(`High link density (${linkCount} URLs).`);\n }\n\n score = Math.min(100, score);\n const category = normaliseCategory(undefined, score);\n\n const recommendedActions: string[] =\n category === \"Phishing\"\n ? [\n \"Do not click links or open attachments.\",\n \"Report to your security team or phishing@ mailbox.\",\n \"Verify sender via a trusted out-of-band channel.\",\n ]\n : category === \"Suspicious\"\n ? [\n \"Verify sender identity through a known channel before acting.\",\n \"Inspect link destinations before clicking.\",\n ]\n : [\"No high-risk signals detected — proceed with normal vigilance.\"];\n\n return {\n riskScore: score,\n category,\n explanation: explanation.length ? explanation : [\"No major high-risk indicators detected.\"],\n recommendedActions,\n engine: \"heuristic\",\n latencyMs: 0,\n };\n}\n\n// ---------------------------------------------------------------------------\n// internals\n// ---------------------------------------------------------------------------\n\nfunction safeGetProvider() {\n try {\n return providerRegistry.getDefault();\n } catch {\n return null;\n }\n}\n\nfunction truncate(s: string, n: number): string {\n return s.length > n ? s.slice(0, n) + \"...[truncated]\" : s;\n}\n\nfunction clampScore(x: unknown): number {\n const n = Number(x);\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.min(100, Math.round(n)));\n}\n\nfunction normaliseCategory(raw: unknown, score: number): AnalysisCategory {\n const v = typeof raw === \"string\" ? raw.toLowerCase() : \"\";\n if (v.includes(\"phish\")) return \"Phishing\";\n if (v.includes(\"suspic\")) return \"Suspicious\";\n if (v.includes(\"safe\")) return \"Safe\";\n if (score >= 70) return \"Phishing\";\n if (score >= 35) return \"Suspicious\";\n return \"Safe\";\n}\n\nfunction extractText(response: unknown): string {\n // Provider response may be { content: string | blocks[] } or shaped differently.\n const r = response as any;\n if (!r) return \"\";\n if (typeof r.content === \"string\") return r.content;\n if (Array.isArray(r.content)) {\n return r.content\n .map((b: any) => (typeof b === \"string\" ? b : b?.text ?? \"\"))\n .join(\"\");\n }\n if (typeof r.text === \"string\") return r.text;\n return \"\";\n}\n\nexport function parseJsonResponse(text: string): {\n riskScore?: unknown;\n category?: unknown;\n explanation?: unknown;\n recommendedActions?: unknown;\n} | null {\n if (!text) return null;\n // Extract the first {...} block — tolerant of LLMs that wrap with code fences or prose.\n const match = text.match(/\\{[\\s\\S]*\\}/);\n if (!match) return null;\n try {\n return JSON.parse(match[0]);\n } catch {\n return null;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;AAWA,SAAS,IAAI,YAAY;AAGzB,IAAM,MAAM,aAAa,eAAe;AAqBxC,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBtB,eAAsB,aAAa,OAA+C;AAChF,QAAM,UAAU,KAAK,IAAI;AACzB,QAAM,WAAW,gBAAgB;AAEjC,MAAI,CAAC,UAAU;AACb,UAAM,SAAS,iBAAiB,KAAK;AACrC,WAAO,EAAE,GAAG,QAAQ,WAAW,KAAK,IAAI,IAAI,QAAQ;AAAA,EACtD;AAEA,QAAM,cAAc,KAAK,UAAU;AAAA,IACjC,SAAS,MAAM;AAAA,IACf,QAAQ,MAAM;AAAA,IACd,MAAM,SAAS,MAAM,QAAQ,IAAI,GAAI;AAAA,IACrC,SAAS,MAAM,WAAW,CAAC;AAAA,EAC7B,CAAC;AAED,MAAI;AACF,UAAM,OAAO,SAAS,gBAAgB;AACtC,UAAM,QACH,MAAc,iBACd,OAAQ,SAAiB,iBAAiB,WAAY,SAAiB,eAAe;AAEzF,UAAM,WAAW,MAAM,SAAS,cAAc;AAAA,MAC5C;AAAA,MACA,YAAY;AAAA,MACZ,QAAQ;AAAA,MACR,UAAU,CAAC,EAAE,MAAM,QAAQ,SAAS,YAAY,CAAC;AAAA,IACnD,CAAC;AAED,UAAM,OAAO,YAAY,QAAQ;AACjC,UAAM,SAAS,kBAAkB,IAAI;AACrC,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,+BAA+B;AAE5D,UAAM,SAAyB;AAAA,MAC7B,WAAW,WAAW,OAAO,SAAS;AAAA,MACtC,UAAU,kBAAkB,OAAO,UAAU,WAAW,OAAO,SAAS,CAAC;AAAA,MACzE,aAAa,MAAM,QAAQ,OAAO,WAAW,IAAI,OAAO,YAAY,IAAI,MAAM,IAAI,CAAC;AAAA,MACnF,oBAAoB,MAAM,QAAQ,OAAO,kBAAkB,IACvD,OAAO,mBAAmB,IAAI,MAAM,IACpC,CAAC;AAAA,MACL,QAAQ;AAAA,MACR;AAAA,MACA,WAAW,KAAK,IAAI,IAAI;AAAA,IAC1B;AACA,WAAO;AAAA,EACT,SAAS,KAAK;AACZ,QAAI,KAAK,kDAAkD;AAAA,MACzD,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,IACxD,CAAC;AACD,UAAM,SAAS,iBAAiB,KAAK;AACrC,WAAO,EAAE,GAAG,QAAQ,WAAW,KAAK,IAAI,IAAI,QAAQ;AAAA,EACtD;AACF;AAcA,eAAsB,gBAAgB,MAAoC;AACxE,QAAM,WAAW,MAAM,GACpB,OAAO,mBAAmB,EAC1B,OAAO;AAAA,IACN,SAAS,KAAK;AAAA,IACd,WAAW,KAAK,aAAa;AAAA,IAC7B,SAAS,KAAK,WAAW;AAAA,IACzB,SAAS,KAAK,MAAM;AAAA,IACpB,QAAQ,KAAK,MAAM;AAAA,IACnB,WAAW,KAAK,OAAO;AAAA,IACvB,UAAU,KAAK,OAAO;AAAA,IACtB,aAAa,KAAK,OAAO;AAAA,IACzB,oBAAoB,KAAK,OAAO;AAAA,IAChC,QAAQ,KAAK,OAAO;AAAA,IACpB,OAAO,KAAK,OAAO,SAAS;AAAA,IAC5B,WAAW,KAAK,OAAO;AAAA,EACzB,CAAC,EACA,UAAU,EAAE,IAAI,oBAAoB,GAAG,CAAC;AAC3C,SAAO,SAAS,CAAC,EAAE;AACrB;AAEA,eAAsB,aAAa,SAAiB,QAAQ,IAAI;AAC9D,SAAO,GACJ,OAAO,EACP,KAAK,mBAAmB,EACxB,MAAM,GAAG,oBAAoB,SAAS,OAAO,CAAC,EAC9C,QAAQ,KAAK,oBAAoB,SAAS,CAAC,EAC3C,MAAM,KAAK;AAChB;AAMA,IAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,iBAAiB,OAAsC;AACrE,QAAM,cAAwB,CAAC;AAC/B,MAAI,QAAQ;AAEZ,QAAM,SAAS,MAAM,OAAO,YAAY;AACxC,QAAM,QAAQ,MAAM,QAAQ,IAAI,YAAY;AAC5C,QAAM,UAAU,MAAM,QAAQ,YAAY;AAC1C,QAAM,WAAW,GAAG,IAAI,IAAI,OAAO;AAEnC,MAAI,6FAA6F,KAAK,QAAQ,GAAG;AAC/G,aAAS;AACT,gBAAY,KAAK,kDAAkD;AAAA,EACrE;AAEA,MAAI,4HAA4H,KAAK,QAAQ,GAAG;AAC9I,aAAS;AACT,gBAAY,KAAK,6CAA6C;AAAA,EAChE;AAEA,MAAI,4EAA4E,KAAK,QAAQ,GAAG;AAC9F,aAAS;AACT,gBAAY,KAAK,wCAAwC;AAAA,EAC3D;AAEA,aAAW,SAAS,cAAc;AAChC,UAAM,YAAY,MAAM,MAAM,GAAG,EAAE,CAAC;AACpC,QAAI,OAAO,SAAS,SAAS,KAAK,CAAC,OAAO,SAAS,IAAI,KAAK,EAAE,KAAK,CAAC,OAAO,SAAS,IAAI,KAAK,EAAE,GAAG;AAChG,eAAS;AACT,kBAAY,KAAK,6BAA6B,KAAK,uCAAkC;AACrF;AAAA,IACF;AAAA,EACF;AAEA,MAAI,8CAA8C,KAAK,MAAM,KAAK,iCAAiC,KAAK,QAAQ,GAAG;AACjH,aAAS;AACT,gBAAY,KAAK,yDAAyD;AAAA,EAC5E;AAEA,QAAM,aAAa,KAAK,MAAM,sBAAsB,KAAK,CAAC,GAAG;AAC7D,MAAI,YAAY,IAAI;AAClB,aAAS;AACT,gBAAY,KAAK,sBAAsB,SAAS,SAAS;AAAA,EAC3D;AAEA,UAAQ,KAAK,IAAI,KAAK,KAAK;AAC3B,QAAM,WAAW,kBAAkB,QAAW,KAAK;AAEnD,QAAM,qBACJ,aAAa,aACT;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,EACF,IACA,aAAa,eACX;AAAA,IACE;AAAA,IACA;AAAA,EACF,IACA,CAAC,qEAAgE;AAEzE,SAAO;AAAA,IACL,WAAW;AAAA,IACX;AAAA,IACA,aAAa,YAAY,SAAS,cAAc,CAAC,yCAAyC;AAAA,IAC1F;AAAA,IACA,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AACF;AAMA,SAAS,kBAAkB;AACzB,MAAI;AACF,WAAO,iBAAiB,WAAW;AAAA,EACrC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,SAAS,GAAW,GAAmB;AAC9C,SAAO,EAAE,SAAS,IAAI,EAAE,MAAM,GAAG,CAAC,IAAI,mBAAmB;AAC3D;AAEA,SAAS,WAAW,GAAoB;AACtC,QAAM,IAAI,OAAO,CAAC;AAClB,MAAI,CAAC,OAAO,SAAS,CAAC,EAAG,QAAO;AAChC,SAAO,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC;AACjD;AAEA,SAAS,kBAAkB,KAAc,OAAiC;AACxE,QAAM,IAAI,OAAO,QAAQ,WAAW,IAAI,YAAY,IAAI;AACxD,MAAI,EAAE,SAAS,OAAO,EAAG,QAAO;AAChC,MAAI,EAAE,SAAS,QAAQ,EAAG,QAAO;AACjC,MAAI,EAAE,SAAS,MAAM,EAAG,QAAO;AAC/B,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI,SAAS,GAAI,QAAO;AACxB,SAAO;AACT;AAEA,SAAS,YAAY,UAA2B;AAE9C,QAAM,IAAI;AACV,MAAI,CAAC,EAAG,QAAO;AACf,MAAI,OAAO,EAAE,YAAY,SAAU,QAAO,EAAE;AAC5C,MAAI,MAAM,QAAQ,EAAE,OAAO,GAAG;AAC5B,WAAO,EAAE,QACN,IAAI,CAAC,MAAY,OAAO,MAAM,WAAW,IAAI,GAAG,QAAQ,EAAG,EAC3D,KAAK,EAAE;AAAA,EACZ;AACA,MAAI,OAAO,EAAE,SAAS,SAAU,QAAO,EAAE;AACzC,SAAO;AACT;AAEO,SAAS,kBAAkB,MAKzB;AACP,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,QAAQ,KAAK,MAAM,aAAa;AACtC,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI;AACF,WAAO,KAAK,MAAM,MAAM,CAAC,CAAC;AAAA,EAC5B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  metric
3
- } from "./chunk-6LTLIYAQ.js";
3
+ } from "./chunk-YEDEAX6Y.js";
4
4
  import {
5
5
  db
6
- } from "./chunk-S4NJJS5C.js";
6
+ } from "./chunk-5BTVJR7R.js";
7
7
  import {
8
8
  errorLogs
9
- } from "./chunk-NYVBXUGD.js";
9
+ } from "./chunk-ZIBRVA3Y.js";
10
10
 
11
11
  // src/core/observability/error-tracker.ts
12
12
  import { eq, and, gte, lte, desc } from "drizzle-orm";
@@ -159,4 +159,4 @@ export {
159
159
  cleanupOldErrors,
160
160
  errorContext
161
161
  };
162
- //# sourceMappingURL=chunk-7MZN73J2.js.map
162
+ //# sourceMappingURL=chunk-TKBVW7ZJ.js.map
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  resolveEntity
3
- } from "./chunk-AR34B6XR.js";
3
+ } from "./chunk-2I5QHYG6.js";
4
4
  import {
5
5
  db
6
- } from "./chunk-S4NJJS5C.js";
6
+ } from "./chunk-5BTVJR7R.js";
7
7
  import {
8
8
  env
9
- } from "./chunk-PUNIMPMY.js";
9
+ } from "./chunk-4KIHDIXZ.js";
10
10
  import {
11
11
  graphEntities,
12
12
  graphRelationships
13
- } from "./chunk-NYVBXUGD.js";
13
+ } from "./chunk-ZIBRVA3Y.js";
14
14
 
15
15
  // src/core/intelligence/enrichment-pipeline.ts
16
16
  import { eq as eq2, sql } from "drizzle-orm";
@@ -2440,4 +2440,4 @@ export {
2440
2440
  enrichEntity,
2441
2441
  batchEnrich
2442
2442
  };
2443
- //# sourceMappingURL=chunk-A24GPVLY.js.map
2443
+ //# sourceMappingURL=chunk-V3OKHQUX.js.map
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  transcribeAudio
3
- } from "./chunk-4YJRBMMA.js";
3
+ } from "./chunk-BNZHWAZC.js";
4
4
  import {
5
5
  scheduleReminder
6
- } from "./chunk-MFK34XSY.js";
6
+ } from "./chunk-GJETKBOY.js";
7
7
  import {
8
8
  chatWithTools
9
- } from "./chunk-6JY4HNUH.js";
9
+ } from "./chunk-ZMML6T63.js";
10
10
 
11
11
  // src/inputs/slack/index.ts
12
12
  import { createRequire } from "module";
@@ -800,4 +800,4 @@ export {
800
800
  createSlackBot,
801
801
  slack_default
802
802
  };
803
- //# sourceMappingURL=chunk-NMSHVO5O.js.map
803
+ //# sourceMappingURL=chunk-WMDVOWN6.js.map
@@ -1,23 +1,23 @@
1
1
  import {
2
2
  metric
3
- } from "./chunk-6LTLIYAQ.js";
3
+ } from "./chunk-YEDEAX6Y.js";
4
4
  import {
5
5
  costTracker
6
- } from "./chunk-BMOUYXLX.js";
6
+ } from "./chunk-6ZNCY2GI.js";
7
7
  import {
8
8
  audit
9
- } from "./chunk-KABG5PG3.js";
9
+ } from "./chunk-BBN4VCNK.js";
10
10
  import {
11
11
  db
12
- } from "./chunk-S4NJJS5C.js";
12
+ } from "./chunk-5BTVJR7R.js";
13
13
  import {
14
14
  env
15
- } from "./chunk-PUNIMPMY.js";
15
+ } from "./chunk-4KIHDIXZ.js";
16
16
  import {
17
17
  agentMessages,
18
18
  agentProgress,
19
19
  subAgents
20
- } from "./chunk-NYVBXUGD.js";
20
+ } from "./chunk-ZIBRVA3Y.js";
21
21
 
22
22
  // src/core/agents/agent-manager.ts
23
23
  import { eq, and, desc } from "drizzle-orm";
@@ -561,4 +561,4 @@ export {
561
561
  updateAgentTokens,
562
562
  agent_manager_default
563
563
  };
564
- //# sourceMappingURL=chunk-643M3AP5.js.map
564
+ //# sourceMappingURL=chunk-WMFYI7XC.js.map
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  db
3
- } from "./chunk-S4NJJS5C.js";
3
+ } from "./chunk-5BTVJR7R.js";
4
4
  import {
5
5
  metrics
6
- } from "./chunk-NYVBXUGD.js";
6
+ } from "./chunk-ZIBRVA3Y.js";
7
7
 
8
8
  // src/core/observability/metrics.ts
9
9
  import { eq, and, gte, lte, desc } from "drizzle-orm";
@@ -191,4 +191,4 @@ export {
191
191
  getSystemMetrics,
192
192
  cleanupOldMetrics
193
193
  };
194
- //# sourceMappingURL=chunk-6LTLIYAQ.js.map
194
+ //# sourceMappingURL=chunk-YEDEAX6Y.js.map
@@ -20,6 +20,9 @@ __export(schema_exports, {
20
20
  graphEntities: () => graphEntities,
21
21
  graphRelationships: () => graphRelationships,
22
22
  incidentTimeline: () => incidentTimeline,
23
+ m365AnalysisResults: () => m365AnalysisResults,
24
+ m365Connections: () => m365Connections,
25
+ m365OauthStates: () => m365OauthStates,
23
26
  memories: () => memories,
24
27
  messages: () => messages,
25
28
  metrics: () => metrics,
@@ -622,6 +625,59 @@ var incidentTimeline = pgTable(
622
625
  },
623
626
  (table) => [index("incident_timeline_incident_idx").on(table.incidentId)]
624
627
  );
628
+ var m365OauthStates = pgTable(
629
+ "m365_oauth_states",
630
+ {
631
+ state: text("state").primaryKey(),
632
+ codeVerifier: text("code_verifier").notNull(),
633
+ userKey: text("user_key"),
634
+ returnTo: text("return_to"),
635
+ createdAt: timestamp("created_at").defaultNow().notNull(),
636
+ expiresAt: timestamp("expires_at").notNull()
637
+ },
638
+ (table) => [index("m365_oauth_states_expires_idx").on(table.expiresAt)]
639
+ );
640
+ var m365Connections = pgTable(
641
+ "m365_connections",
642
+ {
643
+ id: uuid("id").primaryKey().defaultRandom(),
644
+ userKey: text("user_key").notNull().unique(),
645
+ microsoftUserId: text("microsoft_user_id"),
646
+ email: text("email"),
647
+ displayName: text("display_name"),
648
+ accessTokenEncrypted: text("access_token_encrypted").notNull(),
649
+ refreshTokenEncrypted: text("refresh_token_encrypted"),
650
+ scope: text("scope"),
651
+ tokenType: text("token_type").default("Bearer"),
652
+ expiresAt: timestamp("expires_at").notNull(),
653
+ createdAt: timestamp("created_at").defaultNow().notNull(),
654
+ updatedAt: timestamp("updated_at").defaultNow().notNull()
655
+ },
656
+ (table) => [index("m365_connections_user_idx").on(table.userKey)]
657
+ );
658
+ var m365AnalysisResults = pgTable(
659
+ "m365_analysis_results",
660
+ {
661
+ id: uuid("id").primaryKey().defaultRandom(),
662
+ userKey: text("user_key").notNull(),
663
+ inputType: text("input_type").notNull().$type(),
664
+ inputId: text("input_id"),
665
+ subject: text("subject"),
666
+ sender: text("sender"),
667
+ riskScore: integer("risk_score").notNull(),
668
+ category: text("category").notNull().$type(),
669
+ explanation: jsonb("explanation").$type(),
670
+ recommendedActions: jsonb("recommended_actions").$type(),
671
+ engine: text("engine").notNull().$type(),
672
+ model: text("model"),
673
+ latencyMs: integer("latency_ms"),
674
+ createdAt: timestamp("created_at").defaultNow().notNull()
675
+ },
676
+ (table) => [
677
+ index("m365_analysis_user_idx").on(table.userKey),
678
+ index("m365_analysis_created_idx").on(table.createdAt)
679
+ ]
680
+ );
625
681
 
626
682
  export {
627
683
  users,
@@ -657,6 +713,9 @@ export {
657
713
  twoFactorAuth,
658
714
  securityIncidents,
659
715
  incidentTimeline,
716
+ m365OauthStates,
717
+ m365Connections,
718
+ m365AnalysisResults,
660
719
  schema_exports
661
720
  };
662
- //# sourceMappingURL=chunk-NYVBXUGD.js.map
721
+ //# sourceMappingURL=chunk-ZIBRVA3Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/db/schema.ts"],"sourcesContent":["import {\r\n pgTable,\r\n text,\r\n timestamp,\r\n uuid,\r\n integer,\r\n jsonb,\r\n boolean,\r\n vector,\r\n index,\r\n customType,\r\n} from \"drizzle-orm/pg-core\";\r\n\r\n// Custom tsvector type for full-text search\r\nconst tsvector = customType<{ data: string }>({\r\n dataType() {\r\n return \"tsvector\";\r\n },\r\n});\r\n\r\n// Users table\r\nexport const users = pgTable(\"users\", {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n telegramId: text(\"telegram_id\").unique(),\r\n name: text(\"name\"),\r\n preferences: jsonb(\"preferences\").$type<{\r\n timezone?: string;\r\n language?: string;\r\n verbosity?: \"terse\" | \"normal\" | \"detailed\";\r\n persona?: \"formal\" | \"casual\" | \"snarky\";\r\n }>(),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n updatedAt: timestamp(\"updated_at\").defaultNow().notNull(),\r\n});\r\n\r\n// Conversations table\r\nexport const conversations = pgTable(\"conversations\", {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\").references(() => users.id),\r\n title: text(\"title\"),\r\n source: text(\"source\").notNull().default(\"telegram\"), // telegram, web, api\r\n metadata: jsonb(\"metadata\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n updatedAt: timestamp(\"updated_at\").defaultNow().notNull(),\r\n});\r\n\r\n// Messages table\r\nexport const messages = pgTable(\r\n \"messages\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n conversationId: uuid(\"conversation_id\")\r\n .references(() => conversations.id)\r\n .notNull(),\r\n role: text(\"role\").notNull().$type<\"user\" | \"assistant\" | \"system\">(),\r\n content: text(\"content\").notNull(),\r\n tokenCount: integer(\"token_count\"),\r\n metadata: jsonb(\"metadata\"),\r\n encrypted: boolean(\"encrypted\").default(false).notNull(),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n },\r\n (table) => [index(\"messages_conversation_idx\").on(table.conversationId)]\r\n);\r\n\r\n// Memories table with vector embeddings for RAG\r\nexport const memories = pgTable(\r\n \"memories\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\").references(() => users.id),\r\n type: text(\"type\")\r\n .notNull()\r\n .$type<\"episodic\" | \"semantic\" | \"procedural\">(),\r\n content: text(\"content\").notNull(),\r\n embedding: vector(\"embedding\", { dimensions: 1536 }), // OpenAI embedding size\r\n searchVector: tsvector(\"search_vector\"), // Full-text search vector (GIN indexed)\r\n importance: integer(\"importance\").default(5), // 1-10 scale\r\n source: text(\"source\"), // Where this memory came from\r\n provenance: text(\"provenance\"), // Origin tracking: \"conversation:id\", \"api:manual\", \"extraction:auto\"\r\n metadata: jsonb(\"metadata\"),\r\n encrypted: boolean(\"encrypted\").default(false).notNull(),\r\n lastAccessed: timestamp(\"last_accessed\").defaultNow(),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n },\r\n (table) => [index(\"memories_user_idx\").on(table.userId)]\r\n);\r\n\r\n// Scheduled tasks table\r\nexport const scheduledTasks = pgTable(\"scheduled_tasks\", {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\").references(() => users.id),\r\n name: text(\"name\").notNull(),\r\n description: text(\"description\"),\r\n cronExpression: text(\"cron_expression\"),\r\n nextRunAt: timestamp(\"next_run_at\"),\r\n lastRunAt: timestamp(\"last_run_at\"),\r\n enabled: boolean(\"enabled\").default(true),\r\n action: jsonb(\"action\").$type<{\r\n type: \"message\" | \"command\" | \"webhook\";\r\n payload: Record<string, unknown>;\r\n }>(),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n});\r\n\r\n// Tool execution logs\r\nexport const toolLogs = pgTable(\r\n \"tool_logs\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n conversationId: uuid(\"conversation_id\").references(() => conversations.id),\r\n toolName: text(\"tool_name\").notNull(),\r\n input: jsonb(\"input\"),\r\n output: jsonb(\"output\"),\r\n success: boolean(\"success\").notNull(),\r\n durationMs: integer(\"duration_ms\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n },\r\n (table) => [index(\"tool_logs_conversation_idx\").on(table.conversationId)]\r\n);\r\n\r\n// ============================================\r\n// SECURITY TABLES (Phase 1)\r\n// ============================================\r\n\r\n// Sessions table for session management\r\nexport const sessions = pgTable(\r\n \"sessions\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\")\r\n .references(() => users.id)\r\n .notNull(),\r\n token: text(\"token\").notNull().unique(),\r\n deviceInfo: jsonb(\"device_info\").$type<{\r\n userAgent?: string;\r\n platform?: string;\r\n browser?: string;\r\n }>(),\r\n ipAddress: text(\"ip_address\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n expiresAt: timestamp(\"expires_at\").notNull(),\r\n lastActiveAt: timestamp(\"last_active_at\").defaultNow(),\r\n },\r\n (table) => [index(\"sessions_user_idx\").on(table.userId)]\r\n);\r\n\r\n// Audit logs table for tracking all actions\r\nexport const auditLogs = pgTable(\r\n \"audit_logs\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\").references(() => users.id),\r\n sessionId: uuid(\"session_id\").references(() => sessions.id),\r\n action: text(\"action\").notNull(), // 'tool_use', 'login', 'settings_change', etc.\r\n resource: text(\"resource\"), // 'shell', 'file', 'memory', etc.\r\n resourceId: text(\"resource_id\"), // ID of the affected resource\r\n details: jsonb(\"details\"),\r\n ipAddress: text(\"ip_address\"),\r\n userAgent: text(\"user_agent\"),\r\n success: boolean(\"success\").default(true),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n // Tamper-proof chain fields (SOC 2)\r\n sequenceNumber: integer(\"sequence_number\"),\r\n entryHash: text(\"entry_hash\"),\r\n previousHash: text(\"previous_hash\"),\r\n },\r\n (table) => [\r\n index(\"audit_logs_user_idx\").on(table.userId),\r\n index(\"audit_logs_action_idx\").on(table.action),\r\n index(\"audit_logs_created_idx\").on(table.createdAt),\r\n index(\"audit_logs_sequence_idx\").on(table.sequenceNumber),\r\n ]\r\n);\r\n\r\n// API keys table for programmatic access\r\nexport const apiKeys = pgTable(\r\n \"api_keys\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\")\r\n .references(() => users.id)\r\n .notNull(),\r\n name: text(\"name\").notNull(),\r\n keyHash: text(\"key_hash\").notNull(), // bcrypt hash of the key\r\n keyPrefix: text(\"key_prefix\").notNull(), // First 8 chars for identification (e.g., \"mb_live_\")\r\n permissions: jsonb(\"permissions\").$type<string[]>(), // ['chat:basic', 'tools:shell', etc.]\r\n lastUsedAt: timestamp(\"last_used_at\"),\r\n expiresAt: timestamp(\"expires_at\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n revokedAt: timestamp(\"revoked_at\"),\r\n },\r\n (table) => [index(\"api_keys_user_idx\").on(table.userId)]\r\n);\r\n\r\n// Rate limits table for tracking request rates\r\nexport const rateLimits = pgTable(\r\n \"rate_limits\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n identifier: text(\"identifier\").notNull(), // userId, IP, or API key prefix\r\n endpoint: text(\"endpoint\").notNull(), // 'api/chat', 'tool/shell', etc.\r\n windowStart: timestamp(\"window_start\").notNull(),\r\n requestCount: integer(\"request_count\").default(0),\r\n lastRequest: timestamp(\"last_request\"),\r\n },\r\n (table) => [\r\n index(\"rate_limits_identifier_endpoint_idx\").on(\r\n table.identifier,\r\n table.endpoint\r\n ),\r\n ]\r\n);\r\n\r\n// ============================================\r\n// OBSERVABILITY TABLES (Phase 1)\r\n// ============================================\r\n\r\n// Metrics table for performance tracking\r\nexport const metrics = pgTable(\r\n \"metrics\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n name: text(\"name\").notNull(), // 'response_latency', 'token_usage', 'tool_duration', etc.\r\n value: integer(\"value\").notNull(),\r\n unit: text(\"unit\"), // 'ms', 'tokens', 'bytes', etc.\r\n tags: jsonb(\"tags\").$type<Record<string, string>>(), // { tool: 'shell', status: 'success' }\r\n timestamp: timestamp(\"timestamp\").defaultNow().notNull(),\r\n },\r\n (table) => [\r\n index(\"metrics_name_timestamp_idx\").on(table.name, table.timestamp),\r\n ]\r\n);\r\n\r\n// Error logs table for centralized error tracking\r\nexport const errorLogs = pgTable(\r\n \"error_logs\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n source: text(\"source\").notNull(), // 'brain', 'tool', 'telegram', 'api', 'scheduler'\r\n errorType: text(\"error_type\").notNull(), // 'ApiError', 'ValidationError', etc.\r\n errorCode: text(\"error_code\"), // Application-specific error codes\r\n message: text(\"message\").notNull(),\r\n stack: text(\"stack\"),\r\n context: jsonb(\"context\"), // Additional context like request data\r\n userId: uuid(\"user_id\").references(() => users.id),\r\n conversationId: uuid(\"conversation_id\").references(() => conversations.id),\r\n resolved: boolean(\"resolved\").default(false),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n },\r\n (table) => [\r\n index(\"error_logs_source_idx\").on(table.source),\r\n index(\"error_logs_created_idx\").on(table.createdAt),\r\n ]\r\n);\r\n\r\n// ============================================\r\n// EVOLUTION SYSTEM TABLES (Phase 2)\r\n// ============================================\r\n\r\n// Usage patterns for evolution tracking\r\nexport const usagePatterns = pgTable(\r\n \"usage_patterns\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\")\r\n .references(() => users.id)\r\n .notNull(),\r\n patternType: text(\"pattern_type\").notNull(), // 'tool_usage', 'topic', 'time_of_day', 'complexity'\r\n patternKey: text(\"pattern_key\").notNull(), // e.g., 'shell', 'morning', 'coding'\r\n patternData: jsonb(\"pattern_data\"),\r\n confidence: integer(\"confidence\").default(0), // 0-100\r\n firstSeen: timestamp(\"first_seen\").defaultNow().notNull(),\r\n lastSeen: timestamp(\"last_seen\").defaultNow(),\r\n occurrences: integer(\"occurrences\").default(1),\r\n },\r\n (table) => [\r\n index(\"usage_patterns_user_idx\").on(table.userId),\r\n index(\"usage_patterns_type_idx\").on(table.patternType),\r\n ]\r\n);\r\n\r\n// Achievements definitions\r\nexport const achievements = pgTable(\"achievements\", {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n code: text(\"code\").notNull().unique(), // 'first_tool_use', 'power_user', 'researcher'\r\n name: text(\"name\").notNull(),\r\n description: text(\"description\"),\r\n iconEmoji: text(\"icon_emoji\"), // Emoji to display\r\n category: text(\"category\"), // 'exploration', 'productivity', 'mastery'\r\n criteria: jsonb(\"criteria\").$type<{\r\n type: string; // 'count', 'streak', 'threshold'\r\n metric: string; // 'tool_uses', 'conversations', 'memories'\r\n threshold: number;\r\n conditions?: Record<string, unknown>;\r\n }>(),\r\n points: integer(\"points\").default(10),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n});\r\n\r\n// User achievements (unlocked)\r\nexport const userAchievements = pgTable(\r\n \"user_achievements\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\")\r\n .references(() => users.id)\r\n .notNull(),\r\n achievementId: uuid(\"achievement_id\")\r\n .references(() => achievements.id)\r\n .notNull(),\r\n unlockedAt: timestamp(\"unlocked_at\").defaultNow().notNull(),\r\n progress: integer(\"progress\").default(100), // For progressive achievements\r\n notified: boolean(\"notified\").default(false),\r\n },\r\n (table) => [index(\"user_achievements_user_idx\").on(table.userId)]\r\n);\r\n\r\n// Evolution transformation modes\r\nexport const evolutionModes = pgTable(\r\n \"molt_modes\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\")\r\n .references(() => users.id)\r\n .notNull(),\r\n mode: text(\"mode\")\r\n .notNull()\r\n .$type<\"productivity\" | \"creative\" | \"research\" | \"learning\">(),\r\n activatedAt: timestamp(\"activated_at\").defaultNow().notNull(),\r\n deactivatedAt: timestamp(\"deactivated_at\"),\r\n metadata: jsonb(\"metadata\"),\r\n },\r\n (table) => [index(\"molt_modes_user_idx\").on(table.userId)]\r\n);\r\n\r\n// Archived memories (for memory shedding)\r\nexport const archivedMemories = pgTable(\r\n \"archived_memories\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n originalMemoryId: uuid(\"original_memory_id\").notNull(),\r\n userId: uuid(\"user_id\").references(() => users.id),\r\n type: text(\"type\")\r\n .notNull()\r\n .$type<\"episodic\" | \"semantic\" | \"procedural\">(),\r\n content: text(\"content\").notNull(),\r\n reason: text(\"reason\"), // 'stale', 'duplicate', 'low_importance', 'user_request'\r\n originalCreatedAt: timestamp(\"original_created_at\"),\r\n archivedAt: timestamp(\"archived_at\").defaultNow().notNull(),\r\n },\r\n (table) => [index(\"archived_memories_user_idx\").on(table.userId)]\r\n);\r\n\r\n// ============================================\r\n// CALENDAR & TRIGGERS TABLES (Phase 3)\r\n// ============================================\r\n\r\nexport const calendarTriggers = pgTable(\r\n \"calendar_triggers\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\")\r\n .references(() => users.id)\r\n .notNull(),\r\n name: text(\"name\").notNull(),\r\n calendarSource: text(\"calendar_source\").notNull(), // 'google', 'outlook', 'ical'\r\n calendarId: text(\"calendar_id\"),\r\n triggerType: text(\"trigger_type\").notNull(), // 'event_start', 'event_end', 'daily_briefing'\r\n offsetMinutes: integer(\"offset_minutes\").default(0), // Trigger X minutes before/after\r\n action: jsonb(\"action\").$type<{\r\n type: \"message\" | \"tool\" | \"webhook\";\r\n payload: Record<string, unknown>;\r\n }>(),\r\n enabled: boolean(\"enabled\").default(true),\r\n lastTriggered: timestamp(\"last_triggered\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n },\r\n (table) => [index(\"calendar_triggers_user_idx\").on(table.userId)]\r\n);\r\n\r\n// ============================================\r\n// SUB-AGENT TABLES (Phase 4)\r\n// ============================================\r\n\r\nexport const subAgents = pgTable(\r\n \"sub_agents\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n parentConversationId: uuid(\"parent_conversation_id\").references(\r\n () => conversations.id\r\n ),\r\n userId: uuid(\"user_id\")\r\n .references(() => users.id)\r\n .notNull(),\r\n type: text(\"type\")\r\n .notNull()\r\n .$type<\"research\" | \"coding\" | \"writing\" | \"analysis\">(),\r\n name: text(\"name\").notNull(),\r\n status: text(\"status\")\r\n .notNull()\r\n .$type<\"pending\" | \"running\" | \"completed\" | \"failed\" | \"cancelled\">(),\r\n objective: text(\"objective\").notNull(),\r\n context: jsonb(\"context\"),\r\n result: jsonb(\"result\"),\r\n tokenBudget: integer(\"token_budget\").default(50000),\r\n tokensUsed: integer(\"tokens_used\").default(0),\r\n timeBudgetMs: integer(\"time_budget_ms\").default(3600000), // 1 hour default\r\n startedAt: timestamp(\"started_at\"),\r\n completedAt: timestamp(\"completed_at\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n },\r\n (table) => [\r\n index(\"sub_agents_user_idx\").on(table.userId),\r\n index(\"sub_agents_status_idx\").on(table.status),\r\n ]\r\n);\r\n\r\nexport const agentMessages = pgTable(\r\n \"agent_messages\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n agentId: uuid(\"agent_id\")\r\n .references(() => subAgents.id)\r\n .notNull(),\r\n role: text(\"role\")\r\n .notNull()\r\n .$type<\"user\" | \"assistant\" | \"system\" | \"tool_result\">(),\r\n content: text(\"content\").notNull(),\r\n metadata: jsonb(\"metadata\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n },\r\n (table) => [index(\"agent_messages_agent_idx\").on(table.agentId)]\r\n);\r\n\r\nexport const agentProgress = pgTable(\r\n \"agent_progress\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n agentId: uuid(\"agent_id\")\r\n .references(() => subAgents.id)\r\n .notNull(),\r\n step: integer(\"step\").notNull(),\r\n description: text(\"description\").notNull(),\r\n status: text(\"status\")\r\n .notNull()\r\n .$type<\"pending\" | \"running\" | \"completed\" | \"failed\">(),\r\n output: jsonb(\"output\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n },\r\n (table) => [index(\"agent_progress_agent_idx\").on(table.agentId)]\r\n);\r\n\r\n// ============================================\r\n// PERSONALITY TABLES (Phase 5)\r\n// ============================================\r\n\r\nexport const personas = pgTable(\r\n \"personas\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\").references(() => users.id), // null = system persona\r\n name: text(\"name\").notNull(),\r\n description: text(\"description\"),\r\n basePrompt: text(\"base_prompt\").notNull(),\r\n isDefault: boolean(\"is_default\").default(false),\r\n isSystem: boolean(\"is_system\").default(false), // Built-in personas\r\n settings: jsonb(\"settings\").$type<{\r\n verbosity: \"terse\" | \"normal\" | \"detailed\";\r\n humor: \"off\" | \"subtle\" | \"full\";\r\n formality: \"formal\" | \"casual\" | \"professional\";\r\n emoji: boolean;\r\n proactivity: \"minimal\" | \"moderate\" | \"proactive\";\r\n }>(),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n },\r\n (table) => [index(\"personas_user_idx\").on(table.userId)]\r\n);\r\n\r\n// ============================================\r\n// ENTERPRISE TABLES (Phase 6)\r\n// ============================================\r\n\r\nexport const organizations = pgTable(\"organizations\", {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n name: text(\"name\").notNull(),\r\n slug: text(\"slug\").unique(),\r\n settings: jsonb(\"settings\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n updatedAt: timestamp(\"updated_at\").defaultNow(),\r\n});\r\n\r\nexport const organizationMembers = pgTable(\r\n \"organization_members\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n organizationId: uuid(\"organization_id\")\r\n .references(() => organizations.id)\r\n .notNull(),\r\n userId: uuid(\"user_id\")\r\n .references(() => users.id)\r\n .notNull(),\r\n role: text(\"role\").notNull().$type<\"owner\" | \"admin\" | \"member\" | \"viewer\">(),\r\n joinedAt: timestamp(\"joined_at\").defaultNow().notNull(),\r\n },\r\n (table) => [\r\n index(\"org_members_org_idx\").on(table.organizationId),\r\n index(\"org_members_user_idx\").on(table.userId),\r\n ]\r\n);\r\n\r\nexport const sharedMemories = pgTable(\r\n \"shared_memories\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n organizationId: uuid(\"organization_id\")\r\n .references(() => organizations.id)\r\n .notNull(),\r\n memoryId: uuid(\"memory_id\")\r\n .references(() => memories.id)\r\n .notNull(),\r\n sharedBy: uuid(\"shared_by\")\r\n .references(() => users.id)\r\n .notNull(),\r\n sharedAt: timestamp(\"shared_at\").defaultNow().notNull(),\r\n },\r\n (table) => [index(\"shared_memories_org_idx\").on(table.organizationId)]\r\n);\r\n\r\nexport const usageQuotas = pgTable(\r\n \"usage_quotas\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\").references(() => users.id),\r\n organizationId: uuid(\"organization_id\").references(() => organizations.id),\r\n quotaType: text(\"quota_type\").notNull(), // 'tokens_daily', 'tokens_monthly', 'agents_concurrent'\r\n limitValue: integer(\"limit_value\").notNull(),\r\n currentValue: integer(\"current_value\").default(0),\r\n resetAt: timestamp(\"reset_at\"),\r\n updatedAt: timestamp(\"updated_at\").defaultNow(),\r\n },\r\n (table) => [\r\n index(\"usage_quotas_user_idx\").on(table.userId),\r\n index(\"usage_quotas_org_idx\").on(table.organizationId),\r\n ]\r\n);\r\n\r\n// ============================================\r\n// KNOWLEDGE GRAPH TABLES\r\n// ============================================\r\n\r\n// Graph entities — people, projects, topics, events, organizations, locations\r\nexport const graphEntities = pgTable(\r\n \"graph_entities\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\").references(() => users.id),\r\n type: text(\"type\")\r\n .notNull()\r\n .$type<\"person\" | \"project\" | \"topic\" | \"event\" | \"organization\" | \"location\">(),\r\n name: text(\"name\").notNull(),\r\n aliases: jsonb(\"aliases\").$type<string[]>().default([]),\r\n description: text(\"description\"),\r\n attributes: jsonb(\"attributes\").$type<Record<string, unknown>>().default({}),\r\n importance: integer(\"importance\").default(50), // 0-100\r\n mentionCount: integer(\"mention_count\").default(1),\r\n embedding: vector(\"embedding\", { dimensions: 1536 }),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n updatedAt: timestamp(\"updated_at\").defaultNow().notNull(),\r\n },\r\n (table) => [\r\n index(\"graph_entities_user_idx\").on(table.userId),\r\n index(\"graph_entities_type_idx\").on(table.type),\r\n index(\"graph_entities_name_idx\").on(table.name),\r\n ]\r\n);\r\n\r\n// Graph relationships — connections between entities\r\nexport const graphRelationships = pgTable(\r\n \"graph_relationships\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n sourceEntityId: uuid(\"source_entity_id\")\r\n .references(() => graphEntities.id, { onDelete: \"cascade\" })\r\n .notNull(),\r\n targetEntityId: uuid(\"target_entity_id\")\r\n .references(() => graphEntities.id, { onDelete: \"cascade\" })\r\n .notNull(),\r\n type: text(\"type\")\r\n .notNull()\r\n .$type<\r\n | \"knows\" | \"works_with\" | \"works_on\" | \"family\" | \"friend\"\r\n | \"colleague\" | \"manages\" | \"reports_to\" | \"belongs_to\"\r\n | \"related_to\" | \"located_in\" | \"interested_in\" | \"expert_in\"\r\n | \"mentioned_in\" | \"participates_in\"\r\n >(),\r\n strength: integer(\"strength\").default(50), // 0-100\r\n bidirectional: boolean(\"bidirectional\").default(false),\r\n context: text(\"context\"),\r\n attributes: jsonb(\"attributes\").$type<Record<string, unknown>>().default({}),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n updatedAt: timestamp(\"updated_at\").defaultNow().notNull(),\r\n },\r\n (table) => [\r\n index(\"graph_rel_source_idx\").on(table.sourceEntityId),\r\n index(\"graph_rel_target_idx\").on(table.targetEntityId),\r\n index(\"graph_rel_type_idx\").on(table.type),\r\n ]\r\n);\r\n\r\n// ============================================\r\n// DOCUMENT KNOWLEDGE BASE TABLES\r\n// ============================================\r\n\r\nexport const documents = pgTable(\r\n \"documents\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n name: text(\"name\").notNull(),\r\n filename: text(\"filename\"),\r\n mimeType: text(\"mime_type\"),\r\n fileSize: integer(\"file_size\"),\r\n source: text(\"source\"), // 'upload', 'url', 'api'\r\n sourceUrl: text(\"source_url\"),\r\n metadata: jsonb(\"metadata\"),\r\n status: text(\"status\")\r\n .notNull()\r\n .$type<\"pending\" | \"processing\" | \"completed\" | \"failed\">()\r\n .default(\"pending\"),\r\n errorMessage: text(\"error_message\"),\r\n chunkCount: integer(\"chunk_count\").default(0),\r\n totalTokens: integer(\"total_tokens\").default(0),\r\n userId: uuid(\"user_id\").references(() => users.id),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n updatedAt: timestamp(\"updated_at\").defaultNow().notNull(),\r\n processedAt: timestamp(\"processed_at\"),\r\n },\r\n (table) => [\r\n index(\"documents_user_idx\").on(table.userId),\r\n index(\"documents_status_idx\").on(table.status),\r\n ]\r\n);\r\n\r\nexport const documentChunks = pgTable(\r\n \"document_chunks\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n documentId: uuid(\"document_id\")\r\n .references(() => documents.id, { onDelete: \"cascade\" })\r\n .notNull(),\r\n chunkIndex: integer(\"chunk_index\").notNull(),\r\n content: text(\"content\").notNull(),\r\n embedding: vector(\"embedding\", { dimensions: 1536 }),\r\n tokenCount: integer(\"token_count\"),\r\n metadata: jsonb(\"metadata\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n },\r\n (table) => [\r\n index(\"document_chunks_document_idx\").on(table.documentId),\r\n ]\r\n);\r\n\r\n// ============================================\r\n// TYPE EXPORTS\r\n// ============================================\r\n\r\nexport type User = typeof users.$inferSelect;\r\nexport type NewUser = typeof users.$inferInsert;\r\nexport type Conversation = typeof conversations.$inferSelect;\r\nexport type NewConversation = typeof conversations.$inferInsert;\r\nexport type Message = typeof messages.$inferSelect;\r\nexport type NewMessage = typeof messages.$inferInsert;\r\nexport type Memory = typeof memories.$inferSelect;\r\nexport type NewMemory = typeof memories.$inferInsert;\r\n\r\n// Security types\r\nexport type Session = typeof sessions.$inferSelect;\r\nexport type NewSession = typeof sessions.$inferInsert;\r\nexport type AuditLog = typeof auditLogs.$inferSelect;\r\nexport type NewAuditLog = typeof auditLogs.$inferInsert;\r\nexport type ApiKey = typeof apiKeys.$inferSelect;\r\nexport type NewApiKey = typeof apiKeys.$inferInsert;\r\n\r\n// Observability types\r\nexport type Metric = typeof metrics.$inferSelect;\r\nexport type NewMetric = typeof metrics.$inferInsert;\r\nexport type ErrorLog = typeof errorLogs.$inferSelect;\r\nexport type NewErrorLog = typeof errorLogs.$inferInsert;\r\n\r\n// Evolution system types\r\nexport type UsagePattern = typeof usagePatterns.$inferSelect;\r\nexport type NewUsagePattern = typeof usagePatterns.$inferInsert;\r\nexport type Achievement = typeof achievements.$inferSelect;\r\nexport type NewAchievement = typeof achievements.$inferInsert;\r\nexport type UserAchievement = typeof userAchievements.$inferSelect;\r\nexport type EvolutionMode = typeof evolutionModes.$inferSelect;\r\nexport type NewEvolutionMode = typeof evolutionModes.$inferInsert;\r\n\r\n// Sub-agent types\r\nexport type SubAgent = typeof subAgents.$inferSelect;\r\nexport type NewSubAgent = typeof subAgents.$inferInsert;\r\nexport type AgentMessage = typeof agentMessages.$inferSelect;\r\nexport type AgentProgress = typeof agentProgress.$inferSelect;\r\n\r\n// Personality types\r\nexport type Persona = typeof personas.$inferSelect;\r\nexport type NewPersona = typeof personas.$inferInsert;\r\n\r\n// Enterprise types\r\nexport type Organization = typeof organizations.$inferSelect;\r\nexport type NewOrganization = typeof organizations.$inferInsert;\r\nexport type OrganizationMember = typeof organizationMembers.$inferSelect;\r\n\r\n// Knowledge graph types\r\nexport type GraphEntity = typeof graphEntities.$inferSelect;\r\nexport type NewGraphEntity = typeof graphEntities.$inferInsert;\r\nexport type GraphRelationship = typeof graphRelationships.$inferSelect;\r\nexport type NewGraphRelationship = typeof graphRelationships.$inferInsert;\r\n\r\n// Document knowledge base types\r\nexport type Document = typeof documents.$inferSelect;\r\nexport type NewDocument = typeof documents.$inferInsert;\r\nexport type DocumentChunk = typeof documentChunks.$inferSelect;\r\nexport type NewDocumentChunk = typeof documentChunks.$inferInsert;\r\n\r\n// ============================================\r\n// SOC 2 COMPLIANCE TABLES\r\n// ============================================\r\n\r\n// Two-factor authentication (persisted, encrypted secrets)\r\nexport const twoFactorAuth = pgTable(\r\n \"two_factor_auth\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userId: uuid(\"user_id\")\r\n .references(() => users.id, { onDelete: \"cascade\" })\r\n .notNull()\r\n .unique(),\r\n secretEncrypted: text(\"secret_encrypted\").notNull(),\r\n recoveryCodes: jsonb(\"recovery_codes\").$type<string[]>().notNull(),\r\n enabledAt: timestamp(\"enabled_at\").notNull(),\r\n lastVerifiedAt: timestamp(\"last_verified_at\"),\r\n keyVersion: integer(\"key_version\").default(1).notNull(),\r\n metadata: jsonb(\"metadata\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n updatedAt: timestamp(\"updated_at\").defaultNow().notNull(),\r\n },\r\n (table) => [index(\"two_factor_auth_user_idx\").on(table.userId)]\r\n);\r\n\r\n// Security incidents tracking\r\nexport const securityIncidents = pgTable(\r\n \"security_incidents\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n incidentNumber: text(\"incident_number\").notNull().unique(),\r\n title: text(\"title\").notNull(),\r\n description: text(\"description\").notNull(),\r\n type: text(\"type\")\r\n .notNull()\r\n .$type<\r\n | \"brute_force\"\r\n | \"unauthorized_access\"\r\n | \"data_breach\"\r\n | \"suspicious_activity\"\r\n | \"system_compromise\"\r\n | \"policy_violation\"\r\n >(),\r\n severity: text(\"severity\")\r\n .notNull()\r\n .$type<\"low\" | \"medium\" | \"high\" | \"critical\">(),\r\n status: text(\"status\")\r\n .notNull()\r\n .$type<\"open\" | \"investigating\" | \"contained\" | \"resolved\" | \"closed\">()\r\n .default(\"open\"),\r\n userId: uuid(\"user_id\").references(() => users.id),\r\n assignedTo: uuid(\"assigned_to\").references(() => users.id),\r\n source: text(\"source\").notNull(),\r\n sourceData: jsonb(\"source_data\"),\r\n impactAssessment: text(\"impact_assessment\"),\r\n containmentActions: jsonb(\"containment_actions\"),\r\n resolutionNotes: text(\"resolution_notes\"),\r\n relatedIncidents: jsonb(\"related_incidents\").$type<string[]>(),\r\n metadata: jsonb(\"metadata\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n updatedAt: timestamp(\"updated_at\").defaultNow().notNull(),\r\n investigatedAt: timestamp(\"investigated_at\"),\r\n containedAt: timestamp(\"contained_at\"),\r\n resolvedAt: timestamp(\"resolved_at\"),\r\n closedAt: timestamp(\"closed_at\"),\r\n },\r\n (table) => [\r\n index(\"security_incidents_status_idx\").on(table.status),\r\n index(\"security_incidents_severity_idx\").on(table.severity),\r\n index(\"security_incidents_created_idx\").on(table.createdAt),\r\n ]\r\n);\r\n\r\n// Incident timeline events\r\nexport const incidentTimeline = pgTable(\r\n \"incident_timeline\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n incidentId: uuid(\"incident_id\")\r\n .references(() => securityIncidents.id, { onDelete: \"cascade\" })\r\n .notNull(),\r\n eventType: text(\"event_type\")\r\n .notNull()\r\n .$type<\r\n | \"created\"\r\n | \"status_change\"\r\n | \"assignment\"\r\n | \"comment\"\r\n | \"action_taken\"\r\n | \"escalation\"\r\n | \"resolution\"\r\n >(),\r\n description: text(\"description\").notNull(),\r\n performedBy: uuid(\"performed_by\").references(() => users.id),\r\n metadata: jsonb(\"metadata\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n },\r\n (table) => [index(\"incident_timeline_incident_idx\").on(table.incidentId)]\r\n);\r\n\r\n// SOC 2 types\r\nexport type TwoFactorAuthRecord = typeof twoFactorAuth.$inferSelect;\r\nexport type NewTwoFactorAuthRecord = typeof twoFactorAuth.$inferInsert;\r\nexport type SecurityIncident = typeof securityIncidents.$inferSelect;\r\nexport type NewSecurityIncident = typeof securityIncidents.$inferInsert;\r\nexport type IncidentTimelineEvent = typeof incidentTimeline.$inferSelect;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Microsoft 365 / Entra ID integration\r\n// ---------------------------------------------------------------------------\r\n\r\n// Pending OAuth states — CSRF + PKCE. Short-lived (expires in minutes).\r\n// We reject callbacks whose state is not present or expired.\r\nexport const m365OauthStates = pgTable(\r\n \"m365_oauth_states\",\r\n {\r\n state: text(\"state\").primaryKey(),\r\n codeVerifier: text(\"code_verifier\").notNull(),\r\n userKey: text(\"user_key\"),\r\n returnTo: text(\"return_to\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n expiresAt: timestamp(\"expires_at\").notNull(),\r\n },\r\n (table) => [index(\"m365_oauth_states_expires_idx\").on(table.expiresAt)]\r\n);\r\n\r\n// Per-user Microsoft 365 OAuth connections. Tokens are encrypted at rest.\r\nexport const m365Connections = pgTable(\r\n \"m365_connections\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userKey: text(\"user_key\").notNull().unique(),\r\n microsoftUserId: text(\"microsoft_user_id\"),\r\n email: text(\"email\"),\r\n displayName: text(\"display_name\"),\r\n accessTokenEncrypted: text(\"access_token_encrypted\").notNull(),\r\n refreshTokenEncrypted: text(\"refresh_token_encrypted\"),\r\n scope: text(\"scope\"),\r\n tokenType: text(\"token_type\").default(\"Bearer\"),\r\n expiresAt: timestamp(\"expires_at\").notNull(),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n updatedAt: timestamp(\"updated_at\").defaultNow().notNull(),\r\n },\r\n (table) => [index(\"m365_connections_user_idx\").on(table.userKey)]\r\n);\r\n\r\n// Persisted analysis history — lets the dashboard show prior verdicts.\r\nexport const m365AnalysisResults = pgTable(\r\n \"m365_analysis_results\",\r\n {\r\n id: uuid(\"id\").primaryKey().defaultRandom(),\r\n userKey: text(\"user_key\").notNull(),\r\n inputType: text(\"input_type\").notNull().$type<\"email\" | \"file\" | \"document\">(),\r\n inputId: text(\"input_id\"),\r\n subject: text(\"subject\"),\r\n sender: text(\"sender\"),\r\n riskScore: integer(\"risk_score\").notNull(),\r\n category: text(\"category\").notNull().$type<\"Safe\" | \"Suspicious\" | \"Phishing\" | \"Error\">(),\r\n explanation: jsonb(\"explanation\").$type<string[]>(),\r\n recommendedActions: jsonb(\"recommended_actions\").$type<string[]>(),\r\n engine: text(\"engine\").notNull().$type<\"llm\" | \"heuristic\">(),\r\n model: text(\"model\"),\r\n latencyMs: integer(\"latency_ms\"),\r\n createdAt: timestamp(\"created_at\").defaultNow().notNull(),\r\n },\r\n (table) => [\r\n index(\"m365_analysis_user_idx\").on(table.userKey),\r\n index(\"m365_analysis_created_idx\").on(table.createdAt),\r\n ]\r\n);\r\n\r\nexport type M365Connection = typeof m365Connections.$inferSelect;\r\nexport type NewM365Connection = typeof m365Connections.$inferInsert;\r\nexport type M365OauthState = typeof m365OauthStates.$inferSelect;\r\nexport type NewM365OauthState = typeof m365OauthStates.$inferInsert;\r\nexport type M365AnalysisResult = typeof m365AnalysisResults.$inferSelect;\r\nexport type NewM365AnalysisResult = typeof m365AnalysisResults.$inferInsert;\r\n"],"mappings":"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","names":[]}