@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,1174 @@
1
+ import { afterEach, describe, expect, jest, test } from "@jest/globals";
2
+ import MicrosoftSentinelConnector from "../../../../../../Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelConnector";
3
+ import { MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE } from "../../../../../../Server/Utils/SecurityEvent/Connectors/MicrosoftSentinel/MicrosoftSentinelClient";
4
+ import {
5
+ ConnectorFetchOptions,
6
+ ConnectorFetchResult,
7
+ SecurityConnectorSettings,
8
+ } from "../../../../../../Server/Utils/SecurityEvent/Connectors/Types";
9
+ import {
10
+ DataSourceHttpRequest,
11
+ DataSourceHttpResponse,
12
+ } from "../../../../../../Server/Utils/DataSource/HttpFetch";
13
+ import MicrosoftSentinelNormalizer from "../../../../../../Utils/SecurityEvent/Connectors/MicrosoftSentinelNormalizer";
14
+ import APIException from "../../../../../../Types/Exception/ApiException";
15
+ import BadDataException from "../../../../../../Types/Exception/BadDataException";
16
+ import { JSONObject } from "../../../../../../Types/JSON";
17
+ import NormalizedSecurityEvent from "../../../../../../Types/SecurityEvent/NormalizedSecurityEvent";
18
+ import { SecurityConnectorCheck } from "../../../../../../Types/SecurityEvent/Connectors/ConnectorDiagnostics";
19
+ import {
20
+ SecurityEventConnectorDefinition,
21
+ getSecurityEventConnectorDefinition,
22
+ } from "../../../../../../Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog";
23
+ import SecurityEventConnectorProvider from "../../../../../../Types/SecurityEvent/Connectors/SecurityEventConnectorProvider";
24
+
25
+ /*
26
+ * The connector as the poller and the tester use it: settings are read by
27
+ * the catalog's keys, the test checklist carries the fixed keys with a
28
+ * remediation per failure mode, and fetchEvents walks nextLink within the
29
+ * request and record bounds, holding `complete` false whenever a bound
30
+ * stopped it and naming the creation time of the last incident read as
31
+ * `resumeAfter`. The transport is injected; nothing touches the network.
32
+ */
33
+
34
+ const TENANT_ID: string = "b3c1b5fc-828c-45fa-a1e1-10d74f6d6e9c";
35
+ const CLIENT_ID: string = "00001111-aaaa-2222-bbbb-3333cccc4444";
36
+ const CLIENT_SECRET: string = "A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u~verySecret";
37
+ const SUBSCRIPTION_ID: string = "d0cfe6b2-9ac0-4464-9919-dccaee2e48c0";
38
+ const ACCESS_TOKEN: string =
39
+ "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJodHRwczovL21hbmFnZW1lbnQifQ.c2lnbmF0dXJlLXNpZ25hdHVyZQ";
40
+ const START: Date = new Date("2026-09-12T10:00:00.000Z");
41
+ const END: Date = new Date("2026-09-13T10:00:00.000Z");
42
+ const INCIDENTS_PATH: string = `/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/myRg/providers/Microsoft.OperationalInsights/workspaces/myWorkspace/providers/Microsoft.SecurityInsights/incidents`;
43
+ const DAY_IN_MS: number = 24 * 60 * 60 * 1000;
44
+
45
+ const definition: SecurityEventConnectorDefinition =
46
+ getSecurityEventConnectorDefinition(
47
+ SecurityEventConnectorProvider.MicrosoftSentinel,
48
+ )!;
49
+
50
+ type Responder = (
51
+ request: DataSourceHttpRequest,
52
+ ) => DataSourceHttpResponse | Promise<DataSourceHttpResponse>;
53
+
54
+ interface Harness {
55
+ requests: Array<DataSourceHttpRequest>;
56
+ connector: MicrosoftSentinelConnector;
57
+ }
58
+
59
+ function settings(
60
+ overrides: {
61
+ config?: JSONObject;
62
+ secrets?: JSONObject;
63
+ provider?: SecurityEventConnectorProvider;
64
+ } = {},
65
+ ): SecurityConnectorSettings {
66
+ return {
67
+ provider:
68
+ overrides.provider || SecurityEventConnectorProvider.MicrosoftSentinel,
69
+ config: {
70
+ tenantId: TENANT_ID,
71
+ clientId: CLIENT_ID,
72
+ subscriptionId: SUBSCRIPTION_ID,
73
+ resourceGroup: "myRg",
74
+ workspaceName: "myWorkspace",
75
+ cloud: "public",
76
+ ...(overrides.config || {}),
77
+ },
78
+ secrets: { clientSecret: CLIENT_SECRET, ...(overrides.secrets || {}) },
79
+ alertingOnly: false,
80
+ };
81
+ }
82
+
83
+ function fetchOptions(
84
+ overrides: Partial<ConnectorFetchOptions> = {},
85
+ ): ConnectorFetchOptions {
86
+ return {
87
+ maxRequests: 20,
88
+ maxEvents: 10000,
89
+ requestTimeoutInMs: 60000,
90
+ sampleLimit: 25,
91
+ ...overrides,
92
+ };
93
+ }
94
+
95
+ function ok(body: JSONObject): DataSourceHttpResponse {
96
+ return {
97
+ statusCode: 200,
98
+ bodyText: JSON.stringify(body),
99
+ bodyJson: body,
100
+ headers: {},
101
+ };
102
+ }
103
+
104
+ function status(code: number, body: string): DataSourceHttpResponse {
105
+ let bodyJson: unknown = undefined;
106
+
107
+ try {
108
+ bodyJson = JSON.parse(body);
109
+ } catch {
110
+ bodyJson = undefined;
111
+ }
112
+
113
+ return { statusCode: code, bodyText: body, bodyJson, headers: {} };
114
+ }
115
+
116
+ function tokenResponse(): DataSourceHttpResponse {
117
+ return ok({
118
+ token_type: "Bearer",
119
+ expires_in: 3599,
120
+ access_token: ACCESS_TOKEN,
121
+ });
122
+ }
123
+
124
+ function incident(
125
+ name: string,
126
+ severity: string = "High",
127
+ createdTimeUtc: string = "2026-09-12T13:15:30Z",
128
+ ): JSONObject {
129
+ return {
130
+ id: `${INCIDENTS_PATH}/${name}`,
131
+ name,
132
+ type: "Microsoft.SecurityInsights/incidents",
133
+ properties: {
134
+ lastModifiedTimeUtc: "2026-09-12T13:15:30Z",
135
+ createdTimeUtc,
136
+ firstActivityTimeUtc: "2026-09-12T13:00:30Z",
137
+ title: `Incident ${name}`,
138
+ severity,
139
+ status: "New",
140
+ incidentNumber: 42,
141
+ owner: {
142
+ objectId: "2046feea-040d-4a46-9e2b-91c2941bfa70",
143
+ email: "john.doe@contoso.com",
144
+ userPrincipalName: "john@contoso.com",
145
+ assignedTo: "john doe",
146
+ },
147
+ labels: [],
148
+ additionalData: { alertsCount: 1, tactics: ["Persistence"] },
149
+ },
150
+ };
151
+ }
152
+
153
+ function nextLink(token: string): string {
154
+ return `https://management.azure.com${INCIDENTS_PATH}?api-version=2024-03-01&$skipToken=${token}`;
155
+ }
156
+
157
+ function buildHarness(options: {
158
+ token?: Responder;
159
+ incidents?: Array<Responder>;
160
+ }): Harness {
161
+ const requests: Array<DataSourceHttpRequest> = [];
162
+ const incidentResponders: Array<Responder> = [...(options.incidents || [])];
163
+
164
+ const connector: MicrosoftSentinelConnector = new MicrosoftSentinelConnector(
165
+ async (request: DataSourceHttpRequest): Promise<DataSourceHttpResponse> => {
166
+ requests.push(request);
167
+
168
+ if (request.url.includes("/oauth2/v2.0/token")) {
169
+ return (options.token || tokenResponse)(request);
170
+ }
171
+
172
+ const responder: Responder | undefined = incidentResponders.shift();
173
+
174
+ if (!responder) {
175
+ throw new Error(`Unexpected request to ${request.url}`);
176
+ }
177
+
178
+ return responder(request);
179
+ },
180
+ );
181
+
182
+ return { requests, connector };
183
+ }
184
+
185
+ function incidentRequests(
186
+ requests: Array<DataSourceHttpRequest>,
187
+ ): Array<DataSourceHttpRequest> {
188
+ return requests.filter((request: DataSourceHttpRequest): boolean => {
189
+ return request.url.includes("/incidents");
190
+ });
191
+ }
192
+
193
+ function windowOf(request: DataSourceHttpRequest): { start: Date; end: Date } {
194
+ const filter: string = new URL(request.url).searchParams.get("$filter") || "";
195
+ const match: RegExpMatchArray | null = filter.match(
196
+ /^\(properties\/createdTimeUtc ge (\S+)\) and \(properties\/createdTimeUtc lt (\S+)\)$/,
197
+ );
198
+
199
+ if (!match) {
200
+ throw new Error(`Unexpected $filter: ${filter}`);
201
+ }
202
+
203
+ return { start: new Date(match[1]!), end: new Date(match[2]!) };
204
+ }
205
+
206
+ function checkByKey(
207
+ checks: Array<SecurityConnectorCheck>,
208
+ key: string,
209
+ ): SecurityConnectorCheck {
210
+ const check: SecurityConnectorCheck | undefined = checks.find(
211
+ (candidate: SecurityConnectorCheck): boolean => {
212
+ return candidate.key === key;
213
+ },
214
+ );
215
+
216
+ if (!check) {
217
+ throw new Error(`Missing check ${key}`);
218
+ }
219
+
220
+ return check;
221
+ }
222
+
223
+ describe("MicrosoftSentinelConnector", () => {
224
+ afterEach(() => {
225
+ jest.restoreAllMocks();
226
+ });
227
+
228
+ test("is registered under the microsoft-sentinel provider", () => {
229
+ expect(new MicrosoftSentinelConnector().provider).toBe(
230
+ SecurityEventConnectorProvider.MicrosoftSentinel,
231
+ );
232
+ expect(definition.provider).toBe("microsoft-sentinel");
233
+ });
234
+
235
+ describe("validateSettings", () => {
236
+ test("accepts a complete configuration, trimming whitespace", () => {
237
+ const connector: MicrosoftSentinelConnector =
238
+ new MicrosoftSentinelConnector();
239
+
240
+ expect(() => {
241
+ connector.validateSettings(
242
+ settings({
243
+ config: { tenantId: ` ${TENANT_ID} `, cloud: " USGOV " },
244
+ }),
245
+ );
246
+ }).not.toThrow();
247
+ });
248
+
249
+ test("rejects settings meant for another provider", () => {
250
+ expect(() => {
251
+ new MicrosoftSentinelConnector().validateSettings(
252
+ settings({ provider: SecurityEventConnectorProvider.OktaSystemLog }),
253
+ );
254
+ }).toThrow(BadDataException);
255
+ });
256
+
257
+ test("names the offending catalog field", () => {
258
+ const connector: MicrosoftSentinelConnector =
259
+ new MicrosoftSentinelConnector();
260
+
261
+ expect(() => {
262
+ connector.validateSettings(settings({ config: { tenantId: "" } }));
263
+ }).toThrow("Directory (tenant) ID");
264
+ expect(() => {
265
+ connector.validateSettings(settings({ config: { clientId: "abc" } }));
266
+ }).toThrow("Application (client) ID must be a GUID");
267
+ expect(() => {
268
+ connector.validateSettings(
269
+ settings({ config: { subscriptionId: "abc" } }),
270
+ );
271
+ }).toThrow("Subscription ID must be a GUID");
272
+ expect(() => {
273
+ connector.validateSettings(
274
+ settings({ config: { resourceGroup: "bad rg" } }),
275
+ );
276
+ }).toThrow("Resource group");
277
+ expect(() => {
278
+ connector.validateSettings(
279
+ settings({ config: { workspaceName: "_ws" } }),
280
+ );
281
+ }).toThrow("Workspace name");
282
+ expect(() => {
283
+ connector.validateSettings(settings({ config: { cloud: "china" } }));
284
+ }).toThrow('Cloud must be "public" or "usgov"');
285
+ expect(() => {
286
+ connector.validateSettings(settings({ secrets: { clientSecret: "" } }));
287
+ }).toThrow("Client secret is required.");
288
+ });
289
+ });
290
+
291
+ describe("testConnection", () => {
292
+ test("runs authentication, a one-incident read over the last day, and bounded counts over 24 hours and 7 days", async () => {
293
+ const harness: Harness = buildHarness({
294
+ incidents: [
295
+ (): DataSourceHttpResponse => {
296
+ return ok({ value: [incident("i1")] });
297
+ },
298
+ (): DataSourceHttpResponse => {
299
+ return ok({
300
+ value: [incident("i1"), incident("i2"), incident("i3")],
301
+ });
302
+ },
303
+ (): DataSourceHttpResponse => {
304
+ const value: Array<JSONObject> = [];
305
+ for (
306
+ let i: number = 0;
307
+ i < MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE;
308
+ i++
309
+ ) {
310
+ value.push(incident(`w${i}`));
311
+ }
312
+ return ok({ value, nextLink: nextLink("more") });
313
+ },
314
+ ],
315
+ });
316
+
317
+ const before: number = Date.now();
318
+ const checks: Array<SecurityConnectorCheck> =
319
+ await harness.connector.testConnection(settings(), {
320
+ requestTimeoutInMs: 5000,
321
+ });
322
+ const after: number = Date.now();
323
+
324
+ expect(
325
+ checks.map((check: SecurityConnectorCheck): string => {
326
+ return `${check.key}:${check.status}`;
327
+ }),
328
+ ).toEqual([
329
+ "authentication:pass",
330
+ "read-permission:pass",
331
+ "detections-available:pass",
332
+ ]);
333
+
334
+ const reads: Array<DataSourceHttpRequest> = incidentRequests(
335
+ harness.requests,
336
+ );
337
+ expect(reads).toHaveLength(3);
338
+ expect(harness.requests).toHaveLength(4);
339
+
340
+ for (const request of harness.requests) {
341
+ expect(request.timeoutInMs).toBe(5000);
342
+ }
343
+
344
+ // Read probe: one record over the last 24 hours.
345
+ expect(new URL(reads[0]!.url).searchParams.get("$top")).toBe("1");
346
+ const probeWindow: { start: Date; end: Date } = windowOf(reads[0]!);
347
+ expect(probeWindow.end.getTime() - probeWindow.start.getTime()).toBe(
348
+ DAY_IN_MS,
349
+ );
350
+ expect(probeWindow.end.getTime()).toBeGreaterThanOrEqual(before);
351
+ expect(probeWindow.end.getTime()).toBeLessThanOrEqual(after);
352
+
353
+ // Counts: one full page each over 24 hours and 7 days.
354
+ expect(new URL(reads[1]!.url).searchParams.get("$top")).toBe(
355
+ String(MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE),
356
+ );
357
+ expect(new URL(reads[2]!.url).searchParams.get("$top")).toBe(
358
+ String(MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE),
359
+ );
360
+ const dayWindow: { start: Date; end: Date } = windowOf(reads[1]!);
361
+ const weekWindow: { start: Date; end: Date } = windowOf(reads[2]!);
362
+ expect(dayWindow.end.getTime() - dayWindow.start.getTime()).toBe(
363
+ DAY_IN_MS,
364
+ );
365
+ expect(weekWindow.end.getTime() - weekWindow.start.getTime()).toBe(
366
+ 7 * DAY_IN_MS,
367
+ );
368
+
369
+ const available: SecurityConnectorCheck = checkByKey(
370
+ checks,
371
+ "detections-available",
372
+ );
373
+ expect(available.message).toBe(
374
+ "3 incidents created in the last 24 hours and 50+ in the last 7 days.",
375
+ );
376
+ expect(available.details).toEqual({
377
+ createdLast24h: 3,
378
+ hasMoreLast24h: false,
379
+ createdLast7d: 50,
380
+ hasMoreLast7d: true,
381
+ });
382
+ expect(available.remediation).toBeUndefined();
383
+
384
+ const read: SecurityConnectorCheck = checkByKey(
385
+ checks,
386
+ "read-permission",
387
+ );
388
+ expect(read.details).toEqual({
389
+ workspaceName: "myWorkspace",
390
+ sampleIncidentCount: 1,
391
+ });
392
+ });
393
+
394
+ test("warns, with guidance, when nothing was created in the last 7 days", async () => {
395
+ const harness: Harness = buildHarness({
396
+ incidents: [
397
+ (): DataSourceHttpResponse => {
398
+ return ok({ value: [] });
399
+ },
400
+ (): DataSourceHttpResponse => {
401
+ return ok({ value: [] });
402
+ },
403
+ (): DataSourceHttpResponse => {
404
+ return ok({ value: [] });
405
+ },
406
+ ],
407
+ });
408
+
409
+ const checks: Array<SecurityConnectorCheck> =
410
+ await harness.connector.testConnection(settings(), {
411
+ requestTimeoutInMs: 5000,
412
+ });
413
+
414
+ const read: SecurityConnectorCheck = checkByKey(
415
+ checks,
416
+ "read-permission",
417
+ );
418
+ expect(read.status).toBe("pass");
419
+ expect(read.message).toContain(
420
+ "no incident was created in the last 24 hours",
421
+ );
422
+
423
+ const available: SecurityConnectorCheck = checkByKey(
424
+ checks,
425
+ "detections-available",
426
+ );
427
+ expect(available.status).toBe("warn");
428
+ expect(available.message).toBe(
429
+ "No incidents were created in the last 7 days. Polling will import new incidents as Microsoft Sentinel creates them.",
430
+ );
431
+ expect(available.remediation).toContain("analytics rules are enabled");
432
+ });
433
+
434
+ test("fails authentication with the Entra remediation and skips the rest when the token is refused", async () => {
435
+ const harness: Harness = buildHarness({
436
+ token: (): DataSourceHttpResponse => {
437
+ return status(
438
+ 401,
439
+ JSON.stringify({
440
+ error: "invalid_client",
441
+ error_description: `AADSTS7000215: Invalid client secret provided. client_secret=${CLIENT_SECRET}`,
442
+ }),
443
+ );
444
+ },
445
+ });
446
+
447
+ const checks: Array<SecurityConnectorCheck> =
448
+ await harness.connector.testConnection(settings(), {
449
+ requestTimeoutInMs: 5000,
450
+ });
451
+
452
+ expect(
453
+ checks.map((check: SecurityConnectorCheck): string => {
454
+ return `${check.key}:${check.status}`;
455
+ }),
456
+ ).toEqual([
457
+ "authentication:fail",
458
+ "read-permission:skip",
459
+ "detections-available:skip",
460
+ ]);
461
+
462
+ const auth: SecurityConnectorCheck = checkByKey(checks, "authentication");
463
+ expect(auth.message).toMatch(
464
+ /^Microsoft Sentinel token request failed \(HTTP 401\): /,
465
+ );
466
+ expect(auth.message).not.toContain(CLIENT_SECRET);
467
+ expect(auth.remediation).toContain("Certificates & secrets");
468
+ expect(harness.requests).toHaveLength(1);
469
+ });
470
+
471
+ test("maps authentication timeouts, throttling and outages to their own remediation", async () => {
472
+ const timedOut: Harness = buildHarness({
473
+ token: (): DataSourceHttpResponse => {
474
+ throw new APIException(
475
+ "Microsoft Sentinel token request timed out after 5 seconds with no response.",
476
+ );
477
+ },
478
+ });
479
+ const timedOutChecks: Array<SecurityConnectorCheck> =
480
+ await timedOut.connector.testConnection(settings(), {
481
+ requestTimeoutInMs: 5000,
482
+ });
483
+ expect(
484
+ checkByKey(timedOutChecks, "authentication").remediation,
485
+ ).toContain("login.microsoftonline.com");
486
+
487
+ const throttled: Harness = buildHarness({
488
+ token: (): DataSourceHttpResponse => {
489
+ return status(
490
+ 429,
491
+ JSON.stringify({ error: "temporarily_unavailable" }),
492
+ );
493
+ },
494
+ });
495
+ const throttledChecks: Array<SecurityConnectorCheck> =
496
+ await throttled.connector.testConnection(settings(), {
497
+ requestTimeoutInMs: 5000,
498
+ });
499
+ expect(
500
+ checkByKey(throttledChecks, "authentication").remediation,
501
+ ).toContain("throttling this app registration");
502
+
503
+ const down: Harness = buildHarness({
504
+ token: (): DataSourceHttpResponse => {
505
+ return status(502, "Bad Gateway");
506
+ },
507
+ });
508
+ const downChecks: Array<SecurityConnectorCheck> =
509
+ await down.connector.testConnection(settings(), {
510
+ requestTimeoutInMs: 5000,
511
+ });
512
+ expect(checkByKey(downChecks, "authentication").remediation).toContain(
513
+ "server-side problem",
514
+ );
515
+ });
516
+
517
+ test("fails the read check with the role-assignment remediation on 403 and skips the counts", async () => {
518
+ const harness: Harness = buildHarness({
519
+ incidents: [
520
+ (): DataSourceHttpResponse => {
521
+ return status(
522
+ 403,
523
+ JSON.stringify({
524
+ error: {
525
+ code: "AuthorizationFailed",
526
+ message: "does not have authorization to perform action",
527
+ },
528
+ }),
529
+ );
530
+ },
531
+ ],
532
+ });
533
+
534
+ const checks: Array<SecurityConnectorCheck> =
535
+ await harness.connector.testConnection(settings(), {
536
+ requestTimeoutInMs: 5000,
537
+ });
538
+
539
+ expect(
540
+ checks.map((check: SecurityConnectorCheck): string => {
541
+ return `${check.key}:${check.status}`;
542
+ }),
543
+ ).toEqual([
544
+ "authentication:pass",
545
+ "read-permission:fail",
546
+ "detections-available:skip",
547
+ ]);
548
+
549
+ const read: SecurityConnectorCheck = checkByKey(
550
+ checks,
551
+ "read-permission",
552
+ );
553
+ expect(read.message).toMatch(
554
+ /^Microsoft Sentinel incidents list failed \(HTTP 403\): /,
555
+ );
556
+ expect(read.remediation).toContain("Microsoft Sentinel Reader");
557
+ expect(read.remediation).toContain("Access control (IAM)");
558
+ });
559
+
560
+ test("maps 404, 401, 429, 5xx and timeouts on the read check to their own remediation", async () => {
561
+ const unauthorized: Responder = (): DataSourceHttpResponse => {
562
+ return status(
563
+ 401,
564
+ JSON.stringify({
565
+ error: { code: "InvalidAuthenticationToken", message: "x" },
566
+ }),
567
+ );
568
+ };
569
+ const cases: Array<{ responses: Array<Responder>; expected: string }> = [
570
+ {
571
+ responses: [
572
+ (): DataSourceHttpResponse => {
573
+ return status(
574
+ 404,
575
+ JSON.stringify({
576
+ error: { code: "ResourceNotFound", message: "x" },
577
+ }),
578
+ );
579
+ },
580
+ ],
581
+ expected: "Workspace name against the workspace's Overview page",
582
+ },
583
+ {
584
+ /*
585
+ * The authentication check already cached a token, so the read
586
+ * step retries a 401 once with a fresh token before giving up:
587
+ * the case needs two refusals.
588
+ */
589
+ responses: [unauthorized, unauthorized],
590
+ expected: "Confirm the Cloud setting",
591
+ },
592
+ {
593
+ responses: [
594
+ (): DataSourceHttpResponse => {
595
+ return status(
596
+ 429,
597
+ JSON.stringify({
598
+ error: { code: "TooManyRequests", message: "x" },
599
+ }),
600
+ );
601
+ },
602
+ ],
603
+ expected: "throttling requests for this subscription",
604
+ },
605
+ {
606
+ responses: [
607
+ (): DataSourceHttpResponse => {
608
+ return status(503, "Service Unavailable");
609
+ },
610
+ ],
611
+ expected: "server-side problem",
612
+ },
613
+ {
614
+ responses: [
615
+ (): DataSourceHttpResponse => {
616
+ throw new APIException(
617
+ "Microsoft Sentinel incidents list timed out after 5 seconds with no response.",
618
+ );
619
+ },
620
+ ],
621
+ expected: "management.azure.com",
622
+ },
623
+ ];
624
+
625
+ for (const testCase of cases) {
626
+ const harness: Harness = buildHarness({
627
+ incidents: testCase.responses,
628
+ });
629
+ const checks: Array<SecurityConnectorCheck> =
630
+ await harness.connector.testConnection(settings(), {
631
+ requestTimeoutInMs: 5000,
632
+ });
633
+ const read: SecurityConnectorCheck = checkByKey(
634
+ checks,
635
+ "read-permission",
636
+ );
637
+ expect(read.status).toBe("fail");
638
+ expect(read.remediation).toContain(testCase.expected);
639
+ }
640
+ });
641
+
642
+ test("fails only the availability check when a count request fails after the read probe passed", async () => {
643
+ const harness: Harness = buildHarness({
644
+ incidents: [
645
+ (): DataSourceHttpResponse => {
646
+ return ok({ value: [incident("i1")] });
647
+ },
648
+ (): DataSourceHttpResponse => {
649
+ return ok({ value: [incident("i1")] });
650
+ },
651
+ (): DataSourceHttpResponse => {
652
+ return status(500, "Internal Server Error");
653
+ },
654
+ ],
655
+ });
656
+
657
+ const checks: Array<SecurityConnectorCheck> =
658
+ await harness.connector.testConnection(settings(), {
659
+ requestTimeoutInMs: 5000,
660
+ });
661
+
662
+ expect(checkByKey(checks, "read-permission").status).toBe("pass");
663
+ const available: SecurityConnectorCheck = checkByKey(
664
+ checks,
665
+ "detections-available",
666
+ );
667
+ expect(available.status).toBe("fail");
668
+ expect(available.message).toMatch(
669
+ /^Microsoft Sentinel incidents list failed \(HTTP 500\): /,
670
+ );
671
+ expect(available.remediation).toContain("server-side problem");
672
+ });
673
+
674
+ test("reports unusable settings as a failed authentication check without contacting anything", async () => {
675
+ const harness: Harness = buildHarness({});
676
+
677
+ const checks: Array<SecurityConnectorCheck> =
678
+ await harness.connector.testConnection(
679
+ settings({ config: { subscriptionId: "nope" } }),
680
+ { requestTimeoutInMs: 5000 },
681
+ );
682
+
683
+ expect(
684
+ checks.map((check: SecurityConnectorCheck): string => {
685
+ return `${check.key}:${check.status}`;
686
+ }),
687
+ ).toEqual([
688
+ "authentication:fail",
689
+ "read-permission:skip",
690
+ "detections-available:skip",
691
+ ]);
692
+ expect(checkByKey(checks, "authentication").message).toContain(
693
+ "Subscription ID must be a GUID",
694
+ );
695
+ expect(harness.requests).toHaveLength(0);
696
+ });
697
+ });
698
+
699
+ describe("fetchEvents", () => {
700
+ test("lists incidents created in the window, normalizes them with the catalog's vendor and product, and builds samples", async () => {
701
+ const harness: Harness = buildHarness({
702
+ incidents: [
703
+ (): DataSourceHttpResponse => {
704
+ return ok({
705
+ value: [incident("i1", "High"), incident("i2", "Low")],
706
+ });
707
+ },
708
+ ],
709
+ });
710
+
711
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
712
+ settings(),
713
+ { startTime: START, endTime: END },
714
+ fetchOptions({ requestTimeoutInMs: 1234, sampleLimit: 1 }),
715
+ );
716
+
717
+ expect(result.fetchedCount).toBe(2);
718
+ expect(result.events).toHaveLength(2);
719
+ expect(result.rejectedCount).toBe(0);
720
+ expect(result.failedCount).toBe(0);
721
+ expect(result.complete).toBe(true);
722
+ expect(result.resumeAfter).toBeUndefined();
723
+ expect(result.requestCount).toBe(1);
724
+ expect(result.warnings).toEqual([]);
725
+
726
+ for (const event of result.events) {
727
+ expect(event.vendorName).toBe(definition.vendorName);
728
+ expect(event.productName).toBe(definition.productName);
729
+ expect(event.classUid).toBe(2005);
730
+ }
731
+ expect(result.events[0]!.eventUid).toBe("i1");
732
+ expect(result.events[1]!.severityName).toBe("Low");
733
+
734
+ expect(result.samples).toEqual([
735
+ {
736
+ id: "i1",
737
+ title: "Incident i1",
738
+ severity: "High",
739
+ createdTime: "2026-09-12T13:15:30Z",
740
+ eventTime: "2026-09-12T13:00:30Z",
741
+ },
742
+ ]);
743
+
744
+ const reads: Array<DataSourceHttpRequest> = incidentRequests(
745
+ harness.requests,
746
+ );
747
+ expect(reads).toHaveLength(1);
748
+ expect(windowOf(reads[0]!)).toEqual({ start: START, end: END });
749
+ expect(new URL(reads[0]!.url).searchParams.get("$top")).toBe(
750
+ String(MICROSOFT_SENTINEL_DEFAULT_PAGE_SIZE),
751
+ );
752
+ expect(new URL(reads[0]!.url).searchParams.get("$orderby")).toBe(
753
+ "properties/createdTimeUtc asc",
754
+ );
755
+ expect(reads[0]!.timeoutInMs).toBe(1234);
756
+ });
757
+
758
+ test("follows nextLink to the end of the window and reports every page as a request", async () => {
759
+ const harness: Harness = buildHarness({
760
+ incidents: [
761
+ (): DataSourceHttpResponse => {
762
+ return ok({ value: [incident("i1")], nextLink: nextLink("p2") });
763
+ },
764
+ (): DataSourceHttpResponse => {
765
+ return ok({ value: [incident("i2")], nextLink: nextLink("p3") });
766
+ },
767
+ (): DataSourceHttpResponse => {
768
+ return ok({ value: [incident("i3")] });
769
+ },
770
+ ],
771
+ });
772
+
773
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
774
+ settings(),
775
+ { startTime: START, endTime: END },
776
+ fetchOptions(),
777
+ );
778
+
779
+ expect(
780
+ result.events.map((event: NormalizedSecurityEvent): string => {
781
+ return event.eventUid;
782
+ }),
783
+ ).toEqual(["i1", "i2", "i3"]);
784
+ expect(result.requestCount).toBe(3);
785
+ expect(result.complete).toBe(true);
786
+ // A window read to its end names no resume point: the cursor moves to its end.
787
+ expect(result.resumeAfter).toBeUndefined();
788
+
789
+ const reads: Array<DataSourceHttpRequest> = incidentRequests(
790
+ harness.requests,
791
+ );
792
+ expect(reads[1]!.url).toBe(nextLink("p2"));
793
+ expect(reads[2]!.url).toBe(nextLink("p3"));
794
+ expect(harness.requests).toHaveLength(4);
795
+ });
796
+
797
+ /*
798
+ * Review finding connector-bound-hit-permanent-stall: a bound hit used to
799
+ * return complete=false with nothing to resume from, and the warning
800
+ * promised "the poll cursor is held so the next poll continues from the
801
+ * same window". The poller then re-read the same first 1,000 incidents
802
+ * forever. The fetch now reports the creation time of the last incident
803
+ * read so the poller can move past what it already has.
804
+ */
805
+ test("stops at the request bound with complete=false, resumeAfter at the last incident read, and a warning naming it", async () => {
806
+ const harness: Harness = buildHarness({
807
+ incidents: [
808
+ (): DataSourceHttpResponse => {
809
+ return ok({
810
+ value: [
811
+ incident("i1", "High", "2026-09-12T11:00:00Z"),
812
+ incident("i2", "High", "2026-09-12T11:30:00.1234567Z"),
813
+ ],
814
+ nextLink: nextLink("p2"),
815
+ });
816
+ },
817
+ (): DataSourceHttpResponse => {
818
+ return ok({
819
+ value: [incident("i3", "High", "2026-09-12T12:45:10Z")],
820
+ nextLink: nextLink("p3"),
821
+ });
822
+ },
823
+ (): DataSourceHttpResponse => {
824
+ throw new Error("the third page must not be requested");
825
+ },
826
+ ],
827
+ });
828
+
829
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
830
+ settings(),
831
+ { startTime: START, endTime: END },
832
+ fetchOptions({ maxRequests: 2 }),
833
+ );
834
+
835
+ expect(result.events).toHaveLength(3);
836
+ expect(result.requestCount).toBe(2);
837
+ expect(result.complete).toBe(false);
838
+ expect(result.resumeAfter).toEqual(new Date("2026-09-12T12:45:10Z"));
839
+ expect(result.warnings).toEqual([
840
+ "Stopped after 2 incidents requests (the per-run request limit) before reading the whole window. Incidents are read oldest first; every incident created before 2026-09-12T12:45:10.000Z was read.",
841
+ ]);
842
+ expect(result.warnings[0]).not.toContain("cursor is held");
843
+ expect(incidentRequests(harness.requests)).toHaveLength(2);
844
+ });
845
+
846
+ test("stops at the record bound mid-page with complete=false and resumeAfter at the last incident kept, not the last one on the page", async () => {
847
+ const harness: Harness = buildHarness({
848
+ incidents: [
849
+ (): DataSourceHttpResponse => {
850
+ return ok({
851
+ value: [
852
+ incident("i1", "High", "2026-09-12T11:00:00Z"),
853
+ incident("i2", "High", "2026-09-12T11:05:00Z"),
854
+ incident("i3", "High", "2026-09-12T11:10:00Z"),
855
+ ],
856
+ nextLink: nextLink("p2"),
857
+ });
858
+ },
859
+ ],
860
+ });
861
+
862
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
863
+ settings(),
864
+ { startTime: START, endTime: END },
865
+ fetchOptions({ maxEvents: 2 }),
866
+ );
867
+
868
+ expect(
869
+ result.events.map((event: NormalizedSecurityEvent): string => {
870
+ return event.eventUid;
871
+ }),
872
+ ).toEqual(["i1", "i2"]);
873
+ expect(result.fetchedCount).toBe(2);
874
+ expect(result.complete).toBe(false);
875
+ expect(result.resumeAfter).toEqual(new Date("2026-09-12T11:05:00Z"));
876
+ expect(result.requestCount).toBe(1);
877
+ expect(result.warnings[0]).toContain("per-run record limit");
878
+ expect(result.warnings[0]).toContain("2026-09-12T11:05:00.000Z");
879
+ });
880
+
881
+ test("treats reaching the record bound exactly as incomplete only when more pages exist", async () => {
882
+ const withMore: Harness = buildHarness({
883
+ incidents: [
884
+ (): DataSourceHttpResponse => {
885
+ return ok({
886
+ value: [
887
+ incident("i1", "High", "2026-09-12T11:00:00Z"),
888
+ incident("i2", "High", "2026-09-12T11:01:00Z"),
889
+ ],
890
+ nextLink: nextLink("p2"),
891
+ });
892
+ },
893
+ ],
894
+ });
895
+ const incomplete: ConnectorFetchResult =
896
+ await withMore.connector.fetchEvents(
897
+ settings(),
898
+ { startTime: START, endTime: END },
899
+ fetchOptions({ maxEvents: 2 }),
900
+ );
901
+ expect(incomplete.complete).toBe(false);
902
+ expect(incomplete.events).toHaveLength(2);
903
+ expect(incomplete.resumeAfter).toEqual(new Date("2026-09-12T11:01:00Z"));
904
+
905
+ const lastPage: Harness = buildHarness({
906
+ incidents: [
907
+ (): DataSourceHttpResponse => {
908
+ return ok({ value: [incident("i1"), incident("i2")] });
909
+ },
910
+ ],
911
+ });
912
+ const complete: ConnectorFetchResult =
913
+ await lastPage.connector.fetchEvents(
914
+ settings(),
915
+ { startTime: START, endTime: END },
916
+ fetchOptions({ maxEvents: 2 }),
917
+ );
918
+ expect(complete.complete).toBe(true);
919
+ expect(complete.resumeAfter).toBeUndefined();
920
+ expect(complete.warnings).toEqual([]);
921
+ });
922
+
923
+ test("names no resume point when the request bound stops the read before any incident was returned", async () => {
924
+ const harness: Harness = buildHarness({
925
+ incidents: [
926
+ (): DataSourceHttpResponse => {
927
+ return ok({ value: [], nextLink: nextLink("p2") });
928
+ },
929
+ ],
930
+ });
931
+
932
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
933
+ settings(),
934
+ { startTime: START, endTime: END },
935
+ fetchOptions({ maxRequests: 1 }),
936
+ );
937
+
938
+ expect(result.complete).toBe(false);
939
+ expect(result.resumeAfter).toBeUndefined();
940
+ expect(result.warnings).toEqual([
941
+ "Stopped after 1 incidents requests (the per-run request limit) before reading the whole window.",
942
+ ]);
943
+ });
944
+
945
+ test("names no resume point, and says why, when the API returns incidents out of creation-time order", async () => {
946
+ const harness: Harness = buildHarness({
947
+ incidents: [
948
+ (): DataSourceHttpResponse => {
949
+ return ok({
950
+ value: [
951
+ incident("i1", "High", "2026-09-12T12:00:00Z"),
952
+ incident("i2", "High", "2026-09-12T11:00:00Z"),
953
+ ],
954
+ nextLink: nextLink("p2"),
955
+ });
956
+ },
957
+ ],
958
+ });
959
+
960
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
961
+ settings(),
962
+ { startTime: START, endTime: END },
963
+ fetchOptions({ maxRequests: 1 }),
964
+ );
965
+
966
+ expect(result.complete).toBe(false);
967
+ expect(result.resumeAfter).toBeUndefined();
968
+ expect(result.warnings).toEqual([
969
+ "Stopped after 1 incidents requests (the per-run request limit) before reading the whole window.",
970
+ "Microsoft Sentinel returned incidents out of creation-time order, so this run cannot name a point to resume from.",
971
+ ]);
972
+ });
973
+
974
+ test("never resumes past an incident that failed normalization, so the poller can retry it", async () => {
975
+ const harness: Harness = buildHarness({
976
+ incidents: [
977
+ (): DataSourceHttpResponse => {
978
+ return ok({
979
+ value: [
980
+ incident("i1", "High", "2026-09-12T11:00:00Z"),
981
+ incident("i2", "High", "2026-09-12T11:20:00Z"),
982
+ incident("i3", "High", "2026-09-12T11:40:00Z"),
983
+ ],
984
+ nextLink: nextLink("p2"),
985
+ });
986
+ },
987
+ ],
988
+ });
989
+
990
+ const original: (
991
+ raw: JSONObject,
992
+ ) => ReturnType<typeof MicrosoftSentinelNormalizer.normalize> =
993
+ MicrosoftSentinelNormalizer.normalize.bind(MicrosoftSentinelNormalizer);
994
+ jest
995
+ .spyOn(MicrosoftSentinelNormalizer, "normalize")
996
+ .mockImplementation((raw: JSONObject) => {
997
+ if (raw["name"] === "i2") {
998
+ throw new Error("boom");
999
+ }
1000
+
1001
+ return original(raw);
1002
+ });
1003
+
1004
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
1005
+ settings(),
1006
+ { startTime: START, endTime: END },
1007
+ fetchOptions({ maxRequests: 1 }),
1008
+ );
1009
+
1010
+ expect(result.complete).toBe(false);
1011
+ expect(result.failedCount).toBe(1);
1012
+ expect(result.resumeAfter).toEqual(new Date("2026-09-12T11:20:00Z"));
1013
+ });
1014
+
1015
+ test("ignores creation times outside the window when naming the resume point", async () => {
1016
+ const harness: Harness = buildHarness({
1017
+ incidents: [
1018
+ (): DataSourceHttpResponse => {
1019
+ return ok({
1020
+ value: [
1021
+ incident("i1", "High", "2026-09-12T11:00:00Z"),
1022
+ incident("i2", "High", "2026-09-14T00:00:00Z"),
1023
+ ],
1024
+ nextLink: nextLink("p2"),
1025
+ });
1026
+ },
1027
+ ],
1028
+ });
1029
+
1030
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
1031
+ settings(),
1032
+ { startTime: START, endTime: END },
1033
+ fetchOptions({ maxRequests: 1 }),
1034
+ );
1035
+
1036
+ expect(result.complete).toBe(false);
1037
+ expect(result.resumeAfter).toEqual(new Date("2026-09-12T11:00:00Z"));
1038
+ });
1039
+
1040
+ test("counts unrecognized records as rejected and normalization throws as failed, without stopping the page", async () => {
1041
+ const harness: Harness = buildHarness({
1042
+ incidents: [
1043
+ (): DataSourceHttpResponse => {
1044
+ return ok({
1045
+ value: [
1046
+ incident("i1"),
1047
+ { error: { code: "Partial", message: "not an incident" } },
1048
+ incident("i2"),
1049
+ incident("i3"),
1050
+ ],
1051
+ });
1052
+ },
1053
+ ],
1054
+ });
1055
+
1056
+ const original: (
1057
+ raw: JSONObject,
1058
+ ) => ReturnType<typeof MicrosoftSentinelNormalizer.normalize> =
1059
+ MicrosoftSentinelNormalizer.normalize.bind(MicrosoftSentinelNormalizer);
1060
+ jest
1061
+ .spyOn(MicrosoftSentinelNormalizer, "normalize")
1062
+ .mockImplementation((raw: JSONObject) => {
1063
+ if (raw["name"] === "i2") {
1064
+ throw new Error("boom");
1065
+ }
1066
+
1067
+ return original(raw);
1068
+ });
1069
+
1070
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
1071
+ settings(),
1072
+ { startTime: START, endTime: END },
1073
+ fetchOptions(),
1074
+ );
1075
+
1076
+ expect(result.fetchedCount).toBe(4);
1077
+ expect(result.rejectedCount).toBe(1);
1078
+ expect(result.failedCount).toBe(1);
1079
+ expect(
1080
+ result.events.map((event: NormalizedSecurityEvent): string => {
1081
+ return event.eventUid;
1082
+ }),
1083
+ ).toEqual(["i1", "i3"]);
1084
+ expect(result.complete).toBe(true);
1085
+ expect(result.resumeAfter).toBeUndefined();
1086
+ });
1087
+
1088
+ test("returns no samples when the sample limit is zero", async () => {
1089
+ const harness: Harness = buildHarness({
1090
+ incidents: [
1091
+ (): DataSourceHttpResponse => {
1092
+ return ok({ value: [incident("i1")] });
1093
+ },
1094
+ ],
1095
+ });
1096
+
1097
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
1098
+ settings(),
1099
+ { startTime: START, endTime: END },
1100
+ fetchOptions({ sampleLimit: 0 }),
1101
+ );
1102
+
1103
+ expect(result.samples).toEqual([]);
1104
+ expect(result.events).toHaveLength(1);
1105
+ });
1106
+
1107
+ test("propagates authentication and permission failures so the poller records a failed run", async () => {
1108
+ const denied: Harness = buildHarness({
1109
+ incidents: [
1110
+ (): DataSourceHttpResponse => {
1111
+ return status(
1112
+ 403,
1113
+ JSON.stringify({
1114
+ error: { code: "AuthorizationFailed", message: "no" },
1115
+ }),
1116
+ );
1117
+ },
1118
+ ],
1119
+ });
1120
+
1121
+ await expect(
1122
+ denied.connector.fetchEvents(
1123
+ settings(),
1124
+ { startTime: START, endTime: END },
1125
+ fetchOptions(),
1126
+ ),
1127
+ ).rejects.toThrow(
1128
+ /^Microsoft Sentinel incidents list failed \(HTTP 403\): /,
1129
+ );
1130
+
1131
+ const badToken: Harness = buildHarness({
1132
+ token: (): DataSourceHttpResponse => {
1133
+ return status(
1134
+ 401,
1135
+ JSON.stringify({
1136
+ error: "invalid_client",
1137
+ error_description: `AADSTS7000215: bad secret client_secret=${CLIENT_SECRET}`,
1138
+ }),
1139
+ );
1140
+ },
1141
+ });
1142
+
1143
+ let thrown: Error | null = null;
1144
+ try {
1145
+ await badToken.connector.fetchEvents(
1146
+ settings(),
1147
+ { startTime: START, endTime: END },
1148
+ fetchOptions(),
1149
+ );
1150
+ } catch (error) {
1151
+ thrown = error as Error;
1152
+ }
1153
+
1154
+ expect(thrown).toBeInstanceOf(APIException);
1155
+ expect(thrown!.message).toMatch(
1156
+ /^Microsoft Sentinel token request failed \(HTTP 401\): /,
1157
+ );
1158
+ expect(thrown!.message).not.toContain(CLIENT_SECRET);
1159
+ });
1160
+
1161
+ test("rejects unusable settings before contacting anything", async () => {
1162
+ const harness: Harness = buildHarness({});
1163
+
1164
+ await expect(
1165
+ harness.connector.fetchEvents(
1166
+ settings({ config: { workspaceName: "" } }),
1167
+ { startTime: START, endTime: END },
1168
+ fetchOptions(),
1169
+ ),
1170
+ ).rejects.toThrow(BadDataException);
1171
+ expect(harness.requests).toHaveLength(0);
1172
+ });
1173
+ });
1174
+ });