@oneuptime/common 12.0.6 → 12.0.7

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 (424) hide show
  1. package/Models/DatabaseModels/AIInsight.ts +1 -1
  2. package/Models/DatabaseModels/DatabaseBaseModel/FileModel.ts +2 -3
  3. package/Models/DatabaseModels/DeletedProject.ts +595 -0
  4. package/Models/DatabaseModels/Index.ts +2 -0
  5. package/Models/DatabaseModels/Monitor.ts +111 -0
  6. package/Models/DatabaseModels/Project.ts +3 -3
  7. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +19 -1
  8. package/Server/API/FileAPI.ts +15 -2
  9. package/Server/API/MicrosoftTeamsAPI.ts +6 -1
  10. package/Server/API/ProjectAPI.ts +214 -0
  11. package/Server/API/StatusPageAPI.ts +39 -6
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.ts +50 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.ts +67 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.ts +39 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  16. package/Server/Services/AIAgentService.ts +20 -0
  17. package/Server/Services/DashboardDomainService.ts +73 -28
  18. package/Server/Services/DatabaseService.ts +1 -0
  19. package/Server/Services/DeletedProjectService.ts +138 -0
  20. package/Server/Services/FileService.ts +61 -0
  21. package/Server/Services/IncidentEpisodePublicNoteService.ts +18 -0
  22. package/Server/Services/IncidentPublicNoteService.ts +18 -0
  23. package/Server/Services/Index.ts +2 -0
  24. package/Server/Services/MonitorService.ts +311 -0
  25. package/Server/Services/ProbeService.ts +20 -0
  26. package/Server/Services/ProjectService.ts +297 -1
  27. package/Server/Services/PushNotificationService.ts +71 -0
  28. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +18 -0
  29. package/Server/Services/StatusPageAnnouncementService.ts +53 -0
  30. package/Server/Services/StatusPageDomainService.ts +73 -28
  31. package/Server/Services/TeamMemberService.ts +117 -12
  32. package/Server/Services/TelemetryIngestionKeyService.ts +1 -0
  33. package/Server/Services/UserWebhookService.ts +34 -109
  34. package/Server/Services/WorkspaceNotificationRuleService.ts +69 -0
  35. package/Server/Services/WorkspaceProjectAuthTokenService.ts +37 -1
  36. package/Server/Types/Database/DeleteById.ts +2 -0
  37. package/Server/Types/Database/DeleteOneBy.ts +6 -0
  38. package/Server/Types/Domain.ts +41 -0
  39. package/Server/Types/Workflow/Components/API/Delete.ts +2 -1
  40. package/Server/Types/Workflow/Components/API/Get.ts +2 -1
  41. package/Server/Types/Workflow/Components/API/Patch.ts +2 -1
  42. package/Server/Types/Workflow/Components/API/Post.ts +2 -1
  43. package/Server/Types/Workflow/Components/API/Put.ts +2 -1
  44. package/Server/Types/Workflow/Components/API/Utils.ts +41 -2
  45. package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +25 -19
  46. package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +6 -5
  47. package/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.ts +32 -14
  48. package/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.ts +31 -13
  49. package/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.ts +29 -20
  50. package/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.ts +28 -21
  51. package/Server/Types/Workflow/Components/BaseModel/LogComponentError.ts +89 -0
  52. package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +208 -0
  53. package/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts +11 -0
  54. package/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.ts +41 -18
  55. package/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.ts +45 -19
  56. package/Server/Types/Workflow/Components/Discord/SendMessageToChannel.ts +16 -9
  57. package/Server/Types/Workflow/Components/IncomingWebhookUtils.ts +66 -0
  58. package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +15 -9
  59. package/Server/Types/Workflow/Components/Slack/SendMessageToChannel.ts +17 -0
  60. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
  61. package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +171 -0
  62. package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +3 -3
  63. package/Server/Utils/AI/SRE/Insights/FixRouting.ts +3 -2
  64. package/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.ts +1 -1
  65. package/Server/Utils/AI/Toolbox/CodeWriteTools.ts +6 -6
  66. package/Server/Utils/CodeRepository/GitHub/GitHub.ts +43 -5
  67. package/Server/Utils/DataSource/EgressGuard.ts +176 -16
  68. package/Server/Utils/DataSource/HttpFetch.ts +6 -45
  69. package/Server/Utils/Execute.ts +8 -0
  70. package/Server/Utils/InlineImageAccessTokenSync.ts +23 -0
  71. package/Server/Utils/LLM/LLMService.ts +57 -12
  72. package/Server/Utils/Monitor/MonitorAlert.ts +40 -0
  73. package/Server/Utils/Monitor/MonitorDependencySuppression.ts +192 -0
  74. package/Server/Utils/Monitor/MonitorIncident.ts +40 -0
  75. package/Server/Utils/Monitor/MonitorResource.ts +36 -0
  76. package/Server/Utils/Response.ts +142 -6
  77. package/Server/Utils/SSRFProtection.ts +273 -60
  78. package/Server/Utils/StartServer.ts +8 -0
  79. package/Server/Utils/VM/VMRunner.ts +88 -1
  80. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +555 -49
  81. package/Server/Utils/Workspace/Slack/Slack.ts +25 -2
  82. package/Server/Utils/Workspace/WorkspaceBase.ts +6 -0
  83. package/Tests/App/Dashboard/DangerZone.test.tsx +334 -0
  84. package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +539 -0
  85. package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +678 -0
  86. package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +706 -0
  87. package/Tests/App/Dashboard/DashboardVariablesModal.test.tsx +508 -0
  88. package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +470 -0
  89. package/Tests/App/StatusPage/StatusPageDetailPagesNotFound.test.tsx +308 -0
  90. package/Tests/Models/DatabaseModels/DeletedProjectModel.test.ts +251 -0
  91. package/Tests/Models/DatabaseModels/SavedViewJSONColumnTuples.test.ts +115 -0
  92. package/Tests/Server/API/FileAPIAccessControl.test.ts +316 -0
  93. package/Tests/Server/API/ProjectAPI.test.ts +299 -1
  94. package/Tests/Server/API/ProjectAPIAdjustBalance.test.ts +459 -0
  95. package/Tests/Server/API/ProjectAPIAdjustBalanceBillingDisabled.test.ts +177 -0
  96. package/Tests/Server/Services/DatabaseServiceDeletionReason.test.ts +123 -0
  97. package/Tests/Server/Services/DeletedProjectService.test.ts +415 -0
  98. package/Tests/Server/Services/DeletedProjectServiceSelfHosted.test.ts +70 -0
  99. package/Tests/Server/Services/DomainSubdomainHooks.test.ts +94 -0
  100. package/Tests/Server/Services/FileIsPublicBooleanMigration.test.ts +244 -0
  101. package/Tests/Server/Services/FileServiceMimeType.test.ts +89 -0
  102. package/Tests/Server/Services/MonitorServiceDependencyValidation.test.ts +702 -0
  103. package/Tests/Server/Services/ProjectServiceAdjustBalance.test.ts +615 -0
  104. package/Tests/Server/Services/ProjectServiceDeleteAudit.test.ts +406 -0
  105. package/Tests/Server/Services/PublishTimeImageVisibility.test.ts +450 -0
  106. package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +669 -0
  107. package/Tests/Server/Services/UserWebhookSSRF.test.ts +174 -0
  108. package/Tests/Server/Services/WebPushEndpointAllowlist.test.ts +133 -0
  109. package/Tests/Server/Services/WorkspaceProjectAuthTokenRepoint.test.ts +618 -0
  110. package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +26 -1
  111. package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +215 -0
  112. package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +742 -0
  113. package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +256 -0
  114. package/Tests/Server/Types/Workflow/Components/ModelArguments.test.ts +371 -0
  115. package/Tests/Server/Utils/AI/CodeAgentCommandGuard.test.ts +204 -0
  116. package/Tests/Server/Utils/AI/CodeAgentWriteLimits.test.ts +213 -0
  117. package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +52 -5
  118. package/Tests/Server/Utils/AI/LLMServiceBaseUrl.test.ts +3 -0
  119. package/Tests/Server/Utils/AI/LLMServiceEgressGuard.test.ts +315 -0
  120. package/Tests/Server/Utils/AI/LLMServiceModelCompatibility.test.ts +3 -0
  121. package/Tests/Server/Utils/AI/LLMServiceRequestPolicy.test.ts +17 -5
  122. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +14 -1
  123. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +35 -0
  124. package/Tests/Server/Utils/AI/StubLLMEgressGuard.ts +25 -0
  125. package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +62 -7
  126. package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +69 -0
  127. package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +330 -0
  128. package/Tests/Server/Utils/GitHubCreatePullRequestWithToken.test.ts +393 -0
  129. package/Tests/Server/Utils/InlineImageAccessTokenSync.test.ts +202 -0
  130. package/Tests/Server/Utils/Monitor/MonitorDependencySuppression.test.ts +811 -0
  131. package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +604 -0
  132. package/Tests/Server/Utils/ResponseSendFileResponse.test.ts +192 -0
  133. package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +406 -0
  134. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +194 -0
  135. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +1169 -0
  136. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelsList.test.ts +2 -0
  137. package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +1605 -0
  138. package/Tests/Server/Utils/Workspace/MicrosoftTeamsTenantResolution.test.ts +1218 -0
  139. package/Tests/Types/AI/AIChatMessageStatus.test.ts +79 -0
  140. package/Tests/Types/AI/AIInsightStatus.test.ts +40 -0
  141. package/Tests/Types/API/HostnameAuthorityParsing.test.ts +157 -0
  142. package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +27 -0
  143. package/Tests/Types/DataSource/DataSourceLimits.test.ts +71 -0
  144. package/Tests/Types/DataSource/DataSourceType.test.ts +181 -0
  145. package/Tests/Types/DomainSubdomainValidation.test.ts +90 -0
  146. package/Tests/Types/JSONFunctions.test.ts +252 -1
  147. package/Tests/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.test.ts +61 -0
  148. package/Tests/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.test.ts +62 -0
  149. package/Tests/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.test.ts +68 -0
  150. package/Tests/Types/Monitor/SnmpMonitor/SnmpVersion.test.ts +51 -0
  151. package/Tests/UI/Components/404.test.tsx +1 -1
  152. package/Tests/UI/Components/Alert.test.tsx +1 -1
  153. package/Tests/UI/Components/Badge.test.tsx +1 -1
  154. package/Tests/UI/Components/BasicForm.test.tsx +39 -10
  155. package/Tests/UI/Components/Button.test.tsx +1 -1
  156. package/Tests/UI/Components/Card.test.tsx +1 -1
  157. package/Tests/UI/Components/Charts/AxisTickColor.test.tsx +1 -1
  158. package/Tests/UI/Components/ColorViewer.test.tsx +1 -1
  159. package/Tests/UI/Components/ComponentsModal.test.tsx +7 -1
  160. package/Tests/UI/Components/DictionaryOfStrings.test.tsx +1 -1
  161. package/Tests/UI/Components/Dropdown.test.tsx +1 -1
  162. package/Tests/UI/Components/FilePicker.test.tsx +1 -1
  163. package/Tests/UI/Components/HiddenText.test.tsx +1 -1
  164. package/Tests/UI/Components/Input.test.tsx +1 -1
  165. package/Tests/UI/Components/Loader.test.tsx +1 -1
  166. package/Tests/UI/Components/LogTimeRangePicker.test.tsx +1 -1
  167. package/Tests/UI/Components/MasterPage.test.tsx +1 -1
  168. package/Tests/UI/Components/ModalPortalDismissal.test.tsx +489 -0
  169. package/Tests/UI/Components/ModelDelete.test.tsx +214 -0
  170. package/Tests/UI/Components/ModelTable/BaseModelTableBulkSelectAll.test.tsx +1 -1
  171. package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +1 -1
  172. package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +1 -1
  173. package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +1 -1
  174. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1 -1
  175. package/Tests/UI/Components/NavBar.test.tsx +1 -1
  176. package/Tests/UI/Components/OperatorSelectorKeyboard.test.tsx +1 -1
  177. package/Tests/UI/Components/Pagination.test.tsx +1 -1
  178. package/Tests/UI/Components/Pill.test.tsx +1 -1
  179. package/Tests/UI/Components/Probe.test.tsx +1 -1
  180. package/Tests/UI/Components/ProgressBar.test.tsx +1 -1
  181. package/Tests/UI/Components/RadioButtons.test.tsx +1 -1
  182. package/Tests/UI/Components/SideMenuItem.test.tsx +1 -1
  183. package/Tests/UI/Components/SideOver.test.tsx +500 -6
  184. package/Tests/UI/Components/Tabs.test.tsx +1 -1
  185. package/Tests/UI/Components/TelemetrySearchBar.test.tsx +1 -1
  186. package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +1 -1
  187. package/Tests/UI/Components/TextArea.test.tsx +1 -1
  188. package/Tests/UI/Components/Toast.test.tsx +1 -1
  189. package/Tests/UI/Components/Toggle.test.tsx +1 -1
  190. package/Tests/UI/Components/TopSection.test.tsx +1 -1
  191. package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +1 -1
  192. package/Tests/UI/Rum/ReplayScrubber.test.tsx +1 -1
  193. package/Tests/UI/Rum/ReplayStage.test.tsx +1 -1
  194. package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +1 -1
  195. package/Tests/UI/Utils/LocalStorageArrayRoundTrip.test.ts +72 -0
  196. package/Tests/Utils/Dashboard/HtmlWidgetDocument.test.ts +19 -2
  197. package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +44 -0
  198. package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +288 -5
  199. package/Tests/Utils/Dashboard/VariableUrlState.test.ts +42 -0
  200. package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +27 -0
  201. package/Tests/Utils/LegacySerializedArray.test.ts +139 -0
  202. package/Tests/Utils/Monitor/MonitorDependencyRule.test.ts +190 -0
  203. package/Tests/Utils/Realtime.test.ts +78 -0
  204. package/Tests/Utils/Telemetry/SavedViewFilters.test.ts +246 -0
  205. package/Tests/__mocks__/i18next-browser-languagedetector.js +21 -0
  206. package/Types/AI/FixPullRequestCiStatus.ts +1 -1
  207. package/Types/AI/FixVerificationStatus.ts +2 -2
  208. package/Types/API/Hostname.ts +92 -4
  209. package/Types/API/URL.ts +43 -25
  210. package/Types/Billing/BalanceAdjustmentType.ts +14 -0
  211. package/Types/Billing/ProjectBalanceType.ts +13 -0
  212. package/Types/Domain.ts +26 -0
  213. package/Types/File/MimeType.ts +11 -0
  214. package/Types/JSONFunctions.ts +15 -0
  215. package/Types/Telemetry/TelemetrySavedViewState.ts +9 -1
  216. package/Types/Workflow/Components/BaseModel.ts +92 -28
  217. package/Typings/Index.d.ts +12 -0
  218. package/UI/Components/GanttChart/ChartContainer.tsx +4 -3
  219. package/UI/Components/Modal/ConfirmModal.tsx +10 -5
  220. package/UI/Components/Modal/Modal.tsx +27 -47
  221. package/UI/Components/ModelDelete/ModelDelete.tsx +23 -6
  222. package/UI/Components/SideOver/SideOver.tsx +195 -68
  223. package/UI/Utils/PageScrollLock.ts +66 -0
  224. package/Utils/Dashboard/HtmlWidgetDocument.ts +4 -2
  225. package/Utils/Dashboard/VariableInterpolation.ts +19 -1
  226. package/Utils/LegacySerializedArray.ts +60 -0
  227. package/Utils/Monitor/MonitorDependencyRule.ts +88 -0
  228. package/Utils/Telemetry/SavedViewFilters.ts +88 -0
  229. package/build/dist/Models/DatabaseModels/AIInsight.js +1 -1
  230. package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -1
  231. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js +2 -3
  232. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js.map +1 -1
  233. package/build/dist/Models/DatabaseModels/DeletedProject.js +640 -0
  234. package/build/dist/Models/DatabaseModels/DeletedProject.js.map +1 -0
  235. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  236. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  237. package/build/dist/Models/DatabaseModels/Monitor.js +106 -0
  238. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  239. package/build/dist/Models/DatabaseModels/Project.js +3 -3
  240. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  241. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  242. package/build/dist/Server/API/FileAPI.js +14 -2
  243. package/build/dist/Server/API/FileAPI.js.map +1 -1
  244. package/build/dist/Server/API/MicrosoftTeamsAPI.js +6 -1
  245. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  246. package/build/dist/Server/API/ProjectAPI.js +157 -4
  247. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  248. package/build/dist/Server/API/StatusPageAPI.js +27 -3
  249. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  250. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js +34 -0
  251. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js.map +1 -0
  252. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js +30 -0
  253. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js.map +1 -0
  254. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js +20 -0
  255. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js.map +1 -0
  256. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  257. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  258. package/build/dist/Server/Services/AIAgentService.js +17 -0
  259. package/build/dist/Server/Services/AIAgentService.js.map +1 -1
  260. package/build/dist/Server/Services/DashboardDomainService.js +55 -18
  261. package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
  262. package/build/dist/Server/Services/DatabaseService.js +1 -0
  263. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  264. package/build/dist/Server/Services/DeletedProjectService.js +124 -0
  265. package/build/dist/Server/Services/DeletedProjectService.js.map +1 -0
  266. package/build/dist/Server/Services/FileService.js +52 -0
  267. package/build/dist/Server/Services/FileService.js.map +1 -1
  268. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +10 -1
  269. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
  270. package/build/dist/Server/Services/IncidentPublicNoteService.js +10 -1
  271. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  272. package/build/dist/Server/Services/Index.js +2 -0
  273. package/build/dist/Server/Services/Index.js.map +1 -1
  274. package/build/dist/Server/Services/MonitorService.js +232 -0
  275. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  276. package/build/dist/Server/Services/ProbeService.js +17 -0
  277. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  278. package/build/dist/Server/Services/ProjectService.js +228 -6
  279. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  280. package/build/dist/Server/Services/PushNotificationService.js +56 -0
  281. package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
  282. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +10 -1
  283. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  284. package/build/dist/Server/Services/StatusPageAnnouncementService.js +54 -0
  285. package/build/dist/Server/Services/StatusPageAnnouncementService.js.map +1 -1
  286. package/build/dist/Server/Services/StatusPageDomainService.js +55 -18
  287. package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
  288. package/build/dist/Server/Services/TeamMemberService.js +97 -6
  289. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  290. package/build/dist/Server/Services/TelemetryIngestionKeyService.js +1 -0
  291. package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
  292. package/build/dist/Server/Services/UserWebhookService.js +31 -87
  293. package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
  294. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +65 -0
  295. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  296. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +23 -0
  297. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
  298. package/build/dist/Server/Types/Domain.js +37 -0
  299. package/build/dist/Server/Types/Domain.js.map +1 -1
  300. package/build/dist/Server/Types/Workflow/Components/API/Delete.js +2 -1
  301. package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
  302. package/build/dist/Server/Types/Workflow/Components/API/Get.js +2 -1
  303. package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
  304. package/build/dist/Server/Types/Workflow/Components/API/Patch.js +2 -1
  305. package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
  306. package/build/dist/Server/Types/Workflow/Components/API/Post.js +2 -1
  307. package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
  308. package/build/dist/Server/Types/Workflow/Components/API/Put.js +2 -1
  309. package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
  310. package/build/dist/Server/Types/Workflow/Components/API/Utils.js +35 -2
  311. package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
  312. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +15 -11
  313. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
  314. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +2 -3
  315. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
  316. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js +21 -10
  317. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js.map +1 -1
  318. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js +21 -10
  319. package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js.map +1 -1
  320. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js +18 -13
  321. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js.map +1 -1
  322. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js +18 -13
  323. package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js.map +1 -1
  324. package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js +43 -0
  325. package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js.map +1 -0
  326. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +116 -0
  327. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -0
  328. package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js +7 -0
  329. package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js.map +1 -1
  330. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js +24 -13
  331. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js.map +1 -1
  332. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js +27 -13
  333. package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js.map +1 -1
  334. package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js +14 -6
  335. package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js.map +1 -1
  336. package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js +42 -0
  337. package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js.map +1 -0
  338. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +15 -6
  339. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
  340. package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js +10 -2
  341. package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js.map +1 -1
  342. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
  343. package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +141 -0
  344. package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js.map +1 -1
  345. package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js.map +1 -1
  346. package/build/dist/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.js +1 -1
  347. package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js +6 -6
  348. package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js.map +1 -1
  349. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +39 -5
  350. package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
  351. package/build/dist/Server/Utils/DataSource/EgressGuard.js +94 -10
  352. package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
  353. package/build/dist/Server/Utils/DataSource/HttpFetch.js +1 -19
  354. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
  355. package/build/dist/Server/Utils/Execute.js +2 -2
  356. package/build/dist/Server/Utils/Execute.js.map +1 -1
  357. package/build/dist/Server/Utils/InlineImageAccessTokenSync.js +13 -0
  358. package/build/dist/Server/Utils/InlineImageAccessTokenSync.js.map +1 -1
  359. package/build/dist/Server/Utils/LLM/LLMService.js +43 -12
  360. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  361. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +44 -24
  362. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  363. package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js +158 -0
  364. package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js.map +1 -0
  365. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +50 -30
  366. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  367. package/build/dist/Server/Utils/Monitor/MonitorResource.js +32 -0
  368. package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
  369. package/build/dist/Server/Utils/Response.js +112 -5
  370. package/build/dist/Server/Utils/Response.js.map +1 -1
  371. package/build/dist/Server/Utils/SSRFProtection.js +219 -53
  372. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  373. package/build/dist/Server/Utils/StartServer.js +7 -0
  374. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  375. package/build/dist/Server/Utils/VM/VMRunner.js +73 -1
  376. package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
  377. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +445 -43
  378. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  379. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +18 -1
  380. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  381. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
  382. package/build/dist/Types/AI/FixPullRequestCiStatus.js +1 -1
  383. package/build/dist/Types/AI/FixVerificationStatus.js +2 -2
  384. package/build/dist/Types/API/Hostname.js +73 -4
  385. package/build/dist/Types/API/Hostname.js.map +1 -1
  386. package/build/dist/Types/API/URL.js +42 -24
  387. package/build/dist/Types/API/URL.js.map +1 -1
  388. package/build/dist/Types/Billing/BalanceAdjustmentType.js +15 -0
  389. package/build/dist/Types/Billing/BalanceAdjustmentType.js.map +1 -0
  390. package/build/dist/Types/Billing/ProjectBalanceType.js +14 -0
  391. package/build/dist/Types/Billing/ProjectBalanceType.js.map +1 -0
  392. package/build/dist/Types/Domain.js +22 -0
  393. package/build/dist/Types/Domain.js.map +1 -1
  394. package/build/dist/Types/File/MimeType.js +11 -0
  395. package/build/dist/Types/File/MimeType.js.map +1 -1
  396. package/build/dist/Types/JSONFunctions.js +14 -0
  397. package/build/dist/Types/JSONFunctions.js.map +1 -1
  398. package/build/dist/Types/Workflow/Components/BaseModel.js +83 -28
  399. package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
  400. package/build/dist/UI/Components/GanttChart/ChartContainer.js +4 -3
  401. package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +1 -1
  402. package/build/dist/UI/Components/Modal/ConfirmModal.js +3 -1
  403. package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
  404. package/build/dist/UI/Components/Modal/Modal.js +24 -34
  405. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  406. package/build/dist/UI/Components/ModelDelete/ModelDelete.js +11 -6
  407. package/build/dist/UI/Components/ModelDelete/ModelDelete.js.map +1 -1
  408. package/build/dist/UI/Components/SideOver/SideOver.js +105 -30
  409. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  410. package/build/dist/UI/Utils/PageScrollLock.js +52 -0
  411. package/build/dist/UI/Utils/PageScrollLock.js.map +1 -0
  412. package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js +4 -2
  413. package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js.map +1 -1
  414. package/build/dist/Utils/Dashboard/VariableInterpolation.js +19 -1
  415. package/build/dist/Utils/Dashboard/VariableInterpolation.js.map +1 -1
  416. package/build/dist/Utils/LegacySerializedArray.js +51 -0
  417. package/build/dist/Utils/LegacySerializedArray.js.map +1 -0
  418. package/build/dist/Utils/Monitor/MonitorDependencyRule.js +47 -0
  419. package/build/dist/Utils/Monitor/MonitorDependencyRule.js.map +1 -0
  420. package/build/dist/Utils/Telemetry/SavedViewFilters.js +52 -0
  421. package/build/dist/Utils/Telemetry/SavedViewFilters.js.map +1 -0
  422. package/jest.config.json +3 -0
  423. package/package.json +1 -1
  424. package/tsconfig.json +3 -1
