@oneuptime/common 11.7.0 → 11.7.2

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 (264) hide show
  1. package/Models/DatabaseModels/DashboardDomain.ts +1 -0
  2. package/Models/DatabaseModels/Incident.ts +2 -0
  3. package/Models/DatabaseModels/IncidentEpisode.ts +1 -0
  4. package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +1 -0
  5. package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
  6. package/Models/DatabaseModels/IncidentPublicNote.ts +1 -0
  7. package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
  8. package/Models/DatabaseModels/Monitor.ts +1 -0
  9. package/Models/DatabaseModels/MonitorStatusTimeline.ts +1 -0
  10. package/Models/DatabaseModels/NetworkSite.ts +1 -0
  11. package/Models/DatabaseModels/NetworkSiteStatusTimeline.ts +1 -0
  12. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +1 -0
  13. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +2 -0
  14. package/Models/DatabaseModels/Probe.ts +13 -13
  15. package/Models/DatabaseModels/ScheduledMaintenance.ts +1 -0
  16. package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +1 -0
  17. package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
  18. package/Models/DatabaseModels/ScheduledMaintenanceTemplate.ts +1 -0
  19. package/Models/DatabaseModels/StatusPage.ts +1 -0
  20. package/Models/DatabaseModels/StatusPageAnnouncement.ts +1 -0
  21. package/Models/DatabaseModels/StatusPageDomain.ts +1 -0
  22. package/Models/DatabaseModels/WorkspaceNotificationSummary.ts +1 -0
  23. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +11 -0
  24. package/Server/API/BaseAPI.ts +17 -1
  25. package/Server/API/CommonAPI.ts +32 -0
  26. package/Server/API/MicrosoftTeamsAPI.ts +99 -2
  27. package/Server/API/ProbeAPI.ts +2 -0
  28. package/Server/API/SlackAPI.ts +62 -0
  29. package/Server/API/StatusPageAPI.ts +157 -192
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1785140242697-AddHotQueryIndexes.ts +89 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/1785148065137-AddHotQueryIndexesSecondPass.ts +61 -0
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/1785240000000-RepairCrossProjectMonitorStatusReferences.ts +280 -0
  33. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  34. package/Server/Services/DatabaseService.ts +11 -3
  35. package/Server/Services/MonitorGroupService.ts +145 -0
  36. package/Server/Services/MonitorService.ts +231 -30
  37. package/Server/Services/ProbeService.ts +319 -16
  38. package/Server/Services/StatusPageService.ts +72 -42
  39. package/Server/Services/WorkspaceNotificationRuleService.ts +232 -2
  40. package/Server/Utils/Database/PostgresErrorTranslator.ts +131 -0
  41. package/Server/Utils/Monitor/MonitorResource.ts +88 -35
  42. package/Server/Utils/Monitor/MonitorStatusTimeline.ts +21 -1
  43. package/Server/Utils/Monitor/MonitorStepsProjectValidator.ts +158 -0
  44. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +706 -6
  45. package/Tests/Models/DatabaseModels/ProbeColumnAccessControl.test.ts +103 -0
  46. package/Tests/Server/API/BaseAPIUpdateNoOp.test.ts +135 -0
  47. package/Tests/Server/API/CommonAPIAuthGuard.test.ts +317 -0
  48. package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +228 -0
  49. package/Tests/Server/API/ProbeAPI.test.ts +6 -0
  50. package/Tests/Server/API/ZZVerifyChatsAuth.test.ts +167 -0
  51. package/Tests/Server/Services/AddHotQueryIndexesMigration.test.ts +255 -0
  52. package/Tests/Server/Services/AddHotQueryIndexesSecondPassMigration.test.ts +258 -0
  53. package/Tests/Server/Services/DatabaseServiceSanitizeUpdateData.test.ts +1 -1
  54. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +121 -0
  55. package/Tests/Server/Services/HeartbeatWriteFastPathSafety.test.ts +200 -0
  56. package/Tests/Server/Services/HookFreeWriteSafetySecondPass.test.ts +181 -0
  57. package/Tests/Server/Services/MonitorGroupServiceBatchedStatuses.test.ts +513 -0
  58. package/Tests/Server/Services/MonitorResourceProbeAgreementReuse.test.ts +492 -0
  59. package/Tests/Server/Services/MonitorServiceProbeSelection.test.ts +401 -0
  60. package/Tests/Server/Services/MonitorStatusTimelineFastPath.test.ts +453 -0
  61. package/Tests/Server/Services/ProbeAuthKeyCacheAndHeartbeat.test.ts +679 -0
  62. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +3 -3
  63. package/Tests/Server/Services/StatusPageDomainResolutionCache.test.ts +245 -0
  64. package/Tests/Server/Services/StatusPageOverviewTimelineWindow.test.ts +283 -0
  65. package/Tests/Server/Services/StatusPageServiceMcp.test.ts +17 -1
  66. package/Tests/Server/Services/StatusPageServiceMonitorGroupBatching.test.ts +331 -0
  67. package/Tests/Server/Services/UserOnCallLogClaimNotificationRule.test.ts +12 -12
  68. package/Tests/Server/Services/WorkspaceNotificationRuleChats.test.ts +1390 -0
  69. package/Tests/Server/Utils/AI/Insights/InsightFixRouting.test.ts +4 -4
  70. package/Tests/Server/Utils/AI/Insights/InsightScanner.test.ts +2 -2
  71. package/Tests/Server/Utils/AI/Insights/InsightStore.test.ts +1 -3
  72. package/Tests/Server/Utils/AI/Insights/InsightStoreHardening.test.ts +1 -3
  73. package/Tests/Server/Utils/AI/Insights/InsightTriage.test.ts +1 -1
  74. package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +5 -5
  75. package/Tests/Server/Utils/Alert/AlertPrivacyFilter.test.ts +187 -0
  76. package/Tests/Server/Utils/AlertEpisode/AlertEpisodePrivacyFilter.test.ts +170 -0
  77. package/Tests/Server/Utils/Database/PostgresErrorTranslator.test.ts +125 -0
  78. package/Tests/Server/Utils/Incident/IncidentPrivacyFilter.test.ts +264 -0
  79. package/Tests/Server/Utils/IncidentEpisode/IncidentEpisodePrivacyFilter.test.ts +175 -0
  80. package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidator.test.ts +181 -0
  81. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +1 -1
  82. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +2 -2
  83. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelsList.test.ts +341 -0
  84. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +2175 -0
  85. package/Tests/Server/Utils/Workspace/SlackChannelsList.test.ts +585 -0
  86. package/Tests/Types/Billing/MeteredPlan.test.ts +46 -0
  87. package/Tests/Types/DateUserTimezone.test.ts +205 -0
  88. package/Tests/Types/DateUserTimezoneOverridesBrowser.test.ts +73 -0
  89. package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +219 -1
  90. package/Tests/UI/Components/BulkUpdateForm.test.tsx +174 -0
  91. package/Tests/UI/Components/CardModelDetailEdit.test.tsx +315 -0
  92. package/Tests/UI/Components/ModelDetailSelect.test.tsx +229 -0
  93. package/Tests/UI/Components/ModelTable/BaseModelTableBulkSelectAll.test.tsx +1258 -0
  94. package/Tests/UI/Components/ModelTableExportFromColumns.test.ts +153 -0
  95. package/Tests/UI/Components/MonacoLoader.test.ts +67 -0
  96. package/Tests/UI/Components/MonacoRuntime.test.ts +121 -0
  97. package/Tests/UI/Components/TableBulkCsvExport.test.tsx +212 -3
  98. package/Tests/UI/Components/TimePicker/TimePicker.test.tsx +11 -0
  99. package/Tests/UI/Utils/Project.test.ts +809 -0
  100. package/Tests/UI/Utils/TableColumnsToCsv.test.ts +360 -0
  101. package/Tests/Utils/Alerts/AlertMetricType.test.ts +143 -0
  102. package/Tests/Utils/Dashboard/VariableUrlState.test.ts +219 -0
  103. package/Tests/Utils/Incident/IncidentMetricType.test.ts +174 -0
  104. package/Tests/Utils/Monitor/MonitorProbeSelectionUtil.test.ts +145 -0
  105. package/Tests/Utils/StatusPage/ResourceUptime.test.ts +263 -0
  106. package/Types/Date.ts +119 -50
  107. package/Types/Workspace/NotificationRules/BaseNotificationRule.ts +4 -0
  108. package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +25 -10
  109. package/Types/Workspace/WorkspaceMessagePayload.ts +1 -0
  110. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +63 -8
  111. package/UI/Components/CodeEditor/CodeEditor.tsx +3 -0
  112. package/UI/Components/CodeEditor/MonacoLoader.ts +36 -0
  113. package/UI/Components/Forms/Fields/FormField.tsx +13 -3
  114. package/UI/Components/Forms/ModelForm.tsx +41 -18
  115. package/UI/Components/Input/Input.tsx +6 -1
  116. package/UI/Components/ModelDetail/CardModelDetail.tsx +23 -1
  117. package/UI/Components/ModelDetail/ModelDetail.tsx +46 -1
  118. package/UI/Components/ModelTable/BaseModelTable.tsx +300 -30
  119. package/UI/Components/ModelTable/Column.ts +12 -0
  120. package/UI/Components/ModelTable/ExportFromColumns.ts +57 -0
  121. package/UI/Components/Navbar/NavBar.tsx +66 -1
  122. package/UI/Components/Table/Table.tsx +52 -13
  123. package/UI/Components/Table/Types/Column.ts +18 -0
  124. package/UI/Components/TimePicker/TimePicker.tsx +8 -4
  125. package/UI/Utils/Project.ts +214 -18
  126. package/UI/Utils/TableColumnsToCsv.ts +86 -6
  127. package/UI/Utils/User.ts +19 -0
  128. package/UI/esbuild-config.js +34 -0
  129. package/Utils/Monitor/MonitorProbeSelectionUtil.ts +72 -0
  130. package/build/dist/Models/DatabaseModels/DashboardDomain.js +1 -0
  131. package/build/dist/Models/DatabaseModels/DashboardDomain.js.map +1 -1
  132. package/build/dist/Models/DatabaseModels/Incident.js +2 -0
  133. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  134. package/build/dist/Models/DatabaseModels/IncidentEpisode.js +1 -0
  135. package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
  136. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +1 -0
  137. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
  138. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
  139. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
  140. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +1 -0
  141. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  142. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
  143. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
  144. package/build/dist/Models/DatabaseModels/Monitor.js +1 -0
  145. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  146. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js +1 -0
  147. package/build/dist/Models/DatabaseModels/MonitorStatusTimeline.js.map +1 -1
  148. package/build/dist/Models/DatabaseModels/NetworkSite.js +1 -0
  149. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
  150. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js +1 -0
  151. package/build/dist/Models/DatabaseModels/NetworkSiteStatusTimeline.js.map +1 -1
  152. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +1 -0
  153. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
  154. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +2 -0
  155. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  156. package/build/dist/Models/DatabaseModels/Probe.js +13 -13
  157. package/build/dist/Models/DatabaseModels/Probe.js.map +1 -1
  158. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +1 -0
  159. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  160. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +1 -0
  161. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  162. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
  163. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
  164. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js +1 -0
  165. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplate.js.map +1 -1
  166. package/build/dist/Models/DatabaseModels/StatusPage.js +1 -0
  167. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  168. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +1 -0
  169. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
  170. package/build/dist/Models/DatabaseModels/StatusPageDomain.js +1 -0
  171. package/build/dist/Models/DatabaseModels/StatusPageDomain.js.map +1 -1
  172. package/build/dist/Models/DatabaseModels/WorkspaceNotificationSummary.js +1 -0
  173. package/build/dist/Models/DatabaseModels/WorkspaceNotificationSummary.js.map +1 -1
  174. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  175. package/build/dist/Server/API/BaseAPI.js +12 -1
  176. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  177. package/build/dist/Server/API/CommonAPI.js +21 -0
  178. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  179. package/build/dist/Server/API/MicrosoftTeamsAPI.js +72 -2
  180. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  181. package/build/dist/Server/API/ProbeAPI.js +2 -0
  182. package/build/dist/Server/API/ProbeAPI.js.map +1 -1
  183. package/build/dist/Server/API/SlackAPI.js +44 -0
  184. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  185. package/build/dist/Server/API/StatusPageAPI.js +98 -152
  186. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  187. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785140242697-AddHotQueryIndexes.js +36 -0
  188. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785140242697-AddHotQueryIndexes.js.map +1 -0
  189. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785148065137-AddHotQueryIndexesSecondPass.js +26 -0
  190. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785148065137-AddHotQueryIndexesSecondPass.js.map +1 -0
  191. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785240000000-RepairCrossProjectMonitorStatusReferences.js +254 -0
  192. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785240000000-RepairCrossProjectMonitorStatusReferences.js.map +1 -0
  193. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  194. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  195. package/build/dist/Server/Services/DatabaseService.js +10 -2
  196. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  197. package/build/dist/Server/Services/MonitorGroupService.js +118 -0
  198. package/build/dist/Server/Services/MonitorGroupService.js.map +1 -1
  199. package/build/dist/Server/Services/MonitorService.js +198 -24
  200. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  201. package/build/dist/Server/Services/ProbeService.js +238 -9
  202. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  203. package/build/dist/Server/Services/StatusPageService.js +46 -39
  204. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  205. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +178 -3
  206. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  207. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js +80 -0
  208. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js.map +1 -0
  209. package/build/dist/Server/Utils/Monitor/MonitorResource.js +67 -29
  210. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  211. package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js +31 -14
  212. package/build/dist/Server/Utils/Monitor/MonitorStatusTimeline.js.map +1 -1
  213. package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js +117 -0
  214. package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js.map +1 -0
  215. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +549 -7
  216. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  217. package/build/dist/Types/Date.js +106 -35
  218. package/build/dist/Types/Date.js.map +1 -1
  219. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +17 -7
  220. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -1
  221. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +37 -11
  222. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  223. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +2 -0
  224. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  225. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js +34 -0
  226. package/build/dist/UI/Components/CodeEditor/MonacoLoader.js.map +1 -0
  227. package/build/dist/UI/Components/Forms/Fields/FormField.js +11 -3
  228. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  229. package/build/dist/UI/Components/Forms/ModelForm.js +37 -17
  230. package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
  231. package/build/dist/UI/Components/Input/Input.js +6 -1
  232. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  233. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +22 -1
  234. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
  235. package/build/dist/UI/Components/ModelDetail/ModelDetail.js +31 -1
  236. package/build/dist/UI/Components/ModelDetail/ModelDetail.js.map +1 -1
  237. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +234 -21
  238. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  239. package/build/dist/UI/Components/ModelTable/ExportFromColumns.js +30 -0
  240. package/build/dist/UI/Components/ModelTable/ExportFromColumns.js.map +1 -0
  241. package/build/dist/UI/Components/Navbar/NavBar.js +39 -1
  242. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  243. package/build/dist/UI/Components/Table/Table.js +31 -11
  244. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  245. package/build/dist/UI/Components/TimePicker/TimePicker.js +4 -4
  246. package/build/dist/UI/Components/TimePicker/TimePicker.js.map +1 -1
  247. package/build/dist/UI/Utils/Project.js +161 -15
  248. package/build/dist/UI/Utils/Project.js.map +1 -1
  249. package/build/dist/UI/Utils/TableColumnsToCsv.js +67 -6
  250. package/build/dist/UI/Utils/TableColumnsToCsv.js.map +1 -1
  251. package/build/dist/UI/Utils/User.js +19 -0
  252. package/build/dist/UI/Utils/User.js.map +1 -1
  253. package/build/dist/Utils/Monitor/MonitorProbeSelectionUtil.js +52 -0
  254. package/build/dist/Utils/Monitor/MonitorProbeSelectionUtil.js.map +1 -0
  255. package/package.json +4 -3
  256. package/Server/Infrastructure/Postgres/SchemaMigrations/1773414578773-MigrationName.ts +0 -79
  257. package/Server/Infrastructure/Postgres/SchemaMigrations/1773500000000-MigrationName.ts +0 -41
  258. package/Server/Infrastructure/Postgres/SchemaMigrations/1776886248361-MigrationName.ts +0 -17
  259. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1773414578773-MigrationName.js +0 -34
  260. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1773414578773-MigrationName.js.map +0 -1
  261. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1773500000000-MigrationName.js +0 -22
  262. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1773500000000-MigrationName.js.map +0 -1
  263. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776886248361-MigrationName.js +0 -12
  264. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1776886248361-MigrationName.js.map +0 -1
