@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,905 @@
1
+ import "@testing-library/jest-dom";
2
+ import {
3
+ afterEach,
4
+ beforeEach,
5
+ describe,
6
+ expect,
7
+ jest,
8
+ test,
9
+ } from "@jest/globals";
10
+ import {
11
+ act,
12
+ cleanup,
13
+ fireEvent,
14
+ render,
15
+ screen,
16
+ waitFor,
17
+ within,
18
+ } from "@testing-library/react";
19
+ import React, { ReactElement } from "react";
20
+ import { MemoryRouter } from "react-router-dom";
21
+ import SecurityEventConnectionRunDetails from "../../../../App/FeatureSet/Dashboard/src/Components/SecurityEvents/SecurityEventConnectionRunDetails";
22
+ import SecurityEventConnectionsTable from "../../../../App/FeatureSet/Dashboard/src/Components/SecurityEvents/SecurityEventConnectionsTable";
23
+ import {
24
+ CONNECTOR_HEALTH_NO_EVENTS_YET,
25
+ CONNECTOR_HEALTH_SUCCEEDED,
26
+ connectorHealth,
27
+ } from "../../../../App/FeatureSet/Dashboard/src/Components/SecurityEvents/SecurityEventConnectionDiagnosticsUtil";
28
+ import {
29
+ googleSecOpsHealth,
30
+ googleSecOpsTestBody,
31
+ GOOGLE_SECOPS_TEST_NEEDS_KEY_MESSAGE,
32
+ } from "../../../../App/FeatureSet/Dashboard/src/Components/SecurityEvents/GoogleSecOpsDiagnosticsUtil";
33
+ import GoogleSecOpsConnectionsPage from "../../../../App/FeatureSet/Dashboard/src/Pages/SecurityEvents/GoogleSecOpsConnections";
34
+ import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
35
+ import GoogleSecOpsConnection from "../../../Models/DatabaseModels/GoogleSecOpsConnection";
36
+ import Project from "../../../Models/DatabaseModels/Project";
37
+ import SecurityEventConnection from "../../../Models/DatabaseModels/SecurityEventConnection";
38
+ import SecurityEventConnectionRun from "../../../Models/DatabaseModels/SecurityEventConnectionRun";
39
+ import HTTPErrorResponse from "../../../Types/API/HTTPErrorResponse";
40
+ import HTTPResponse from "../../../Types/API/HTTPResponse";
41
+ import Route from "../../../Types/API/Route";
42
+ import { JSONObject } from "../../../Types/JSON";
43
+ import ObjectID from "../../../Types/ObjectID";
44
+ import { SecurityConnectorTestReport } from "../../../Types/SecurityEvent/Connectors/ConnectorDiagnostics";
45
+ import { SecurityEventConnectionRunResult } from "../../../Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics";
46
+ import SecurityEventConnectorProvider from "../../../Types/SecurityEvent/Connectors/SecurityEventConnectorProvider";
47
+ import { GoogleSecOpsRunResult } from "../../../Types/SecurityEvent/GoogleSecOpsDiagnostics";
48
+ import { CardButtonSchema } from "../../../UI/Components/Card/Card";
49
+ import ModelColumn from "../../../UI/Components/ModelTable/Column";
50
+ import { ComponentProps as ModelTableProps } from "../../../UI/Components/ModelTable/ModelTable";
51
+ import TableRow from "../../../UI/Components/Table/TableRow";
52
+ import TableColumn from "../../../UI/Components/Table/Types/Column";
53
+ import FieldType from "../../../UI/Components/Types/FieldType";
54
+ import API from "../../../UI/Utils/API/API";
55
+ import ModelAPI from "../../../UI/Utils/ModelAPI/ModelAPI";
56
+ import PermissionGate from "../../../UI/Utils/PermissionGate";
57
+ import ProjectUtil from "../../../UI/Utils/Project";
58
+
59
+ /*
60
+ * Replace only ModelTable's data-loading boundary, the way
61
+ * GoogleSecOpsConnectionsErrors.test.tsx does: the real TableRow decides
62
+ * action visibility and dispatches the selected row, and every modal the
63
+ * table opens stays real. Rows are keyed by model so the Google SecOps
64
+ * page, which renders both tables, gets each of its rows in the right one.
65
+ */
66
+ const mockRows: Map<string, Array<BaseModel>> = new Map();
67
+ const mockTableProps: Map<string, ModelTableProps<BaseModel>> = new Map();
68
+
69
+ jest.mock("../../../UI/Components/ModelTable/ModelTable", () => {
70
+ return {
71
+ __esModule: true,
72
+ default: (props: ModelTableProps<BaseModel>): ReactElement => {
73
+ const tableName: string = new props.modelType().tableName || "";
74
+ mockTableProps.set(tableName, props);
75
+ const columns: Array<TableColumn<BaseModel>> = [
76
+ ...props.columns.map(
77
+ (column: ModelColumn<BaseModel>): TableColumn<BaseModel> => {
78
+ return {
79
+ title: column.title,
80
+ type: column.type,
81
+ key: Object.keys(column.field)[0] as keyof BaseModel,
82
+ getElement: column.getElement,
83
+ noValueMessage: column.noValueMessage,
84
+ };
85
+ },
86
+ ),
87
+ { title: "Actions", type: FieldType.Actions },
88
+ ];
89
+
90
+ return (
91
+ <table aria-label={props.cardProps?.title as string}>
92
+ <thead>
93
+ <tr>
94
+ {columns.map((column: TableColumn<BaseModel>): ReactElement => {
95
+ return <th key={column.title}>{column.title}</th>;
96
+ })}
97
+ </tr>
98
+ </thead>
99
+ {(mockRows.get(tableName) || []).map(
100
+ (row: BaseModel): ReactElement => {
101
+ return (
102
+ <tbody
103
+ key={row._id}
104
+ data-testid={(row as unknown as { name: string }).name}
105
+ >
106
+ <TableRow
107
+ item={row}
108
+ columns={columns}
109
+ actionButtons={props.actionButtons}
110
+ isMobile={false}
111
+ />
112
+ </tbody>
113
+ );
114
+ },
115
+ )}
116
+ </table>
117
+ );
118
+ },
119
+ };
120
+ });
121
+
122
+ const PROJECT_ID: ObjectID = new ObjectID(
123
+ "11111111-1111-4111-8111-111111111111",
124
+ );
125
+ const CONNECTION_ID: string = "22222222-2222-4222-8222-222222222222";
126
+ const GOOGLE_ID: string = "33333333-3333-4333-8333-333333333333";
127
+ const NOW: number = new Date("2026-09-10T12:00:00Z").getTime();
128
+
129
+ function pollResult(
130
+ overrides: Partial<SecurityEventConnectionRunResult> = {},
131
+ ): SecurityEventConnectionRunResult {
132
+ return {
133
+ type: "poll",
134
+ provider: "okta",
135
+ status: "success",
136
+ startedAt: "2026-09-10T11:59:00Z",
137
+ completedAt: "2026-09-10T11:59:02Z",
138
+ durationMs: 2000,
139
+ windowStart: "2026-09-10T11:53:00Z",
140
+ windowEnd: "2026-09-10T11:59:00Z",
141
+ fetchedCount: 0,
142
+ ingestedCount: 0,
143
+ duplicateCount: 0,
144
+ rejectedCount: 0,
145
+ failedCount: 0,
146
+ complete: true,
147
+ requestCount: 1,
148
+ warnings: [],
149
+ samples: [],
150
+ checks: [],
151
+ ...overrides,
152
+ };
153
+ }
154
+
155
+ /*
156
+ * Unlike Partial<>, an override may set a field to undefined, which is how a
157
+ * test describes a connection that was never polled.
158
+ */
159
+ type SecurityEventConnectionOverrides = {
160
+ [Key in keyof SecurityEventConnection]?:
161
+ | SecurityEventConnection[Key]
162
+ | undefined;
163
+ };
164
+
165
+ function connection(
166
+ overrides: SecurityEventConnectionOverrides = {},
167
+ ): SecurityEventConnection {
168
+ const value: SecurityEventConnection = new SecurityEventConnection();
169
+ value._id = CONNECTION_ID;
170
+ value.projectId = PROJECT_ID;
171
+ value.name = "Acme Okta";
172
+ value.provider = SecurityEventConnectorProvider.OktaSystemLog;
173
+ value.config = { orgUrl: "https://acme.okta.com" };
174
+ value.isEnabled = true;
175
+ value.pollIntervalInMinutes = 5;
176
+ value.alertingOnly = true;
177
+ value.createdAt = new Date(NOW - 60 * 60_000);
178
+ value.lastPolledAt = new Date(NOW - 60_000);
179
+ value.lastSuccessfulPollAt = new Date(NOW - 60_000);
180
+ value.lastPollResult = pollResult() as unknown as JSONObject;
181
+ Object.assign(value, overrides);
182
+ return value;
183
+ }
184
+
185
+ function report(provider: string): SecurityConnectorTestReport {
186
+ return {
187
+ provider,
188
+ status: "warn",
189
+ startedAt: "2026-09-10T12:00:00.000Z",
190
+ completedAt: "2026-09-10T12:00:01.000Z",
191
+ durationMs: 1000,
192
+ summary: "Access works; nothing was created in the last 7 days.",
193
+ checks: [
194
+ {
195
+ key: "authentication",
196
+ name: "Authenticate",
197
+ status: "pass",
198
+ durationMs: 200,
199
+ message: "Accepted.",
200
+ },
201
+ {
202
+ key: "detections-available",
203
+ name: "Records available to import",
204
+ status: "warn",
205
+ durationMs: 300,
206
+ message: "No records were created in the last 7 days.",
207
+ remediation: "Polling will import new records as they are created.",
208
+ },
209
+ ],
210
+ };
211
+ }
212
+
213
+ function renderTable(rows: Array<SecurityEventConnection>): void {
214
+ mockRows.set("SecurityEventConnection", rows);
215
+ render(
216
+ <MemoryRouter>
217
+ <SecurityEventConnectionsTable />
218
+ </MemoryRouter>,
219
+ );
220
+ }
221
+
222
+ function row(name: string = "Acme Okta"): HTMLElement {
223
+ return screen.getByTestId(name);
224
+ }
225
+
226
+ function postCall(index: number = 0): JSONObject {
227
+ return jest.mocked(API.post).mock.calls[index]?.[0] as unknown as JSONObject;
228
+ }
229
+
230
+ describe("SecurityEventConnectionsTable", () => {
231
+ beforeEach((): void => {
232
+ /*
233
+ * Health is judged against the clock, so pin it next to the fixtures'
234
+ * timestamps the way GoogleSecOpsDiagnostics.test.tsx does.
235
+ */
236
+ jest.useFakeTimers();
237
+ jest.setSystemTime(NOW);
238
+ mockRows.clear();
239
+ mockTableProps.clear();
240
+ jest.spyOn(ProjectUtil, "getCurrentProjectId").mockReturnValue(PROJECT_ID);
241
+ jest.spyOn(PermissionGate, "check").mockReturnValue({ isAllowed: true });
242
+ jest
243
+ .spyOn(ModelAPI, "getCommonHeaders")
244
+ .mockReturnValue({ "project-id": PROJECT_ID.toString() });
245
+ jest
246
+ .spyOn(ModelAPI, "getList")
247
+ .mockResolvedValue({ data: [], count: 0, skip: 0, limit: 20 });
248
+ jest.spyOn(ModelAPI, "getItem").mockResolvedValue(connection());
249
+ jest
250
+ .spyOn(API, "post")
251
+ .mockResolvedValue(
252
+ new HTTPResponse(200, report("okta") as unknown as JSONObject, {}),
253
+ );
254
+ });
255
+
256
+ afterEach((): void => {
257
+ cleanup();
258
+ jest.clearAllTimers();
259
+ jest.useRealTimers();
260
+ jest.restoreAllMocks();
261
+ });
262
+
263
+ test("declares the generic table without ModelTable's own create form and with an Add connection header button", (): void => {
264
+ renderTable([]);
265
+
266
+ const props: ModelTableProps<BaseModel> = mockTableProps.get(
267
+ "SecurityEventConnection",
268
+ ) as ModelTableProps<BaseModel>;
269
+ expect(props.isCreateable).toBe(false);
270
+ expect(props.isEditable).toBe(false);
271
+ expect(props.formFields).toBeUndefined();
272
+ expect(props.selectMoreFields).toEqual(
273
+ expect.objectContaining({
274
+ lastError: true,
275
+ provider: true,
276
+ config: true,
277
+ lastEventIngestedAt: true,
278
+ }),
279
+ );
280
+ expect(props.selectMoreFields).not.toHaveProperty("secrets");
281
+ expect(props.query).toEqual({ projectId: PROJECT_ID });
282
+
283
+ const button: CardButtonSchema = props.cardProps
284
+ ?.buttons?.[0] as CardButtonSchema;
285
+ expect(button.title).toBe("Add connection");
286
+ expect(button.disabled).toBe(false);
287
+ expect(
288
+ props.columns.map((column: ModelColumn<BaseModel>): string => {
289
+ return column.title;
290
+ }),
291
+ ).toEqual([
292
+ "Name",
293
+ "Provider",
294
+ "Status",
295
+ "Health",
296
+ "Interval (Minutes)",
297
+ "Last Polled",
298
+ "Last Successful Poll",
299
+ "Last Event Imported",
300
+ ]);
301
+ });
302
+
303
+ test("the empty state explains prerequisites and links every provider's setup guide", (): void => {
304
+ renderTable([]);
305
+
306
+ const props: ModelTableProps<BaseModel> = mockTableProps.get(
307
+ "SecurityEventConnection",
308
+ ) as ModelTableProps<BaseModel>;
309
+ render(<MemoryRouter>{props.noItemsMessage as ReactElement}</MemoryRouter>);
310
+
311
+ expect(screen.getByText(/read-only credential/)).toBeVisible();
312
+ expect(screen.getByText(/running OneUptime worker/)).toBeVisible();
313
+ const links: Array<HTMLElement> = screen.getAllByRole("link");
314
+ expect(
315
+ links.map((link: HTMLElement): string => {
316
+ return link.textContent || "";
317
+ }),
318
+ ).toEqual([
319
+ "Microsoft Sentinel",
320
+ "Microsoft Defender XDR",
321
+ "CrowdStrike Falcon",
322
+ "Splunk Enterprise Security",
323
+ "Elastic Security",
324
+ "AWS Security Hub",
325
+ "Okta System Log",
326
+ ]);
327
+ for (const link of links) {
328
+ expect(link).toHaveAttribute("target", "_blank");
329
+ expect(link.getAttribute("href")).toMatch(
330
+ /\/docs\/integrations\/[a-z-]+$/,
331
+ );
332
+ }
333
+ });
334
+
335
+ test("shows the catalog title, status and the honest health vocabulary per row", (): void => {
336
+ const imported: SecurityEventConnection = connection({
337
+ _id: "44444444-4444-4444-8444-444444444444",
338
+ name: "Imported Sentinel",
339
+ provider: SecurityEventConnectorProvider.MicrosoftSentinel,
340
+ lastEventIngestedAt: new Date(NOW - 30_000),
341
+ });
342
+ const paused: SecurityEventConnection = connection({
343
+ _id: "55555555-5555-4555-8555-555555555555",
344
+ name: "Paused Splunk",
345
+ provider: SecurityEventConnectorProvider.SplunkEnterpriseSecurity,
346
+ isEnabled: false,
347
+ });
348
+ renderTable([connection(), imported, paused]);
349
+
350
+ expect(row("Acme Okta")).toHaveTextContent("Okta System Log");
351
+ expect(row("Acme Okta")).toHaveTextContent("Enabled");
352
+ expect(row("Acme Okta")).toHaveTextContent(CONNECTOR_HEALTH_NO_EVENTS_YET);
353
+ expect(row("Acme Okta")).not.toHaveTextContent(CONNECTOR_HEALTH_SUCCEEDED);
354
+
355
+ expect(row("Imported Sentinel")).toHaveTextContent("Microsoft Sentinel");
356
+ expect(row("Imported Sentinel")).toHaveTextContent(
357
+ CONNECTOR_HEALTH_SUCCEEDED,
358
+ );
359
+
360
+ expect(row("Paused Splunk")).toHaveTextContent(
361
+ "Splunk Enterprise Security",
362
+ );
363
+ expect(row("Paused Splunk")).toHaveTextContent("Disabled");
364
+ expect(row("Paused Splunk")).toHaveTextContent("Schedule paused");
365
+ });
366
+
367
+ test("read-only members keep View Error and Diagnostics while every write action is locked", (): void => {
368
+ jest.spyOn(PermissionGate, "check").mockReturnValue({
369
+ isAllowed: false,
370
+ disabledReason: "You do not have permission to update connections.",
371
+ });
372
+ renderTable([
373
+ connection({ lastError: "Okta System Log request failed (HTTP 401)" }),
374
+ ]);
375
+
376
+ const current: HTMLElement = row();
377
+ for (const title of [
378
+ "Test connection",
379
+ "Run now",
380
+ "Edit",
381
+ "Update credentials",
382
+ ]) {
383
+ expect(
384
+ within(current).getByRole("button", { name: title }),
385
+ ).toBeDisabled();
386
+ }
387
+ expect(
388
+ within(current).getByRole("button", { name: "Diagnostics" }),
389
+ ).toBeEnabled();
390
+ expect(
391
+ within(current).getByRole("button", { name: "View Error" }),
392
+ ).toBeEnabled();
393
+
394
+ const props: ModelTableProps<BaseModel> = mockTableProps.get(
395
+ "SecurityEventConnection",
396
+ ) as ModelTableProps<BaseModel>;
397
+ const button: CardButtonSchema = props.cardProps
398
+ ?.buttons?.[0] as CardButtonSchema;
399
+ expect(button.disabled).toBe(true);
400
+ expect(button.tooltip).toBe(
401
+ "You do not have permission to update connections.",
402
+ );
403
+ expect(API.post).not.toHaveBeenCalled();
404
+ });
405
+
406
+ test("View Error appears only for rows with an error and opens the full message", (): void => {
407
+ renderTable([
408
+ connection({ lastError: "Okta System Log request failed (HTTP 401)" }),
409
+ connection({
410
+ _id: "44444444-4444-4444-8444-444444444444",
411
+ name: "Healthy",
412
+ }),
413
+ ]);
414
+
415
+ expect(
416
+ within(row("Healthy")).queryByRole("button", { name: "View Error" }),
417
+ ).not.toBeInTheDocument();
418
+ fireEvent.click(within(row()).getByRole("button", { name: "View Error" }));
419
+ const dialog: HTMLElement = screen.getByRole("dialog", {
420
+ name: "Last Error",
421
+ });
422
+ expect(
423
+ within(dialog).getByLabelText("Full error message").textContent,
424
+ ).toBe("Okta System Log request failed (HTTP 401)");
425
+ });
426
+
427
+ test("Test connection posts the connection id to the synchronous test route and shows the checklist", async (): Promise<void> => {
428
+ renderTable([connection()]);
429
+
430
+ fireEvent.click(
431
+ within(row()).getByRole("button", { name: "Test connection" }),
432
+ );
433
+
434
+ const dialog: HTMLElement = await screen.findByRole("dialog", {
435
+ name: "Test connection: Acme Okta",
436
+ });
437
+ expect(
438
+ await within(dialog).findByText("Passed with warnings"),
439
+ ).toBeVisible();
440
+ expect(dialog).toHaveTextContent("Access to Okta System Log");
441
+ expect(dialog).toHaveTextContent("What is available to import");
442
+
443
+ expect(API.post).toHaveBeenCalledTimes(1);
444
+ expect(postCall()["data"]).toEqual({ connectionId: CONNECTION_ID });
445
+ expect(postCall()["headers"]).toEqual({
446
+ "project-id": PROJECT_ID.toString(),
447
+ });
448
+ const destination: globalThis.URL = new globalThis.URL(
449
+ String(postCall()["url"]),
450
+ );
451
+ expect(destination.pathname).toMatch(/\/security-event-connection\/test$/);
452
+ expect(Array.from(destination.searchParams.keys()).sort()).toEqual([]);
453
+ });
454
+
455
+ test("Run now opens diagnostics and queues a poll for that connection", async (): Promise<void> => {
456
+ jest
457
+ .mocked(API.post)
458
+ .mockResolvedValue(
459
+ new HTTPResponse(
460
+ 200,
461
+ { runId: "66666666-6666-4666-8666-666666666666" },
462
+ {},
463
+ ),
464
+ );
465
+ renderTable([connection()]);
466
+
467
+ fireEvent.click(within(row()).getByRole("button", { name: "Run now" }));
468
+
469
+ expect(
470
+ await screen.findByRole("dialog", {
471
+ name: "Connection diagnostics: Acme Okta",
472
+ }),
473
+ ).toBeVisible();
474
+ await waitFor((): void => {
475
+ expect(API.post).toHaveBeenCalledTimes(1);
476
+ });
477
+ expect(postCall()["data"]).toEqual({ type: "poll" });
478
+ expect(new globalThis.URL(String(postCall()["url"])).pathname).toMatch(
479
+ new RegExp(`/security-event-connection/${CONNECTION_ID}/run$`),
480
+ );
481
+ // The diagnostics modal never selects the write-only secrets column.
482
+ expect(
483
+ jest.mocked(ModelAPI.getItem).mock.calls[0]?.[0].select,
484
+ ).not.toHaveProperty("secrets");
485
+ });
486
+
487
+ test("Diagnostics shows the same health wording and UTC times with a local-time title", async (): Promise<void> => {
488
+ renderTable([connection()]);
489
+
490
+ fireEvent.click(within(row()).getByRole("button", { name: "Diagnostics" }));
491
+
492
+ const dialog: HTMLElement = await screen.findByRole("dialog", {
493
+ name: "Connection diagnostics: Acme Okta",
494
+ });
495
+ expect(
496
+ within(dialog).getByRole("region", { name: "Scheduled polling" }),
497
+ ).toHaveTextContent(CONNECTOR_HEALTH_NO_EVENTS_YET);
498
+ const lastAttempt: HTMLElement = within(dialog).getAllByText(
499
+ "2026-09-10 11:59:00 UTC",
500
+ )[0] as HTMLElement;
501
+ expect(lastAttempt.getAttribute("title")).toMatch(/^Local time: /);
502
+ expect(API.post).not.toHaveBeenCalled();
503
+ });
504
+
505
+ /*
506
+ * stale-report-after-failed-rerun: Diagnostics kept the previous
507
+ * checklist when a later Test connection request failed.
508
+ */
509
+ test("Diagnostics Test connection clears the previous checklist when a re-run fails", async (): Promise<void> => {
510
+ renderTable([connection()]);
511
+
512
+ fireEvent.click(within(row()).getByRole("button", { name: "Diagnostics" }));
513
+ const dialog: HTMLElement = await screen.findByRole("dialog", {
514
+ name: "Connection diagnostics: Acme Okta",
515
+ });
516
+ const checks: HTMLElement = within(dialog).getByRole("region", {
517
+ name: "On-demand checks",
518
+ });
519
+
520
+ fireEvent.click(
521
+ within(checks).getByRole("button", { name: "Test connection" }),
522
+ );
523
+ expect(
524
+ await within(checks).findByText("Passed with warnings"),
525
+ ).toBeVisible();
526
+
527
+ jest
528
+ .mocked(API.post)
529
+ .mockResolvedValue(
530
+ new HTTPErrorResponse(
531
+ 502,
532
+ { message: "The API could not reach Okta." },
533
+ {},
534
+ ),
535
+ );
536
+ fireEvent.click(
537
+ within(checks).getByRole("button", { name: "Test connection" }),
538
+ );
539
+
540
+ expect(
541
+ await within(checks).findByText("The API could not reach Okta."),
542
+ ).toBeVisible();
543
+ expect(
544
+ within(checks).queryByText("Passed with warnings"),
545
+ ).not.toBeInTheDocument();
546
+ expect(
547
+ within(checks).queryByRole("region", { name: "Connection test report" }),
548
+ ).not.toBeInTheDocument();
549
+ });
550
+
551
+ test("Edit and Update credentials open the form modal in the matching mode", async (): Promise<void> => {
552
+ renderTable([connection()]);
553
+
554
+ fireEvent.click(within(row()).getByRole("button", { name: "Edit" }));
555
+ const edit: HTMLElement = await screen.findByRole("dialog", {
556
+ name: "Edit connection: Acme Okta",
557
+ });
558
+ expect(within(edit).getByLabelText(/^Okta organization URL/)).toHaveValue(
559
+ "https://acme.okta.com",
560
+ );
561
+ fireEvent.click(within(edit).getAllByRole("button", { name: "Close" })[0]!);
562
+ await waitFor((): void => {
563
+ expect(screen.queryByRole("dialog")).not.toBeInTheDocument();
564
+ });
565
+
566
+ fireEvent.click(
567
+ within(row()).getByRole("button", { name: "Update credentials" }),
568
+ );
569
+ const credentials: HTMLElement = await screen.findByRole("dialog", {
570
+ name: "Update credentials: Acme Okta",
571
+ });
572
+ expect(within(credentials).getByLabelText(/^API token/)).toHaveAttribute(
573
+ "placeholder",
574
+ "Unchanged",
575
+ );
576
+ expect(
577
+ within(credentials).queryByLabelText(/^Okta organization URL/),
578
+ ).not.toBeInTheDocument();
579
+ });
580
+ });
581
+
582
+ /*
583
+ * A window that cannot be read in one poll no longer pins polling (review
584
+ * findings bound-hit-window-never-advances and
585
+ * alerts-view-budget-pins-cursor-forever). The poller records what it did
586
+ * in chunkMinutes, nextChunkMinutes and forcedAdvance; run details must say
587
+ * it plainly, and a forced advance must name the range to import.
588
+ */
589
+ describe("run details for a window one poll could not read", () => {
590
+ function run(
591
+ overrides: Partial<SecurityEventConnectionRunResult>,
592
+ type: SecurityEventConnectionRun["type"] = "poll",
593
+ ): SecurityEventConnectionRun {
594
+ const value: SecurityEventConnectionRun = new SecurityEventConnectionRun();
595
+ value._id = "77777777-7777-4777-8777-777777777777";
596
+ value.securityEventConnectionId = new ObjectID(CONNECTION_ID);
597
+ value.type = type;
598
+ value.status = overrides.status || "partial";
599
+ value.startedAt = new Date("2026-09-10T12:00:00Z");
600
+ value.completedAt = new Date("2026-09-10T12:00:05Z");
601
+ value.result = pollResult({
602
+ type: type || "poll",
603
+ provider: SecurityEventConnectorProvider.AwsSecurityHub,
604
+ status: "partial",
605
+ complete: false,
606
+ windowStart: "2026-09-10T11:29:00Z",
607
+ windowEnd: "2026-09-10T12:00:00Z",
608
+ ...overrides,
609
+ }) as unknown as JSONObject;
610
+ return value;
611
+ }
612
+
613
+ function renderRun(value: SecurityEventConnectionRun): HTMLElement {
614
+ render(
615
+ <MemoryRouter>
616
+ <SecurityEventConnectionRunDetails run={value} />
617
+ </MemoryRouter>,
618
+ );
619
+ return screen.getByRole("region", { name: "Run details" });
620
+ }
621
+
622
+ afterEach((): void => {
623
+ cleanup();
624
+ });
625
+
626
+ test("a forced advance is an alert naming the minute to import", (): void => {
627
+ const details: HTMLElement = renderRun(
628
+ run({
629
+ chunkMinutes: 1,
630
+ nextChunkMinutes: 1,
631
+ forcedAdvance: true,
632
+ warnings: [
633
+ "More records were created in the one minute from 2026-09-10T11:59:00.000Z to 2026-09-10T12:00:00.000Z than one poll can read.",
634
+ ],
635
+ }),
636
+ );
637
+
638
+ const forcedAdvanceNotice: RegExp = /Polling moved past one minute/;
639
+ const alert: HTMLElement = within(details)
640
+ .getAllByRole("alert")
641
+ .find((element: HTMLElement): boolean => {
642
+ return forcedAdvanceNotice.test(element.textContent || "");
643
+ }) as HTMLElement;
644
+ expect(alert).toBeVisible();
645
+ expect(alert).toHaveTextContent(
646
+ "More findings were created in one minute than one poll can read.",
647
+ );
648
+ expect(alert).toHaveTextContent(
649
+ "use Import this time range under Find historical findings for 2026-09-10 11:59:00 UTC → 2026-09-10 12:00:00 UTC",
650
+ );
651
+ expect(details).toHaveTextContent("Window read by this poll1 minute");
652
+ // The specific notice replaces the generic "did not finish" line.
653
+ expect(details).not.toHaveTextContent("did not finish processing");
654
+ // The poller's own warning is still listed verbatim.
655
+ expect(details).toHaveTextContent(
656
+ "More records were created in the one minute from",
657
+ );
658
+ });
659
+
660
+ test("a narrowed window says the next poll reads a shorter window from the same start", (): void => {
661
+ const details: HTMLElement = renderRun(
662
+ run({ chunkMinutes: 1440, nextChunkMinutes: 720 }),
663
+ );
664
+
665
+ expect(details).toHaveTextContent("Window read by this poll24 hours");
666
+ expect(details).toHaveTextContent(
667
+ "Next scheduled poll readsUp to 12 hours",
668
+ );
669
+ expect(details).toHaveTextContent(
670
+ "The next scheduled poll reads a window of 12 hours from the same starting point",
671
+ );
672
+ expect(details).not.toHaveTextContent("Polling moved past one minute");
673
+ expect(details).not.toHaveTextContent("moved the cursor to the last");
674
+ });
675
+
676
+ test("a resumed window says the cursor moved to the last record read", (): void => {
677
+ const details: HTMLElement = renderRun(
678
+ run({ chunkMinutes: 60, nextChunkMinutes: 60 }),
679
+ );
680
+
681
+ expect(details).toHaveTextContent("1 hour, the same length");
682
+ expect(details).toHaveTextContent(
683
+ "moved the cursor to the last finding it read. The next scheduled poll continues from there with a window of 1 hour.",
684
+ );
685
+ expect(details).not.toHaveTextContent("from the same starting point");
686
+ });
687
+
688
+ test("a complete poll widens the next window without any alert", (): void => {
689
+ const details: HTMLElement = renderRun(
690
+ run({
691
+ status: "success",
692
+ complete: true,
693
+ chunkMinutes: 30,
694
+ nextChunkMinutes: 60,
695
+ }),
696
+ );
697
+
698
+ expect(details).toHaveTextContent("Next scheduled poll readsUp to 1 hour");
699
+ expect(within(details).queryAllByRole("alert")).toHaveLength(0);
700
+ });
701
+
702
+ test("a failed poll keeps its window and raises no volume notice", (): void => {
703
+ const details: HTMLElement = renderRun(
704
+ run({
705
+ status: "failed",
706
+ chunkMinutes: 30,
707
+ nextChunkMinutes: 30,
708
+ error: "AWS Security Hub request failed (HTTP 503)",
709
+ }),
710
+ );
711
+
712
+ expect(details).toHaveTextContent(
713
+ "A failed poll does not change the window",
714
+ );
715
+ expect(details).not.toHaveTextContent("moved the cursor to the last");
716
+ // A failure is not a volume signal: no narrowing notice.
717
+ expect(details).not.toHaveTextContent("reads a window of");
718
+ expect(details).not.toHaveTextContent("than one poll can read");
719
+ });
720
+
721
+ test("runs without window fields keep the generic notice, with range advice for imports", (): void => {
722
+ const details: HTMLElement = renderRun(run({}, "backfill"));
723
+
724
+ expect(details).toHaveTextContent(
725
+ "This run did not finish processing every record in the window. Choose a shorter time range to read the rest",
726
+ );
727
+ expect(
728
+ within(details).queryByTestId("poll-window-progress"),
729
+ ).not.toBeInTheDocument();
730
+ });
731
+ });
732
+
733
+ describe("Google SecOps page test action", () => {
734
+ function googleConnection(): GoogleSecOpsConnection {
735
+ const value: GoogleSecOpsConnection = new GoogleSecOpsConnection();
736
+ value._id = GOOGLE_ID;
737
+ value.projectId = PROJECT_ID;
738
+ value.name = "Customer SecOps";
739
+ value.isEnabled = true;
740
+ value.pollIntervalInMinutes = 5;
741
+ value.createdAt = new Date(NOW - 60 * 60_000);
742
+ value.lastPolledAt = new Date(NOW - 60_000);
743
+ value.lastPollResult = {
744
+ ...pollResult(),
745
+ includeNonAlertingDetections: false,
746
+ } as unknown as JSONObject;
747
+ return value;
748
+ }
749
+
750
+ beforeEach((): void => {
751
+ jest.useFakeTimers();
752
+ jest.setSystemTime(NOW);
753
+ mockRows.clear();
754
+ mockTableProps.clear();
755
+ jest.spyOn(ProjectUtil, "getCurrentProjectId").mockReturnValue(PROJECT_ID);
756
+ jest.spyOn(PermissionGate, "check").mockReturnValue({ isAllowed: true });
757
+ jest
758
+ .spyOn(ModelAPI, "getCommonHeaders")
759
+ .mockReturnValue({ "project-id": PROJECT_ID.toString() });
760
+ jest
761
+ .spyOn(API, "post")
762
+ .mockResolvedValue(
763
+ new HTTPResponse(
764
+ 200,
765
+ report("google-secops") as unknown as JSONObject,
766
+ {},
767
+ ),
768
+ );
769
+ });
770
+
771
+ afterEach((): void => {
772
+ cleanup();
773
+ jest.clearAllTimers();
774
+ jest.useRealTimers();
775
+ jest.restoreAllMocks();
776
+ });
777
+
778
+ test("renders the generic table above the Google table and tests a Google row synchronously", async (): Promise<void> => {
779
+ mockRows.set("GoogleSecOpsConnection", [googleConnection()]);
780
+ const project: Project = new Project();
781
+ project.id = PROJECT_ID;
782
+ await act(async (): Promise<void> => {
783
+ render(
784
+ <MemoryRouter>
785
+ <GoogleSecOpsConnectionsPage
786
+ pageRoute={new Route("/dashboard/security-events/connections")}
787
+ currentProject={project}
788
+ hasPaymentMethod={true}
789
+ />
790
+ </MemoryRouter>,
791
+ );
792
+ });
793
+
794
+ const tables: Array<HTMLElement> = screen.getAllByRole("table");
795
+ expect(
796
+ tables.map((table: HTMLElement): string | null => {
797
+ return table.getAttribute("aria-label");
798
+ }),
799
+ ).toEqual(["Security Event Connections", "Google SecOps Connections"]);
800
+
801
+ const googleRow: HTMLElement = screen.getByTestId("Customer SecOps");
802
+ expect(googleRow).toHaveTextContent(CONNECTOR_HEALTH_NO_EVENTS_YET);
803
+
804
+ fireEvent.click(
805
+ within(googleRow).getByRole("button", { name: "Test connection" }),
806
+ );
807
+ const dialog: HTMLElement = await screen.findByRole("dialog", {
808
+ name: "Test connection: Customer SecOps",
809
+ });
810
+ expect(
811
+ await within(dialog).findByText("Passed with warnings"),
812
+ ).toBeVisible();
813
+ expect(dialog).toHaveTextContent("Access to Google SecOps");
814
+ expect(API.post).toHaveBeenCalledTimes(1);
815
+ expect(postCall()["data"]).toEqual({ connectionId: GOOGLE_ID });
816
+ expect(new globalThis.URL(String(postCall()["url"])).pathname).toMatch(
817
+ /\/google-secops-connection\/test$/,
818
+ );
819
+ });
820
+
821
+ test("the unsaved-settings body sends the pasted key, or the id when editing without one", (): void => {
822
+ expect(
823
+ googleSecOpsTestBody({
824
+ region: " us ",
825
+ instanceResourceName: "projects/p/locations/us/instances/i",
826
+ serviceAccountJson: '{"client_email":"a@b"}',
827
+ includeNonAlertingDetections: true,
828
+ }),
829
+ ).toEqual({
830
+ region: "us",
831
+ instanceResourceName: "projects/p/locations/us/instances/i",
832
+ serviceAccountJson: '{"client_email":"a@b"}',
833
+ includeNonAlertingDetections: true,
834
+ });
835
+
836
+ expect(
837
+ googleSecOpsTestBody({
838
+ _id: GOOGLE_ID,
839
+ region: "europe",
840
+ instanceResourceName: "projects/p/locations/europe/instances/i",
841
+ serviceAccountJson: "",
842
+ }),
843
+ ).toEqual({
844
+ connectionId: GOOGLE_ID,
845
+ region: "europe",
846
+ instanceResourceName: "projects/p/locations/europe/instances/i",
847
+ includeNonAlertingDetections: false,
848
+ });
849
+
850
+ expect((): void => {
851
+ googleSecOpsTestBody({ region: "us" });
852
+ }).toThrow(GOOGLE_SECOPS_TEST_NEEDS_KEY_MESSAGE);
853
+ });
854
+ });
855
+
856
+ describe("connection health vocabulary", () => {
857
+ test("a succeeding poll that never imported reads as polling, not success", (): void => {
858
+ const item: SecurityEventConnection = connection();
859
+ expect(connectorHealth(item, NOW)).toBe(CONNECTOR_HEALTH_NO_EVENTS_YET);
860
+
861
+ item.lastEventIngestedAt = new Date(NOW - 30_000);
862
+ expect(connectorHealth(item, NOW)).toBe(CONNECTOR_HEALTH_SUCCEEDED);
863
+ });
864
+
865
+ test("mirrors the Google decision tree for every other state", (): void => {
866
+ const item: SecurityEventConnection = connection({
867
+ lastPolledAt: undefined,
868
+ lastSuccessfulPollAt: undefined,
869
+ lastPollResult: undefined,
870
+ createdAt: new Date(NOW - 60_000),
871
+ });
872
+ expect(connectorHealth(item, NOW)).toBe("Waiting for first poll");
873
+ item.lastPolledAt = new Date(NOW - 60_000);
874
+ expect(connectorHealth(item, NOW)).toBe("Details unavailable");
875
+ item.lastPollResult = pollResult({
876
+ status: "empty",
877
+ windowEnd: "2026-09-10T12:00:00Z",
878
+ }) as unknown as JSONObject;
879
+ expect(connectorHealth(item, NOW)).toBe("No records returned");
880
+ item.lastError = "Permission denied";
881
+ expect(connectorHealth(item, NOW)).toBe("Last poll failed");
882
+ item.lastPolledAt = new Date(NOW - 8 * 60_000);
883
+ expect(connectorHealth(item, NOW)).toBe("Poll overdue");
884
+ item.isEnabled = false;
885
+ expect(connectorHealth(item, NOW)).toBe("Schedule paused");
886
+ });
887
+
888
+ test("Google SecOps applies the same rule to its own success state", (): void => {
889
+ const item: GoogleSecOpsConnection = new GoogleSecOpsConnection();
890
+ item._id = GOOGLE_ID;
891
+ item.isEnabled = true;
892
+ item.pollIntervalInMinutes = 5;
893
+ item.createdAt = new Date(NOW - 60 * 60_000);
894
+ item.lastPolledAt = new Date(NOW - 60_000);
895
+ const result: GoogleSecOpsRunResult = {
896
+ ...pollResult(),
897
+ includeNonAlertingDetections: false,
898
+ } as unknown as GoogleSecOpsRunResult;
899
+ item.lastPollResult = result as unknown as JSONObject;
900
+
901
+ expect(googleSecOpsHealth(item, NOW)).toBe(CONNECTOR_HEALTH_NO_EVENTS_YET);
902
+ item.lastEventIngestedAt = new Date(NOW - 30_000);
903
+ expect(googleSecOpsHealth(item, NOW)).toBe(CONNECTOR_HEALTH_SUCCEEDED);
904
+ });
905
+ });