@@ -44,6 +44,15 @@ import MicrosoftTeamsOnCallDutyActions from "./Actions/OnCallDutyPolicy";
44
44
  import AccessTokenService from "../../../Services/AccessTokenService";
45
45
  // Microsoft Teams apps should always be single-tenant
46
46
  const MICROSOFT_TEAMS_APP_TYPE = "SingleTenant";
47
+ /*
48
+ * Microsoft's wording when the Bot Framework refuses a proactive post because
49
+ * the app is not a member of the target conversation. Matched case-insensitively
50
+ * so we can replace it with something the admin can act on.
51
+ */
52
+ const MICROSOFT_TEAMS_ROSTER_ERROR_FRAGMENTS = [
53
+ "not part of the conversation roster",
54
+ "bot is not part of the conversation",
55
+ ];
47
56
  // Maximum number of pages to fetch when paginating teams
48
57
  const MICROSOFT_TEAMS_MAX_PAGES = 500;
49
58
  /*
@@ -51,7 +60,7 @@ const MICROSOFT_TEAMS_MAX_PAGES = 500;
51
60
  * issued on outlook.office.com / outlook.office365.com, and per-tenant ones on
52
61
  * <tenant>.webhook.office.com — all covered by these two registrable domains.
53
62
  */
54
- const MICROSOFT_TEAMS_WEBHOOK_DOMAINS = [
63
+ export const MICROSOFT_TEAMS_WEBHOOK_DOMAINS = [
55
64
  "office.com",
56
65
  "office365.com",
57
66
  ];
@@ -473,6 +482,14 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
473
482
  static async sendMessageToChannelViaIncomingWebhook(data) {
474
483
  logger.debug("Sending message to Teams channel via incoming webhook:");
475
484
  logger.debug(data);
485
+ /*
486
+ * Enforced at the sink, not only at the callers: this URL reaches here from
487
+ * workflow arguments and from status page subscribers, and a caller that
488
+ * forgets the pin is an SSRF from the API server.
489
+ */
490
+ if (!MicrosoftTeamsUtil.isValidMicrosoftTeamsIncomingWebhookUrl(data.url)) {
491
+ throw new BadDataException(`Microsoft Teams Webhook URL must be an https URL on ${MICROSOFT_TEAMS_WEBHOOK_DOMAINS.join(" or ")}.`);
492
+ }
476
493
  // Build a structured MessageCard from markdown for better rendering in Teams
477
494
  const payload = this.buildMessageCardFromMarkdown(data.text);
478
495
  const apiResult = await API.post({
@@ -718,6 +735,7 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
718
735
  name: displayName,
719
736
  workspaceType: WorkspaceType.MicrosoftTeams,
720
737
  teamId: data.teamId,
738
+ membershipType: channelData["membershipType"],
721
739
  };
722
740
  logger.debug(`Channel match found: ${JSON.stringify(foundChannel)}`);
723
741
  return foundChannel;
@@ -757,6 +775,16 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
757
775
  const workspaceChannelsToPostTo = [];
758
776
  logger.debug(`Processing ${data.workspaceMessagePayload.channelNames.length} channel names`);
759
777
  logger.debug(`Channel names: ${JSON.stringify(data.workspaceMessagePayload.channelNames)}`);
778
+ /*
779
+ * Declared before destination resolution so that a destination we cannot
780
+ * even resolve is reported as an error. Silently skipping it made a
781
+ * typo'd or deleted channel look like a successful send.
782
+ */
783
+ const workspaceMessageResponse = {
784
+ threads: [],
785
+ workspaceType: WorkspaceType.MicrosoftTeams,
786
+ errors: [],
787
+ };
760
788
  // Resolve channel names
761
789
  for (const channelName of data.workspaceMessagePayload.channelNames) {
762
790
  logger.debug(`Attempting to resolve channel name: ${channelName}`);
@@ -775,6 +803,15 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
775
803
  }
776
804
  else {
777
805
  logger.warn(`Channel not found: ${channelName}`);
806
+ workspaceMessageResponse.errors.push({
807
+ channel: {
808
+ id: "",
809
+ name: channelName,
810
+ workspaceType: WorkspaceType.MicrosoftTeams,
811
+ teamId: data.workspaceMessagePayload.teamId,
812
+ },
813
+ error: `Channel "${channelName}" was not found in this Microsoft Teams team. It may have been renamed or deleted.`,
814
+ });
778
815
  }
779
816
  }
780
817
  logger.debug("=== Starting message sending loop ===");
@@ -802,16 +839,20 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
802
839
  channelId: channelId,
803
840
  });