@@ -28,8 +28,9 @@ import UserService from "../../../Services/UserService";
28
28
  // Import database utilities
29
29
  import QueryHelper from "../../../Types/Database/QueryHelper";
30
30
  import SortOrder from "../../../../Types/BaseDatabase/SortOrder";
31
+ import LIMIT_MAX from "../../../../Types/Database/LimitMax";
31
32
  // Bot Framework SDK imports
32
- import { CloudAdapter, ConfigurationBotFrameworkAuthentication, TeamsActivityHandler, MessageFactory, } from "botbuilder";
33
+ import { CloudAdapter, ConfigurationBotFrameworkAuthentication, TeamsActivityHandler, TeamsInfo, MessageFactory, } from "botbuilder";
33
34
  // Teams action handlers and types
34
35
  import MicrosoftTeamsAuthAction from "./Actions/Auth";
35
36
  import MicrosoftTeamsIncidentActions from "./Actions/Incident";
@@ -227,8 +228,28 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
227
228
  const now = OneUptimeDate.getCurrentDate();
228
229
  const expiryDate = OneUptimeDate.addRemoveSeconds(now, expiresIn - 300); // Subtrutes buffer
229
230
  logger.debug(`Token expiry calculated: ${OneUptimeDate.toString(expiryDate)}`);
