@oneuptime/common 13.0.4 → 13.0.5

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 (673) hide show
  1. package/Models/DatabaseModels/Index.ts +4 -0
  2. package/Models/DatabaseModels/RumApplication.ts +1 -1
  3. package/Models/DatabaseModels/SecurityEventConnection.ts +457 -0
  4. package/Models/DatabaseModels/SecurityEventConnectionRun.ts +263 -0
  5. package/Models/DatabaseModels/TelemetryIngestionKey.ts +2 -2
  6. package/Server/API/AIInvestigationAPI.ts +484 -24
  7. package/Server/API/GoogleSecOpsConnectionAPI.ts +249 -8
  8. package/Server/API/SecurityEventConnectionAPI.ts +250 -0
  9. package/Server/API/TelemetryAPI.ts +402 -265
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.ts +99 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  12. package/Server/Middleware/TelemetryIngest.ts +101 -6
  13. package/Server/Services/ExceptionAggregationService.ts +7 -16
  14. package/Server/Services/GoogleSecOpsConnectionService.ts +15 -0
  15. package/Server/Services/Index.ts +4 -0
  16. package/Server/Services/InventoryItemService.ts +28 -0
  17. package/Server/Services/LogAggregationService.ts +17 -23
  18. package/Server/Services/MetricAggregationService.ts +4 -14
  19. package/Server/Services/SecurityEventConnectionRunService.ts +10 -0
  20. package/Server/Services/SecurityEventConnectionService.ts +538 -0
  21. package/Server/Services/TraceAggregationService.ts +77 -28
  22. package/Server/Types/AnalyticsDatabase/ModelPermission.ts +9 -0
  23. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +13 -1
  24. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +15 -1
  25. package/Server/Utils/AI/SRE/InvestigationEvidence.ts +658 -0
  26. package/Server/Utils/AI/SRE/InvestigationReferences.ts +324 -0
  27. package/Server/Utils/AI/Toolbox/Index.ts +38 -0
  28. package/Server/Utils/AI/Toolbox/TimelineTools.ts +9 -2
  29. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +80 -0
  30. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +5 -3
  31. package/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.ts +1108 -0
  32. package/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.ts +732 -0
  33. package/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.ts +495 -0
  34. package/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.ts +689 -0
  35. package/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.ts +767 -0
  36. package/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.ts +571 -0
  37. package/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.ts +827 -0
  38. package/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.ts +610 -0
  39. package/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.ts +549 -0
  40. package/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.ts +830 -0
  41. package/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.ts +684 -0
  42. package/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.ts +487 -0
  43. package/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.ts +778 -0
  44. package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.ts +1002 -0
  45. package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.ts +556 -0
  46. package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.ts +275 -0
  47. package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.ts +53 -0
  48. package/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.ts +709 -0
  49. package/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.ts +596 -0
  50. package/Server/Utils/SecurityEvent/Connectors/Types.ts +191 -0
  51. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.ts +353 -65
  52. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.ts +777 -0
  53. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +747 -148
  54. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.ts +48 -2
  55. package/Server/Utils/SecurityEvent/SecurityEventDedupe.ts +81 -0
  56. package/Server/Utils/SessionReplay/SessionReplayReadService.ts +741 -40
  57. package/Server/Utils/StartServer.ts +10 -0
  58. package/Server/Utils/Telemetry/EntityRegistry.ts +8 -0
  59. package/Server/Utils/Telemetry/KubernetesResourceAttributes.ts +108 -0
  60. package/Server/Utils/Telemetry/ResourceEntityFilter.ts +174 -93
  61. package/Server/Utils/Telemetry/ResourceFacetPlanner.ts +251 -0
  62. package/Server/Utils/Telemetry/ResourceFacetResolver.ts +248 -413
  63. package/Server/Utils/Telemetry/ServiceDependencyDiscovery.ts +668 -0
  64. package/Server/Utils/Telemetry/TraceContextPropagation.ts +348 -0
  65. package/Server/Utils/Telemetry.ts +18 -0
  66. package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +413 -0
  67. package/Tests/App/Dashboard/AIRootCauseFeedItem.test.tsx +285 -0
  68. package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +242 -0
  69. package/Tests/App/Dashboard/AlertEpisodeViewFields.test.tsx +601 -15
  70. package/Tests/App/Dashboard/ChangeAlertStateAIHeader.test.tsx +835 -0
  71. package/Tests/App/Dashboard/CloudResourceTelemetryScope.test.ts +41 -0
  72. package/Tests/App/Dashboard/ConnectionTestModal.test.tsx +604 -0
  73. package/Tests/App/Dashboard/ConnectorTestReportView.test.tsx +738 -0
  74. package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +153 -6
  75. package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +165 -0
  76. package/Tests/App/Dashboard/EpisodeChangeState.test.tsx +1069 -0
  77. package/Tests/App/Dashboard/EpisodeMembersCard.test.tsx +772 -0
  78. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +2354 -0
  79. package/Tests/App/Dashboard/EventOverviewSkeleton.test.tsx +210 -0
  80. package/Tests/App/Dashboard/EventStatBar.test.tsx +392 -0
  81. package/Tests/App/Dashboard/EventStatusPanel.test.tsx +247 -0
  82. package/Tests/App/Dashboard/ExceptionAIAssistance.test.tsx +606 -0
  83. package/Tests/App/Dashboard/ExceptionBreadcrumbTimeline.test.tsx +273 -0
  84. package/Tests/App/Dashboard/ExceptionDetailSideMenu.test.tsx +176 -0
  85. package/Tests/App/Dashboard/ExceptionOverviewCards.test.tsx +366 -0
  86. package/Tests/App/Dashboard/ExceptionSignalPages.test.tsx +371 -0
  87. package/Tests/App/Dashboard/ExceptionStackFrameViewer.test.tsx +440 -0
  88. package/Tests/App/Dashboard/ExceptionSummary.test.tsx +381 -0
  89. package/Tests/App/Dashboard/ExceptionTriage.test.tsx +306 -0
  90. package/Tests/App/Dashboard/ExceptionsResourceFacets.test.tsx +604 -0
  91. package/Tests/App/Dashboard/ExceptionsViewerEntityChips.test.tsx +706 -0
  92. package/Tests/App/Dashboard/FeedOrdering.test.ts +32 -0
  93. package/Tests/App/Dashboard/GoogleSecOpsConnectionForm.test.tsx +838 -0
  94. package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +18 -0
  95. package/Tests/App/Dashboard/GoogleSecOpsDiagnostics.test.tsx +297 -20
  96. package/Tests/App/Dashboard/IncidentEpisodeViewFields.test.tsx +618 -13
  97. package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +254 -207
  98. package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +303 -135
  99. package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +1251 -0
  100. package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +303 -0
  101. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +876 -8
  102. package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +35 -0
  103. package/Tests/App/Dashboard/InvestigationReferenceLink.test.tsx +177 -0
  104. package/Tests/App/Dashboard/InvestigationReportView.test.tsx +1295 -0
  105. package/Tests/App/Dashboard/KubernetesImageReferenceView.test.tsx +114 -0
  106. package/Tests/App/Dashboard/KubernetesLogsTabChips.test.tsx +285 -0
  107. package/Tests/App/Dashboard/LogsEntityChipNames.test.tsx +316 -0
  108. package/Tests/App/Dashboard/LogsResourceFacetChips.test.tsx +361 -0
  109. package/Tests/App/Dashboard/ProfileTableEntityNames.test.tsx +432 -0
  110. package/Tests/App/Dashboard/ProfileViewEntityName.test.tsx +250 -0
  111. package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +10 -0
  112. package/Tests/App/Dashboard/ResourceLogsTabsBareLayout.test.tsx +700 -0
  113. package/Tests/App/Dashboard/ResourcePageEntityNameProps.test.tsx +803 -0
  114. package/Tests/App/Dashboard/RumSessionReplaySideMenu.test.tsx +11 -1
  115. package/Tests/App/Dashboard/ScheduledMaintenanceChangeState.test.tsx +1026 -0
  116. package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +436 -0
  117. package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +1195 -0
  118. package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +1022 -0
  119. package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +905 -0
  120. package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +247 -0
  121. package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +375 -274
  122. package/Tests/App/Dashboard/SessionReplayAuditTable.test.tsx +410 -0
  123. package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +774 -0
  124. package/Tests/App/Dashboard/TopErrorsPanelResourceNames.test.tsx +316 -0
  125. package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +30 -0
  126. package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +88 -24
  127. package/Tests/App/Dashboard/TraceExplorer.test.tsx +1590 -0
  128. package/Tests/App/Dashboard/TraceWaterfall.test.tsx +488 -0
  129. package/Tests/App/Dashboard/TracesAnalyticsSeriesLabels.test.tsx +367 -0
  130. package/Tests/App/Dashboard/TracesEntityNames.test.tsx +585 -0
  131. package/Tests/App/Dashboard/TracesResourceFacets.test.tsx +613 -0
  132. package/Tests/App/Dashboard/UseServiceNames.test.tsx +359 -0
  133. package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +7 -0
  134. package/Tests/Models/InventoryItemNaming.test.ts +132 -16
  135. package/Tests/Models/SecurityDomainAccessControl.test.ts +61 -17
  136. package/Tests/Server/API/AIInvestigationAPI.test.ts +611 -2
  137. package/Tests/Server/API/AIInvestigationEvidenceAPI.test.ts +1098 -0
  138. package/Tests/Server/API/GoogleSecOpsConnectionAPI.test.ts +409 -0
  139. package/Tests/Server/API/SecurityEventConnectionAPI.test.ts +856 -0
  140. package/Tests/Server/API/SessionReplayAPI.test.ts +528 -1
  141. package/Tests/Server/API/TelemetryFacetsAPI.test.ts +810 -0
  142. package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +240 -0
  143. package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +229 -0
  144. package/Tests/Server/Services/InventoryItemDisplayName.test.ts +66 -0
  145. package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
  146. package/Tests/Server/Services/SecurityEventConnectionService.test.ts +1233 -0
  147. package/Tests/Server/Services/TelemetryIngestionKeyValidation.test.ts +53 -0
  148. package/Tests/Server/Services/TelemetryResourceFacetCounting.test.ts +218 -0
  149. package/Tests/Server/Services/TelemetryResourceFacetFilters.test.ts +155 -1
  150. package/Tests/Server/Services/TraceAggregationExceptionScope.test.ts +142 -0
  151. package/Tests/Server/Services/TraceAnalyticsResourceDisplayNames.test.ts +85 -24
  152. package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +33 -0
  153. package/Tests/Server/Utils/AI/InvestigationEvidence.test.ts +1395 -0
  154. package/Tests/Server/Utils/AI/InvestigationReferences.test.ts +616 -0
  155. package/Tests/Server/Utils/AI/TimelineTools.test.ts +119 -0
  156. package/Tests/Server/Utils/AI/Toolbox/AIToolbox.test.ts +151 -0
  157. package/Tests/Server/Utils/AnalyticsDatabase/StatementGenerator.test.ts +65 -0
  158. package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorExceptionScope.test.ts +224 -0
  159. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorPerSeriesFanout.test.ts +55 -2
  160. package/Tests/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.test.ts +1240 -0
  161. package/Tests/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.test.ts +1853 -0
  162. package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.test.ts +1129 -0
  163. package/Tests/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.test.ts +1066 -0
  164. package/Tests/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.test.ts +1568 -0
  165. package/Tests/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.test.ts +930 -0
  166. package/Tests/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.test.ts +1409 -0
  167. package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.test.ts +763 -0
  168. package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.test.ts +1296 -0
  169. package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.test.ts +1102 -0
  170. package/Tests/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.test.ts +1174 -0
  171. package/Tests/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.test.ts +1032 -0
  172. package/Tests/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.test.ts +1558 -0
  173. package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.test.ts +3041 -0
  174. package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.test.ts +1168 -0
  175. package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.test.ts +906 -0
  176. package/Tests/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.test.ts +1068 -0
  177. package/Tests/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.test.ts +1004 -0
  178. package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.test.ts +784 -0
  179. package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.test.ts +113 -1
  180. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClient.test.ts +5 -1
  181. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsDiagnostics.test.ts +93 -13
  182. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsHttpIntegration.test.ts +23 -1
  183. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +25 -3
  184. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +22 -8
  185. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +82 -16
  186. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSearchDetections.test.ts +730 -0
  187. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsThreePassPoller.test.ts +1577 -0
  188. package/Tests/Server/Utils/SessionReplay/SessionReplayOriginAllowlist.test.ts +41 -0
  189. package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +1453 -18
  190. package/Tests/Server/Utils/Telemetry/KubernetesResourceAttributes.test.ts +162 -0
  191. package/Tests/Server/Utils/Telemetry/ResourceEntityFilter.test.ts +460 -13
  192. package/Tests/Server/Utils/Telemetry/ResourceFacetPlanner.test.ts +678 -0
  193. package/Tests/Server/Utils/Telemetry/ResourceFacetResolver.test.ts +348 -2
  194. package/Tests/Server/Utils/Telemetry/ServiceDependencyDiscovery.test.ts +525 -0
  195. package/Tests/Server/Utils/Telemetry/TraceContextPropagation.test.ts +420 -0
  196. package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +73 -0
  197. package/Tests/Types/Rum/SessionReplayTransportContracts.test.ts +95 -0
  198. package/Tests/Types/SecurityEvent/Connectors/ConnectorDiagnostics.test.ts +82 -0
  199. package/Tests/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.test.ts +314 -0
  200. package/Tests/Types/Telemetry/ExceptionSpanScope.test.ts +89 -0
  201. package/Tests/Types/Telemetry/ResourceEntityFacet.test.ts +96 -0
  202. package/Tests/Types/Telemetry/ResourceFacetCatalog.test.ts +304 -0
  203. package/Tests/UI/Components/ActiveFilterChipsLockedFilters.test.tsx +357 -0
  204. package/Tests/UI/Components/Card.test.tsx +312 -1
  205. package/Tests/UI/Components/CardModelDetailHeaderLayout.test.tsx +253 -0
  206. package/Tests/UI/Components/CardModelDetailRefresher.test.tsx +342 -0
  207. package/Tests/UI/Components/Checkbox.test.tsx +79 -0
  208. package/Tests/UI/Components/CopyTextButton.test.tsx +142 -0
  209. package/Tests/UI/Components/DetailCompactStyle.test.tsx +621 -0
  210. package/Tests/UI/Components/ErrorBoundary.test.tsx +60 -0
  211. package/Tests/UI/Components/FacetSections.test.tsx +581 -0
  212. package/Tests/UI/Components/FacetSidebarControls.test.tsx +812 -0
  213. package/Tests/UI/Components/FacetVisibility.test.ts +429 -0
  214. package/Tests/UI/Components/LockedFilterActions.test.tsx +396 -0
  215. package/Tests/UI/Components/LockedFilterChip.test.tsx +651 -0
  216. package/Tests/UI/Components/LogsEntityNames.test.ts +1769 -0
  217. package/Tests/UI/Components/LogsEntityNamesComponents.test.tsx +696 -0
  218. package/Tests/UI/Components/LogsFacetSidebarHiddenFacets.test.tsx +600 -0
  219. package/Tests/UI/Components/LogsViewerEntityNames.test.tsx +713 -0
  220. package/Tests/UI/Components/MarkdownInlineReferences.test.tsx +2079 -0
  221. package/Tests/UI/Components/MemberRoleAssignment.test.tsx +446 -0
  222. package/Tests/UI/Components/ModelDetailRefetch.test.tsx +397 -0
  223. package/Tests/UI/Components/ModelListRefetch.test.tsx +233 -0
  224. package/Tests/UI/Components/ModelPageModelChange.test.tsx +409 -0
  225. package/Tests/UI/Components/PaginationIntegration.test.tsx +25 -0
  226. package/Tests/UI/Components/ResourceFacetConfigs.test.ts +172 -0
  227. package/Tests/UI/Components/SavedViewsSidebarIntegration.test.tsx +32 -14
  228. package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +44 -1
  229. package/Tests/UI/Components/TelemetryActiveFilterChipsLockedFilters.test.tsx +304 -0
  230. package/Tests/UI/Components/TelemetryFacetSidebarHiddenFacets.test.tsx +718 -0
  231. package/Tests/UI/Monitor/EvaluationLogList.test.tsx +303 -0
  232. package/Tests/UI/Monitor/MonitorSummarySnapshotRender.test.tsx +55 -1
  233. package/Tests/UI/Rum/FidelityNotices.test.ts +22 -0
  234. package/Tests/UI/Rum/RecordingHealthCard.test.tsx +120 -136
  235. package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +988 -0
  236. package/Tests/UI/Rum/ReplayCard.test.tsx +32 -0
  237. package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +709 -12
  238. package/Tests/UI/Rum/ReplayHeader.test.tsx +50 -1
  239. package/Tests/UI/Rum/ReplayPinControl.test.tsx +67 -10
  240. package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +41 -12
  241. package/Tests/UI/Rum/ReplayStage.test.tsx +663 -1
  242. package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +173 -0
  243. package/Tests/UI/Rum/ReplayUi.test.tsx +189 -2
  244. package/Tests/UI/Rum/ReplayUserSessionsMenu.test.tsx +91 -0
  245. package/Tests/UI/Rum/SessionReplayEmptyState.test.tsx +1 -1
  246. package/Tests/UI/Rum/SessionReplaySettingsPolicyLoading.test.tsx +585 -0
  247. package/Tests/UI/Rum/SessionReplayTable.test.tsx +844 -51
  248. package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +29 -1
  249. package/Tests/UI/Telemetry/TelemetryDetailPanel.test.tsx +288 -0
  250. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +31 -1
  251. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +6 -0
  252. package/Tests/UI/Utils/Clipboard.test.ts +154 -0
  253. package/Tests/UI/Utils/Navigation.test.ts +24 -0
  254. package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +2205 -0
  255. package/Tests/UI/Utils/Telemetry/UseTelemetryEntityNames.test.tsx +844 -0
  256. package/Tests/Utils/AI/InvestigationReport.test.ts +2430 -0
  257. package/Tests/Utils/APIOutgoingRequestTracer.test.ts +137 -0
  258. package/Tests/Utils/Rum/SessionReplayHealthDiagnosis.test.ts +40 -0
  259. package/Tests/Utils/Rum/SessionReplayRecordingEnded.test.ts +619 -0
  260. package/Tests/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.test.ts +631 -0
  261. package/Tests/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.test.ts +479 -0
  262. package/Tests/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.test.ts +507 -0
  263. package/Tests/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.test.ts +686 -0
  264. package/Tests/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.test.ts +474 -0
  265. package/Tests/Utils/SecurityEvent/Connectors/OktaNormalizer.test.ts +736 -0
  266. package/Tests/Utils/SecurityEvent/Connectors/SplunkNormalizer.test.ts +407 -0
  267. package/Tests/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.test.ts +129 -0
  268. package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +57 -1
  269. package/Tests/Utils/Telemetry/EntityRelationship.test.ts +36 -0
  270. package/Tests/Utils/Telemetry/LockedFilterSearch.test.ts +600 -0
  271. package/Tests/Utils/Telemetry/NetworkHost.test.ts +48 -0
  272. package/Tests/Utils/Telemetry/OriginAllowList.test.ts +154 -0
  273. package/Tests/Utils/Traces/CriticalPath.test.ts +25 -0
  274. package/Types/AI/AIChatTypes.ts +8 -0
  275. package/Types/AI/InvestigationEvidence.ts +96 -0
  276. package/Types/Monitor/MonitorEvaluationSummary.ts +5 -0
  277. package/Types/Permission.ts +2 -2
  278. package/Types/Rum/SessionReplay.ts +109 -0
  279. package/Types/Rum/SessionReplayApi.ts +31 -0
  280. package/Types/SecurityEvent/Connectors/ConnectorDiagnostics.ts +111 -0
  281. package/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.ts +87 -0
  282. package/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.ts +492 -0
  283. package/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.ts +41 -0
  284. package/Types/SecurityEvent/GoogleSecOpsDiagnostics.ts +56 -1
  285. package/Types/SecurityEvent/GoogleSecOpsRegion.ts +34 -0
  286. package/Types/Telemetry/EntityType.ts +14 -0
  287. package/Types/Telemetry/ExceptionSpanScope.ts +83 -0
  288. package/Types/Telemetry/LockedFilterDetail.ts +46 -0
  289. package/Types/Telemetry/ResourceEntityFacet.ts +17 -10
  290. package/Types/Telemetry/ResourceFacetCatalog.ts +171 -0
  291. package/UI/Components/Card/Card.tsx +118 -83
  292. package/UI/Components/Checkbox/Checkbox.tsx +8 -5
  293. package/UI/Components/CopyTextButton/CopyTextButton.tsx +7 -1
  294. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +4 -1
  295. package/UI/Components/Detail/Detail.tsx +137 -22
  296. package/UI/Components/ErrorBoundary.tsx +38 -0
  297. package/UI/Components/LogsViewer/LogsEntityNames.ts +912 -0
  298. package/UI/Components/LogsViewer/LogsViewer.tsx +156 -77
  299. package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +28 -11
  300. package/UI/Components/LogsViewer/components/FacetSection.tsx +66 -79
  301. package/UI/Components/LogsViewer/components/FacetValueRow.tsx +17 -2
  302. package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +45 -5
  303. package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +100 -19
  304. package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +156 -39
  305. package/UI/Components/LogsViewer/components/LogsTable.tsx +30 -8
  306. package/UI/Components/LogsViewer/types.ts +6 -0
  307. package/UI/Components/Markdown.tsx/InlineReferences.tsx +628 -0
  308. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +385 -312
  309. package/UI/Components/MemberRoleAssignment/MemberRoleAssignment.tsx +50 -22
  310. package/UI/Components/ModelDetail/CardModelDetail.tsx +15 -0
  311. package/UI/Components/ModelDetail/ModelDetail.tsx +64 -19
  312. package/UI/Components/ModelList/ModelList.tsx +33 -8
  313. package/UI/Components/Page/ModelPage.tsx +119 -54
  314. package/UI/Components/Table/Table.tsx +8 -0
  315. package/UI/Components/Table/TableRow.tsx +13 -5
  316. package/UI/Components/TelemetryViewer/FacetVisibility.ts +229 -0
  317. package/UI/Components/TelemetryViewer/ResourceFacetConfigs.ts +46 -0
  318. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +11 -0
  319. package/UI/Components/TelemetryViewer/components/FacetSearchInput.tsx +79 -0
  320. package/UI/Components/TelemetryViewer/components/FacetSectionHeader.tsx +69 -0
  321. package/UI/Components/TelemetryViewer/components/FacetShowMoreButton.tsx +36 -0
  322. package/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.tsx +88 -0
  323. package/UI/Components/TelemetryViewer/components/LockedFilterActions.tsx +205 -0
  324. package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +496 -0
  325. package/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.tsx +30 -10
  326. package/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.tsx +203 -10
  327. package/UI/Components/TelemetryViewer/components/TelemetryFacetSection.tsx +60 -73
  328. package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +94 -7
  329. package/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.tsx +17 -2
  330. package/UI/Components/TelemetryViewer/types.ts +19 -0
  331. package/UI/Components/TelemetryViewer/useFacetSearchExemptions.ts +158 -0
  332. package/UI/Components/TelemetryViewer/useFacetSectionSearch.ts +102 -0
  333. package/UI/Utils/Clipboard.ts +68 -2
  334. package/UI/Utils/Navigation.ts +17 -2
  335. package/UI/Utils/Telemetry/TelemetryEntityNames.ts +620 -0
  336. package/UI/Utils/Telemetry/UseTelemetryEntityNames.ts +151 -0
  337. package/Utils/AI/InvestigationReport.ts +1789 -0
  338. package/Utils/API.ts +90 -1
  339. package/Utils/Rum/SessionReplayHealth.ts +11 -0
  340. package/Utils/Rum/SessionReplayRecordingEnded.ts +134 -0
  341. package/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.ts +427 -0
  342. package/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.ts +197 -0
  343. package/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.ts +464 -0
  344. package/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.ts +567 -0
  345. package/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.ts +299 -0
  346. package/Utils/SecurityEvent/Connectors/OktaNormalizer.ts +467 -0
  347. package/Utils/SecurityEvent/Connectors/SplunkNormalizer.ts +439 -0
  348. package/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.ts +124 -12
  349. package/Utils/Telemetry/CrossSignalScope.ts +22 -8
  350. package/Utils/Telemetry/EntityRelationship.ts +8 -0
  351. package/Utils/Telemetry/LockedFilterSearch.ts +412 -0
  352. package/Utils/Telemetry/NetworkHost.ts +43 -0
  353. package/Utils/Telemetry/OriginAllowList.ts +139 -4
  354. package/Utils/Traces/CriticalPath.ts +10 -4
  355. package/build/dist/Models/DatabaseModels/Index.js +4 -0
  356. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  357. package/build/dist/Models/DatabaseModels/RumApplication.js +1 -1
  358. package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
  359. package/build/dist/Models/DatabaseModels/SecurityEventConnection.js +490 -0
  360. package/build/dist/Models/DatabaseModels/SecurityEventConnection.js.map +1 -0
  361. package/build/dist/Models/DatabaseModels/SecurityEventConnectionRun.js +287 -0
  362. package/build/dist/Models/DatabaseModels/SecurityEventConnectionRun.js.map +1 -0
  363. package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js +2 -2
  364. package/build/dist/Models/DatabaseModels/TelemetryIngestionKey.js.map +1 -1
  365. package/build/dist/Server/API/AIInvestigationAPI.js +336 -27
  366. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  367. package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js +182 -7
  368. package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js.map +1 -1
  369. package/build/dist/Server/API/SecurityEventConnectionAPI.js +171 -0
  370. package/build/dist/Server/API/SecurityEventConnectionAPI.js.map +1 -0
  371. package/build/dist/Server/API/TelemetryAPI.js +248 -170
  372. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  373. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.js +40 -0
  374. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792700000000-AddSecurityEventConnections.js.map +1 -0
  375. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  376. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  377. package/build/dist/Server/Middleware/TelemetryIngest.js +57 -4
  378. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  379. package/build/dist/Server/Services/ExceptionAggregationService.js +7 -16
  380. package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
  381. package/build/dist/Server/Services/GoogleSecOpsConnectionService.js +8 -0
  382. package/build/dist/Server/Services/GoogleSecOpsConnectionService.js.map +1 -1
  383. package/build/dist/Server/Services/Index.js +4 -0
  384. package/build/dist/Server/Services/Index.js.map +1 -1
  385. package/build/dist/Server/Services/InventoryItemService.js +22 -0
  386. package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
  387. package/build/dist/Server/Services/LogAggregationService.js +8 -17
  388. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  389. package/build/dist/Server/Services/MetricAggregationService.js +4 -14
  390. package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
  391. package/build/dist/Server/Services/SecurityEventConnectionRunService.js +9 -0
  392. package/build/dist/Server/Services/SecurityEventConnectionRunService.js.map +1 -0
  393. package/build/dist/Server/Services/SecurityEventConnectionService.js +356 -0
  394. package/build/dist/Server/Services/SecurityEventConnectionService.js.map +1 -0
  395. package/build/dist/Server/Services/TraceAggregationService.js +51 -25
  396. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  397. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js +9 -0
  398. package/build/dist/Server/Types/AnalyticsDatabase/ModelPermission.js.map +1 -1
  399. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +3 -0
  400. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  401. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +14 -7
  402. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  403. package/build/dist/Server/Utils/AI/SRE/InvestigationEvidence.js +468 -0
  404. package/build/dist/Server/Utils/AI/SRE/InvestigationEvidence.js.map +1 -0
  405. package/build/dist/Server/Utils/AI/SRE/InvestigationReferences.js +230 -0
  406. package/build/dist/Server/Utils/AI/SRE/InvestigationReferences.js.map +1 -0
  407. package/build/dist/Server/Utils/AI/Toolbox/Index.js +32 -0
  408. package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
  409. package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js +6 -2
  410. package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js.map +1 -1
  411. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +59 -0
  412. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  413. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +5 -3
  414. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  415. package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.js +752 -0
  416. package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubClient.js.map +1 -0
  417. package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.js +493 -0
  418. package/build/dist/Server/Utils/SecurityEvent/Connectors/AwsSecurityHub/AwsSecurityHubConnector.js.map +1 -0
  419. package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js +352 -0
  420. package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js.map +1 -0
  421. package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.js +405 -0
  422. package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconClient.js.map +1 -0
  423. package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.js +466 -0
  424. package/build/dist/Server/Utils/SecurityEvent/Connectors/CrowdStrikeFalcon/CrowdStrikeFalconConnector.js.map +1 -0
  425. package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.js +344 -0
  426. package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient.js.map +1 -0
  427. package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.js +511 -0
  428. package/build/dist/Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector.js.map +1 -0
  429. package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.js +406 -0
  430. package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrClient.js.map +1 -0
  431. package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.js +336 -0
  432. package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdr/MicrosoftDefenderXdrConnector.js.map +1 -0
  433. package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.js +474 -0
  434. package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient.js.map +1 -0
  435. package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.js +417 -0
  436. package/build/dist/Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector.js.map +1 -0
  437. package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.js +314 -0
  438. package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaClient.js.map +1 -0
  439. package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.js +494 -0
  440. package/build/dist/Server/Utils/SecurityEvent/Connectors/Okta/OktaConnector.js.map +1 -0
  441. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js +719 -0
  442. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js.map +1 -0
  443. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js +404 -0
  444. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js.map +1 -0
  445. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js +209 -0
  446. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js.map +1 -0
  447. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js +40 -0
  448. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js.map +1 -0
  449. package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.js +494 -0
  450. package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkClient.js.map +1 -0
  451. package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.js +379 -0
  452. package/build/dist/Server/Utils/SecurityEvent/Connectors/Splunk/SplunkConnector.js.map +1 -0
  453. package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js +27 -0
  454. package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js.map +1 -0
  455. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js +234 -61
  456. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +1 -1
  457. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js +537 -0
  458. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js.map +1 -0
  459. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +572 -115
  460. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
  461. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js +35 -1
  462. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js.map +1 -1
  463. package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js +52 -0
  464. package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js.map +1 -0
  465. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +521 -32
  466. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
  467. package/build/dist/Server/Utils/StartServer.js +10 -0
  468. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  469. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +8 -0
  470. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  471. package/build/dist/Server/Utils/Telemetry/KubernetesResourceAttributes.js +80 -0
  472. package/build/dist/Server/Utils/Telemetry/KubernetesResourceAttributes.js.map +1 -0
  473. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +122 -67
  474. package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
  475. package/build/dist/Server/Utils/Telemetry/ResourceFacetPlanner.js +146 -0
  476. package/build/dist/Server/Utils/Telemetry/ResourceFacetPlanner.js.map +1 -0
  477. package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js +174 -248
  478. package/build/dist/Server/Utils/Telemetry/ResourceFacetResolver.js.map +1 -1
  479. package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js +492 -0
  480. package/build/dist/Server/Utils/Telemetry/ServiceDependencyDiscovery.js.map +1 -0
  481. package/build/dist/Server/Utils/Telemetry/TraceContextPropagation.js +259 -0
  482. package/build/dist/Server/Utils/Telemetry/TraceContextPropagation.js.map +1 -0
  483. package/build/dist/Server/Utils/Telemetry.js +11 -5
  484. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  485. package/build/dist/Types/AI/InvestigationEvidence.js +2 -0
  486. package/build/dist/Types/AI/InvestigationEvidence.js.map +1 -0
  487. package/build/dist/Types/Permission.js +2 -2
  488. package/build/dist/Types/Permission.js.map +1 -1
  489. package/build/dist/Types/Rum/SessionReplay.js +95 -0
  490. package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
  491. package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
  492. package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js +18 -0
  493. package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js.map +1 -0
  494. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js +2 -0
  495. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js.map +1 -0
  496. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js +374 -0
  497. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js.map +1 -0
  498. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js +35 -0
  499. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js.map +1 -0
  500. package/build/dist/Types/SecurityEvent/GoogleSecOpsRegion.js +35 -0
  501. package/build/dist/Types/SecurityEvent/GoogleSecOpsRegion.js.map +1 -0
  502. package/build/dist/Types/Telemetry/EntityType.js +14 -0
  503. package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
  504. package/build/dist/Types/Telemetry/ExceptionSpanScope.js +59 -0
  505. package/build/dist/Types/Telemetry/ExceptionSpanScope.js.map +1 -0
  506. package/build/dist/Types/Telemetry/LockedFilterDetail.js +16 -0
  507. package/build/dist/Types/Telemetry/LockedFilterDetail.js.map +1 -0
  508. package/build/dist/Types/Telemetry/ResourceEntityFacet.js +16 -10
  509. package/build/dist/Types/Telemetry/ResourceEntityFacet.js.map +1 -1
  510. package/build/dist/Types/Telemetry/ResourceFacetCatalog.js +119 -0
  511. package/build/dist/Types/Telemetry/ResourceFacetCatalog.js.map +1 -0
  512. package/build/dist/UI/Components/Card/Card.js +34 -17
  513. package/build/dist/UI/Components/Card/Card.js.map +1 -1
  514. package/build/dist/UI/Components/Checkbox/Checkbox.js +6 -4
  515. package/build/dist/UI/Components/Checkbox/Checkbox.js.map +1 -1
  516. package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js +5 -1
  517. package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js.map +1 -1
  518. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +1 -1
  519. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  520. package/build/dist/UI/Components/Detail/Detail.js +63 -13
  521. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  522. package/build/dist/UI/Components/ErrorBoundary.js +34 -0
  523. package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
  524. package/build/dist/UI/Components/LogsViewer/LogsEntityNames.js +535 -0
  525. package/build/dist/UI/Components/LogsViewer/LogsEntityNames.js.map +1 -0
  526. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +117 -57
  527. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  528. package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +5 -7
  529. package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
  530. package/build/dist/UI/Components/LogsViewer/components/FacetSection.js +31 -44
  531. package/build/dist/UI/Components/LogsViewer/components/FacetSection.js.map +1 -1
  532. package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js +17 -3
  533. package/build/dist/UI/Components/LogsViewer/components/FacetValueRow.js.map +1 -1
  534. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +19 -3
  535. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
  536. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +64 -18
  537. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
  538. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +100 -41
  539. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
  540. package/build/dist/UI/Components/LogsViewer/components/LogsTable.js +13 -5
  541. package/build/dist/UI/Components/LogsViewer/components/LogsTable.js.map +1 -1
  542. package/build/dist/UI/Components/LogsViewer/types.js.map +1 -1
  543. package/build/dist/UI/Components/Markdown.tsx/InlineReferences.js +403 -0
  544. package/build/dist/UI/Components/Markdown.tsx/InlineReferences.js.map +1 -0
  545. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +197 -179
  546. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  547. package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js +30 -21
  548. package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js.map +1 -1
  549. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +12 -0
  550. package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
  551. package/build/dist/UI/Components/ModelDetail/ModelDetail.js +46 -12
  552. package/build/dist/UI/Components/ModelDetail/ModelDetail.js.map +1 -1
  553. package/build/dist/UI/Components/ModelList/ModelList.js +26 -7
  554. package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
  555. package/build/dist/UI/Components/Page/ModelPage.js +62 -34
  556. package/build/dist/UI/Components/Page/ModelPage.js.map +1 -1
  557. package/build/dist/UI/Components/Table/Table.js +3 -1
  558. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  559. package/build/dist/UI/Components/Table/TableRow.js +8 -1
  560. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  561. package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +111 -0
  562. package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -0
  563. package/build/dist/UI/Components/TelemetryViewer/ResourceFacetConfigs.js +22 -0
  564. package/build/dist/UI/Components/TelemetryViewer/ResourceFacetConfigs.js.map +1 -0
  565. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +1 -1
  566. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  567. package/build/dist/UI/Components/TelemetryViewer/components/FacetSearchInput.js +36 -0
  568. package/build/dist/UI/Components/TelemetryViewer/components/FacetSearchInput.js.map +1 -0
  569. package/build/dist/UI/Components/TelemetryViewer/components/FacetSectionHeader.js +21 -0
  570. package/build/dist/UI/Components/TelemetryViewer/components/FacetSectionHeader.js.map +1 -0
  571. package/build/dist/UI/Components/TelemetryViewer/components/FacetShowMoreButton.js +14 -0
  572. package/build/dist/UI/Components/TelemetryViewer/components/FacetShowMoreButton.js.map +1 -0
  573. package/build/dist/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.js +27 -0
  574. package/build/dist/UI/Components/TelemetryViewer/components/HiddenFacetsFooter.js.map +1 -0
  575. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js +88 -0
  576. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js.map +1 -0
  577. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +228 -0
  578. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -0
  579. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js +6 -6
  580. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js.map +1 -1
  581. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js +111 -12
  582. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryDetailPanel.js.map +1 -1
  583. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSection.js +27 -40
  584. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSection.js.map +1 -1
  585. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +70 -10
  586. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
  587. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js +17 -3
  588. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetValueRow.js.map +1 -1
  589. package/build/dist/UI/Components/TelemetryViewer/types.js +0 -4
  590. package/build/dist/UI/Components/TelemetryViewer/types.js.map +1 -1
  591. package/build/dist/UI/Components/TelemetryViewer/useFacetSearchExemptions.js +70 -0
  592. package/build/dist/UI/Components/TelemetryViewer/useFacetSearchExemptions.js.map +1 -0
  593. package/build/dist/UI/Components/TelemetryViewer/useFacetSectionSearch.js +52 -0
  594. package/build/dist/UI/Components/TelemetryViewer/useFacetSectionSearch.js.map +1 -0
  595. package/build/dist/UI/Utils/Clipboard.js +59 -2
  596. package/build/dist/UI/Utils/Clipboard.js.map +1 -1
  597. package/build/dist/UI/Utils/Navigation.js +11 -2
  598. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  599. package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +471 -0
  600. package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -0
  601. package/build/dist/UI/Utils/Telemetry/UseTelemetryEntityNames.js +113 -0
  602. package/build/dist/UI/Utils/Telemetry/UseTelemetryEntityNames.js.map +1 -0
  603. package/build/dist/Utils/AI/InvestigationReport.js +1241 -0
  604. package/build/dist/Utils/AI/InvestigationReport.js.map +1 -0
  605. package/build/dist/Utils/API.js +25 -0
  606. package/build/dist/Utils/API.js.map +1 -1
  607. package/build/dist/Utils/Rum/SessionReplayHealth.js +10 -0
  608. package/build/dist/Utils/Rum/SessionReplayHealth.js.map +1 -1
  609. package/build/dist/Utils/Rum/SessionReplayRecordingEnded.js +54 -0
  610. package/build/dist/Utils/Rum/SessionReplayRecordingEnded.js.map +1 -0
  611. package/build/dist/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.js +311 -0
  612. package/build/dist/Utils/SecurityEvent/Connectors/AwsSecurityHubNormalizer.js.map +1 -0
  613. package/build/dist/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.js +150 -0
  614. package/build/dist/Utils/SecurityEvent/Connectors/CrowdStrikeFalconNormalizer.js.map +1 -0
  615. package/build/dist/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.js +328 -0
  616. package/build/dist/Utils/SecurityEvent/Connectors/ElasticSecurityNormalizer.js.map +1 -0
  617. package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.js +405 -0
  618. package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftDefenderXdrNormalizer.js.map +1 -0
  619. package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.js +212 -0
  620. package/build/dist/Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer.js.map +1 -0
  621. package/build/dist/Utils/SecurityEvent/Connectors/OktaNormalizer.js +351 -0
  622. package/build/dist/Utils/SecurityEvent/Connectors/OktaNormalizer.js.map +1 -0
  623. package/build/dist/Utils/SecurityEvent/Connectors/SplunkNormalizer.js +348 -0
  624. package/build/dist/Utils/SecurityEvent/Connectors/SplunkNormalizer.js.map +1 -0
  625. package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js +103 -10
  626. package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js.map +1 -1
  627. package/build/dist/Utils/Telemetry/CrossSignalScope.js +16 -5
  628. package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
  629. package/build/dist/Utils/Telemetry/EntityRelationship.js +7 -0
  630. package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
  631. package/build/dist/Utils/Telemetry/LockedFilterSearch.js +277 -0
  632. package/build/dist/Utils/Telemetry/LockedFilterSearch.js.map +1 -0
  633. package/build/dist/Utils/Telemetry/NetworkHost.js +39 -0
  634. package/build/dist/Utils/Telemetry/NetworkHost.js.map +1 -0
  635. package/build/dist/Utils/Telemetry/OriginAllowList.js +105 -4
  636. package/build/dist/Utils/Telemetry/OriginAllowList.js.map +1 -1
  637. package/build/dist/Utils/Traces/CriticalPath.js +9 -4
  638. package/build/dist/Utils/Traces/CriticalPath.js.map +1 -1
  639. package/package.json +1 -1
  640. package/Tests/UI/Rum/RecordingHealthStrip.test.tsx +0 -600
  641. package/UI/Components/GanttChart/Bar/BarLabel.tsx +0 -17
  642. package/UI/Components/GanttChart/Bar/Index.tsx +0 -149
  643. package/UI/Components/GanttChart/ChartContainer.tsx +0 -50
  644. package/UI/Components/GanttChart/Index.tsx +0 -90
  645. package/UI/Components/GanttChart/Row/Index.tsx +0 -22
  646. package/UI/Components/GanttChart/Row/Row.tsx +0 -231
  647. package/UI/Components/GanttChart/Row/RowLabel.tsx +0 -30
  648. package/UI/Components/GanttChart/Rows.tsx +0 -59
  649. package/UI/Components/GanttChart/Timeline/Index.tsx +0 -46
  650. package/UI/Components/GanttChart/Timeline/TimelineInterval.tsx +0 -33
  651. package/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.tsx +0 -43
  652. package/build/dist/UI/Components/GanttChart/Bar/BarLabel.js +0 -8
  653. package/build/dist/UI/Components/GanttChart/Bar/BarLabel.js.map +0 -1
  654. package/build/dist/UI/Components/GanttChart/Bar/Index.js +0 -77
  655. package/build/dist/UI/Components/GanttChart/Bar/Index.js.map +0 -1
  656. package/build/dist/UI/Components/GanttChart/ChartContainer.js +0 -33
  657. package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +0 -1
  658. package/build/dist/UI/Components/GanttChart/Index.js +0 -39
  659. package/build/dist/UI/Components/GanttChart/Index.js.map +0 -1
  660. package/build/dist/UI/Components/GanttChart/Row/Index.js +0 -7
  661. package/build/dist/UI/Components/GanttChart/Row/Index.js.map +0 -1
  662. package/build/dist/UI/Components/GanttChart/Row/Row.js +0 -106
  663. package/build/dist/UI/Components/GanttChart/Row/Row.js.map +0 -1
  664. package/build/dist/UI/Components/GanttChart/Row/RowLabel.js +0 -10
  665. package/build/dist/UI/Components/GanttChart/Row/RowLabel.js.map +0 -1
  666. package/build/dist/UI/Components/GanttChart/Rows.js +0 -19
  667. package/build/dist/UI/Components/GanttChart/Rows.js.map +0 -1
  668. package/build/dist/UI/Components/GanttChart/Timeline/Index.js +0 -16
  669. package/build/dist/UI/Components/GanttChart/Timeline/Index.js.map +0 -1
  670. package/build/dist/UI/Components/GanttChart/Timeline/TimelineInterval.js +0 -13
  671. package/build/dist/UI/Components/GanttChart/Timeline/TimelineInterval.js.map +0 -1
  672. package/build/dist/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.js +0 -13
  673. package/build/dist/UI/Components/GanttChart/Timeline/TimelineIntervalMarks.js.map +0 -1