804
841
  logger.error(err);
842
+ workspaceMessageResponse.errors.push({
843
+ channel: {
844
+ id: channelId,
845
+ name: channelId,
846
+ workspaceType: WorkspaceType.MicrosoftTeams,
847
+ teamId: data.workspaceMessagePayload.teamId,
848
+ },
849
+ error: err instanceof Error ? err.message : String(err),
850
+ });
805
851
  }
806
852
  }
807
853
  logger.debug("=== Starting message sending loop ===");
808
854
  logger.debug(`Total channels to post to: ${workspaceChannelsToPostTo.length}`);
809
855
  logger.debug(`Channels: ${JSON.stringify(workspaceChannelsToPostTo)}`);
810
- const workspaceMessageResponse = {
811
- threads: [],
812
- workspaceType: WorkspaceType.MicrosoftTeams,
813
- errors: [],
814
- };
815
856
  for (const channel of workspaceChannelsToPostTo) {
816
857
  try {
817
858
  logger.debug(`Attempting to send message to channel: ${JSON.stringify(channel)}`);
@@ -936,6 +977,34 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
936
977
  throw new BadDataException("Microsoft Teams App Client ID not configured");
937
978
  }
938
979
  logger.debug(`Using bot ID: ${miscData.botId}`);
980
+ /*
981
+ * Bots cannot post to shared channels at all, so fail with the reason
982
+ * rather than letting Microsoft reject the send with a generic error.
983
+ */
984
+ if (data.workspaceChannel.membershipType === "shared") {
985
+ throw new BadDataException(`"${data.workspaceChannel.name}" is a shared channel, and Microsoft Teams does not allow bots to post in shared channels. Please pick a standard or private channel instead.`);
986
+ }
987
+ /*
988
+ * Preflight: refuse before calling the Bot Framework when we know the
989
+ * app was never installed into this team. Channels are discovered with
990
+ * tenant-wide Graph application permissions, which see every team
991
+ * regardless of installation — so reaching this point proves nothing
992
+ * about whether we can actually post.
993
+ *
994
+ * installedTeams is only populated from install events, so an empty map
995
+ * means "we have not observed any installs" (for example on a workspace
996
+ * connected before this shipped), not "nothing is installed". Only
997
+ * enforce once we have at least one record, and let the Bot Framework
998
+ * error be translated below otherwise.
999
+ */
1000
+ const installedTeams = miscData.installedTeams || {};
1001
+ const installedTeam = installedTeams[data.teamId];
1002
+ if (Object.keys(installedTeams).length > 0 && !installedTeam) {
1003
+ throw new BadDataException(this.getBotNotInTeamMessage({
1004
+ channelName: data.workspaceChannel.name,
1005
+ membershipType: data.workspaceChannel.membershipType,
1006
+ }));
1007
+ }
939
1008
  // Get Bot Framework adapter
940
1009
  const adapter = this.getBotAdapter();
941
1010
  // Create conversation reference for the channel
@@ -952,7 +1021,12 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
952
1021
  tenantId: tenantId,
953
1022
  },