230
- // Update the miscData with new token and expiry
231
- const updatedMiscData = Object.assign(Object.assign({}, data.miscData), { appAccessToken: newAccessToken, appAccessTokenExpiresAt: OneUptimeDate.toString(expiryDate), lastAppTokenIssuedAt: OneUptimeDate.toString(now), tenantId: data.tenantId });
231
+ /*
232
+ * Merge the token fields into a FRESH read of miscData instead of the
233
+ * snapshot taken before the OAuth round-trip. The snapshot can be
234
+ * seconds old, and writing it back verbatim would erase concurrent
235
+ * miscData updates — in particular chats captured into availableChats
236
+ * by bot install events, which cannot be re-derived from Graph.
237
+ */
238
+ let latestMiscData = data.miscData;
239
+ try {
240
+ const latestProjectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
241
+ projectId: data.projectId,
242
+ workspaceType: WorkspaceType.MicrosoftTeams,
243
+ });
244
+ if (latestProjectAuth === null || latestProjectAuth === void 0 ? void 0 : latestProjectAuth.miscData) {
245
+ latestMiscData = latestProjectAuth.miscData;
246
+ }
247
+ }
248
+ catch (err) {
249
+ logger.debug("Could not re-read miscData before token refresh write");
250
+ logger.debug(err);
251
+ }
252
+ const updatedMiscData = Object.assign(Object.assign({}, latestMiscData), { appAccessToken: newAccessToken, appAccessTokenExpiresAt: OneUptimeDate.toString(expiryDate), lastAppTokenIssuedAt: OneUptimeDate.toString(now), tenantId: data.tenantId });
232
253
  logger.debug("Saving updated token to database");
