@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,1409 @@
1
+ import { describe, expect, test } from "@jest/globals";
2
+ import ElasticSecurityConnector from "../../../../../../Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityConnector";
3
+ import {
4
+ ELASTIC_SECURITY_MAX_EXCLUDED_ID_BYTES,
5
+ ELASTIC_SECURITY_MAX_PAGE_SIZE,
6
+ } from "../../../../../../Server/Utils/SecurityEvent/Connectors/ElasticSecurity/ElasticSecurityClient";
7
+ import {
8
+ ConnectorFetchOptions,
9
+ ConnectorFetchResult,
10
+ SecurityConnectorSettings,
11
+ } from "../../../../../../Server/Utils/SecurityEvent/Connectors/Types";
12
+ import {
13
+ DataSourceHttpRequest,
14
+ DataSourceHttpResponse,
15
+ } from "../../../../../../Server/Utils/DataSource/HttpFetch";
16
+ import BadDataException from "../../../../../../Types/Exception/BadDataException";
17
+ import { JSONArray, JSONObject } from "../../../../../../Types/JSON";
18
+ import NormalizedSecurityEvent from "../../../../../../Types/SecurityEvent/NormalizedSecurityEvent";
19
+ import {
20
+ SecurityConnectorCheck,
21
+ SecurityConnectorSample,
22
+ } from "../../../../../../Types/SecurityEvent/Connectors/ConnectorDiagnostics";
23
+ import SecurityEventConnectorProvider from "../../../../../../Types/SecurityEvent/Connectors/SecurityEventConnectorProvider";
24
+ import {
25
+ ConnectorField,
26
+ SecurityEventConnectorDefinition,
27
+ getSecurityEventConnectorDefinition,
28
+ } from "../../../../../../Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog";
29
+
30
+ /*
31
+ * The connector as the poller and the tester see it: settings validation
32
+ * in the catalog's vocabulary, the three provider checks with their
33
+ * skip-on-earlier-failure rule, and a creation-time fetch that pages by
34
+ * advancing the @timestamp lower bound while excluding the alerts already
35
+ * read at that instant, respects every bound, and reports a bound hit as
36
+ * incomplete with the resume point. Transport is injected; nothing
37
+ * touches the network.
38
+ */
39
+
40
+ const KIBANA_URL: string = "https://kibana.example.com";
41
+ const SPACE: string = "security";
42
+ const API_KEY: string =
43
+ "VnVhQ2ZHY0JDZGJrUW0tZTVhT3g6dWkybHAyYXhUTm1zeWFrdzl0dk5udw==";
44
+ const START: Date = new Date("2026-09-12T10:00:00.000Z");
45
+ const END: Date = new Date("2026-09-13T10:00:00.000Z");
46
+ const DAY_IN_MS: number = 24 * 60 * 60 * 1000;
47
+
48
+ const DEFINITION: SecurityEventConnectorDefinition =
49
+ getSecurityEventConnectorDefinition(
50
+ SecurityEventConnectorProvider.ElasticSecurity,
51
+ )!;
52
+
53
+ function fieldTitle(key: string): string {
54
+ const field: ConnectorField | undefined = [
55
+ ...DEFINITION.configFields,
56
+ ...DEFINITION.secretFields,
57
+ ].find((candidate: ConnectorField): boolean => {
58
+ return candidate.key === key;
59
+ });
60
+
61
+ return field!.title;
62
+ }
63
+
64
+ type Responder = (
65
+ request: DataSourceHttpRequest,
66
+ ) => DataSourceHttpResponse | Promise<DataSourceHttpResponse>;
67
+
68
+ interface Harness {
69
+ requests: Array<DataSourceHttpRequest>;
70
+ connector: ElasticSecurityConnector;
71
+ }
72
+
73
+ function ok(body: JSONObject): DataSourceHttpResponse {
74
+ return {
75
+ statusCode: 200,
76
+ bodyText: JSON.stringify(body),
77
+ bodyJson: body,
78
+ headers: {},
79
+ };
80
+ }
81
+
82
+ function status(code: number, body: string): DataSourceHttpResponse {
83
+ let bodyJson: unknown = undefined;
84
+
85
+ try {
86
+ bodyJson = JSON.parse(body);
87
+ } catch {
88
+ bodyJson = undefined;
89
+ }
90
+
91
+ return { statusCode: code, bodyText: body, bodyJson, headers: {} };
92
+ }
93
+
94
+ function statusBody(): JSONObject {
95
+ return {
96
+ name: "kibana-0",
97
+ version: { number: "9.1.0" },
98
+ status: {
99
+ overall: {
100
+ level: "available",
101
+ summary: "All services and plugins are available",
102
+ },
103
+ },
104
+ };
105
+ }
106
+
107
+ function alertHit(
108
+ id: string,
109
+ timestamp: string,
110
+ overrides?: JSONObject | undefined,
111
+ ): JSONObject {
112
+ return {
113
+ _index: `.internal.alerts-security.alerts-${SPACE}-000001`,
114
+ _id: id,
115
+ _score: null,
116
+ _source: {
117
+ "@timestamp": timestamp,
118
+ "event.kind": "signal",
119
+ "kibana.alert.uuid": id,
120
+ "kibana.alert.rule.uuid": "5f2d8e1a-6c3b-4e9f-8a7d-1b2c3d4e5f60",
121
+ "kibana.alert.rule.name": "Potential Privilege Escalation via PKEXEC",
122
+ "kibana.alert.rule.threat": [
123
+ {
124
+ framework: "MITRE ATT&CK",
125
+ tactic: {
126
+ id: "TA0004",
127
+ name: "Privilege Escalation",
128
+ reference: "https://attack.mitre.org/tactics/TA0004/",
129
+ },
130
+ technique: [
131
+ {
132
+ id: "T1068",
133
+ name: "Exploitation for Privilege Escalation",
134
+ reference: "https://attack.mitre.org/techniques/T1068/",
135
+ },
136
+ ],
137
+ },
138
+ ],
139
+ "kibana.alert.severity": "high",
140
+ "kibana.alert.risk_score": 73,
141
+ "kibana.alert.workflow_status": "open",
142
+ "kibana.alert.reason":
143
+ "process event with process pkexec, by www-data on web-01 created high alert Potential Privilege Escalation via PKEXEC.",
144
+ "kibana.alert.original_time": "2026-09-12T09:58:41.117Z",
145
+ host: { name: "web-01", ip: ["10.20.30.40"] },
146
+ user: { name: "www-data" },
147
+ process: { name: "pkexec" },
148
+ ...(overrides || {}),
149
+ },
150
+ sort: [Date.parse(timestamp)],
151
+ };
152
+ }
153
+
154
+ /*
155
+ * A full page of distinct alerts, one second apart, starting `offset`
156
+ * seconds into the window. Full pages are what make the connector page.
157
+ */
158
+ function fullPage(offset: number): Array<JSONObject> {
159
+ const hits: Array<JSONObject> = [];
160
+
161
+ for (let index: number = 0; index < ELASTIC_SECURITY_MAX_PAGE_SIZE; index++) {
162
+ const timestamp: string = new Date(
163
+ START.getTime() + (offset + index) * 1000,
164
+ ).toISOString();
165
+ hits.push(alertHit(`alert-${offset + index}`, timestamp));
166
+ }
167
+
168
+ return hits;
169
+ }
170
+
171
+ function searchBody(
172
+ hits: Array<JSONObject>,
173
+ total?: JSONObject | undefined,
174
+ ): JSONObject {
175
+ const envelope: JSONObject = { hits };
176
+
177
+ if (total !== undefined) {
178
+ envelope["total"] = total;
179
+ }
180
+
181
+ return {
182
+ took: 3,
183
+ timed_out: false,
184
+ _shards: { total: 1, successful: 1, skipped: 0, failed: 0 },
185
+ hits: envelope,
186
+ };
187
+ }
188
+
189
+ function settings(
190
+ overrides?: Partial<SecurityConnectorSettings> | undefined,
191
+ ): SecurityConnectorSettings {
192
+ return {
193
+ provider: SecurityEventConnectorProvider.ElasticSecurity,
194
+ config: { kibanaUrl: KIBANA_URL, space: SPACE },
195
+ secrets: { apiKey: API_KEY },
196
+ alertingOnly: false,
197
+ ...(overrides || {}),
198
+ };
199
+ }
200
+
201
+ function fetchOptions(
202
+ overrides?: Partial<ConnectorFetchOptions> | undefined,
203
+ ): ConnectorFetchOptions {
204
+ return {
205
+ maxRequests: 20,
206
+ maxEvents: 10000,
207
+ requestTimeoutInMs: 60000,
208
+ sampleLimit: 25,
209
+ ...(overrides || {}),
210
+ };
211
+ }
212
+
213
+ /*
214
+ * Scripted responders are consumed in order; `kibana` answers every search
215
+ * request once they run out, for tests that simulate the index itself.
216
+ */
217
+ function buildHarness(options: {
218
+ status?: Responder | undefined;
219
+ search?: Array<Responder> | undefined;
220
+ kibana?: Responder | undefined;
221
+ }): Harness {
222
+ const requests: Array<DataSourceHttpRequest> = [];
223
+ const searchResponders: Array<Responder> = [...(options.search || [])];
224
+
225
+ const connector: ElasticSecurityConnector = new ElasticSecurityConnector(
226
+ async (request: DataSourceHttpRequest): Promise<DataSourceHttpResponse> => {
227
+ requests.push(request);
228
+
229
+ if (new URL(request.url).pathname.endsWith("/api/status")) {
230
+ const responder: Responder =
231
+ options.status ||
232
+ ((): DataSourceHttpResponse => {
233
+ return ok(statusBody());
234
+ });
235
+ return responder(request);
236
+ }
237
+
238
+ const responder: Responder | undefined =
239
+ searchResponders.shift() || options.kibana;
240
+
241
+ if (!responder) {
242
+ throw new Error(`Unexpected request to ${request.url}`);
243
+ }
244
+
245
+ return responder(request);
246
+ },
247
+ );
248
+
249
+ return { requests, connector };
250
+ }
251
+
252
+ function parseBody(request: DataSourceHttpRequest): JSONObject {
253
+ expect(typeof request.body).toBe("string");
254
+ return JSON.parse(request.body as string) as JSONObject;
255
+ }
256
+
257
+ /*
258
+ * The range sits at the top of the query, or inside bool.filter when the
259
+ * request also excludes the ids already read at the lower bound.
260
+ */
261
+ function rangeOf(request: DataSourceHttpRequest): { gte: string; lt: string } {
262
+ const query: JSONObject = parseBody(request)["query"] as JSONObject;
263
+ const bool: JSONObject | undefined = query["bool"] as JSONObject | undefined;
264
+ const clause: JSONObject = bool
265
+ ? ((bool["filter"] as JSONArray)[0] as JSONObject)
266
+ : query;
267
+ const range: JSONObject = (clause["range"] as JSONObject)[
268
+ "@timestamp"
269
+ ] as JSONObject;
270
+
271
+ return { gte: String(range["gte"]), lt: String(range["lt"]) };
272
+ }
273
+
274
+ function excludedIdsOf(request: DataSourceHttpRequest): Array<string> {
275
+ const query: JSONObject = parseBody(request)["query"] as JSONObject;
276
+ const bool: JSONObject | undefined = query["bool"] as JSONObject | undefined;
277
+
278
+ if (!bool) {
279
+ return [];
280
+ }
281
+
282
+ const mustNot: JSONArray = bool["must_not"] as JSONArray;
283
+ return (mustNot[0]!["ids"] as JSONObject)["values"] as Array<string>;
284
+ }
285
+
286
+ interface FakeAlert {
287
+ id: string;
288
+ timestamp: string;
289
+ }
290
+
291
+ /*
292
+ * A detection alerts index that answers the way Elasticsearch does: the
293
+ * range on @timestamp, the must_not ids exclusion, ascending @timestamp
294
+ * and the size. Elasticsearch promises no order among hits with equal
295
+ * sort values, so the tie order flips on every request: a connector that
296
+ * relied on it would re-read or skip alerts here.
297
+ */
298
+ function fakeKibana(alerts: Array<FakeAlert>): Responder {
299
+ let requestNumber: number = 0;
300
+
301
+ return (request: DataSourceHttpRequest): DataSourceHttpResponse => {
302
+ requestNumber += 1;
303
+
304
+ const range: { gte: string; lt: string } = rangeOf(request);
305
+ const from: number = Date.parse(range.gte);
306
+ const to: number = Date.parse(range.lt);
307
+ const excluded: Set<string> = new Set<string>(excludedIdsOf(request));
308
+ const size: number = Number(parseBody(request)["size"]);
309
+ const tieDirection: number = requestNumber % 2 === 0 ? -1 : 1;
310
+
311
+ const matching: Array<FakeAlert> = alerts
312
+ .filter((alert: FakeAlert): boolean => {
313
+ const time: number = Date.parse(alert.timestamp);
314
+ return time >= from && time < to && !excluded.has(alert.id);
315
+ })
316
+ .sort((left: FakeAlert, right: FakeAlert): number => {
317
+ const byTime: number =
318
+ Date.parse(left.timestamp) - Date.parse(right.timestamp);
319
+
320
+ if (byTime !== 0) {
321
+ return byTime;
322
+ }
323
+
324
+ return tieDirection * left.id.localeCompare(right.id);
325
+ });
326
+
327
+ return ok(
328
+ searchBody(
329
+ matching.slice(0, size).map((alert: FakeAlert): JSONObject => {
330
+ return alertHit(alert.id, alert.timestamp);
331
+ }),
332
+ ),
333
+ );
334
+ };
335
+ }
336
+
337
+ function alertsAt(
338
+ prefix: string,
339
+ count: number,
340
+ timestamp: (index: number) => string,
341
+ ): Array<FakeAlert> {
342
+ const alerts: Array<FakeAlert> = [];
343
+
344
+ for (let index: number = 0; index < count; index++) {
345
+ alerts.push({ id: `${prefix}-${index}`, timestamp: timestamp(index) });
346
+ }
347
+
348
+ return alerts;
349
+ }
350
+
351
+ function eventUids(result: ConnectorFetchResult): Array<string> {
352
+ return result.events.map((event: NormalizedSecurityEvent): string => {
353
+ return event.eventUid;
354
+ });
355
+ }
356
+
357
+ function checkByKey(
358
+ checks: Array<SecurityConnectorCheck>,
359
+ key: string,
360
+ ): SecurityConnectorCheck {
361
+ const check: SecurityConnectorCheck | undefined = checks.find(
362
+ (candidate: SecurityConnectorCheck): boolean => {
363
+ return candidate.key === key;
364
+ },
365
+ );
366
+
367
+ expect(check).toBeDefined();
368
+ return check!;
369
+ }
370
+
371
+ function expectNoSecret(checks: Array<SecurityConnectorCheck>): void {
372
+ expect(JSON.stringify(checks)).not.toContain(API_KEY);
373
+ }
374
+
375
+ describe("ElasticSecurityConnector", () => {
376
+ test("registers under the catalog's provider", () => {
377
+ const connector: ElasticSecurityConnector = new ElasticSecurityConnector(
378
+ (): Promise<DataSourceHttpResponse> => {
379
+ throw new Error("must not be called");
380
+ },
381
+ );
382
+
383
+ expect(connector.provider).toBe(
384
+ SecurityEventConnectorProvider.ElasticSecurity,
385
+ );
386
+ expect(connector.provider).toBe(DEFINITION.provider);
387
+ });
388
+
389
+ describe("validateSettings", () => {
390
+ const connector: ElasticSecurityConnector = new ElasticSecurityConnector(
391
+ (): Promise<DataSourceHttpResponse> => {
392
+ throw new Error("must not be called");
393
+ },
394
+ );
395
+
396
+ test("accepts a Kibana origin, a space id and a base64 key", () => {
397
+ expect(() => {
398
+ connector.validateSettings(settings());
399
+ }).not.toThrow();
400
+ expect(() => {
401
+ connector.validateSettings(
402
+ settings({ config: { kibanaUrl: `${KIBANA_URL}/`, space: "" } }),
403
+ );
404
+ }).not.toThrow();
405
+ expect(() => {
406
+ connector.validateSettings(
407
+ settings({
408
+ config: {
409
+ kibanaUrl: "https://abc123.kb.us-east-1.aws.found.io:9243",
410
+ },
411
+ }),
412
+ );
413
+ }).not.toThrow();
414
+ });
415
+
416
+ test.each([
417
+ [
418
+ { kibanaUrl: "", space: "" },
419
+ { apiKey: API_KEY },
420
+ `${fieldTitle("kibanaUrl")} is required.`,
421
+ ],
422
+ [
423
+ { kibanaUrl: "kibana.example.com", space: "" },
424
+ { apiKey: API_KEY },
425
+ `${fieldTitle("kibanaUrl")} must be an absolute URL`,
426
+ ],
427
+ [
428
+ { kibanaUrl: "ftp://kibana.example.com", space: "" },
429
+ { apiKey: API_KEY },
430
+ `${fieldTitle("kibanaUrl")} must use https`,
431
+ ],
432
+ [
433
+ { kibanaUrl: `${KIBANA_URL}/?x=1`, space: "" },
434
+ { apiKey: API_KEY },
435
+ "must not contain a query string",
436
+ ],
437
+ [
438
+ { kibanaUrl: `${KIBANA_URL}/s/security`, space: "" },
439
+ { apiKey: API_KEY },
440
+ `put the space id in the ${fieldTitle("space")} field`,
441
+ ],
442
+ [
443
+ { kibanaUrl: `${KIBANA_URL}/api/status`, space: "" },
444
+ { apiKey: API_KEY },
445
+ "without an /api path",
446
+ ],
447
+ [
448
+ { kibanaUrl: KIBANA_URL, space: "Security Team" },
449
+ { apiKey: API_KEY },
450
+ `${fieldTitle("space")} must be a space id`,
451
+ ],
452
+ [
453
+ { kibanaUrl: KIBANA_URL, space: "" },
454
+ { apiKey: "" },
455
+ `${fieldTitle("apiKey")} is required.`,
456
+ ],
457
+ [
458
+ { kibanaUrl: KIBANA_URL, space: "" },
459
+ { apiKey: `ApiKey ${API_KEY}` },
460
+ "without the 'ApiKey' prefix",
461
+ ],
462
+ [
463
+ { kibanaUrl: KIBANA_URL, space: "" },
464
+ { apiKey: "VuaCfGcBCdbkQm-e5aOx:ui2lp2axTNmsyakw9tvNnw" },
465
+ "not the raw id:api_key pair",
466
+ ],
467
+ ])(
468
+ "rejects config %j with secrets shaped like %j",
469
+ (config: JSONObject, secrets: JSONObject, expected: string) => {
470
+ expect(() => {
471
+ connector.validateSettings(settings({ config, secrets }));
472
+ }).toThrow(BadDataException);
473
+ expect(() => {
474
+ connector.validateSettings(settings({ config, secrets }));
475
+ }).toThrow(expected);
476
+ },
477
+ );
478
+ });
479
+
480
+ describe("testConnection", () => {
481
+ test("runs status, a one-record read over the last day, then 24h and 7d counts, and passes every check", async () => {
482
+ const harness: Harness = buildHarness({
483
+ search: [
484
+ (): DataSourceHttpResponse => {
485
+ return ok(searchBody([alertHit("a1", "2026-09-12T10:05:03.412Z")]));
486
+ },
487
+ (): DataSourceHttpResponse => {
488
+ return ok(searchBody([], { value: 12, relation: "eq" }));
489
+ },
490
+ (): DataSourceHttpResponse => {
491
+ return ok(searchBody([], { value: 140, relation: "eq" }));
492
+ },
493
+ ],
494
+ });
495
+
496
+ const before: number = Date.now();
497
+ const checks: Array<SecurityConnectorCheck> =
498
+ await harness.connector.testConnection(settings(), {
499
+ requestTimeoutInMs: 20000,
500
+ });
501
+ const after: number = Date.now();
502
+
503
+ expect(
504
+ checks.map((check: SecurityConnectorCheck): string => {
505
+ return `${check.key}:${check.status}`;
506
+ }),
507
+ ).toEqual([
508
+ "authentication:pass",
509
+ "read-permission:pass",
510
+ "detections-available:pass",
511
+ ]);
512
+ expectNoSecret(checks);
513
+
514
+ expect(checkByKey(checks, "authentication").message).toContain(
515
+ "kibana.example.com accepted the API key",
516
+ );
517
+ expect(checkByKey(checks, "authentication").details).toEqual({
518
+ kibanaVersion: "9.1.0",
519
+ level: "available",
520
+ summary: "All services and plugins are available",
521
+ });
522
+ expect(checkByKey(checks, "read-permission").message).toContain(
523
+ 'rule "Potential Privilege Escalation via PKEXEC"',
524
+ );
525
+ expect(checkByKey(checks, "detections-available").message).toBe(
526
+ "12 alerts created in the last 24 hours and 140 in the last 7 days.",
527
+ );
528
+ expect(checkByKey(checks, "detections-available").details).toEqual({
529
+ createdLast24h: 12,
530
+ createdLast7d: 140,
531
+ hasMoreLast24h: false,
532
+ hasMoreLast7d: false,
533
+ });
534
+
535
+ expect(harness.requests).toHaveLength(4);
536
+ expect(new URL(harness.requests[0]!.url).pathname).toBe(
537
+ `/s/${SPACE}/api/status`,
538
+ );
539
+
540
+ for (const request of harness.requests) {
541
+ expect(request.timeoutInMs).toBe(20000);
542
+ expect(request.headers?.["Authorization"]).toBe(`ApiKey ${API_KEY}`);
543
+ }
544
+
545
+ const probe: JSONObject = parseBody(harness.requests[1]!);
546
+ expect(Object.keys(probe).sort()).toEqual(["query", "size", "sort"]);
547
+ expect(probe["size"]).toBe(1);
548
+ const probeRange: { gte: string; lt: string } = rangeOf(
549
+ harness.requests[1]!,
550
+ );
551
+ expect(Date.parse(probeRange.lt) - Date.parse(probeRange.gte)).toBe(
552
+ DAY_IN_MS,
553
+ );
554
+ expect(Date.parse(probeRange.lt)).toBeGreaterThanOrEqual(before);
555
+ expect(Date.parse(probeRange.lt)).toBeLessThanOrEqual(after);
556
+
557
+ const count24h: JSONObject = parseBody(harness.requests[2]!);
558
+ expect(Object.keys(count24h).sort()).toEqual([
559
+ "query",
560
+ "size",
561
+ "track_total_hits",
562
+ ]);
563
+ expect(count24h["size"]).toBe(0);
564
+ const range24h: { gte: string; lt: string } = rangeOf(
565
+ harness.requests[2]!,
566
+ );
567
+ expect(Date.parse(range24h.lt) - Date.parse(range24h.gte)).toBe(
568
+ DAY_IN_MS,
569
+ );
570
+ const range7d: { gte: string; lt: string } = rangeOf(
571
+ harness.requests[3]!,
572
+ );
573
+ expect(Date.parse(range7d.lt) - Date.parse(range7d.gte)).toBe(
574
+ 7 * DAY_IN_MS,
575
+ );
576
+ });
577
+
578
+ test("warns with remediation when nothing was created in seven days", async () => {
579
+ const harness: Harness = buildHarness({
580
+ search: [
581
+ (): DataSourceHttpResponse => {
582
+ return ok(searchBody([]));
583
+ },
584
+ (): DataSourceHttpResponse => {
585
+ return ok(searchBody([], { value: 0, relation: "eq" }));
586
+ },
587
+ (): DataSourceHttpResponse => {
588
+ return ok(searchBody([], { value: 0, relation: "eq" }));
589
+ },
590
+ ],
591
+ });
592
+
593
+ const checks: Array<SecurityConnectorCheck> =
594
+ await harness.connector.testConnection(settings(), {
595
+ requestTimeoutInMs: 20000,
596
+ });
597
+
598
+ expect(checkByKey(checks, "read-permission").message).toContain(
599
+ "No alert was created in the last 24 hours",
600
+ );
601
+
602
+ const availability: SecurityConnectorCheck = checkByKey(
603
+ checks,
604
+ "detections-available",
605
+ );
606
+ expect(availability.status).toBe("warn");
607
+ expect(availability.message).toBe(
608
+ "No alerts were created in the last 7 days. Polling will import new alerts as Elastic Security creates them.",
609
+ );
610
+ expect(availability.remediation).toContain("detection rules are enabled");
611
+ });
612
+
613
+ test("labels a lower-bound count with a plus sign", async () => {
614
+ const harness: Harness = buildHarness({
615
+ search: [
616
+ (): DataSourceHttpResponse => {
617
+ return ok(searchBody([alertHit("a1", "2026-09-12T10:05:03.412Z")]));
618
+ },
619
+ (): DataSourceHttpResponse => {
620
+ return ok(searchBody([], { value: 1, relation: "eq" }));
621
+ },
622
+ (): DataSourceHttpResponse => {
623
+ return ok(searchBody([], { value: 10000, relation: "gte" }));
624
+ },
625
+ ],
626
+ });
627
+
628
+ const checks: Array<SecurityConnectorCheck> =
629
+ await harness.connector.testConnection(settings(), {
630
+ requestTimeoutInMs: 20000,
631
+ });
632
+
633
+ const availability: SecurityConnectorCheck = checkByKey(
634
+ checks,
635
+ "detections-available",
636
+ );
637
+ expect(availability.status).toBe("pass");
638
+ expect(availability.message).toBe(
639
+ "1 alert created in the last 24 hours and 10000+ in the last 7 days.",
640
+ );
641
+ expect(availability.details?.["hasMoreLast7d"]).toBe(true);
642
+ });
643
+
644
+ test("fails authentication on a redacted status document and skips the rest without another request", async () => {
645
+ const harness: Harness = buildHarness({
646
+ status: (): DataSourceHttpResponse => {
647
+ return ok({ status: { overall: { level: "degraded" } } });
648
+ },
649
+ });
650
+
651
+ const checks: Array<SecurityConnectorCheck> =
652
+ await harness.connector.testConnection(settings(), {
653
+ requestTimeoutInMs: 20000,
654
+ });
655
+
656
+ expect(
657
+ checks.map((check: SecurityConnectorCheck): string => {
658
+ return `${check.key}:${check.status}`;
659
+ }),
660
+ ).toEqual([
661
+ "authentication:fail",
662
+ "read-permission:skip",
663
+ "detections-available:skip",
664
+ ]);
665
+ expect(checkByKey(checks, "authentication").message).toContain(
666
+ "redacted to the overall level only (degraded)",
667
+ );
668
+ expect(checkByKey(checks, "authentication").remediation).toContain(
669
+ "anonymous access",
670
+ );
671
+ expect(harness.requests).toHaveLength(1);
672
+ });
673
+
674
+ test("fails authentication on a 401 with key remediation and never leaks the key", async () => {
675
+ const harness: Harness = buildHarness({
676
+ status: (): DataSourceHttpResponse => {
677
+ return status(
678
+ 401,
679
+ JSON.stringify({
680
+ statusCode: 401,
681
+ error: "Unauthorized",
682
+ message: `unable to authenticate; Authorization: ApiKey ${API_KEY}`,
683
+ api_key: API_KEY,
684
+ }),
685
+ );
686
+ },
687
+ });
688
+
689
+ const checks: Array<SecurityConnectorCheck> =
690
+ await harness.connector.testConnection(settings(), {
691
+ requestTimeoutInMs: 20000,
692
+ });
693
+
694
+ const auth: SecurityConnectorCheck = checkByKey(checks, "authentication");
695
+ expect(auth.status).toBe("fail");
696
+ expect(auth.message).toMatch(
697
+ /^Elastic Security status request failed \(HTTP 401\): /,
698
+ );
699
+ expect(auth.remediation).toContain("Create a new API key");
700
+ expect(checkByKey(checks, "read-permission").status).toBe("skip");
701
+ expect(checkByKey(checks, "detections-available").status).toBe("skip");
702
+ expectNoSecret(checks);
703
+ });
704
+
705
+ test("fails the read check on a 403 with privilege remediation and skips the count", async () => {
706
+ const harness: Harness = buildHarness({
707
+ search: [
708
+ (): DataSourceHttpResponse => {
709
+ return status(
710
+ 403,
711
+ JSON.stringify({
712
+ statusCode: 403,
713
+ error: "Forbidden",
714
+ message:
715
+ "action [indices:data/read/search] is unauthorized for API key",
716
+ }),
717
+ );
718
+ },
719
+ ],
720
+ });
721
+
722
+ const checks: Array<SecurityConnectorCheck> =
723
+ await harness.connector.testConnection(settings(), {
724
+ requestTimeoutInMs: 20000,
725
+ });
726
+
727
+ expect(checkByKey(checks, "authentication").status).toBe("pass");
728
+
729
+ const read: SecurityConnectorCheck = checkByKey(
730
+ checks,
731
+ "read-permission",
732
+ );
733
+ expect(read.status).toBe("fail");
734
+ expect(read.message).toMatch(
735
+ /^Elastic Security alerts search failed \(HTTP 403\): /,
736
+ );
737
+ expect(read.remediation).toContain(".alerts-security.alerts-<space-id>");
738
+ expect(checkByKey(checks, "detections-available").status).toBe("skip");
739
+ expect(harness.requests).toHaveLength(2);
740
+ });
741
+
742
+ test("fails the count check on a 429 after a successful read", async () => {
743
+ const harness: Harness = buildHarness({
744
+ search: [
745
+ (): DataSourceHttpResponse => {
746
+ return ok(searchBody([]));
747
+ },
748
+ (): DataSourceHttpResponse => {
749
+ return status(429, "Too Many Requests");
750
+ },
751
+ ],
752
+ });
753
+
754
+ const checks: Array<SecurityConnectorCheck> =
755
+ await harness.connector.testConnection(settings(), {
756
+ requestTimeoutInMs: 20000,
757
+ });
758
+
759
+ expect(checkByKey(checks, "read-permission").status).toBe("pass");
760
+
761
+ const availability: SecurityConnectorCheck = checkByKey(
762
+ checks,
763
+ "detections-available",
764
+ );
765
+ expect(availability.status).toBe("fail");
766
+ expect(availability.message).toMatch(
767
+ /^Elastic Security alerts search failed \(HTTP 429\): Too Many Requests/,
768
+ );
769
+ expect(availability.remediation).toContain("rate limiting");
770
+ });
771
+
772
+ test("explains a timeout on the status probe as a reachability problem", async () => {
773
+ const harness: Harness = buildHarness({
774
+ status: (): DataSourceHttpResponse => {
775
+ throw new BadDataException(
776
+ "Could not reach data source: timeout of 20000ms exceeded",
777
+ );
778
+ },
779
+ });
780
+
781
+ const checks: Array<SecurityConnectorCheck> =
782
+ await harness.connector.testConnection(settings(), {
783
+ requestTimeoutInMs: 20000,
784
+ });
785
+
786
+ const auth: SecurityConnectorCheck = checkByKey(checks, "authentication");
787
+ expect(auth.status).toBe("fail");
788
+ expect(auth.message).toBe(
789
+ "Elastic Security status request did not complete: Could not reach data source: timeout of 20000ms exceeded",
790
+ );
791
+ expect(auth.remediation).toContain("reachable from the OneUptime");
792
+ });
793
+
794
+ test("explains a 404 on the read as a wrong URL or space", async () => {
795
+ const harness: Harness = buildHarness({
796
+ search: [
797
+ (): DataSourceHttpResponse => {
798
+ return status(
799
+ 404,
800
+ JSON.stringify({ statusCode: 404, error: "Not Found" }),
801
+ );
802
+ },
803
+ ],
804
+ });
805
+
806
+ const checks: Array<SecurityConnectorCheck> =
807
+ await harness.connector.testConnection(settings(), {
808
+ requestTimeoutInMs: 20000,
809
+ });
810
+
811
+ expect(checkByKey(checks, "read-permission").remediation).toContain(
812
+ `Check the ${fieldTitle("kibanaUrl")} and ${fieldTitle("space")}`,
813
+ );
814
+ });
815
+
816
+ test("never contacts Kibana when the settings are invalid", async () => {
817
+ const harness: Harness = buildHarness({});
818
+
819
+ const checks: Array<SecurityConnectorCheck> =
820
+ await harness.connector.testConnection(
821
+ settings({ secrets: { apiKey: "" } }),
822
+ { requestTimeoutInMs: 20000 },
823
+ );
824
+
825
+ expect(
826
+ checks.map((check: SecurityConnectorCheck): string => {
827
+ return `${check.key}:${check.status}`;
828
+ }),
829
+ ).toEqual([
830
+ "authentication:fail",
831
+ "read-permission:skip",
832
+ "detections-available:skip",
833
+ ]);
834
+ expect(checkByKey(checks, "authentication").message).toBe(
835
+ `${fieldTitle("apiKey")} is required.`,
836
+ );
837
+ expect(harness.requests).toHaveLength(0);
838
+ });
839
+ });
840
+
841
+ describe("fetchEvents", () => {
842
+ test("reads one short page over the window, normalizes it and attributes it to the catalog's vendor and product", async () => {
843
+ const harness: Harness = buildHarness({
844
+ search: [
845
+ (): DataSourceHttpResponse => {
846
+ return ok(
847
+ searchBody([
848
+ alertHit("a1", "2026-09-12T10:05:03.412Z"),
849
+ alertHit("a2", "2026-09-12T11:00:00.000Z", {
850
+ "kibana.alert.severity": "low",
851
+ "kibana.alert.reason": "",
852
+ }),
853
+ ]),
854
+ );
855
+ },
856
+ ],
857
+ });
858
+
859
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
860
+ settings(),
861
+ { startTime: START, endTime: END },
862
+ fetchOptions({ sampleLimit: 1, requestTimeoutInMs: 60000 }),
863
+ );
864
+
865
+ expect(result.complete).toBe(true);
866
+ expect(result.resumeAfter).toBeUndefined();
867
+ expect(result.requestCount).toBe(1);
868
+ expect(result.fetchedCount).toBe(2);
869
+ expect(result.rejectedCount).toBe(0);
870
+ expect(result.failedCount).toBe(0);
871
+ expect(result.warnings).toEqual([]);
872
+ expect(result.events).toHaveLength(2);
873
+
874
+ const first: NormalizedSecurityEvent = result.events[0]!;
875
+ expect(first.eventUid).toBe("a1");
876
+ expect(first.vendorName).toBe(DEFINITION.vendorName);
877
+ expect(first.productName).toBe(DEFINITION.productName);
878
+ expect(first.classUid).toBe(2004);
879
+ expect(first.severityName).toBe("High");
880
+ expect(first.ruleName).toBe("Potential Privilege Escalation via PKEXEC");
881
+ expect(first.principalHost).toBe("web-01");
882
+ expect(first.mitreTechniques).toEqual(["T1068"]);
883
+ expect(first.time.toISOString()).toBe("2026-09-12T09:58:41.117Z");
884
+
885
+ expect(result.samples).toHaveLength(1);
886
+ const sample: SecurityConnectorSample = result.samples[0]!;
887
+ expect(sample).toEqual({
888
+ id: "a1",
889
+ title: "Potential Privilege Escalation via PKEXEC",
890
+ severity: "High",
891
+ createdTime: "2026-09-12T10:05:03.412Z",
892
+ eventTime: "2026-09-12T09:58:41.117Z",
893
+ });
894
+
895
+ const request: DataSourceHttpRequest = harness.requests[0]!;
896
+ expect(request.timeoutInMs).toBe(60000);
897
+ expect(new URL(request.url).pathname).toBe(
898
+ `/s/${SPACE}/api/detection_engine/signals/search`,
899
+ );
900
+ expect(rangeOf(request)).toEqual({
901
+ gte: START.toISOString(),
902
+ lt: END.toISOString(),
903
+ });
904
+ expect(parseBody(request)["size"]).toBe(ELASTIC_SECURITY_MAX_PAGE_SIZE);
905
+ expect(parseBody(request)["sort"]).toEqual([{ "@timestamp": "asc" }]);
906
+ });
907
+
908
+ test("pages by advancing the lower bound to the last hit's @timestamp, excludes the alert read there, and reports where to resume", async () => {
909
+ const harness: Harness = buildHarness({
910
+ search: [
911
+ (): DataSourceHttpResponse => {
912
+ return ok(
913
+ searchBody([
914
+ alertHit("a1", "2026-09-12T10:05:03.412Z"),
915
+ alertHit("a2", "2026-09-12T11:00:00.000Z"),
916
+ ]),
917
+ );
918
+ },
919
+ (): DataSourceHttpResponse => {
920
+ return ok(
921
+ searchBody([
922
+ alertHit("a2", "2026-09-12T11:00:00.000Z"),
923
+ alertHit("a3", "2026-09-12T12:00:00.000Z"),
924
+ ]),
925
+ );
926
+ },
927
+ (): DataSourceHttpResponse => {
928
+ return ok(searchBody([alertHit("a3", "2026-09-12T12:00:00.000Z")]));
929
+ },
930
+ ],
931
+ });
932
+
933
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
934
+ settings(),
935
+ { startTime: START, endTime: END },
936
+ fetchOptions({ maxEvents: 2 }),
937
+ );
938
+
939
+ expect(result.complete).toBe(false);
940
+ expect(result.fetchedCount).toBe(2);
941
+ expect(eventUids(result)).toEqual(["a1", "a2"]);
942
+ expect(result.requestCount).toBe(2);
943
+ /*
944
+ * Review finding bound-hit-window-never-advances: the warning used to
945
+ * say the cursor is held, and the poller re-read the same alerts
946
+ * forever. The fetch now reports the last alert read as the resume
947
+ * point.
948
+ */
949
+ expect(result.resumeAfter?.toISOString()).toBe(
950
+ "2026-09-12T11:00:00.000Z",
951
+ );
952
+ expect(result.warnings).toEqual([
953
+ "Stopped after collecting 2 alerts; the window holds more.",
954
+ ]);
955
+
956
+ expect(parseBody(harness.requests[0]!)["size"]).toBe(2);
957
+ expect(excludedIdsOf(harness.requests[0]!)).toEqual([]);
958
+ expect(rangeOf(harness.requests[1]!)).toEqual({
959
+ gte: "2026-09-12T11:00:00.000Z",
960
+ lt: END.toISOString(),
961
+ });
962
+ expect(excludedIdsOf(harness.requests[1]!)).toEqual(["a2"]);
963
+ });
964
+
965
+ test("reads a full page, then the rest from the last timestamp, and finishes complete on the short page", async () => {
966
+ const firstPage: Array<JSONObject> = fullPage(0);
967
+ const lastOfFirstPage: JSONObject = firstPage[firstPage.length - 1]!;
968
+ const lastTimestamp: string = String(
969
+ (lastOfFirstPage["_source"] as JSONObject)["@timestamp"],
970
+ );
971
+ const harness: Harness = buildHarness({
972
+ search: [
973
+ (): DataSourceHttpResponse => {
974
+ return ok(searchBody(firstPage));
975
+ },
976
+ (): DataSourceHttpResponse => {
977
+ return ok(
978
+ searchBody([
979
+ lastOfFirstPage,
980
+ alertHit("tail", "2026-09-12T20:00:00.000Z"),
981
+ ]),
982
+ );
983
+ },
984
+ ],
985
+ });
986
+
987
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
988
+ settings(),
989
+ { startTime: START, endTime: END },
990
+ fetchOptions(),
991
+ );
992
+
993
+ expect(result.complete).toBe(true);
994
+ expect(result.resumeAfter).toBeUndefined();
995
+ expect(result.warnings).toEqual([]);
996
+ expect(result.requestCount).toBe(2);
997
+ expect(result.fetchedCount).toBe(ELASTIC_SECURITY_MAX_PAGE_SIZE + 1);
998
+ expect(result.events).toHaveLength(ELASTIC_SECURITY_MAX_PAGE_SIZE + 1);
999
+ expect(result.events[result.events.length - 1]!.eventUid).toBe("tail");
1000
+ expect(result.samples).toHaveLength(25);
1001
+
1002
+ expect(parseBody(harness.requests[0]!)["size"]).toBe(
1003
+ ELASTIC_SECURITY_MAX_PAGE_SIZE,
1004
+ );
1005
+ expect(rangeOf(harness.requests[0]!)).toEqual({
1006
+ gte: START.toISOString(),
1007
+ lt: END.toISOString(),
1008
+ });
1009
+ expect(rangeOf(harness.requests[1]!)).toEqual({
1010
+ gte: lastTimestamp,
1011
+ lt: END.toISOString(),
1012
+ });
1013
+ expect(excludedIdsOf(harness.requests[1]!)).toEqual([
1014
+ String(lastOfFirstPage["_id"]),
1015
+ ]);
1016
+ });
1017
+
1018
+ test("stops at the request bound and reports the window as incomplete", async () => {
1019
+ const harness: Harness = buildHarness({
1020
+ search: [
1021
+ (): DataSourceHttpResponse => {
1022
+ return ok(
1023
+ searchBody([
1024
+ alertHit("a1", "2026-09-12T10:05:03.412Z"),
1025
+ alertHit("a2", "2026-09-12T11:00:00.000Z"),
1026
+ ]),
1027
+ );
1028
+ },
1029
+ ],
1030
+ });
1031
+
1032
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
1033
+ settings(),
1034
+ { startTime: START, endTime: END },
1035
+ fetchOptions({ maxEvents: 2, maxRequests: 1 }),
1036
+ );
1037
+
1038
+ expect(result.complete).toBe(false);
1039
+ expect(result.requestCount).toBe(1);
1040
+ expect(result.fetchedCount).toBe(2);
1041
+ expect(result.events).toHaveLength(2);
1042
+ expect(result.resumeAfter?.toISOString()).toBe(
1043
+ "2026-09-12T11:00:00.000Z",
1044
+ );
1045
+ expect(result.warnings).toEqual([
1046
+ "Stopped after 1 requests with alerts still unread from 2026-09-12T11:00:00.000Z.",
1047
+ ]);
1048
+ expect(harness.requests).toHaveLength(1);
1049
+ });
1050
+
1051
+ /*
1052
+ * Review finding bound-hit-window-never-advances: this test used to
1053
+ * assert that a full page sharing one creation time ends the fetch as
1054
+ * incomplete. Nothing could ever read past it, so the poller stayed on
1055
+ * that window (and a rule execution that wrote exactly a page of
1056
+ * alerts was reported Partial with everything read). The next request
1057
+ * now excludes the ids already read at that instant.
1058
+ */
1059
+ test("pages past a full page sharing one creation time by excluding the alerts already read there", async () => {
1060
+ const harness: Harness = buildHarness({
1061
+ search: [
1062
+ (): DataSourceHttpResponse => {
1063
+ return ok(
1064
+ searchBody([
1065
+ alertHit("a1", "2026-09-12T10:05:03.412Z"),
1066
+ alertHit("a2", "2026-09-12T10:05:03.412Z"),
1067
+ ]),
1068
+ );
1069
+ },
1070
+ (): DataSourceHttpResponse => {
1071
+ return ok(searchBody([]));
1072
+ },
1073
+ ],
1074
+ });
1075
+
1076
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
1077
+ settings(),
1078
+ { startTime: START, endTime: END },
1079
+ fetchOptions({ maxEvents: 2 }),
1080
+ );
1081
+
1082
+ expect(result.complete).toBe(true);
1083
+ expect(result.resumeAfter).toBeUndefined();
1084
+ expect(result.warnings).toEqual([]);
1085
+ expect(result.requestCount).toBe(2);
1086
+ expect(eventUids(result)).toEqual(["a1", "a2"]);
1087
+ expect(rangeOf(harness.requests[1]!)).toEqual({
1088
+ gte: "2026-09-12T10:05:03.412Z",
1089
+ lt: END.toISOString(),
1090
+ });
1091
+ expect(excludedIdsOf(harness.requests[1]!)).toEqual(["a1", "a2"]);
1092
+ });
1093
+
1094
+ test("reads more than one page of alerts sharing one @timestamp without skipping or re-reading any", async () => {
1095
+ const tie: string = "2026-09-12T12:00:00.000Z";
1096
+ const alerts: Array<FakeAlert> = [
1097
+ ...alertsAt("before", 10, (index: number): string => {
1098
+ return new Date(START.getTime() + (index + 1) * 1000).toISOString();
1099
+ }),
1100
+ ...alertsAt("tie", 2500, (): string => {
1101
+ return tie;
1102
+ }),
1103
+ ...alertsAt("after", 10, (index: number): string => {
1104
+ return new Date(Date.parse(tie) + (index + 1) * 1000).toISOString();
1105
+ }),
1106
+ ];
1107
+ const harness: Harness = buildHarness({ kibana: fakeKibana(alerts) });
1108
+
1109
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
1110
+ settings(),
1111
+ { startTime: START, endTime: END },
1112
+ fetchOptions(),
1113
+ );
1114
+
1115
+ expect(result.complete).toBe(true);
1116
+ expect(result.resumeAfter).toBeUndefined();
1117
+ expect(result.warnings).toEqual([]);
1118
+ expect(result.fetchedCount).toBe(alerts.length);
1119
+
1120
+ const uids: Array<string> = eventUids(result);
1121
+ expect(new Set<string>(uids).size).toBe(alerts.length);
1122
+ expect(uids.slice(-10)).toEqual(
1123
+ alertsAt("after", 10, (): string => {
1124
+ return "";
1125
+ }).map((alert: FakeAlert): string => {
1126
+ return alert.id;
1127
+ }),
1128
+ );
1129
+
1130
+ /*
1131
+ * Page 1: 10 older alerts and 990 at the tie. Page 2: 1,000 more at
1132
+ * the tie, excluding the 990. Page 3: the last 510 at the tie and the
1133
+ * 10 newer alerts, excluding all 1,990 read at the tie.
1134
+ */
1135
+ expect(result.requestCount).toBe(3);
1136
+ expect(
1137
+ harness.requests.map((request: DataSourceHttpRequest): number => {
1138
+ return excludedIdsOf(request).length;
1139
+ }),
1140
+ ).toEqual([0, 990, 1990]);
1141
+ expect(rangeOf(harness.requests[1]!).gte).toBe(tie);
1142
+ expect(rangeOf(harness.requests[2]!).gte).toBe(tie);
1143
+ });
1144
+
1145
+ test("finishes complete when exactly one page of alerts shares a timestamp", async () => {
1146
+ const tie: string = "2026-09-12T12:00:00.000Z";
1147
+ const alerts: Array<FakeAlert> = alertsAt(
1148
+ "tie",
1149
+ ELASTIC_SECURITY_MAX_PAGE_SIZE,
1150
+ (): string => {
1151
+ return tie;
1152
+ },
1153
+ );
1154
+ const harness: Harness = buildHarness({ kibana: fakeKibana(alerts) });
1155
+
1156
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
1157
+ settings(),
1158
+ { startTime: START, endTime: END },
1159
+ fetchOptions(),
1160
+ );
1161
+
1162
+ expect(result.complete).toBe(true);
1163
+ expect(result.resumeAfter).toBeUndefined();
1164
+ expect(result.fetchedCount).toBe(ELASTIC_SECURITY_MAX_PAGE_SIZE);
1165
+ expect(result.requestCount).toBe(2);
1166
+ });
1167
+
1168
+ test("resumes from resumeAfter across fetches, the way the poller does, until every alert is read", async () => {
1169
+ const firstTie: string = "2026-09-12T12:00:00.000Z";
1170
+ const secondTie: string = "2026-09-12T15:00:00.000Z";
1171
+ const alerts: Array<FakeAlert> = [
1172
+ ...alertsAt("early", 300, (index: number): string => {
1173
+ return new Date(START.getTime() + (index + 10) * 1000).toISOString();
1174
+ }),
1175
+ ...alertsAt("first-tie", 1500, (): string => {
1176
+ return firstTie;
1177
+ }),
1178
+ ...alertsAt("middle", 700, (index: number): string => {
1179
+ return new Date(
1180
+ Date.parse(firstTie) + (index + 1) * 1000,
1181
+ ).toISOString();
1182
+ }),
1183
+ ...alertsAt("second-tie", 1200, (): string => {
1184
+ return secondTie;
1185
+ }),
1186
+ ...alertsAt("late", 100, (index: number): string => {
1187
+ return new Date(
1188
+ Date.parse(secondTie) + (index + 1) * 1000,
1189
+ ).toISOString();
1190
+ }),
1191
+ ];
1192
+ const harness: Harness = buildHarness({ kibana: fakeKibana(alerts) });
1193
+ const overlapInMs: number = 60 * 1000;
1194
+ const imported: Set<string> = new Set<string>();
1195
+ let startTime: Date = START;
1196
+ let polls: number = 0;
1197
+ let complete: boolean = false;
1198
+
1199
+ while (!complete && polls < 10) {
1200
+ polls += 1;
1201
+
1202
+ const result: ConnectorFetchResult =
1203
+ await harness.connector.fetchEvents(
1204
+ settings(),
1205
+ { startTime, endTime: END },
1206
+ fetchOptions({ maxEvents: 2000 }),
1207
+ );
1208
+
1209
+ for (const uid of eventUids(result)) {
1210
+ imported.add(uid);
1211
+ }
1212
+
1213
+ complete = result.complete;
1214
+
1215
+ if (!complete) {
1216
+ // The poller only moves on when the resume point is past the overlap.
1217
+ expect(result.resumeAfter).toBeDefined();
1218
+ expect(result.resumeAfter!.getTime()).toBeGreaterThan(
1219
+ startTime.getTime() + overlapInMs,
1220
+ );
1221
+ startTime = new Date(result.resumeAfter!.getTime() - overlapInMs);
1222
+ }
1223
+ }
1224
+
1225
+ expect(complete).toBe(true);
1226
+ expect(polls).toBe(2);
1227
+ expect(imported.size).toBe(alerts.length);
1228
+ });
1229
+
1230
+ test("stops as incomplete when the alerts sharing one timestamp are too many to exclude in one request", async () => {
1231
+ const tie: string = "2026-09-12T12:00:00.000Z";
1232
+ const padding: string = "x".repeat(600);
1233
+ const alerts: Array<FakeAlert> = alertsAt(
1234
+ `${padding}-tie`,
1235
+ ELASTIC_SECURITY_MAX_PAGE_SIZE + 100,
1236
+ (): string => {
1237
+ return tie;
1238
+ },
1239
+ );
1240
+ expect(
1241
+ Buffer.byteLength(
1242
+ JSON.stringify(
1243
+ alerts
1244
+ .slice(0, ELASTIC_SECURITY_MAX_PAGE_SIZE)
1245
+ .map((alert: FakeAlert): string => {
1246
+ return alert.id;
1247
+ }),
1248
+ ),
1249
+ ),
1250
+ ).toBeGreaterThan(ELASTIC_SECURITY_MAX_EXCLUDED_ID_BYTES);
1251
+ const harness: Harness = buildHarness({ kibana: fakeKibana(alerts) });
1252
+
1253
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
1254
+ settings(),
1255
+ { startTime: START, endTime: END },
1256
+ fetchOptions(),
1257
+ );
1258
+
1259
+ expect(result.complete).toBe(false);
1260
+ expect(result.requestCount).toBe(1);
1261
+ expect(result.fetchedCount).toBe(ELASTIC_SECURITY_MAX_PAGE_SIZE);
1262
+ expect(result.resumeAfter?.toISOString()).toBe(tie);
1263
+ expect(result.warnings).toEqual([
1264
+ `${ELASTIC_SECURITY_MAX_PAGE_SIZE} alerts read so far share the creation time ${tie}, more than one search request can exclude, so the rest of the alerts created at that instant were not read.`,
1265
+ ]);
1266
+ });
1267
+
1268
+ test("stops when a full page carries only already-read alerts instead of looping", async () => {
1269
+ const page: Array<JSONObject> = fullPage(0);
1270
+ const harness: Harness = buildHarness({
1271
+ search: [
1272
+ (): DataSourceHttpResponse => {
1273
+ return ok(searchBody(page));
1274
+ },
1275
+ (): DataSourceHttpResponse => {
1276
+ return ok(searchBody(page));
1277
+ },
1278
+ ],
1279
+ });
1280
+
1281
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
1282
+ settings(),
1283
+ { startTime: START, endTime: END },
1284
+ fetchOptions(),
1285
+ );
1286
+
1287
+ const lastTimestamp: string = new Date(
1288
+ START.getTime() + (ELASTIC_SECURITY_MAX_PAGE_SIZE - 1) * 1000,
1289
+ ).toISOString();
1290
+
1291
+ expect(result.complete).toBe(false);
1292
+ expect(result.requestCount).toBe(2);
1293
+ expect(result.fetchedCount).toBe(ELASTIC_SECURITY_MAX_PAGE_SIZE);
1294
+ expect(result.resumeAfter?.toISOString()).toBe(lastTimestamp);
1295
+ expect(result.warnings).toEqual([
1296
+ `A full page of alerts from ${lastTimestamp} contained only alerts already read, so the window cannot be paged further.`,
1297
+ ]);
1298
+ expect(harness.requests).toHaveLength(2);
1299
+ // The scripted source ignored this exclusion; the id memory still held.
1300
+ expect(excludedIdsOf(harness.requests[1]!)).toEqual([
1301
+ `alert-${ELASTIC_SECURITY_MAX_PAGE_SIZE - 1}`,
1302
+ ]);
1303
+ });
1304
+
1305
+ test("counts documents the normalizer does not recognize as rejected and keeps going", async () => {
1306
+ const harness: Harness = buildHarness({
1307
+ search: [
1308
+ (): DataSourceHttpResponse => {
1309
+ return ok(
1310
+ searchBody([
1311
+ alertHit("a1", "2026-09-12T10:05:03.412Z"),
1312
+ {
1313
+ _index: "logs-000001",
1314
+ _id: "not-an-alert",
1315
+ _source: {
1316
+ "@timestamp": "2026-09-12T10:06:00.000Z",
1317
+ message: "hi",
1318
+ },
1319
+ },
1320
+ ]),
1321
+ );
1322
+ },
1323
+ ],
1324
+ });
1325
+
1326
+ const result: ConnectorFetchResult = await harness.connector.fetchEvents(
1327
+ settings(),
1328
+ { startTime: START, endTime: END },
1329
+ fetchOptions(),
1330
+ );
1331
+
1332
+ expect(result.complete).toBe(true);
1333
+ expect(result.fetchedCount).toBe(2);
1334
+ expect(result.rejectedCount).toBe(1);
1335
+ expect(result.failedCount).toBe(0);
1336
+ expect(result.events).toHaveLength(1);
1337
+ });
1338
+
1339
+ test("throws on an authentication failure so the poller records a failed run, without the key", async () => {
1340
+ const harness: Harness = buildHarness({
1341
+ search: [
1342
+ (): DataSourceHttpResponse => {
1343
+ return status(
1344
+ 401,
1345
+ JSON.stringify({
1346
+ statusCode: 401,
1347
+ error: "Unauthorized",
1348
+ message: `Authorization: ApiKey ${API_KEY}`,
1349
+ }),
1350
+ );
1351
+ },
1352
+ ],
1353
+ });
1354
+
1355
+ let thrown: Error | null = null;
1356
+
1357
+ try {
1358
+ await harness.connector.fetchEvents(
1359
+ settings(),
1360
+ { startTime: START, endTime: END },
1361
+ fetchOptions(),
1362
+ );
1363
+ } catch (error) {
1364
+ thrown = error as Error;
1365
+ }
1366
+
1367
+ expect(thrown).not.toBeNull();
1368
+ expect(thrown!.message).toMatch(
1369
+ /^Elastic Security alerts search failed \(HTTP 401\): /,
1370
+ );
1371
+ expect(thrown!.message).not.toContain(API_KEY);
1372
+ });
1373
+
1374
+ test("throws on a timeout so the cursor is held", async () => {
1375
+ const harness: Harness = buildHarness({
1376
+ search: [
1377
+ (): DataSourceHttpResponse => {
1378
+ throw new BadDataException(
1379
+ "Could not reach data source: timeout of 60000ms exceeded",
1380
+ );
1381
+ },
1382
+ ],
1383
+ });
1384
+
1385
+ await expect(
1386
+ harness.connector.fetchEvents(
1387
+ settings(),
1388
+ { startTime: START, endTime: END },
1389
+ fetchOptions(),
1390
+ ),
1391
+ ).rejects.toThrow(
1392
+ "Elastic Security alerts search did not complete: Could not reach data source: timeout of 60000ms exceeded",
1393
+ );
1394
+ });
1395
+
1396
+ test("rejects invalid settings before contacting Kibana", async () => {
1397
+ const harness: Harness = buildHarness({});
1398
+
1399
+ await expect(
1400
+ harness.connector.fetchEvents(
1401
+ settings({ config: { kibanaUrl: "not a url" } }),
1402
+ { startTime: START, endTime: END },
1403
+ fetchOptions(),
1404
+ ),
1405
+ ).rejects.toThrow(BadDataException);
1406
+ expect(harness.requests).toHaveLength(0);
1407
+ });
1408
+ });
1409
+ });