954
1023
  channelId: "msteams",
955
- serviceUrl: "https://smba.trafficmanager.net/teams/",
1024
+ /*
1025
+ * Fallback is the commercial-cloud global endpoint; the serviceUrl
1026
+ * captured from the install event is preferred (required for GCC/DoD),
1027
+ * matching what sendAdaptiveCardToChat already does.
1028
+ */
1029
+ serviceUrl: (installedTeam === null || installedTeam === void 0 ? void 0 : installedTeam.serviceUrl) || "https://smba.trafficmanager.net/teams/",
956
1030
  };
957
1031
  logger.debug(`Conversation reference: ${JSON.stringify(conversationReference)}`);
958
1032
  // Send proactive message using Bot Framework
@@ -982,9 +1056,44 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
982
1056
  teamId: data.teamId,
983
1057
  });
984
1058
  logger.error(error);
1059
+ /*
1060
+ * Microsoft's roster rejection is meaningless to an admin ("The bot is
1061
+ * not part of the conversation roster"). Replace it with the action that
1062
+ * actually fixes it.
1063
+ */
1064
+ if (this.isBotNotInConversationRosterError(error)) {
1065
+ throw new BadDataException(this.getBotNotInTeamMessage({
1066
+ channelName: data.workspaceChannel.name,
1067
+ membershipType: data.workspaceChannel.membershipType,
1068
+ }));
1069
+ }
985
1070
  throw error;