233
254
  // Save the updated token to the database
234
255
  await WorkspaceProjectAuthTokenService.refreshAuthToken({
@@ -685,6 +706,7 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
685
706
  return null;
686
707
  }
687
708
  static async sendMessage(data) {
709
+ var _a;
688
710
  logger.debug("=== MicrosoftTeamsUtil.sendMessage called ===", {
689
711
  projectId: data.projectId.toString(),
690
712
  });
@@ -803,6 +825,46 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
803
825
  });
804
826
  }
805
827
  }
828
+ // Send to Teams chats (group / personal chats the OneUptime app was added to).
829
+ const chatIdsToPostTo = data.workspaceMessagePayload.chatIds || [];
830
+ if (chatIdsToPostTo.length > 0) {
831
+ logger.debug(`Processing ${chatIdsToPostTo.length} chat ids`);
832
+ const availableChats = await this.getChatsForProject({
833
+ projectId: data.projectId,
834
+ });
835
+ for (const chatId of chatIdsToPostTo) {
836
+ const chatAsChannel = {
837
+ id: chatId,
838
+ name: ((_a = availableChats[chatId]) === null || _a === void 0 ? void 0 : _a.name) || chatId,
839
+ workspaceType: WorkspaceType.MicrosoftTeams,
840
+ };
841
+ try {
842
+ let lastThread;
843
+ for (const adaptiveCard of adaptiveCards) {
844
+ lastThread = await this.sendAdaptiveCardToChat({
845
+ chatId: chatId,
846
+ adaptiveCard: adaptiveCard,
847
+ projectId: data.projectId,
848
+ });
849
+ }
850
+ if (lastThread) {
851
+ logger.debug(`Message sent successfully to chat ${chatAsChannel.name}, thread: ${JSON.stringify(lastThread)}`);
852
+ workspaceMessageResponse.threads.push(lastThread);
853
+ }
854
+ }
855
+ catch (e) {
856
+ logger.error(`Error sending message to chat ID ${chatId}:`, {
857
+ projectId: data.projectId.toString(),
858
+ chatId: chatId,
859
+ });
860
+ logger.error(e);
861
+ workspaceMessageResponse.errors.push({
862
+ channel: chatAsChannel,
863
+ error: e instanceof Error ? e.message : String(e),
864
+ });
865
+ }
866
+ }
867
+ }
806
868
  logger.debug("=== Message sending completed ===");
807
869
  logger.debug(`Final thread count: ${workspaceMessageResponse.threads.length}`);
808
870
  logger.debug(`Final response: ${JSON.stringify(workspaceMessageResponse)}`);
@@ -902,6 +964,92 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
902
964
  throw error;
903
965
  }
904
966
  }