@@ -0,0 +1,1102 @@
1
+ import { describe, expect, test } from "@jest/globals";
2
+ import MicrosoftSentinelClient, {
3
+ MICROSOFT_SENTINEL_API_VERSION,
4
+ MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE,
5
+ MICROSOFT_SENTINEL_MAX_PAGE_SIZE,
6
+ MicrosoftSentinelCloud,
7
+ MicrosoftSentinelIncidentCount,
8
+ MicrosoftSentinelIncidentsPage,
9
+ } from "../../../../../../Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient";
10
+ import {
11
+ DataSourceHttpRequest,
12
+ DataSourceHttpResponse,
13
+ } from "../../../../../../Server/Utils/DataSource/HttpFetch";
14
+ import APIException from "../../../../../../Types/Exception/ApiException";
15
+ import BadDataException from "../../../../../../Types/Exception/BadDataException";
16
+ import Dictionary from "../../../../../../Types/Dictionary";
17
+ import { JSONObject } from "../../../../../../Types/JSON";
18
+
19
+ /*
20
+ * The ARM client contract as the connector depends on it: the Entra token
21
+ * request, the incidents URL (creation-time filter, ascending order, page
22
+ * size), nextLink pagination and its host pinning, the one-shot 401
23
+ * retry, the failure taxonomy per status, and — above everything — that
24
+ * no credential can leave through an error message. The transport is the
25
+ * injected seam; nothing here touches the network.
26
+ */
27
+
28
+ const TENANT_ID: string = "b3c1b5fc-828c-45fa-a1e1-10d74f6d6e9c";
29
+ const CLIENT_ID: string = "00001111-aaaa-2222-bbbb-3333cccc4444";
30
+ const CLIENT_SECRET: string = "A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u~verySecret";
31
+ const SUBSCRIPTION_ID: string = "d0cfe6b2-9ac0-4464-9919-dccaee2e48c0";
32
+ const RESOURCE_GROUP: string = "myRg";
33
+ const WORKSPACE_NAME: string = "myWorkspace";
34
+ const ACCESS_TOKEN: string =
35
+ "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQifQ.c2lnbmF0dXJlLXNpZ25hdHVyZQ";
36
+ const FRESH_TOKEN: string =
37
+ "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJmcmVzaC10b2tlbi1hdWRpZW5jZSJ9.ZnJlc2gtc2lnbmF0dXJl";
38
+ const START: Date = new Date("2026-09-12T10:00:00.000Z");
39
+ const END: Date = new Date("2026-09-13T10:00:00.000Z");
40
+ const INCIDENTS_PATH: string = `/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP}/providers/Microsoft.OperationalInsights/workspaces/${WORKSPACE_NAME}/providers/Microsoft.SecurityInsights/incidents`;
41
+
42
+ type Responder = (
43
+ request: DataSourceHttpRequest,
44
+ ) => DataSourceHttpResponse | Promise<DataSourceHttpResponse>;
45
+
46
+ interface Harness {
47
+ requests: Array<DataSourceHttpRequest>;
48
+ client: MicrosoftSentinelClient;
49
+ }
50
+
51
+ function ok(body: JSONObject): DataSourceHttpResponse {
52
+ return {
53
+ statusCode: 200,
54
+ bodyText: JSON.stringify(body),
55
+ bodyJson: body,
56
+ headers: {},
57
+ };
58
+ }
59
+
60
+ function status(code: number, body: string): DataSourceHttpResponse {
61
+ let bodyJson: unknown = undefined;
62
+
63
+ try {
64
+ bodyJson = JSON.parse(body);
65
+ } catch {
66
+ bodyJson = undefined;
67
+ }
68
+
69
+ return { statusCode: code, bodyText: body, bodyJson, headers: {} };
70
+ }
71
+
72
+ function tokenResponse(token: string = ACCESS_TOKEN): DataSourceHttpResponse {
73
+ return ok({ token_type: "Bearer", expires_in: 3599, access_token: token });
74
+ }
75
+
76
+ /*
77
+ * Shaped like the sample response of the Incidents - List reference
78
+ * (api-version 2024-03-01).
79
+ */
80
+ function incident(name: string): JSONObject {
81
+ return {
82
+ id: `${INCIDENTS_PATH}/${name}`,
83
+ name,
84
+ type: "Microsoft.SecurityInsights/incidents",
85
+ etag: '"0300bf09-0000-0000-0000-5c37296e0000"',
86
+ properties: {
87
+ lastModifiedTimeUtc: "2026-09-12T13:15:30Z",
88
+ createdTimeUtc: "2026-09-12T13:15:30Z",
89
+ lastActivityTimeUtc: "2026-09-12T13:05:30Z",
90
+ firstActivityTimeUtc: "2026-09-12T13:00:30Z",
91
+ description: "This is a demo incident",
92
+ title: "My incident",
93
+ severity: "High",
94
+ status: "New",
95
+ incidentNumber: 3177,
96
+ labels: [],
97
+ providerName: "Azure Sentinel",
98
+ providerIncidentId: "3177",
99
+ relatedAnalyticRuleIds: [],
100
+ additionalData: {
101
+ alertsCount: 1,
102
+ bookmarksCount: 0,
103
+ commentsCount: 0,
104
+ alertProductNames: ["Azure Sentinel"],
105
+ tactics: ["Persistence"],
106
+ },
107
+ },
108
+ };
109
+ }
110
+
111
+ function armError(code: string, message: string): string {
112
+ return JSON.stringify({ error: { code, message } });
113
+ }
114
+
115
+ /*
116
+ * Routes token and incidents requests to scripted responders. Incidents
117
+ * responders are consumed in order so a test can script "401 then 200";
118
+ * token responders are consumed in order when more than one is given.
119
+ */
120
+ function buildHarness(options: {
121
+ cloud?: MicrosoftSentinelCloud;
122
+ token?: Responder | Array<Responder>;
123
+ incidents?: Array<Responder>;
124
+ requestTimeoutInMs?: number;
125
+ }): Harness {
126
+ const requests: Array<DataSourceHttpRequest> = [];
127
+ const tokenResponders: Array<Responder> = Array.isArray(options.token)
128
+ ? [...options.token]
129
+ : [
130
+ options.token ||
131
+ ((): DataSourceHttpResponse => {
132
+ return tokenResponse();
133
+ }),
134
+ ];
135
+ const incidentResponders: Array<Responder> = [...(options.incidents || [])];
136
+
137
+ const client: MicrosoftSentinelClient = new MicrosoftSentinelClient({
138
+ tenantId: TENANT_ID,
139
+ clientId: CLIENT_ID,
140
+ clientSecret: CLIENT_SECRET,
141
+ subscriptionId: SUBSCRIPTION_ID,
142
+ resourceGroup: RESOURCE_GROUP,
143
+ workspaceName: WORKSPACE_NAME,
144
+ cloud: options.cloud || "public",
145
+ requestTimeoutInMs: options.requestTimeoutInMs || 20000,
146
+ transport: async (
147
+ request: DataSourceHttpRequest,
148
+ ): Promise<DataSourceHttpResponse> => {
149
+ requests.push(request);
150
+
151
+ if (request.url.includes("/oauth2/v2.0/token")) {
152
+ const responder: Responder | undefined =
153
+ tokenResponders.length > 1
154
+ ? tokenResponders.shift()
155
+ : tokenResponders[0];
156
+ return responder!(request);
157
+ }
158
+
159
+ const responder: Responder | undefined = incidentResponders.shift();
160
+
161
+ if (!responder) {
162
+ throw new Error(`Unexpected request to ${request.url}`);
163
+ }
164
+
165
+ return responder(request);
166
+ },
167
+ });
168
+
169
+ return { requests, client };
170
+ }
171
+
172
+ function tokenRequests(
173
+ requests: Array<DataSourceHttpRequest>,
174
+ ): Array<DataSourceHttpRequest> {
175
+ return requests.filter((request: DataSourceHttpRequest): boolean => {
176
+ return request.url.includes("/oauth2/v2.0/token");
177
+ });
178
+ }
179
+
180
+ async function expectRejection(
181
+ promise: Promise<unknown>,
182
+ ): Promise<APIException> {
183
+ try {
184
+ await promise;
185
+ } catch (error) {
186
+ expect(error).toBeInstanceOf(APIException);
187
+ return error as APIException;
188
+ }
189
+
190
+ throw new Error("Expected the call to reject.");
191
+ }
192
+
193
+ describe("MicrosoftSentinelClient", () => {
194
+ describe("construction and validation", () => {
195
+ test("rejects an unknown cloud before anything is contacted", () => {
196
+ expect(() => {
197
+ return new MicrosoftSentinelClient({
198
+ tenantId: TENANT_ID,
199
+ clientId: CLIENT_ID,
200
+ clientSecret: CLIENT_SECRET,
201
+ subscriptionId: SUBSCRIPTION_ID,
202
+ resourceGroup: RESOURCE_GROUP,
203
+ workspaceName: WORKSPACE_NAME,
204
+ cloud: "china" as unknown as MicrosoftSentinelCloud,
205
+ transport: (): Promise<DataSourceHttpResponse> => {
206
+ throw new Error("must not be called");
207
+ },
208
+ });
209
+ }).toThrow(BadDataException);
210
+ });
211
+
212
+ test("accepts a tenant GUID or a verified tenant domain and refuses path-like values", () => {
213
+ expect(() => {
214
+ MicrosoftSentinelClient.validateTenantId(TENANT_ID);
215
+ }).not.toThrow();
216
+ expect(() => {
217
+ MicrosoftSentinelClient.validateTenantId("contoso.onmicrosoft.com");
218
+ }).not.toThrow();
219
+ expect(() => {
220
+ MicrosoftSentinelClient.validateTenantId("contoso/../common");
221
+ }).toThrow(BadDataException);
222
+ expect(() => {
223
+ MicrosoftSentinelClient.validateTenantId("");
224
+ }).toThrow(BadDataException);
225
+ });
226
+
227
+ test("requires GUIDs for the client and subscription ids", () => {
228
+ expect(() => {
229
+ MicrosoftSentinelClient.validateGuid("not-a-guid", "Subscription ID");
230
+ }).toThrow("Subscription ID must be a GUID");
231
+ expect(() => {
232
+ MicrosoftSentinelClient.validateGuid(` ${CLIENT_ID} `, "x");
233
+ }).not.toThrow();
234
+ });
235
+
236
+ test("applies the Azure resource group and workspace name rules", () => {
237
+ expect(() => {
238
+ MicrosoftSentinelClient.validateResourceGroup("rg-sentinel_(prod).1");
239
+ }).not.toThrow();
240
+ expect(() => {
241
+ MicrosoftSentinelClient.validateResourceGroup("ends-with-period.");
242
+ }).toThrow(BadDataException);
243
+ expect(() => {
244
+ MicrosoftSentinelClient.validateResourceGroup("has space");
245
+ }).toThrow(BadDataException);
246
+ expect(() => {
247
+ MicrosoftSentinelClient.validateResourceGroup("a".repeat(91));
248
+ }).toThrow(BadDataException);
249
+
250
+ expect(() => {
251
+ MicrosoftSentinelClient.validateWorkspaceName("my-Workspace-01");
252
+ }).not.toThrow();
253
+ expect(() => {
254
+ MicrosoftSentinelClient.validateWorkspaceName("-leading");
255
+ }).toThrow(BadDataException);
256
+ expect(() => {
257
+ MicrosoftSentinelClient.validateWorkspaceName("has_underscore");
258
+ }).toThrow(BadDataException);
259
+ expect(() => {
260
+ MicrosoftSentinelClient.validateWorkspaceName("a".repeat(91));
261
+ }).toThrow(BadDataException);
262
+ });
263
+
264
+ test("requires a client secret", () => {
265
+ expect(() => {
266
+ return new MicrosoftSentinelClient({
267
+ tenantId: TENANT_ID,
268
+ clientId: CLIENT_ID,
269
+ clientSecret: "",
270
+ subscriptionId: SUBSCRIPTION_ID,
271
+ resourceGroup: RESOURCE_GROUP,
272
+ workspaceName: WORKSPACE_NAME,
273
+ cloud: "public",
274
+ transport: (): Promise<DataSourceHttpResponse> => {
275
+ throw new Error("must not be called");
276
+ },
277
+ });
278
+ }).toThrow("Client secret is required.");
279
+ });
280
+ });
281
+
282
+ describe("token request", () => {
283
+ test("posts the client credentials grant as a form body to the tenant's v2.0 token endpoint with the ARM scope", async () => {
284
+ const harness: Harness = buildHarness({ requestTimeoutInMs: 12345 });
285
+
286
+ const token: string = await harness.client.getAccessToken();
287
+
288
+ expect(token).toBe(ACCESS_TOKEN);
289
+ expect(harness.requests).toHaveLength(1);
290
+
291
+ const request: DataSourceHttpRequest = harness.requests[0]!;
292
+ expect(request.method).toBe("POST");
293
+ expect(request.url).toBe(
294
+ `https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token`,
295
+ );
296
+ expect(request.formUrlEncoded).toBe(true);
297
+ expect(request.timeoutInMs).toBe(12345);
298
+ expect(request.headers?.["Accept"]).toBe("application/json");
299
+
300
+ const body: Dictionary<string> = request.body as Dictionary<string>;
301
+ expect(Object.keys(body).sort()).toEqual([
302
+ "client_id",
303
+ "client_secret",
304
+ "grant_type",
305
+ "scope",
306
+ ]);
307
+ expect(body["client_id"]).toBe(CLIENT_ID);
308
+ expect(body["client_secret"]).toBe(CLIENT_SECRET);
309
+ expect(body["grant_type"]).toBe("client_credentials");
310
+ expect(body["scope"]).toBe("https://management.azure.com/.default");
311
+ });
312
+
313
+ test("uses the Azure Government login and Resource Manager hosts for the usgov cloud", async () => {
314
+ const harness: Harness = buildHarness({
315
+ cloud: "usgov",
316
+ incidents: [
317
+ (): DataSourceHttpResponse => {
318
+ return ok({ value: [] });
319
+ },
320
+ ],
321
+ });
322
+
323
+ await harness.client.listIncidents({ startTime: START, endTime: END });
324
+
325
+ expect(new URL(harness.requests[0]!.url).host).toBe(
326
+ "login.microsoftonline.us",
327
+ );
328
+ expect((harness.requests[0]!.body as Dictionary<string>)["scope"]).toBe(
329
+ "https://management.usgovcloudapi.net/.default",
330
+ );
331
+ expect(new URL(harness.requests[1]!.url).host).toBe(
332
+ "management.usgovcloudapi.net",
333
+ );
334
+ });
335
+
336
+ test("caches the token across requests on the same instance and counts every request", async () => {
337
+ const harness: Harness = buildHarness({
338
+ incidents: [
339
+ (): DataSourceHttpResponse => {
340
+ return ok({ value: [] });
341
+ },
342
+ (): DataSourceHttpResponse => {
343
+ return ok({ value: [] });
344
+ },
345
+ ],
346
+ });
347
+
348
+ await harness.client.listIncidents({ startTime: START, endTime: END });
349
+ await harness.client.listIncidents({ startTime: START, endTime: END });
350
+
351
+ expect(tokenRequests(harness.requests)).toHaveLength(1);
352
+ expect(harness.client.getRequestCount()).toBe(3);
353
+ });
354
+
355
+ test("names the token step and the status on an Entra rejection, hints at the secret for invalid_client, and never echoes the secret", async () => {
356
+ const entraBody: string = JSON.stringify({
357
+ error: "invalid_client",
358
+ error_description: `AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID. client_secret=${CLIENT_SECRET}`,
359
+ error_codes: [7000215],
360
+ });
361
+ const harness: Harness = buildHarness({
362
+ token: (): DataSourceHttpResponse => {
363
+ return status(401, entraBody);
364
+ },
365
+ });
366
+
367
+ const error: APIException = await expectRejection(
368
+ harness.client.getAccessToken(),
369
+ );
370
+
371
+ expect(error.message).toMatch(
372
+ /^Microsoft Sentinel token request failed \(HTTP 401\): /,
373
+ );
374
+ expect(error.message).toContain("AADSTS7000215");
375
+ expect(error.message).toContain("rejected the client secret");
376
+ expect(error.message).not.toContain(CLIENT_SECRET);
377
+ });
378
+
379
+ test("hints at the tenant and client id when Entra cannot find the application", async () => {
380
+ const harness: Harness = buildHarness({
381
+ token: (): DataSourceHttpResponse => {
382
+ return status(
383
+ 400,
384
+ JSON.stringify({
385
+ error: "unauthorized_client",
386
+ error_description:
387
+ "AADSTS700016: Application with identifier '...' was not found in the directory.",
388
+ error_codes: [700016],
389
+ }),
390
+ );
391
+ },
392
+ });
393
+
394
+ const error: APIException = await expectRejection(
395
+ harness.client.getAccessToken(),
396
+ );
397
+
398
+ expect(error.message).toMatch(
399
+ /^Microsoft Sentinel token request failed \(HTTP 400\): /,
400
+ );
401
+ expect(error.message).toContain("was not found in this tenant");
402
+ });
403
+
404
+ test("hints at the tenant id when Entra reports the tenant does not exist", async () => {
405
+ const harness: Harness = buildHarness({
406
+ token: (): DataSourceHttpResponse => {
407
+ return status(
408
+ 400,
409
+ JSON.stringify({
410
+ error: "invalid_request",
411
+ error_description:
412
+ "AADSTS90002: Tenant 'x' not found. Check to make sure you have the correct tenant ID.",
413
+ }),
414
+ );
415
+ },
416
+ });
417
+
418
+ const error: APIException = await expectRejection(
419
+ harness.client.getAccessToken(),
420
+ );
421
+
422
+ expect(error.message).toContain("does not name an existing tenant");
423
+ });
424
+
425
+ test("reports throttling and server-side failures on the token step", async () => {
426
+ const throttled: Harness = buildHarness({
427
+ token: (): DataSourceHttpResponse => {
428
+ return status(
429
+ 429,
430
+ JSON.stringify({ error: "temporarily_unavailable" }),
431
+ );
432
+ },
433
+ });
434
+ const throttledError: APIException = await expectRejection(
435
+ throttled.client.getAccessToken(),
436
+ );
437
+ expect(throttledError.message).toMatch(
438
+ /^Microsoft Sentinel token request failed \(HTTP 429\): /,
439
+ );
440
+ expect(throttledError.message).toContain("throttling token requests");
441
+
442
+ const down: Harness = buildHarness({
443
+ token: (): DataSourceHttpResponse => {
444
+ return status(503, "Service Unavailable");
445
+ },
446
+ });
447
+ const downError: APIException = await expectRejection(
448
+ down.client.getAccessToken(),
449
+ );
450
+ expect(downError.message).toBe(
451
+ "Microsoft Sentinel token request failed (HTTP 503): Service Unavailable — Microsoft Entra reported a server-side problem; the next poll retries.",
452
+ );
453
+ });
454
+
455
+ test("reports a non-JSON token body without guessing", async () => {
456
+ const harness: Harness = buildHarness({
457
+ token: (): DataSourceHttpResponse => {
458
+ return status(200, "<html>gateway</html>");
459
+ },
460
+ });
461
+
462
+ const error: APIException = await expectRejection(
463
+ harness.client.getAccessToken(),
464
+ );
465
+
466
+ expect(error.message).toBe(
467
+ "Microsoft Sentinel token request returned a non-JSON body: <html>gateway</html>",
468
+ );
469
+ });
470
+
471
+ test("reports a JSON token body that carries no access_token", async () => {
472
+ const harness: Harness = buildHarness({
473
+ token: (): DataSourceHttpResponse => {
474
+ return ok({ token_type: "Bearer", expires_in: 3599 });
475
+ },
476
+ });
477
+
478
+ const error: APIException = await expectRejection(
479
+ harness.client.getAccessToken(),
480
+ );
481
+
482
+ expect(error.message).toBe(
483
+ 'Microsoft Sentinel token request returned no access_token: {"token_type":"Bearer","expires_in":3599}',
484
+ );
485
+ });
486
+
487
+ test("surfaces a transport failure on the token step with the step prefix", async () => {
488
+ const harness: Harness = buildHarness({
489
+ token: (): DataSourceHttpResponse => {
490
+ throw new BadDataException(
491
+ "Could not reach data source: timeout of 20000ms exceeded",
492
+ );
493
+ },
494
+ });
495
+
496
+ const error: APIException = await expectRejection(
497
+ harness.client.getAccessToken(),
498
+ );
499
+
500
+ expect(error.message).toBe(
501
+ "Microsoft Sentinel token request failed: Could not reach data source: timeout of 20000ms exceeded",
502
+ );
503
+ });
504
+
505
+ test("gives up on a transport that never settles once the request timeout elapses", async () => {
506
+ const harness: Harness = buildHarness({
507
+ requestTimeoutInMs: 30,
508
+ token: (): Promise<DataSourceHttpResponse> => {
509
+ return new Promise<DataSourceHttpResponse>((): void => {
510
+ // Never resolves: simulates a socket that neither answers nor closes.
511
+ });
512
+ },
513
+ });
514
+
515
+ const error: APIException = await expectRejection(
516
+ harness.client.getAccessToken(),
517
+ );
518
+
519
+ expect(error.message).toMatch(
520
+ /^Microsoft Sentinel token request timed out after \d+ seconds with no response\.$/,
521
+ );
522
+ });
523
+ });
524
+
525
+ describe("incidents request", () => {
526
+ test("filters by createdTimeUtc over the half-open window, orders ascending, pages with $top, and sends the bearer token", async () => {
527
+ const harness: Harness = buildHarness({
528
+ requestTimeoutInMs: 4321,
529
+ incidents: [
530
+ (): DataSourceHttpResponse => {
531
+ return ok({ value: [incident("i1"), incident("i2")] });
532
+ },
533
+ ],
534
+ });
535
+
536
+ const page: MicrosoftSentinelIncidentsPage =
537
+ await harness.client.listIncidents({ startTime: START, endTime: END });
538
+
539
+ expect(
540
+ page.incidents.map((item: JSONObject): string => {
541
+ return String(item["name"]);
542
+ }),
543
+ ).toEqual(["i1", "i2"]);
544
+ expect(page.nextLink).toBeNull();
545
+
546
+ const request: DataSourceHttpRequest = harness.requests[1]!;
547
+ const url: URL = new URL(request.url);
548
+
549
+ expect(request.method).toBe("GET");
550
+ expect(url.origin).toBe("https://management.azure.com");
551
+ expect(url.pathname).toBe(INCIDENTS_PATH);
552
+ expect(Array.from(url.searchParams.keys()).sort()).toEqual([
553
+ "$filter",
554
+ "$orderby",
555
+ "$top",
556
+ "api-version",
557
+ ]);
558
+ expect(url.searchParams.get("api-version")).toBe(
559
+ MICROSOFT_SENTINEL_API_VERSION,
560
+ );
561
+ expect(url.searchParams.get("$filter")).toBe(
562
+ `(properties/createdTimeUtc ge ${START.toISOString()}) and (properties/createdTimeUtc lt ${END.toISOString()})`,
563
+ );
564
+ expect(url.searchParams.get("$orderby")).toBe(
565
+ "properties/createdTimeUtc asc",
566
+ );
567
+ expect(url.searchParams.get("$top")).toBe(
568
+ String(MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE),
569
+ );
570
+ expect(request.headers?.["Authorization"]).toBe(`Bearer ${ACCESS_TOKEN}`);
571
+ expect(request.headers?.["Accept"]).toBe("application/json");
572
+ expect(request.timeoutInMs).toBe(4321);
573
+ expect(request.body).toBeUndefined();
574
+ });
575
+
576
+ test("clamps $top to the documented maximum of 1000 and never below one", () => {
577
+ expect(MicrosoftSentinelClient.clampPageSize(1)).toBe(1);
578
+ expect(MicrosoftSentinelClient.clampPageSize(5000)).toBe(
579
+ MICROSOFT_SENTINEL_MAX_PAGE_SIZE,
580
+ );
581
+ expect(MicrosoftSentinelClient.clampPageSize(0)).toBe(
582
+ MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE,
583
+ );
584
+ expect(MicrosoftSentinelClient.clampPageSize(undefined)).toBe(
585
+ MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE,
586
+ );
587
+
588
+ const harness: Harness = buildHarness({});
589
+ expect(
590
+ new URL(
591
+ harness.client.buildIncidentsUrl({
592
+ startTime: START,
593
+ endTime: END,
594
+ top: 1,
595
+ }),
596
+ ).searchParams.get("$top"),
597
+ ).toBe("1");
598
+ expect(
599
+ new URL(
600
+ harness.client.buildIncidentsUrl({
601
+ startTime: START,
602
+ endTime: END,
603
+ top: 99999,
604
+ }),
605
+ ).searchParams.get("$top"),
606
+ ).toBe("1000");
607
+ });
608
+
609
+ test("builds the incidents path from the trimmed settings, which validation keeps URL-safe", () => {
610
+ const client: MicrosoftSentinelClient = new MicrosoftSentinelClient({
611
+ tenantId: ` ${TENANT_ID} `,
612
+ clientId: CLIENT_ID,
613
+ clientSecret: CLIENT_SECRET,
614
+ subscriptionId: ` ${SUBSCRIPTION_ID} `,
615
+ resourceGroup: " rg-(prod).01 ",
616
+ workspaceName: ` ${WORKSPACE_NAME} `,
617
+ cloud: "public",
618
+ transport: (): Promise<DataSourceHttpResponse> => {
619
+ throw new Error("must not be called");
620
+ },
621
+ });
622
+
623
+ expect(new URL(client.getIncidentsBaseUrl()).pathname).toBe(
624
+ `/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/rg-(prod).01/providers/Microsoft.OperationalInsights/workspaces/${WORKSPACE_NAME}/providers/Microsoft.SecurityInsights/incidents`,
625
+ );
626
+ expect(client.getTokenUrl()).toBe(
627
+ `https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token`,
628
+ );
629
+
630
+ // A value that would need escaping never reaches the URL builder.
631
+ expect(() => {
632
+ MicrosoftSentinelClient.validateResourceGroup("rg/../other");
633
+ }).toThrow(BadDataException);
634
+ });
635
+
636
+ test("follows nextLink exactly as ARM returned it and stops when the last page has none", async () => {
637
+ const nextLink: string = `https://management.azure.com${INCIDENTS_PATH}?api-version=2024-03-01&$filter=properties%2FcreatedTimeUtc+ge+${START.toISOString()}&$top=50&$skipToken=abc123`;
638
+ const harness: Harness = buildHarness({
639
+ incidents: [
640
+ (): DataSourceHttpResponse => {
641
+ return ok({ value: [incident("i1")], nextLink: ` ${nextLink} ` });
642
+ },
643
+ (): DataSourceHttpResponse => {
644
+ return ok({ value: [incident("i2")] });
645
+ },
646
+ ],
647
+ });
648
+
649
+ const first: MicrosoftSentinelIncidentsPage =
650
+ await harness.client.listIncidents({ startTime: START, endTime: END });
651
+ expect(first.nextLink).toBe(nextLink);
652
+
653
+ const second: MicrosoftSentinelIncidentsPage =
654
+ await harness.client.listIncidents({
655
+ startTime: START,
656
+ endTime: END,
657
+ nextLink: first.nextLink,
658
+ });
659
+
660
+ expect(
661
+ second.incidents.map((item: JSONObject): string => {
662
+ return String(item["name"]);
663
+ }),
664
+ ).toEqual(["i2"]);
665
+ expect(second.nextLink).toBeNull();
666
+ expect(harness.requests[2]!.url).toBe(nextLink);
667
+ expect(harness.requests[2]!.headers?.["Authorization"]).toBe(
668
+ `Bearer ${ACCESS_TOKEN}`,
669
+ );
670
+ expect(tokenRequests(harness.requests)).toHaveLength(1);
671
+ });
672
+
673
+ test("refuses a nextLink that points off the Resource Manager host, without sending the token anywhere", async () => {
674
+ const harness: Harness = buildHarness({});
675
+
676
+ const error: APIException = await expectRejection(
677
+ harness.client.listIncidents({
678
+ startTime: START,
679
+ endTime: END,
680
+ nextLink: `https://evil.example.com${INCIDENTS_PATH}?$skipToken=x`,
681
+ }),
682
+ );
683
+
684
+ expect(error.message).toBe(
685
+ "Microsoft Sentinel incidents list returned a nextLink on an unexpected host: evil.example.com (expected management.azure.com).",
686
+ );
687
+ expect(harness.requests).toHaveLength(0);
688
+ });
689
+
690
+ test("refuses a plain-http nextLink and one that is not a URL", async () => {
691
+ const harness: Harness = buildHarness({});
692
+
693
+ const insecure: APIException = await expectRejection(
694
+ harness.client.listIncidents({
695
+ startTime: START,
696
+ endTime: END,
697
+ nextLink: `http://management.azure.com${INCIDENTS_PATH}?$skipToken=x`,
698
+ }),
699
+ );
700
+ expect(insecure.message).toContain("nextLink on an unexpected host");
701
+
702
+ const garbage: APIException = await expectRejection(
703
+ harness.client.listIncidents({
704
+ startTime: START,
705
+ endTime: END,
706
+ nextLink: "not a url",
707
+ }),
708
+ );
709
+ expect(garbage.message).toBe(
710
+ "Microsoft Sentinel incidents list returned an unusable nextLink: not a url",
711
+ );
712
+ expect(harness.requests).toHaveLength(0);
713
+ });
714
+
715
+ test("retries once with a fresh token when a cached token is refused with 401", async () => {
716
+ const harness: Harness = buildHarness({
717
+ token: [
718
+ (): DataSourceHttpResponse => {
719
+ return tokenResponse(ACCESS_TOKEN);
720
+ },
721
+ (): DataSourceHttpResponse => {
722
+ return tokenResponse(FRESH_TOKEN);
723
+ },
724
+ ],
725
+ incidents: [
726
+ (): DataSourceHttpResponse => {
727
+ return ok({ value: [] });
728
+ },
729
+ (): DataSourceHttpResponse => {
730
+ return status(
731
+ 401,
732
+ armError(
733
+ "ExpiredAuthenticationToken",
734
+ "The access token expiry UTC time is earlier than current UTC time.",
735
+ ),
736
+ );
737
+ },
738
+ (): DataSourceHttpResponse => {
739
+ return ok({ value: [incident("i1")] });
740
+ },
741
+ ],
742
+ });
743
+
744
+ await harness.client.listIncidents({ startTime: START, endTime: END });
745
+ const page: MicrosoftSentinelIncidentsPage =
746
+ await harness.client.listIncidents({ startTime: START, endTime: END });
747
+
748
+ expect(page.incidents).toHaveLength(1);
749
+ expect(tokenRequests(harness.requests)).toHaveLength(2);
750
+ expect(harness.client.getRequestCount()).toBe(5);
751
+ expect(harness.requests[4]!.headers?.["Authorization"]).toBe(
752
+ `Bearer ${FRESH_TOKEN}`,
753
+ );
754
+ });
755
+
756
+ test("does not retry when a freshly minted token is refused, and hints at the cloud setting", async () => {
757
+ const harness: Harness = buildHarness({
758
+ incidents: [
759
+ (): DataSourceHttpResponse => {
760
+ return status(
761
+ 401,
762
+ armError(
763
+ "InvalidAuthenticationToken",
764
+ "The access token has been obtained for wrong audience or resource.",
765
+ ),
766
+ );
767
+ },
768
+ ],
769
+ });
770
+
771
+ const error: APIException = await expectRejection(
772
+ harness.client.listIncidents({ startTime: START, endTime: END }),
773
+ );
774
+
775
+ expect(error.message).toMatch(
776
+ /^Microsoft Sentinel incidents list failed \(HTTP 401\): /,
777
+ );
778
+ expect(error.message).toContain("InvalidAuthenticationToken");
779
+ expect(error.message).toContain("wrong audience or resource");
780
+ expect(error.message).toContain("rejected the access token");
781
+ expect(error.message).not.toContain(ACCESS_TOKEN);
782
+ expect(harness.client.getRequestCount()).toBe(2);
783
+ });
784
+
785
+ test("explains a 403 as the missing Microsoft Sentinel Reader role", async () => {
786
+ const harness: Harness = buildHarness({
787
+ incidents: [
788
+ (): DataSourceHttpResponse => {
789
+ return status(
790
+ 403,
791
+ armError(
792
+ "AuthorizationFailed",
793
+ `The client '${CLIENT_ID}' with object id '...' does not have authorization to perform action 'Microsoft.SecurityInsights/incidents/read' over scope '...'.`,
794
+ ),
795
+ );
796
+ },
797
+ ],
798
+ });
799
+
800
+ const error: APIException = await expectRejection(
801
+ harness.client.listIncidents({ startTime: START, endTime: END }),
802
+ );
803
+
804
+ expect(error.message).toMatch(
805
+ /^Microsoft Sentinel incidents list failed \(HTTP 403\): /,
806
+ );
807
+ expect(error.message).toContain("AuthorizationFailed");
808
+ expect(error.message).toContain("Microsoft Sentinel Reader");
809
+ });
810
+
811
+ test("explains a 404 as a workspace that could not be found", async () => {
812
+ const harness: Harness = buildHarness({
813
+ incidents: [
814
+ (): DataSourceHttpResponse => {
815
+ return status(
816
+ 404,
817
+ armError(
818
+ "ResourceNotFound",
819
+ "The Resource 'Microsoft.OperationalInsights/workspaces/myWorkspace' under resource group 'myRg' was not found.",
820
+ ),
821
+ );
822
+ },
823
+ ],
824
+ });
825
+
826
+ const error: APIException = await expectRejection(
827
+ harness.client.listIncidents({ startTime: START, endTime: END }),
828
+ );
829
+
830
+ expect(error.message).toMatch(
831
+ /^Microsoft Sentinel incidents list failed \(HTTP 404\): /,
832
+ );
833
+ expect(error.message).toContain("No workspace matched");
834
+ });
835
+
836
+ test("reports throttling as ARM's rate limit", async () => {
837
+ const harness: Harness = buildHarness({
838
+ incidents: [
839
+ (): DataSourceHttpResponse => {
840
+ return status(
841
+ 429,
842
+ armError("TooManyRequests", "Too many requests. Please retry."),
843
+ );
844
+ },
845
+ ],
846
+ });
847
+
848
+ const error: APIException = await expectRejection(
849
+ harness.client.listIncidents({ startTime: START, endTime: END }),
850
+ );
851
+
852
+ expect(error.message).toMatch(
853
+ /^Microsoft Sentinel incidents list failed \(HTTP 429\): /,
854
+ );
855
+ expect(error.message).toContain("throttling requests");
856
+ });
857
+
858
+ test("reports a 5xx as ARM's fault and keeps the non-JSON body", async () => {
859
+ const harness: Harness = buildHarness({
860
+ incidents: [
861
+ (): DataSourceHttpResponse => {
862
+ return status(500, "<html>Internal Server Error</html>");
863
+ },
864
+ ],
865
+ });
866
+
867
+ const error: APIException = await expectRejection(
868
+ harness.client.listIncidents({ startTime: START, endTime: END }),
869
+ );
870
+
871
+ expect(error.message).toBe(
872
+ "Microsoft Sentinel incidents list failed (HTTP 500): <html>Internal Server Error</html> — Azure Resource Manager reported a server-side problem; the next poll retries.",
873
+ );
874
+ });
875
+
876
+ test("reports a 400 as a connector-built query ARM rejected", async () => {
877
+ const harness: Harness = buildHarness({
878
+ incidents: [
879
+ (): DataSourceHttpResponse => {
880
+ return status(
881
+ 400,
882
+ armError("BadRequest", "Invalid filter clause."),
883
+ );
884
+ },
885
+ ],
886
+ });
887
+
888
+ const error: APIException = await expectRejection(
889
+ harness.client.listIncidents({ startTime: START, endTime: END }),
890
+ );
891
+
892
+ expect(error.message).toMatch(
893
+ /^Microsoft Sentinel incidents list failed \(HTTP 400\): /,
894
+ );
895
+ expect(error.message).toContain("rejected the query");
896
+ });
897
+
898
+ test("folds the transport's own HTTP-status exception back into the status taxonomy", async () => {
899
+ const harness: Harness = buildHarness({
900
+ incidents: [
901
+ (): DataSourceHttpResponse => {
902
+ throw new BadDataException(
903
+ `Data source responded with HTTP 403: ${armError(
904
+ "AuthorizationFailed",
905
+ "no",
906
+ )}`,
907
+ );
908
+ },
909
+ ],
910
+ });
911
+
912
+ const error: APIException = await expectRejection(
913
+ harness.client.listIncidents({ startTime: START, endTime: END }),
914
+ );
915
+
916
+ expect(error.message).toMatch(
917
+ /^Microsoft Sentinel incidents list failed \(HTTP 403\): /,
918
+ );
919
+ expect(error.message).toContain("AuthorizationFailed");
920
+ expect(error.message).toContain("Microsoft Sentinel Reader");
921
+ });
922
+
923
+ test("surfaces a transport timeout on the incidents step with the step prefix", async () => {
924
+ const harness: Harness = buildHarness({
925
+ incidents: [
926
+ (): DataSourceHttpResponse => {
927
+ throw new BadDataException(
928
+ "Could not reach data source: timeout of 20000ms exceeded",
929
+ );
930
+ },
931
+ ],
932
+ });
933
+
934
+ const error: APIException = await expectRejection(
935
+ harness.client.listIncidents({ startTime: START, endTime: END }),
936
+ );
937
+
938
+ expect(error.message).toBe(
939
+ "Microsoft Sentinel incidents list failed: Could not reach data source: timeout of 20000ms exceeded",
940
+ );
941
+ });
942
+
943
+ test("gives up on an incidents request that never settles once the request timeout elapses", async () => {
944
+ const harness: Harness = buildHarness({
945
+ requestTimeoutInMs: 30,
946
+ incidents: [
947
+ (): Promise<DataSourceHttpResponse> => {
948
+ return new Promise<DataSourceHttpResponse>((): void => {
949
+ // Never resolves.
950
+ });
951
+ },
952
+ ],
953
+ });
954
+
955
+ const error: APIException = await expectRejection(
956
+ harness.client.listIncidents({ startTime: START, endTime: END }),
957
+ );
958
+
959
+ expect(error.message).toMatch(
960
+ /^Microsoft Sentinel incidents list timed out after \d+ seconds with no response\.$/,
961
+ );
962
+ });
963
+
964
+ test("reports a non-JSON incidents body rather than treating it as an empty window", async () => {
965
+ const harness: Harness = buildHarness({
966
+ incidents: [
967
+ (): DataSourceHttpResponse => {
968
+ return status(200, "<html>ok</html>");
969
+ },
970
+ ],
971
+ });
972
+
973
+ const error: APIException = await expectRejection(
974
+ harness.client.listIncidents({ startTime: START, endTime: END }),
975
+ );
976
+
977
+ expect(error.message).toBe(
978
+ "Microsoft Sentinel incidents list returned a non-JSON body: <html>ok</html>",
979
+ );
980
+ });
981
+
982
+ test("reports a JSON body that is not an object or has no value array as an unrecognized shape", async () => {
983
+ const arrayBody: Harness = buildHarness({
984
+ incidents: [
985
+ (): DataSourceHttpResponse => {
986
+ return status(200, JSON.stringify([incident("i1")]));
987
+ },
988
+ ],
989
+ });
990
+ const arrayError: APIException = await expectRejection(
991
+ arrayBody.client.listIncidents({ startTime: START, endTime: END }),
992
+ );
993
+ expect(arrayError.message).toBe(
994
+ "Microsoft Sentinel incidents list returned an unrecognized response shape: expected a JSON object, received an array.",
995
+ );
996
+
997
+ const noValue: Harness = buildHarness({
998
+ incidents: [
999
+ (): DataSourceHttpResponse => {
1000
+ return ok({ incidents: [] });
1001
+ },
1002
+ ],
1003
+ });
1004
+ const noValueError: APIException = await expectRejection(
1005
+ noValue.client.listIncidents({ startTime: START, endTime: END }),
1006
+ );
1007
+ expect(noValueError.message).toBe(
1008
+ 'Microsoft Sentinel incidents list returned an unrecognized response shape: expected a "value" array, received keys incidents.',
1009
+ );
1010
+ });
1011
+
1012
+ test("drops non-object entries from value instead of passing them to the normalizer", async () => {
1013
+ const harness: Harness = buildHarness({
1014
+ incidents: [
1015
+ (): DataSourceHttpResponse => {
1016
+ return ok({ value: [incident("i1"), "junk", null, 42] as never });
1017
+ },
1018
+ ],
1019
+ });
1020
+
1021
+ const page: MicrosoftSentinelIncidentsPage =
1022
+ await harness.client.listIncidents({ startTime: START, endTime: END });
1023
+
1024
+ expect(page.incidents).toHaveLength(1);
1025
+ });
1026
+
1027
+ test("redacts credentials ARM echoes back in an error body", async () => {
1028
+ const harness: Harness = buildHarness({
1029
+ incidents: [
1030
+ (): DataSourceHttpResponse => {
1031
+ return status(
1032
+ 400,
1033
+ JSON.stringify({
1034
+ error: {
1035
+ code: "BadRequest",
1036
+ message: `Authorization: Bearer ${ACCESS_TOKEN} was malformed; client_secret=${CLIENT_SECRET}`,
1037
+ access_token: ACCESS_TOKEN,
1038
+ },
1039
+ }),
1040
+ );
1041
+ },
1042
+ ],
1043
+ });
1044
+
1045
+ const error: APIException = await expectRejection(
1046
+ harness.client.listIncidents({ startTime: START, endTime: END }),
1047
+ );
1048
+
1049
+ expect(error.message).toMatch(
1050
+ /^Microsoft Sentinel incidents list failed \(HTTP 400\): /,
1051
+ );
1052
+ expect(error.message).not.toContain(ACCESS_TOKEN);
1053
+ expect(error.message).not.toContain(CLIENT_SECRET);
1054
+ expect(error.message).toContain("[REDACTED]");
1055
+ });
1056
+ });
1057
+
1058
+ describe("countIncidentsCreated", () => {
1059
+ test("returns the first page size and flags a floor when ARM paged, reading a single page", async () => {
1060
+ const harness: Harness = buildHarness({
1061
+ incidents: [
1062
+ (): DataSourceHttpResponse => {
1063
+ return ok({
1064
+ value: [incident("i1"), incident("i2")],
1065
+ nextLink: `https://management.azure.com${INCIDENTS_PATH}?$skipToken=x`,
1066
+ });
1067
+ },
1068
+ (): DataSourceHttpResponse => {
1069
+ return ok({ value: [] });
1070
+ },
1071
+ ],
1072
+ });
1073
+
1074
+ const paged: MicrosoftSentinelIncidentCount =
1075
+ await harness.client.countIncidentsCreated({
1076
+ startTime: START,
1077
+ endTime: END,
1078
+ });
1079
+ expect(paged).toEqual({ count: 2, hasMore: true });
1080
+
1081
+ const empty: MicrosoftSentinelIncidentCount =
1082
+ await harness.client.countIncidentsCreated({
1083
+ startTime: START,
1084
+ endTime: END,
1085
+ top: 7,
1086
+ });
1087
+ expect(empty).toEqual({ count: 0, hasMore: false });
1088
+
1089
+ const incidentRequests: Array<DataSourceHttpRequest> =
1090
+ harness.requests.filter((request: DataSourceHttpRequest): boolean => {
1091
+ return request.url.includes("/incidents");
1092
+ });
1093
+ expect(incidentRequests).toHaveLength(2);
1094
+ expect(new URL(incidentRequests[0]!.url).searchParams.get("$top")).toBe(
1095
+ String(MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE),
1096
+ );
1097
+ expect(new URL(incidentRequests[1]!.url).searchParams.get("$top")).toBe(
1098
+ "7",
1099
+ );
1100
+ });
1101
+ });
1102
+ });