986
1071
  }
987
1072
  }
1073
+ /*
1074
+ * True when an error is Microsoft's "bot is not in this conversation"
1075
+ * rejection from a proactive Bot Framework send.
1076
+ */
1077
+ static isBotNotInConversationRosterError(error) {
1078
+ const message = (error instanceof Error ? error.message : String(error || "")).toLowerCase();
1079
+ if (!message) {
1080
+ return false;
1081
+ }
1082
+ return MICROSOFT_TEAMS_ROSTER_ERROR_FRAGMENTS.some((fragment) => {
1083
+ return message.includes(fragment);
1084
+ });
1085
+ }
1086
+ /*
1087
+ * Actionable replacement for the roster error. Private channels need the app
1088
+ * installed into the channel itself; a parent-team install does not cover
1089
+ * them, so the two cases get different instructions.
1090
+ */
1091
+ static getBotNotInTeamMessage(data) {
1092
+ if (data.membershipType === "private") {
1093
+ return `The OneUptime app is not installed in the private channel "${data.channelName}". In Microsoft Teams, open the channel, click the "..." menu, then Manage channel > Apps > Add an app, and add OneUptime. Installing OneUptime in the parent team does not cover private channels.`;
1094
+ }
1095
+ return `The OneUptime app is not installed in the Microsoft Teams team that owns "${data.channelName}". In Microsoft Teams, click the "..." next to the team name, then Manage team > Apps > More apps, and add OneUptime. Installing OneUptime for yourself or in a chat is not the same as adding it to the team.`;
1096
+ }
988
1097
  /*
989
1098
  * Sends an adaptive card to a Teams group chat or personal (1:1) chat via a
990
1099
  * proactive Bot Framework message. The OneUptime app must have been added to
@@ -1130,6 +1239,7 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
1130
1239
  name: channelData["displayName"],
1131
1240
  workspaceType: WorkspaceType.MicrosoftTeams,
1132
1241
  teamId: data.teamId,
1242
+ membershipType: channelData["membershipType"],
1133
1243
  };
1134
1244
  logger.debug(`Channel info retrieved: ${JSON.stringify(channel)}`);
1135
1245
  return channel;
@@ -1272,10 +1382,21 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
1272
1382
  const channelsArray = channelsData["value"] || [];
1273
1383
  const channelsDict = {};
1274
1384
  for (const channelData of channelsArray) {
1385
+ const membershipType = channelData["membershipType"];
1386
+ /*
1387
+ * Microsoft Teams does not support bots in shared channels, so offering
1388
+ * one as a notification destination can only ever produce a failed send.
1389
+ */
1390
+ if (membershipType === "shared") {
1391
+ logger.debug(`Skipping shared channel ${channelData["displayName"]} — Teams does not support bots in shared channels.`);
1392
+ continue;
1393
+ }
1275
1394
  const channel = {
1276
1395
  id: channelData["id"],
1277
1396
  name: channelData["displayName"],
1278
1397
  workspaceType: WorkspaceType.MicrosoftTeams,
1398
+ teamId: data.teamId,
1399
+ membershipType: membershipType,
1279
1400
  };