967
+ /*
968
+ * Sends an adaptive card to a Teams group chat or personal (1:1) chat via a
969
+ * proactive Bot Framework message. The OneUptime app must have been added to
970
+ * the chat — Graph has no app-only permission for posting to chats, so the
971
+ * bot conversation is the only supported transport.
972
+ */
973
+ static async sendAdaptiveCardToChat(data) {
974
+ var _a;
975
+ logger.debug("sendAdaptiveCardToChat called with data:");
976
+ logger.debug(`Chat ID: ${data.chatId}`);
977
+ logger.debug(`Project ID: ${data.projectId.toString()}`);
978
+ try {
979
+ const projectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
980
+ projectId: data.projectId,
981
+ workspaceType: WorkspaceType.MicrosoftTeams,
982
+ });
983
+ if (!projectAuth || !projectAuth.miscData) {
984
+ throw new BadDataException("Microsoft Teams integration not found for this project");
985
+ }
986
+ const miscData = projectAuth.miscData;
987
+ if (!miscData.botId) {
988
+ throw new BadDataException("Bot ID not found in Microsoft Teams integration");
989
+ }
990
+ const tenantId = projectAuth.workspaceProjectId;
991
+ if (!tenantId) {
992
+ throw new BadDataException("Tenant ID not found in Microsoft Teams integration");
993
+ }
994
+ if (!MicrosoftTeamsAppClientId) {
995
+ throw new BadDataException("Microsoft Teams App Client ID not configured");
996
+ }
997
+ const chat = (_a = miscData.availableChats) === null || _a === void 0 ? void 0 : _a[data.chatId];
998
+ if (!chat) {
999
+ throw new BadDataException("This chat is not connected to OneUptime. Please add the OneUptime app to the chat in Microsoft Teams and try again.");
1000
+ }
1001
+ const adapter = this.getBotAdapter();
1002
+ const conversationReference = {
1003
+ bot: {
1004
+ id: MicrosoftTeamsAppClientId,
1005
+ name: "OneUptime Bot",
1006
+ },
1007
+ conversation: {
1008
+ id: chat.id,
1009
+ name: chat.name,
1010
+ isGroup: chat.chatType === "groupChat",
1011
+ conversationType: chat.chatType,
1012
+ tenantId: tenantId,
1013
+ },
1014
+ channelId: "msteams",
1015
+ /*
1016
+ * Fallback is the commercial-cloud global endpoint; the serviceUrl
1017
+ * captured from bot activities is preferred (required for GCC/DoD).
1018
+ */
1019
+ serviceUrl: chat.serviceUrl || "https://smba.trafficmanager.net/teams/",
1020
+ };
1021
+ logger.debug(`Chat conversation reference: ${JSON.stringify(conversationReference)}`);
1022
+ let messageId = "";
1023
+ await adapter.continueConversationAsync(MicrosoftTeamsAppClientId, conversationReference, async (context) => {
1024
+ logger.debug("Sending adaptive card to chat as proactive message");
1025
+ const message = MessageFactory.attachment({
1026
+ contentType: "application/vnd.microsoft.card.adaptive",
1027
+ content: data.adaptiveCard,
1028
+ });
1029
+ const response = await context.sendActivity(message);
1030
+ messageId = (response === null || response === void 0 ? void 0 : response.id) || "";
1031
+ logger.debug(`Chat message sent with ID: ${messageId}`);
1032
+ });
1033
+ const thread = {
1034
+ channel: {
1035
+ id: chat.id,
1036
+ name: chat.name,
1037
+ workspaceType: WorkspaceType.MicrosoftTeams,
1038
+ },
1039
+ threadId: messageId,
1040
+ };
1041
+ logger.debug(`Sent message to chat via Bot Framework: ${JSON.stringify(thread)}`);
1042
+ return thread;
1043
+ }
1044
+ catch (error) {
1045
+ logger.error("Error sending adaptive card to chat via Bot Framework:", {
1046
+ projectId: data.projectId.toString(),
1047
+ chatId: data.chatId,
1048
+ });
1049
+ logger.error(error);
1050
+ throw error;
1051
+ }
1052
+ }
905
1053
  static async getWorkspaceChannelFromChannelId(data) {
906
1054
  var _a;
907
1055
  logger.debug("=== getWorkspaceChannelFromChannelId called ===", {
@@ -1243,6 +1391,25 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
1243
1391
  logger.debug("Message activity originates from the bot itself; ignoring to prevent a loop");
1244
1392
  return;
1245
1393
  }
1394
+ /*
1395
+ * Backfill chat capture from inbound messages. Chats where the app was
1396
+ * installed before chat capture shipped never fire install events — per
1397
+ * Microsoft docs, app upgrades only send installationUpdate when the
1398
+ * manifest's bot is added or removed, so a version bump alone re-fires
1399
+ * nothing. Messaging the bot in a chat is the documented recovery path,
1400
+ * and this also keeps the stored serviceUrl fresh (docs: verify the
1401
+ * stored serviceUrl when a new message arrives). Cheap when the chat is
1402
+ * already captured (single read, no roster fetch, no write).
1403
+ */
1404
+ const messageConversationType = conversation["conversationType"] || "";
1405
+ if (messageConversationType === "personal" ||
1406
+ messageConversationType === "groupChat") {
1407
+ await this.captureChatFromBotActivity({
1408
+ activity: data.activity,
1409
+ turnContext: data.turnContext,
1410
+ onlyIfMissingOrStale: true,
1411
+ });
1412
+ }
1246
1413
  // If this is actually an Adaptive Card submit wrapped as a message, route to invoke handler
1247
1414
  if (possibleActionValue["action"] ||
1248
1415
  ((_b = possibleActionValue["data"]) === null || _b === void 0 ? void 0 : _b["action"])) {
@@ -2226,10 +2393,23 @@ All monitoring checks are passing normally.`;
2226
2393
  const botWasAdded = membersAdded.some((member) => {
2227
2394
  return member["id"] === recipientId;
2228
2395
  });
2396
+ const botWasRemoved = membersRemoved.some((member) => {
2397
+ return member["id"] === recipientId;
2398
+ });
2229
2399
  if (botWasAdded) {
2230
2400
  logger.debug("OneUptime bot was added to a Teams conversation");
2401
+ await this.captureChatFromBotActivity({
2402
+ activity: data.activity,
2403
+ turnContext: data.turnContext,
2404
+ });
2231
2405
  await this.sendWelcomeAdaptiveCard(data.turnContext);
2232
2406
  }
2407
+ if (botWasRemoved) {
2408
+ logger.debug("OneUptime bot was removed from a Teams conversation");
2409
+ await this.removeChatFromBotActivity({
2410
+ activity: data.activity,
2411
+ });
2412
+ }
2233
2413
  }
2234
2414
  static async handleInstallationUpdateActivity(data) {
2235
2415
  // Handle bot installation/uninstallation
@@ -2237,13 +2417,302 @@ All monitoring checks are passing normally.`;
2237
2417
  const conversation = data.activity["conversation"] || {};
2238
2418
  logger.debug(`Installation update - Action: ${action}`);
2239
2419
  logger.debug(`Conversation: ${JSON.stringify(conversation)}`);
2240
- if (action === "add") {
2420
+ /*
2421
+ * Teams sends "add-upgrade" / "remove-upgrade" when an app upgrade adds
2422
+ * or removes the bot in the manifest (per Microsoft docs, a plain
2423
+ * version bump fires no installationUpdate at all). Treat them the same
2424
+ * as add/remove. Chats installed before chat capture shipped are
2425
+ * backfilled from inbound messages in handleBotMessageActivity instead.
2426
+ */
2427
+ if (action === "add" || action === "add-upgrade") {
2241
2428
  logger.debug("OneUptime bot was installed");
2429
+ await this.captureChatFromBotActivity({
2430
+ activity: data.activity,
2431
+ turnContext: data.turnContext,
2432
+ });
2242
2433
  }
2243
- else if (action === "remove") {
2434
+ else if (action === "remove" || action === "remove-upgrade") {
2244
2435
  logger.debug("OneUptime bot was uninstalled");
2436
+ await this.removeChatFromBotActivity({
2437
+ activity: data.activity,
2438
+ });
2439
+ }
2440
+ }
2441
+ /*
2442
+ * Chats (group chats and personal 1:1 chats) cannot be listed with the
2443
+ * app-only Graph token, so the only way OneUptime learns about them is by
2444
+ * capturing the conversation details when the OneUptime app is added to a
2445
+ * chat. These captured chats power the "post to chat" notification rules.
2446
+ */
2447
+ static getChatTypeFromConversation(conversation) {
2448
+ const conversationType = conversation["conversationType"] || "";
2449
+ if (conversationType === "personal" || conversationType === "groupChat") {
2450
+ return conversationType;
2451
+ }
2452
+ return null; // channels and meetings are not chats.
2453
+ }
2454
+ static getChatDisplayName(data) {
2455
+ /*
2456
+ * Keep well under the 100-char ShortText columns that store the chat
2457
+ * name in notification logs — Teams chat topics can be much longer.
2458
+ */
2459
+ const maxNameLength = 80;
2460
+ const truncate = (name) => {
2461
+ return name.length > maxNameLength
2462
+ ? `${name.substring(0, maxNameLength - 1)}…`
2463
+ : name;
2464
+ };
2465
+ if (data.topic && data.topic.trim()) {
2466
+ return truncate(data.topic.trim());
2467
+ }
2468
+ const memberNames = data.memberNames.filter((name) => {
2469
+ return Boolean(name && name.trim());
2470
+ });
2471
+ if (data.chatType === "personal") {
2472
+ return memberNames[0] ? truncate(`${memberNames[0]}`) : "Personal chat";
2473
+ }
2474
+ if (memberNames.length === 0) {
2475
+ return "Group chat";
2476
+ }
2477
+ const maxNamesToShow = 3;
2478
+ const shownNames = memberNames.slice(0, maxNamesToShow);
2479
+ const remainingCount = memberNames.length - shownNames.length;
2480
+ if (remainingCount > 0) {
2481
+ return truncate(`${shownNames.join(", ")} + ${remainingCount} more`);
2482
+ }
2483
+ return truncate(shownNames.join(", "));
2484
+ }
2485
+ /*
2486
+ * Returns true when every connected project of this tenant already has
2487
+ * this chat stored with the same service URL — i.e. there is nothing to
2488
+ * capture or refresh.
2489
+ */
2490
+ static async isChatCapturedForTenant(data) {
2491
+ var _a, _b;
2492
+ const projectAuths = await WorkspaceProjectAuthTokenService.findBy({
2493
+ query: {
2494
+ workspaceType: WorkspaceType.MicrosoftTeams,
2495
+ workspaceProjectId: data.tenantId,
2496
+ },
2497
+ select: {
2498
+ _id: true,
2499
+ miscData: true,
2500
+ },
2501
+ limit: LIMIT_MAX,
2502
+ skip: 0,
2503
+ props: {
2504
+ isRoot: true,
2505
+ },
2506
+ });
2507
+ if (projectAuths.length === 0) {
2508
+ return true; // no connected projects — nothing to capture into.
2509
+ }
2510
+ for (const projectAuth of projectAuths) {
2511
+ const chat = (_b = (_a = projectAuth.miscData) === null || _a === void 0 ? void 0 : _a.availableChats) === null || _b === void 0 ? void 0 : _b[data.chatId];
2512
+ if (!chat) {
2513
+ return false;
2514
+ }
2515
+ if (data.serviceUrl && chat.serviceUrl !== data.serviceUrl) {
2516
+ return false; // stored serviceUrl is stale.
2517
+ }
2518
+ }
2519
+ return true;
2520
+ }
2521
+ static async captureChatFromBotActivity(data) {
2522
+ var _a, _b;
2523
+ try {
2524
+ const conversation = data.activity["conversation"] || {};
2525
+ const chatType = this.getChatTypeFromConversation(conversation);
2526
+ if (!chatType) {
2527
+ return; // bot was added to a team channel, not a chat.
2528
+ }
2529
+ const chatId = conversation["id"] || "";
2530
+ if (!chatId) {
2531
+ logger.debug("No conversation id found on chat activity. Skipping.");
2532
+ return;
2533
+ }
2534
+ const channelData = data.activity["channelData"] || {};
2535
+ const tenantId = ((_a = channelData["tenant"]) === null || _a === void 0 ? void 0 : _a["id"]) ||
2536
+ conversation["tenantId"] ||
2537
+ "";
2538
+ if (!tenantId) {
2539
+ logger.debug("No tenant id found on chat activity. Skipping.");
2540
+ return;
2541
+ }
2542
+ const activityServiceUrl = data.activity["serviceUrl"] ||
2543
+ data.turnContext.activity.serviceUrl ||
2544
+ undefined;
2545
+ /*
2546
+ * On the message-backfill path, skip the roster fetch and DB writes
2547
+ * when the chat is already captured with a fresh serviceUrl.
2548
+ */
2549
+ if (data.onlyIfMissingOrStale) {
2550
+ const alreadyCaptured = await this.isChatCapturedForTenant({
2551
+ tenantId: tenantId,
2552
+ chatId: chatId,
2553
+ serviceUrl: activityServiceUrl,
2554
+ });
2555
+ if (alreadyCaptured) {
2556
+ return;
2557
+ }
2558
+ }
2559
+ // Resolve a human friendly name for the chat.
2560
+ const topic = conversation["name"];
2561
+ let memberNames = [];
2562
+ try {
2563
+ const botId = (_b = data.turnContext.activity.recipient) === null || _b === void 0 ? void 0 : _b.id;
2564
+ /*
2565
+ * TeamsInfo.getMembers is deprecated — page through the roster
2566
+ * instead. Chats return the full roster in one page in practice.
2567
+ */
2568
+ const members = [];
2569
+ let continuationToken = undefined;
2570
+ do {
2571
+ const page = await TeamsInfo.getPagedMembers(data.turnContext, 500, continuationToken);
2572
+ members.push(...(page.members || []));
2573
+ continuationToken = page.continuationToken;
2574
+ } while (continuationToken);
2575
+ memberNames = members
2576
+ .filter((member) => {
2577
+ return member.id !== botId;
2578
+ })
2579
+ .map((member) => {
2580
+ return member.name || "";
2581
+ });
2582
+ }
2583
+ catch (err) {
2584
+ logger.debug("Could not fetch chat members for chat name resolution");
2585
+ logger.debug(err);
2586
+ }
2587
+ const chat = {
2588
+ id: chatId,
2589
+ name: this.getChatDisplayName({
2590
+ chatType: chatType,
2591
+ topic: topic,
2592
+ memberNames: memberNames,
2593
+ }),
2594
+ chatType: chatType,
2595
+ serviceUrl: activityServiceUrl,
2596
+ addedAt: OneUptimeDate.getCurrentDate().toISOString(),
2597
+ };
2598
+ await this.saveChatToProjectAuthTokens({
2599
+ tenantId: tenantId,
2600
+ chat: chat,
2601
+ });
2602
+ logger.debug(`Captured Microsoft Teams chat ${chatId} (${chat.name}) for tenant ${tenantId}`);
2603
+ }
2604
+ catch (err) {
2605
+ logger.error("Error capturing Microsoft Teams chat from bot activity:");
2606
+ logger.error(err);
2607
+ }
2608
+ }
2609
+ static async removeChatFromBotActivity(data) {
2610
+ var _a;
2611
+ try {
2612
+ const conversation = data.activity["conversation"] || {};
2613
+ const chatType = this.getChatTypeFromConversation(conversation);
2614
+ if (!chatType) {
2615
+ return;
2616
+ }
2617
+ const chatId = conversation["id"] || "";
2618
+ const channelData = data.activity["channelData"] || {};
2619
+ const tenantId = ((_a = channelData["tenant"]) === null || _a === void 0 ? void 0 : _a["id"]) ||
2620
+ conversation["tenantId"] ||
2621
+ "";
2622
+ if (!chatId || !tenantId) {
2623
+ return;
2624
+ }
2625
+ await this.removeChatFromProjectAuthTokens({
2626
+ tenantId: tenantId,
2627
+ chatId: chatId,
2628
+ });
2629
+ logger.debug(`Removed Microsoft Teams chat ${chatId} for tenant ${tenantId}`);
2630
+ }
2631
+ catch (err) {
2632
+ logger.error("Error removing Microsoft Teams chat from bot activity:");
2633
+ logger.error(err);
2634
+ }
2635
+ }
2636
+ static async saveChatToProjectAuthTokens(data) {
2637
+ /*
2638
+ * A tenant can be connected to more than one OneUptime project, and the
2639
+ * install event does not say which project it belongs to — so save the
2640
+ * chat on every project connected to this tenant.
2641
+ */
2642
+ const projectAuths = await WorkspaceProjectAuthTokenService.findBy({
2643
+ query: {
2644
+ workspaceType: WorkspaceType.MicrosoftTeams,
2645
+ workspaceProjectId: data.tenantId,
2646
+ },
2647
+ select: {
2648
+ _id: true,
2649
+ miscData: true,
2650
+ },
2651
+ limit: LIMIT_MAX,
2652
+ skip: 0,
2653
+ props: {
2654
+ isRoot: true,
2655
+ },
2656
+ });
2657
+ for (const projectAuth of projectAuths) {
2658
+ const miscData = Object.assign({}, (projectAuth.miscData || {}));
2659
+ miscData.availableChats = Object.assign(Object.assign({}, (miscData.availableChats || {})), { [data.chat.id]: data.chat });
2660
+ await WorkspaceProjectAuthTokenService.updateOneById({
2661
+ id: projectAuth.id,
2662
+ data: {
2663
+ miscData: miscData,
2664
+ },
2665
+ props: {
2666
+ isRoot: true,
2667
+ },
2668
+ });
2669
+ }
2670
+ }
2671
+ static async removeChatFromProjectAuthTokens(data) {
2672
+ const projectAuths = await WorkspaceProjectAuthTokenService.findBy({
2673
+ query: {
2674
+ workspaceType: WorkspaceType.MicrosoftTeams,
2675
+ workspaceProjectId: data.tenantId,
2676
+ },
2677
+ select: {
2678
+ _id: true,
2679
+ miscData: true,
2680
+ },
2681
+ limit: LIMIT_MAX,
2682
+ skip: 0,
2683
+ props: {
2684
+ isRoot: true,
2685
+ },
2686
+ });
2687
+ for (const projectAuth of projectAuths) {
2688
+ const miscData = Object.assign({}, (projectAuth.miscData || {}));
2689
+ if (!miscData.availableChats || !miscData.availableChats[data.chatId]) {
2690
+ continue;
2691
+ }
2692
+ const availableChats = Object.assign({}, miscData.availableChats);
2693
+ delete availableChats[data.chatId];
2694
+ miscData.availableChats = availableChats;
2695
+ await WorkspaceProjectAuthTokenService.updateOneById({
2696
+ id: projectAuth.id,
2697
+ data: {
2698
+ miscData: miscData,
2699
+ },
2700
+ props: {
2701
+ isRoot: true,
2702
+ },
2703
+ });
2245
2704
  }
2246
2705
  }
2706
+ static async getChatsForProject(data) {
2707
+ const projectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
2708
+ projectId: data.projectId,
2709
+ workspaceType: WorkspaceType.MicrosoftTeams,
2710
+ });
2711
+ if (!projectAuth || !projectAuth.miscData) {
2712
+ return {};
2713
+ }
2714
+ return (projectAuth.miscData.availableChats || {});
2715
+ }
2247
2716
  /**
2248
2717
  * Process Bot Framework activity using the botbuilder SDK adapter.processActivity
2249
2718
  * This replaces the manual JWT validation and activity handling with proper SDK methods
@@ -2290,6 +2759,15 @@ All monitoring checks are passing normally.`;
2290
2759
  });
2291
2760
  await next();
2292
2761
  });
2762
+ this.onMembersRemoved(async (context, next) => {
2763
+ logger.debug("Handling members removed activity: " +
2764
+ JSON.stringify(context.activity));
2765
+ await MicrosoftTeamsUtil.handleConversationUpdateActivity({
2766
+ activity: context.activity,
2767
+ turnContext: context,
2768
+ });
2769
+ await next();
2770
+ });
2293
2771
  this.onInstallationUpdateAdd(async (context, next) => {
2294
2772
  logger.debug("Handling installation update add activity: " +
2295
2773
  JSON.stringify(context.activity));
@@ -2299,6 +2777,15 @@ All monitoring checks are passing normally.`;
2299
2777
  });
2300
2778
  await next();
2301
2779
  });
2780
+ this.onInstallationUpdateRemove(async (context, next) => {
2781
+ logger.debug("Handling installation update remove activity: " +
2782
+ JSON.stringify(context.activity));
2783
+ await MicrosoftTeamsUtil.handleInstallationUpdateActivity({
2784
+ activity: context.activity,
2785
+ turnContext: context,
2786
+ });
2787
+ await next();
2788
+ });
2302
2789
  }
2303
2790
  async onInvokeActivity(context) {
2304
2791
  logger.debug("Handling invoke activity: " + JSON.stringify(context.activity));
@@ -2562,8 +3049,27 @@ All monitoring checks are passing normally.`;
2562
3049
  return acc;
2563
3050
  }, {});
2564
3051
  logger.debug(`Processed ${Object.keys(availableTeams).length} teams`);
2565
- // Update project auth token with new teams
2566
- const miscData = projectAuth.miscData || {};
3052
+ /*
3053
+ * Update project auth token with new teams. Re-read miscData first
3054
+ * the snapshot from the start of this method is stale by the length
3055
+ * of the paginated Graph fetch, and writing it back verbatim would
3056
+ * erase concurrent updates (e.g. chats captured into availableChats
3057
+ * by bot install events, which cannot be re-derived).
3058
+ */
3059
+ let miscData = projectAuth.miscData || {};
3060
+ try {
3061
+ const latestProjectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
3062
+ projectId: data.projectId,
3063
+ workspaceType: WorkspaceType.MicrosoftTeams,
3064
+ });
3065
+ if (latestProjectAuth === null || latestProjectAuth === void 0 ? void 0 : latestProjectAuth.miscData) {
3066
+ miscData = latestProjectAuth.miscData;
3067
+ }
3068
+ }
3069
+ catch (err) {
3070
+ logger.debug("Could not re-read miscData before teams refresh write");
3071
+ logger.debug(err);
3072
+ }
2567
3073
  miscData.availableTeams = availableTeams;