1280
1401
  channelsDict[channel.id] = channel;
1281
1402
  }
@@ -1431,6 +1552,18 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
1431
1552
  onlyIfMissingOrStale: true,
1432
1553
  });
1433
1554
  }
1555
+ /*
1556
+ * Same backfill for team installs. Teams the app was added to before we
1557
+ * started recording installs fire no new install event, so an @mention in
1558
+ * any channel of that team is the recovery path that makes proactive
1559
+ * channel notifications work again.
1560
+ */
1561
+ if (messageConversationType === "channel") {
1562
+ await this.captureTeamFromBotActivity({
1563
+ activity: data.activity,
1564
+ turnContext: data.turnContext,
1565
+ });
1566
+ }
1434
1567
  // If this is actually an Adaptive Card submit wrapped as a message, route to invoke handler
1435
1568
  if (possibleActionValue["action"] ||
1436
1569
  ((_b = possibleActionValue["data"]) === null || _b === void 0 ? void 0 : _b["action"])) {
@@ -1463,27 +1596,15 @@ class MicrosoftTeamsUtil extends WorkspaceBase {
1463
1596
  return;
1464
1597
  }
1465
1598
  // Get project auth by tenant ID
1466
- const projectAuth = await WorkspaceProjectAuthTokenService.findOneBy({
1467
- query: {
1468
- workspaceType: WorkspaceType.MicrosoftTeams,
1469
- workspaceProjectId: tenantId,
1470
- },
1471
- select: {
1472
- projectId: true,
1473
- workspaceProjectId: true,
1474
- },
1475
- props: {
1476
- isRoot: true,
1477
- },
1599
+ const tenantResolution = await this.resolveProjectByTenantId({
1600
+ tenantId: tenantId,
1478
1601
  });
1479
- if (!projectAuth || !projectAuth.projectId) {
1480
- logger.error("Project auth not found for tenant ID: " + tenantId, {
1481
- tenantId: tenantId,
1482
- });
1483
- await data.turnContext.sendActivity("Sorry, I couldn't find your project configuration. Please try again later.");
1602
+ if (!tenantResolution.projectAuth ||
1603
+ !tenantResolution.projectAuth.projectId) {
1604
+ await data.turnContext.sendActivity(this.getTenantResolutionFailureMessage(tenantResolution));
1484
1605
  return;
1485
1606
  }
1486
- const projectId = projectAuth.projectId;
1607
+ const projectId = tenantResolution.projectAuth.projectId;
1487
1608
  logger.debug(`Found project ID: ${projectId.toString()} for tenant ID: ${tenantId}`);
1488
1609
  // Clean the message text by removing bot mentions
1489
1610
  const cleanText = messageText
@@ -2274,26 +2395,15 @@ All monitoring checks are passing normally.`;
2274
2395
  await data.turnContext.sendActivity("Sorry, I couldn't identify your organization. Please try again later.");
2275
2396
  return;
2276
2397
  }
2277
- const projectAuth = await WorkspaceProjectAuthTokenService.findOneBy({
2278
- query: {
2279
- workspaceType: WorkspaceType.MicrosoftTeams,
2280
- workspaceProjectId: tenantId,
2281
- },
2282
- select: {
2283
- projectId: true,
2284
- authToken: true,
2285
- workspaceProjectId: true,
2286
- },
2287
- props: { isRoot: true },
2398
+ const tenantResolution = await this.resolveProjectByTenantId({
2399
+ tenantId: tenantId,
2288
2400
  });
2289
- if (!projectAuth || !projectAuth.projectId) {
2290
- logger.error("Project auth not found for invoke activity tenant: " + tenantId, {
2291
- tenantId: tenantId,
2292
- });
2293
- await data.turnContext.sendActivity("Sorry, I couldn't find your project configuration.");
2401
+ if (!tenantResolution.projectAuth ||
2402
+ !tenantResolution.projectAuth.projectId) {
2403
+ await data.turnContext.sendActivity(this.getTenantResolutionFailureMessage(tenantResolution));
2294
2404
  return;
2295
2405
  }
2296
- const projectId = projectAuth.projectId;
2406
+ const projectId = tenantResolution.projectAuth.projectId;
2297
2407
  const fromObj = (data.activity["from"] ||
2298
2408
  {});
2299
2409
  const teamsUserId = fromObj["aadObjectId"] || undefined;
@@ -2423,6 +2533,10 @@ All monitoring checks are passing normally.`;
2423
2533
  activity: data.activity,
2424
2534
  turnContext: data.turnContext,
2425
2535
  });
2536
+ await this.captureTeamFromBotActivity({
2537
+ activity: data.activity,
2538
+ turnContext: data.turnContext,
2539
+ });
2426
2540
  await this.sendWelcomeAdaptiveCard(data.turnContext);
2427
2541
  }
2428
2542
  if (botWasRemoved) {
@@ -2430,6 +2544,9 @@ All monitoring checks are passing normally.`;
2430
2544
  await this.removeChatFromBotActivity({
2431
2545
  activity: data.activity,
2432
2546
  });
2547
+ await this.removeTeamFromBotActivity({
2548
+ activity: data.activity,
2549
+ });
2433
2550
  }
2434
2551
  }
2435
2552
  static async handleInstallationUpdateActivity(data) {
@@ -2451,13 +2568,115 @@ All monitoring checks are passing normally.`;
2451
2568
  activity: data.activity,
2452
2569
  turnContext: data.turnContext,
2453
2570
  });
2571
+ await this.captureTeamFromBotActivity({
2572
+ activity: data.activity,
2573
+ turnContext: data.turnContext,
2574
+ });
2454
2575
  }
2455
2576
  else if (action === "remove" || action === "remove-upgrade") {
2456
2577
  logger.debug("OneUptime bot was uninstalled");
2457
2578
  await this.removeChatFromBotActivity({
2458
2579
  activity: data.activity,
2459
2580
  });
2581
+ await this.removeTeamFromBotActivity({
2582
+ activity: data.activity,
2583
+ });
2584
+ }
2585
+ }
2586
+ /*
2587
+ * Resolve the OneUptime project that owns a Microsoft tenant.
2588
+ *
2589
+ * Bot activities carry a tenant id and nothing else, so the tenant is the
2590
+ * only key we can resolve a project by. A tenant may legitimately be
2591
+ * connected to more than one OneUptime project (saveChatToProjectAuthTokens
2592
+ * fans out for exactly that reason), and when that happens the tenant alone
2593
+ * does NOT identify a project.
2594
+ *
2595
+ * Previously this was a bare findOneBy, which silently returned whichever
2596
+ * row sorted first and served that project's incidents, alerts and AI
2597
+ * assistant answers to anyone in the tenant — including users with no access
2598
+ * to it. The bot's message path performs no per-user authorization, so
2599
+ * picking arbitrarily is a cross-project disclosure. Refuse instead.
2600
+ */
2601
+ static async resolveProjectByTenantId(data) {
2602
+ const projectAuths = await WorkspaceProjectAuthTokenService.findBy({
2603
+ query: {
2604
+ workspaceType: WorkspaceType.MicrosoftTeams,
2605
+ workspaceProjectId: data.tenantId,
2606
+ },
2607
+ select: {
2608
+ projectId: true,
2609
+ authToken: true,
2610
+ workspaceProjectId: true,
2611
+ miscData: true,
2612
+ },
2613
+ limit: LIMIT_MAX,
2614
+ skip: 0,
2615
+ props: {
2616
+ isRoot: true,
2617
+ },
2618
+ });
2619
+ /*
2620
+ * Ambiguity is about distinct PROJECTS, not rows. Two rows pointing at the
2621
+ * same project are a data-integrity wart, not a question we cannot answer,
2622
+ * so collapse them rather than refusing to serve that tenant forever.
2623
+ */
2624
+ const seenProjectIds = new Set();
2625
+ const usableProjectAuths = [];
2626
+ for (const projectAuth of projectAuths) {
2627
+ if (!projectAuth.projectId) {
2628
+ continue;
2629
+ }
2630
+ const projectIdString = projectAuth.projectId.toString();
2631
+ if (seenProjectIds.has(projectIdString)) {
2632
+ continue;
2633
+ }
2634
+ seenProjectIds.add(projectIdString);
2635
+ usableProjectAuths.push(projectAuth);
2636
+ }
2637
+ if (usableProjectAuths.length === 0) {
2638
+ logger.error("Project auth not found for tenant ID: " + data.tenantId, {
2639
+ tenantId: data.tenantId,
2640
+ });
2641
+ return {
2642
+ projectAuth: null,
2643
+ isAmbiguous: false,
2644
+ candidateProjectIds: [],
2645
+ };
2646
+ }
2647
+ if (usableProjectAuths.length > 1) {
2648
+ const candidateProjectIds = usableProjectAuths.map((projectAuth) => {
2649
+ return projectAuth.projectId;
2650
+ });
2651
+ logger.error(`Microsoft tenant ${data.tenantId} is connected to ${usableProjectAuths.length} OneUptime projects. Refusing to guess which one this bot activity belongs to.`, {
2652
+ tenantId: data.tenantId,
2653
+ projectIds: candidateProjectIds
2654
+ .map((projectId) => {
2655
+ return projectId.toString();
2656
+ })
2657
+ .join(", "),
2658
+ });
2659
+ return {
2660
+ projectAuth: null,
2661
+ isAmbiguous: true,
2662
+ candidateProjectIds: candidateProjectIds,
2663
+ };
2664
+ }
2665
+ return {
2666
+ projectAuth: usableProjectAuths[0],
2667
+ isAmbiguous: false,
2668
+ candidateProjectIds: [usableProjectAuths[0].projectId],
2669
+ };
2670
+ }
2671
+ /*
2672
+ * User-facing text for a failed tenant resolution. The two cases need
2673
+ * different remedies, so they must not share a message.
2674
+ */
2675
+ static getTenantResolutionFailureMessage(resolution) {
2676
+ if (resolution.isAmbiguous) {
2677
+ return "This Microsoft 365 organization is connected to more than one OneUptime project, so I can't tell which one you mean. Please ask your OneUptime admin to disconnect Microsoft Teams from all but one project.";
2460
2678
  }
2679
+ return "Sorry, I couldn't find your project configuration. This usually means the Microsoft 365 organization you're messaging me from isn't the one connected to OneUptime. Please ask your OneUptime admin to check the Microsoft Teams integration in Project Settings.";
2461
2680
  }