2568
3074
  miscData.tenantId = tenantId;
2569
3075
  await WorkspaceProjectAuthTokenService.updateOneById({
@@ -2818,6 +3324,12 @@ __decorate([
2818
3324
  __metadata("design:paramtypes", [Object]),
2819
3325
  __metadata("design:returntype", Promise)
2820
3326
  ], MicrosoftTeamsUtil, "sendAdaptiveCardToChannel", null);
3327
+ __decorate([
3328
+ CaptureSpan(),
3329
+ __metadata("design:type", Function),
3330
+ __metadata("design:paramtypes", [Object]),
3331
+ __metadata("design:returntype", Promise)
3332
+ ], MicrosoftTeamsUtil, "sendAdaptiveCardToChat", null);
2821
3333
  __decorate([
2822
3334
  CaptureSpan(),
2823
3335
  __metadata("design:type", Function),
@@ -2998,6 +3510,36 @@ __decorate([
2998
3510
  __metadata("design:paramtypes", [Object]),
2999
3511
  __metadata("design:returntype", Promise)
3000
3512
  ], MicrosoftTeamsUtil, "handleInstallationUpdateActivity", null);
3513
+ __decorate([
3514
+ CaptureSpan(),
3515
+ __metadata("design:type", Function),
3516
+ __metadata("design:paramtypes", [Object]),
3517
+ __metadata("design:returntype", Promise)
3518
+ ], MicrosoftTeamsUtil, "captureChatFromBotActivity", null);
3519
+ __decorate([
3520
+ CaptureSpan(),
3521
+ __metadata("design:type", Function),
3522
+ __metadata("design:paramtypes", [Object]),
3523
+ __metadata("design:returntype", Promise)
3524
+ ], MicrosoftTeamsUtil, "removeChatFromBotActivity", null);
3525
+ __decorate([
3526
+ CaptureSpan(),
3527
+ __metadata("design:type", Function),
3528
+ __metadata("design:paramtypes", [Object]),
3529
+ __metadata("design:returntype", Promise)
3530
+ ], MicrosoftTeamsUtil, "saveChatToProjectAuthTokens", null);
3531
+ __decorate([
3532
+ CaptureSpan(),
3533
+ __metadata("design:type", Function),
3534
+ __metadata("design:paramtypes", [Object]),
3535
+ __metadata("design:returntype", Promise)
3536
+ ], MicrosoftTeamsUtil, "removeChatFromProjectAuthTokens", null);
3537
+ __decorate([
3538
+ CaptureSpan(),
3539
+ __metadata("design:type", Function),
3540
+ __metadata("design:paramtypes", [Object]),
3541
+ __metadata("design:returntype", Promise)
3542
+ ], MicrosoftTeamsUtil, "getChatsForProject", null);
3001
3543
  __decorate([
3002
3544
  CaptureSpan(),
3003
3545
  __metadata("design:type", Function),