2462
2681
  /*
2463
2682
  * Chats (group chats and personal 1:1 chats) cannot be listed with the
@@ -2734,6 +2953,148 @@ All monitoring checks are passing normally.`;
2734
2953
  }
2735
2954
  return (projectAuth.miscData.availableChats || {});
2736
2955
  }
2956
+ /*
2957
+ * Record that the OneUptime app was installed into a team.
2958
+ *
2959
+ * Team installs arrive as conversationUpdate / installationUpdate activities
2960
+ * whose conversation is a channel. captureChatFromBotActivity drops those
2961
+ * (channels are not chats), so before this existed we threw away the only
2962
+ * signal that tells us a proactive channel post will be accepted.
2963
+ */
2964
+ static async captureTeamFromBotActivity(data) {
2965
+ var _a;
2966
+ try {
2967
+ const channelData = data.activity["channelData"] || {};
2968
+ const team = channelData["team"];
2969
+ const teamId = (team === null || team === void 0 ? void 0 : team["id"]) || "";
2970
+ if (!teamId) {
2971
+ // Not a team-scoped activity (personal or group chat). Nothing to do.
2972
+ return;
2973
+ }
2974
+ const tenantId = ((_a = channelData["tenant"]) === null || _a === void 0 ? void 0 : _a["id"]) || "";
2975
+ if (!tenantId) {
2976
+ logger.debug("No tenant id found on team activity. Skipping.");
2977
+ return;
2978
+ }
2979
+ const installedTeam = {
2980
+ id: teamId,
2981
+ name: (team === null || team === void 0 ? void 0 : team["name"]) || undefined,
2982
+ serviceUrl: data.activity["serviceUrl"] ||
2983
+ data.turnContext.activity.serviceUrl ||
2984
+ undefined,
2985
+ addedAt: OneUptimeDate.getCurrentDate().toISOString(),
2986
+ };
2987
+ await this.saveTeamToProjectAuthTokens({
2988
+ tenantId: tenantId,
2989
+ team: installedTeam,
2990
+ });
2991
+ logger.debug(`Captured Microsoft Teams team install ${teamId} for tenant ${tenantId}`);
2992
+ }
2993
+ catch (err) {
2994
+ logger.error("Error capturing Microsoft Teams team from bot activity:");
2995
+ logger.error(err);
2996
+ }
2997
+ }
2998
+ static async removeTeamFromBotActivity(data) {
2999
+ var _a, _b;
3000
+ try {
3001
+ const channelData = data.activity["channelData"] || {};
3002
+ const teamId = ((_a = channelData["team"]) === null || _a === void 0 ? void 0 : _a["id"]) || "";
3003
+ const tenantId = ((_b = channelData["tenant"]) === null || _b === void 0 ? void 0 : _b["id"]) || "";
3004
+ if (!teamId || !tenantId) {
3005
+ return;
3006
+ }
3007
+ await this.removeTeamFromProjectAuthTokens({
3008
+ tenantId: tenantId,
3009
+ teamId: teamId,
3010
+ });
3011
+ logger.debug(`Removed Microsoft Teams team install ${teamId} for tenant ${tenantId}`);
3012
+ }
3013
+ catch (err) {
3014
+ logger.error("Error removing Microsoft Teams team from bot activity:");
3015
+ logger.error(err);
3016
+ }
3017
+ }
3018
+ static async saveTeamToProjectAuthTokens(data) {
3019
+ /*
3020
+ * Same fan-out reasoning as saveChatToProjectAuthTokens: the install event
3021
+ * does not say which project it belongs to, so record it on every project
3022
+ * connected to this tenant.
3023
+ */
3024
+ const projectAuths = await WorkspaceProjectAuthTokenService.findBy({
3025
+ query: {
3026
+ workspaceType: WorkspaceType.MicrosoftTeams,
3027
+ workspaceProjectId: data.tenantId,
3028
+ },
3029
+ select: {
3030
+ _id: true,
3031
+ miscData: true,
3032
+ },
3033
+ limit: LIMIT_MAX,
3034
+ skip: 0,
3035
+ props: {
3036
+ isRoot: true,
3037
+ },
3038
+ });
3039
+ for (const projectAuth of projectAuths) {
3040
+ const miscData = Object.assign({}, (projectAuth.miscData || {}));
3041
+ miscData.installedTeams = Object.assign(Object.assign({}, (miscData.installedTeams || {})), { [data.team.id]: data.team });
3042
+ await WorkspaceProjectAuthTokenService.updateOneById({
3043
+ id: projectAuth.id,
3044
+ data: {
3045
+ miscData: miscData,
3046
+ },
3047
+ props: {
3048
+ isRoot: true,
3049
+ },
3050
+ });
3051
+ }
3052
+ }
3053
+ static async removeTeamFromProjectAuthTokens(data) {
3054
+ const projectAuths = await WorkspaceProjectAuthTokenService.findBy({
3055
+ query: {
3056
+ workspaceType: WorkspaceType.MicrosoftTeams,
3057
+ workspaceProjectId: data.tenantId,
3058
+ },
3059
+ select: {
3060
+ _id: true,
3061
+ miscData: true,
3062
+ },
3063
+ limit: LIMIT_MAX,
3064
+ skip: 0,
3065
+ props: {
3066
+ isRoot: true,
3067
+ },
3068
+ });
3069
+ for (const projectAuth of projectAuths) {
3070
+ const miscData = Object.assign({}, (projectAuth.miscData || {}));
3071
+ if (!miscData.installedTeams || !miscData.installedTeams[data.teamId]) {
3072
+ continue;
3073
+ }
3074
+ const installedTeams = Object.assign({}, miscData.installedTeams);
3075
+ delete installedTeams[data.teamId];
3076
+ miscData.installedTeams = installedTeams;
3077
+ await WorkspaceProjectAuthTokenService.updateOneById({
3078
+ id: projectAuth.id,
3079
+ data: {
3080
+ miscData: miscData,
3081
+ },
3082
+ props: {
3083
+ isRoot: true,
3084
+ },
3085
+ });
3086
+ }
3087
+ }
3088
+ static async getInstalledTeamsForProject(data) {
3089
+ const projectAuth = await WorkspaceProjectAuthTokenService.getProjectAuth({
3090
+ projectId: data.projectId,
3091
+ workspaceType: WorkspaceType.MicrosoftTeams,
3092
+ });
3093
+ if (!projectAuth || !projectAuth.miscData) {
3094
+ return {};
3095
+ }
3096
+ return (projectAuth.miscData.installedTeams || {});
3097
+ }
2737
3098
  /**
2738
3099
  * Process Bot Framework activity using the botbuilder SDK adapter.processActivity
2739
3100
  * This replaces the manual JWT validation and activity handling with proper SDK methods
@@ -3066,7 +3427,12 @@ All monitoring checks are passing normally.`;
3066
3427
  id: t["id"],
3067
3428
  name: t["displayName"] || "Unnamed Team",
3068
3429
  };
3069
- acc[team.name] = team;
3430
+ /*
3431
+ * Keyed by id, not display name — Teams allows duplicate team
3432
+ * names, and keying by name silently collapsed them so only the
3433
+ * last one of each name was selectable.
3434
+ */
3435
+ acc[team.id] = team;
3070
3436
  return acc;
3071
3437
  }, {});
3072
3438
  logger.debug(`Processed ${Object.keys(availableTeams).length} teams`);
@@ -3531,6 +3897,12 @@ __decorate([
3531
3897
  __metadata("design:paramtypes", [Object]),
3532
3898
  __metadata("design:returntype", Promise)
3533
3899
  ], MicrosoftTeamsUtil, "handleInstallationUpdateActivity", null);
3900
+ __decorate([
3901
+ CaptureSpan(),
3902
+ __metadata("design:type", Function),
3903
+ __metadata("design:paramtypes", [Object]),
3904
+ __metadata("design:returntype", Promise)
3905
+ ], MicrosoftTeamsUtil, "resolveProjectByTenantId", null);
3534
3906
  __decorate([
3535
3907
  CaptureSpan(),
3536
3908
  __metadata("design:type", Function),
@@ -3561,6 +3933,36 @@ __decorate([
3561
3933
  __metadata("design:paramtypes", [Object]),
3562
3934
  __metadata("design:returntype", Promise)
3563
3935
  ], MicrosoftTeamsUtil, "getChatsForProject", null);
3936
+ __decorate([
3937
+ CaptureSpan(),
3938
+ __metadata("design:type", Function),
3939
+ __metadata("design:paramtypes", [Object]),
3940
+ __metadata("design:returntype", Promise)
3941
+ ], MicrosoftTeamsUtil, "captureTeamFromBotActivity", null);
3942
+ __decorate([
3943
+ CaptureSpan(),
3944
+ __metadata("design:type", Function),
3945
+ __metadata("design:paramtypes", [Object]),
3946
+ __metadata("design:returntype", Promise)
3947
+ ], MicrosoftTeamsUtil, "removeTeamFromBotActivity", null);
3948
+ __decorate([
3949
+ CaptureSpan(),
3950
+ __metadata("design:type", Function),
3951
+ __metadata("design:paramtypes", [Object]),
3952
+ __metadata("design:returntype", Promise)
3953
+ ], MicrosoftTeamsUtil, "saveTeamToProjectAuthTokens", null);
3954
+ __decorate([
3955
+ CaptureSpan(),
3956
+ __metadata("design:type", Function),
3957
+ __metadata("design:paramtypes", [Object]),
3958
+ __metadata("design:returntype", Promise)
3959
+ ], MicrosoftTeamsUtil, "removeTeamFromProjectAuthTokens", null);
3960
+ __decorate([
3961
+ CaptureSpan(),
3962
+ __metadata("design:type", Function),
3963
+ __metadata("design:paramtypes", [Object]),
3964
+ __metadata("design:returntype", Promise)
3965
+ ], MicrosoftTeamsUtil, "getInstalledTeamsForProject", null);
3564
3966
  __decorate([
3565
3967
  CaptureSpan(),
3566
3968
  __metadata("design:type", Function),