@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,1129 @@
1
+ import Queue from "../../../../../Server/Infrastructure/Queue";
2
+ import ConnectorPlatformHealth, {
3
+ CONNECTOR_OVERDUE_GRACE_IN_MS,
4
+ CONNECTOR_SCHEDULER_JOB_NAMES,
5
+ ConnectorScheduleFacts,
6
+ ConnectorSchedulerEntry,
7
+ } from "../../../../../Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth";
8
+ import {
9
+ ConnectorPlatformStatus,
10
+ SecurityConnectorCheck,
11
+ } from "../../../../../Types/SecurityEvent/Connectors/ConnectorDiagnostics";
12
+ import { JSONObject } from "../../../../../Types/JSON";
13
+ import { getJestSpyOn } from "../../../../Spy";
14
+ import { afterEach, describe, expect, jest, test } from "@jest/globals";
15
+ import { createHash } from "crypto";
16
+ import type { Mock } from "jest-mock";
17
+
18
+ /*
19
+ * The platform checks are the half of "Test connection" that looks at
20
+ * OneUptime instead of the source. Their whole value is being right when
21
+ * Redis or the workers are broken, so the probes are exercised with a
22
+ * hand-built queue that can answer, be missing a method, or throw - and
23
+ * every one of those must land as a value or a null, never as a rejected
24
+ * test. The check text is pinned because the docs quote it.
25
+ */
26
+
27
+ /*
28
+ * One entry of BullMQ's getJobSchedulers() as BullMQ really returns it.
29
+ * Deliberately has no `id`: the old fake handed back
30
+ * { id: "SecurityEvents-PollSecurityEventConnections" }, a shape BullMQ
31
+ * never produces, which is how a scheduler check that failed on every
32
+ * healthy install passed here (review finding
33
+ * scheduler-check-always-fails).
34
+ */
35
+ interface FakeScheduler {
36
+ key: string;
37
+ name: string;
38
+ next?: number | undefined;
39
+ pattern?: string | undefined;
40
+ }
41
+
42
+ interface FakeQueue {
43
+ getWorkersCount?: (() => Promise<number>) | undefined;
44
+ getWorkers?: (() => Promise<Array<unknown>>) | undefined;
45
+ getJobSchedulers?:
46
+ | ((
47
+ start?: number,
48
+ end?: number,
49
+ asc?: boolean,
50
+ ) => Promise<Array<FakeScheduler | undefined>>)
51
+ | undefined;
52
+ getWaitingCount: () => Promise<number>;
53
+ getFailedCount: () => Promise<number>;
54
+ }
55
+
56
+ const NOW: Date = new Date("2026-09-10T12:00:00.000Z");
57
+ const NEXT_TICK_MS: number = Date.parse("2026-09-10T12:01:00.000Z");
58
+ const GENERIC_POLL_JOB: string = "SecurityEvents:PollSecurityEventConnections";
59
+ const GOOGLE_POLL_JOB: string = "SecurityEvents:PollGoogleSecOpsConnections";
60
+ const EVERY_MINUTE: string = "* * * * *";
61
+
62
+ /*
63
+ * The concatenated repeat key BullMQ 5.76.2 builds for
64
+ * queue.add(name, data, { jobId, repeat: { pattern, jobId } }), which is
65
+ * what RunCron -> Queue.addJob sends: getRepeatConcatOptions in
66
+ * bullmq/dist/cjs/classes/repeat.js joins name, jobId, endDate, tz and
67
+ * pattern with ":". Queue.addJob passes the job name with ":" replaced by
68
+ * "-" as the jobId.
69
+ */
70
+ function legacyRepeatKey(jobName: string): string {
71
+ return `${jobName}:${jobName.replace(/:/g, "-")}:::${EVERY_MINUTE}`;
72
+ }
73
+
74
+ /*
75
+ * What getJobSchedulers() returns for that registration. updateRepeatableJob
76
+ * stores it under md5(legacyRepeatKey); addRepeatableJob-2.lua writes only
77
+ * `name` and `pattern` into repeat:<md5>; JobScheduler.transformSchedulerData
78
+ * turns that hash into { key, name, next, pattern }.
79
+ */
80
+ function bullmqRepeatable(jobName: string, next?: number): FakeScheduler {
81
+ return {
82
+ key: createHash("md5").update(legacyRepeatKey(jobName)).digest("hex"),
83
+ name: jobName,
84
+ ...(next !== undefined ? { next } : {}),
85
+ pattern: EVERY_MINUTE,
86
+ };
87
+ }
88
+
89
+ /*
90
+ * The two BullMQ internals that decide what getJobSchedulers() lists for a
91
+ * RunCron registration: Repeat.updateRepeatableJob, which picks the stored
92
+ * key and metadata, and JobScheduler.transformSchedulerData, which turns
93
+ * that metadata back into a listing entry.
94
+ */
95
+ interface BullmqRepeatInternals {
96
+ getNextMillis: (millis: number, opts: JSONObject) => number | undefined;
97
+ Repeat: {
98
+ prototype: {
99
+ hash: (value: string) => string;
100
+ updateRepeatableJob: (
101
+ name: string,
102
+ data: JSONObject,
103
+ opts: JSONObject,
104
+ flags: { override: boolean },
105
+ ) => Promise<unknown>;
106
+ };
107
+ };
108
+ JobScheduler: {
109
+ prototype: {
110
+ transformSchedulerData: (
111
+ key: string,
112
+ jobData: Record<string, string>,
113
+ next: number,
114
+ ) => unknown;
115
+ };
116
+ };
117
+ }
118
+
119
+ /*
120
+ * jest.requireActual returns unknown, so each module is checked for the
121
+ * members this suite drives before they are used. A BullMQ upgrade that
122
+ * moves or renames one then fails with a message naming it, not with
123
+ * "cannot read properties of undefined" halfway through a test.
124
+ */
125
+ function hasPrototypeMethods(value: unknown, methods: Array<string>): boolean {
126
+ if (typeof value !== "function") {
127
+ return false;
128
+ }
129
+
130
+ const prototype: unknown = value.prototype;
131
+
132
+ return methods.every((method: string): boolean => {
133
+ return (
134
+ typeof prototype === "object" &&
135
+ prototype !== null &&
136
+ typeof Reflect.get(prototype, method) === "function"
137
+ );
138
+ });
139
+ }
140
+
141
+ function isBullmqRepeatModule(
142
+ value: unknown,
143
+ ): value is Pick<BullmqRepeatInternals, "getNextMillis" | "Repeat"> {
144
+ return (
145
+ typeof value === "object" &&
146
+ value !== null &&
147
+ "getNextMillis" in value &&
148
+ typeof value.getNextMillis === "function" &&
149
+ "Repeat" in value &&
150
+ hasPrototypeMethods(value.Repeat, ["hash", "updateRepeatableJob"])
151
+ );
152
+ }
153
+
154
+ function isBullmqJobSchedulerModule(
155
+ value: unknown,
156
+ ): value is Pick<BullmqRepeatInternals, "JobScheduler"> {
157
+ return (
158
+ typeof value === "object" &&
159
+ value !== null &&
160
+ "JobScheduler" in value &&
161
+ hasPrototypeMethods(value.JobScheduler, ["transformSchedulerData"])
162
+ );
163
+ }
164
+
165
+ /*
166
+ * Loaded from BullMQ's CommonJS build because the "bullmq" import is mapped
167
+ * to a stub in this suite. This test environment resolves msgpackr, which
168
+ * BullMQ's script runner instantiates at load time, to its ES module build
169
+ * that Jest cannot parse; nothing exercised here packs anything, so a no-op
170
+ * packer stands in for it.
171
+ */
172
+ function loadBullmqRepeatInternals(): BullmqRepeatInternals {
173
+ const loaded: Array<BullmqRepeatInternals> = [];
174
+
175
+ jest.isolateModules((): void => {
176
+ jest.doMock("msgpackr", (): Record<string, unknown> => {
177
+ return {
178
+ Packr: class {
179
+ public pack(): Buffer {
180
+ return Buffer.alloc(0);
181
+ }
182
+ },
183
+ };
184
+ });
185
+ const repeat: unknown = jest.requireActual(
186
+ "bullmq/dist/cjs/classes/repeat",
187
+ );
188
+ const jobScheduler: unknown = jest.requireActual(
189
+ "bullmq/dist/cjs/classes/job-scheduler",
190
+ );
191
+
192
+ if (!isBullmqRepeatModule(repeat)) {
193
+ throw new Error(
194
+ "bullmq/dist/cjs/classes/repeat no longer exports getNextMillis and a Repeat class with hash and updateRepeatableJob.",
195
+ );
196
+ }
197
+
198
+ if (!isBullmqJobSchedulerModule(jobScheduler)) {
199
+ throw new Error(
200
+ "bullmq/dist/cjs/classes/job-scheduler no longer exports a JobScheduler class with transformSchedulerData.",
201
+ );
202
+ }
203
+
204
+ loaded.push({
205
+ getNextMillis: repeat.getNextMillis,
206
+ Repeat: repeat.Repeat,
207
+ JobScheduler: jobScheduler.JobScheduler,
208
+ });
209
+ });
210
+
211
+ if (!loaded[0]) {
212
+ throw new Error("BullMQ's repeat internals did not load.");
213
+ }
214
+
215
+ return loaded[0];
216
+ }
217
+
218
+ function makeQueue(overrides: Partial<FakeQueue> = {}): FakeQueue {
219
+ return {
220
+ getWorkersCount: (): Promise<number> => {
221
+ return Promise.resolve(2);
222
+ },
223
+ getJobSchedulers: (): Promise<Array<FakeScheduler | undefined>> => {
224
+ return Promise.resolve([
225
+ bullmqRepeatable("Unrelated:Job", NEXT_TICK_MS - 30_000),
226
+ bullmqRepeatable(GENERIC_POLL_JOB, NEXT_TICK_MS),
227
+ ]);
228
+ },
229
+ getWaitingCount: (): Promise<number> => {
230
+ return Promise.resolve(3);
231
+ },
232
+ getFailedCount: (): Promise<number> => {
233
+ return Promise.resolve(1);
234
+ },
235
+ ...overrides,
236
+ };
237
+ }
238
+
239
+ function storageUp(): Promise<boolean> {
240
+ return Promise.resolve(true);
241
+ }
242
+
243
+ function findCheck(
244
+ checks: Array<SecurityConnectorCheck>,
245
+ key: string,
246
+ ): SecurityConnectorCheck {
247
+ const check: SecurityConnectorCheck | undefined = checks.find(
248
+ (candidate: SecurityConnectorCheck): boolean => {
249
+ return candidate.key === key;
250
+ },
251
+ );
252
+
253
+ expect(check).toBeDefined();
254
+
255
+ return check!;
256
+ }
257
+
258
+ function healthyStatus(): ConnectorPlatformStatus {
259
+ return {
260
+ workerConsumers: 1,
261
+ schedulerRegistered: true,
262
+ schedulerNextRunAt: new Date(NEXT_TICK_MS).toISOString(),
263
+ queueWaiting: 0,
264
+ queueFailed: 0,
265
+ storageReachable: true,
266
+ };
267
+ }
268
+
269
+ function facts(
270
+ overrides: Partial<ConnectorScheduleFacts> = {},
271
+ ): ConnectorScheduleFacts {
272
+ return {
273
+ isEnabled: true,
274
+ pollIntervalInMinutes: 5,
275
+ ...overrides,
276
+ };
277
+ }
278
+
279
+ afterEach(() => {
280
+ jest.restoreAllMocks();
281
+ });
282
+
283
+ describe("ConnectorPlatformHealth.getPlatformStatus", () => {
284
+ test("reads every probe off an answering queue and the storage probe", async () => {
285
+ const status: ConnectorPlatformStatus =
286
+ await ConnectorPlatformHealth.getPlatformStatus({
287
+ queueOverride: makeQueue(),
288
+ storageProbeOverride: storageUp,
289
+ });
290
+
291
+ expect(status).toEqual({
292
+ workerConsumers: 2,
293
+ schedulerRegistered: true,
294
+ schedulerNextRunAt: new Date(NEXT_TICK_MS).toISOString(),
295
+ queueWaiting: 3,
296
+ queueFailed: 1,
297
+ storageReachable: true,
298
+ });
299
+ });
300
+
301
+ test("asks for the first thousand schedulers in ascending order", async () => {
302
+ const getJobSchedulers: Mock<
303
+ (
304
+ start?: number,
305
+ end?: number,
306
+ asc?: boolean,
307
+ ) => Promise<Array<FakeScheduler | undefined>>
308
+ > = jest.fn(
309
+ (
310
+ _start?: number,
311
+ _end?: number,
312
+ _asc?: boolean,
313
+ ): Promise<Array<FakeScheduler | undefined>> => {
314
+ return Promise.resolve([]);
315
+ },
316
+ );
317
+
318
+ await ConnectorPlatformHealth.getPlatformStatus({
319
+ queueOverride: makeQueue({ getJobSchedulers }),
320
+ storageProbeOverride: storageUp,
321
+ });
322
+
323
+ expect(getJobSchedulers).toHaveBeenCalledWith(0, 1000, true);
324
+ });
325
+
326
+ test("either connector family's scheduler counts as registered, by its raw job name", () => {
327
+ /*
328
+ * The raw RunCron names, colon included: BullMQ reports `name` as
329
+ * passed to queue.add, never the sanitized jobId.
330
+ */
331
+ expect(CONNECTOR_SCHEDULER_JOB_NAMES).toEqual([
332
+ GOOGLE_POLL_JOB,
333
+ GENERIC_POLL_JOB,
334
+ ]);
335
+ });
336
+
337
+ test("a healthy registration, in the exact shape BullMQ returns, passes the scheduler check", async () => {
338
+ const entry: FakeScheduler = bullmqRepeatable(
339
+ GENERIC_POLL_JOB,
340
+ NEXT_TICK_MS,
341
+ );
342
+
343
+ // Pin the shape itself, so a fake with an invented `id` cannot creep back.
344
+ expect(entry).toEqual({
345
+ key: expect.stringMatching(/^[0-9a-f]{32}$/),
346
+ name: "SecurityEvents:PollSecurityEventConnections",
347
+ next: NEXT_TICK_MS,
348
+ pattern: "* * * * *",
349
+ });
350
+ expect(entry).not.toHaveProperty("id");
351
+
352
+ const status: ConnectorPlatformStatus =
353
+ await ConnectorPlatformHealth.getPlatformStatus({
354
+ queueOverride: makeQueue({
355
+ getJobSchedulers: (): Promise<Array<FakeScheduler | undefined>> => {
356
+ return Promise.resolve([entry]);
357
+ },
358
+ }),
359
+ storageProbeOverride: storageUp,
360
+ });
361
+
362
+ expect(status.schedulerRegistered).toBe(true);
363
+ expect(status.schedulerNextRunAt).toBe(
364
+ new Date(NEXT_TICK_MS).toISOString(),
365
+ );
366
+
367
+ const check: SecurityConnectorCheck = findCheck(
368
+ ConnectorPlatformHealth.toPlatformChecks(status),
369
+ "scheduler",
370
+ );
371
+
372
+ expect(check.status).toBe("pass");
373
+ expect(check.message).toBe(
374
+ `Registered; next tick at ${new Date(NEXT_TICK_MS).toISOString()}.`,
375
+ );
376
+ });
377
+
378
+ test("the fixture is what the installed BullMQ stores and lists for a RunCron registration", async () => {
379
+ /*
380
+ * Drives BullMQ's own code with the exact options Queue.addJob sends for
381
+ * RunCron's scheduleAt, then lists the stored metadata back through
382
+ * BullMQ's own transform. A BullMQ upgrade that changes the listing
383
+ * shape fails here instead of silently failing the scheduler check.
384
+ */
385
+ const bullmq: BullmqRepeatInternals = loadBullmqRepeatInternals();
386
+ const storedCalls: Array<{ key: string; opts: JSONObject }> = [];
387
+ const repeatContext: Record<string, unknown> = {
388
+ repeatStrategy: bullmq.getNextMillis,
389
+ repeatKeyHashAlgorithm: "md5",
390
+ hash: bullmq.Repeat.prototype.hash,
391
+ scripts: {
392
+ addRepeatableJob: (
393
+ customKey: string,
394
+ _nextMillis: number,
395
+ opts: JSONObject,
396
+ ): Promise<string> => {
397
+ storedCalls.push({ key: customKey, opts });
398
+ return Promise.resolve(customKey);
399
+ },
400
+ },
401
+ createNextJob: (): Promise<undefined> => {
402
+ return Promise.resolve(undefined);
403
+ },
404
+ };
405
+ const jobId: string = GENERIC_POLL_JOB.replace(/:/g, "-");
406
+
407
+ await bullmq.Repeat.prototype.updateRepeatableJob.call(
408
+ repeatContext,
409
+ GENERIC_POLL_JOB,
410
+ {},
411
+ { jobId, repeat: { pattern: EVERY_MINUTE, jobId } },
412
+ { override: true },
413
+ );
414
+
415
+ expect(storedCalls).toHaveLength(1);
416
+
417
+ /*
418
+ * addRepeatableJob-2.lua: HMSET repeat:<key> with `name` plus only the
419
+ * options that are set (msgpack turns the undefined ones into nil).
420
+ */
421
+ const metadata: Record<string, string> = {};
422
+
423
+ for (const [field, value] of Object.entries(storedCalls[0]!.opts)) {
424
+ if (value !== undefined && value !== null) {
425
+ metadata[field] = String(value);
426
+ }
427
+ }
428
+
429
+ const listed: unknown =
430
+ bullmq.JobScheduler.prototype.transformSchedulerData.call(
431
+ bullmq.JobScheduler.prototype,
432
+ storedCalls[0]!.key,
433
+ metadata,
434
+ NEXT_TICK_MS,
435
+ );
436
+
437
+ expect(listed).toEqual(bullmqRepeatable(GENERIC_POLL_JOB, NEXT_TICK_MS));
438
+ expect(listed).not.toHaveProperty("id");
439
+ expect(
440
+ ConnectorPlatformHealth.isConnectorScheduler(
441
+ listed as ConnectorSchedulerEntry,
442
+ ),
443
+ ).toBe(true);
444
+ });
445
+
446
+ test("an entry that only carries the sanitized id is not a registration BullMQ can report", async () => {
447
+ /*
448
+ * The shape the old code matched on. BullMQ never fills `id` for a
449
+ * RunCron registration, so accepting it would only make a fabricated
450
+ * fixture pass again.
451
+ */
452
+ const status: ConnectorPlatformStatus =
453
+ await ConnectorPlatformHealth.getPlatformStatus({
454
+ queueOverride: makeQueue({
455
+ getJobSchedulers: (): Promise<Array<FakeScheduler | undefined>> => {
456
+ return Promise.resolve([
457
+ {
458
+ id: "SecurityEvents-PollSecurityEventConnections",
459
+ next: NEXT_TICK_MS,
460
+ } as unknown as FakeScheduler,
461
+ ]);
462
+ },
463
+ }),
464
+ storageProbeOverride: storageUp,
465
+ });
466
+
467
+ expect(status.schedulerRegistered).toBe(false);
468
+ });
469
+
470
+ test("a repeatable still kept under its concatenated key with no metadata hash is recognised by the key", async () => {
471
+ /*
472
+ * BullMQ rebuilds such an entry by splitting the key on ":", which
473
+ * reports the name as "SecurityEvents" and the rest of the job name
474
+ * as the id (JobScheduler.keyToData).
475
+ */
476
+ const key: string = legacyRepeatKey(GENERIC_POLL_JOB);
477
+ const status: ConnectorPlatformStatus =
478
+ await ConnectorPlatformHealth.getPlatformStatus({
479
+ queueOverride: makeQueue({
480
+ getJobSchedulers: (): Promise<Array<FakeScheduler | undefined>> => {
481
+ return Promise.resolve([
482
+ {
483
+ key,
484
+ name: "SecurityEvents",
485
+ id: "PollSecurityEventConnections",
486
+ endDate: null,
487
+ tz: null,
488
+ pattern: `:${EVERY_MINUTE}`,
489
+ next: NEXT_TICK_MS,
490
+ } as unknown as FakeScheduler,
491
+ ]);
492
+ },
493
+ }),
494
+ storageProbeOverride: storageUp,
495
+ });
496
+
497
+ expect(status.schedulerRegistered).toBe(true);
498
+ expect(status.schedulerNextRunAt).toBe(
499
+ new Date(NEXT_TICK_MS).toISOString(),
500
+ );
501
+ });
502
+
503
+ test("an undefined entry (a repeat key whose metadata is gone) is skipped, not a probe failure", async () => {
504
+ const status: ConnectorPlatformStatus =
505
+ await ConnectorPlatformHealth.getPlatformStatus({
506
+ queueOverride: makeQueue({
507
+ getJobSchedulers: (): Promise<Array<FakeScheduler | undefined>> => {
508
+ return Promise.resolve([
509
+ undefined,
510
+ bullmqRepeatable(GOOGLE_POLL_JOB, NEXT_TICK_MS),
511
+ ]);
512
+ },
513
+ }),
514
+ storageProbeOverride: storageUp,
515
+ });
516
+
517
+ expect(status.schedulerRegistered).toBe(true);
518
+ });
519
+
520
+ test("a job whose name only starts with a poll job name is not the poll scheduler", () => {
521
+ const lookalike: ConnectorSchedulerEntry = bullmqRepeatable(
522
+ `${GENERIC_POLL_JOB}Extra`,
523
+ );
524
+
525
+ expect(ConnectorPlatformHealth.isConnectorScheduler(lookalike)).toBe(false);
526
+ expect(
527
+ ConnectorPlatformHealth.isConnectorScheduler({
528
+ key: legacyRepeatKey(`${GENERIC_POLL_JOB}Extra`),
529
+ name: "SecurityEvents",
530
+ }),
531
+ ).toBe(false);
532
+ });
533
+
534
+ test("the Google scheduler alone marks the scheduler registered", async () => {
535
+ const status: ConnectorPlatformStatus =
536
+ await ConnectorPlatformHealth.getPlatformStatus({
537
+ queueOverride: makeQueue({
538
+ getJobSchedulers: (): Promise<Array<FakeScheduler | undefined>> => {
539
+ return Promise.resolve([bullmqRepeatable(GOOGLE_POLL_JOB)]);
540
+ },
541
+ }),
542
+ storageProbeOverride: storageUp,
543
+ });
544
+
545
+ expect(status.schedulerRegistered).toBe(true);
546
+ // No usable `next` on the entry, so no next-run timestamp is invented.
547
+ expect(status.schedulerNextRunAt).toBeUndefined();
548
+ });
549
+
550
+ test("reports the earliest next tick when both schedulers are registered", async () => {
551
+ const status: ConnectorPlatformStatus =
552
+ await ConnectorPlatformHealth.getPlatformStatus({
553
+ queueOverride: makeQueue({
554
+ getJobSchedulers: (): Promise<Array<FakeScheduler | undefined>> => {
555
+ return Promise.resolve([
556
+ bullmqRepeatable(GENERIC_POLL_JOB, NEXT_TICK_MS + 5_000),
557
+ bullmqRepeatable(GOOGLE_POLL_JOB, NEXT_TICK_MS),
558
+ ]);
559
+ },
560
+ }),
561
+ storageProbeOverride: storageUp,
562
+ });
563
+
564
+ expect(status.schedulerNextRunAt).toBe(
565
+ new Date(NEXT_TICK_MS).toISOString(),
566
+ );
567
+ });
568
+
569
+ test("no matching scheduler is a definite false, not an unknown", async () => {
570
+ const status: ConnectorPlatformStatus =
571
+ await ConnectorPlatformHealth.getPlatformStatus({
572
+ queueOverride: makeQueue({
573
+ getJobSchedulers: (): Promise<Array<FakeScheduler | undefined>> => {
574
+ return Promise.resolve([
575
+ bullmqRepeatable("Unrelated:Job", NEXT_TICK_MS),
576
+ ]);
577
+ },
578
+ }),
579
+ storageProbeOverride: storageUp,
580
+ });
581
+
582
+ expect(status.schedulerRegistered).toBe(false);
583
+ expect(status.schedulerNextRunAt).toBeUndefined();
584
+ });
585
+
586
+ test("falls back to getWorkers().length when getWorkersCount is not available", async () => {
587
+ const status: ConnectorPlatformStatus =
588
+ await ConnectorPlatformHealth.getPlatformStatus({
589
+ queueOverride: makeQueue({
590
+ getWorkersCount: undefined,
591
+ getWorkers: (): Promise<Array<unknown>> => {
592
+ return Promise.resolve([{}, {}, {}]);
593
+ },
594
+ }),
595
+ storageProbeOverride: storageUp,
596
+ });
597
+
598
+ expect(status.workerConsumers).toBe(3);
599
+ });
600
+
601
+ test("a queue without any worker accessor leaves the consumer count unknown", async () => {
602
+ const status: ConnectorPlatformStatus =
603
+ await ConnectorPlatformHealth.getPlatformStatus({
604
+ queueOverride: makeQueue({ getWorkersCount: undefined }),
605
+ storageProbeOverride: storageUp,
606
+ });
607
+
608
+ expect(status.workerConsumers).toBeNull();
609
+ });
610
+
611
+ test("a queue without getJobSchedulers leaves the scheduler unknown", async () => {
612
+ const status: ConnectorPlatformStatus =
613
+ await ConnectorPlatformHealth.getPlatformStatus({
614
+ queueOverride: makeQueue({ getJobSchedulers: undefined }),
615
+ storageProbeOverride: storageUp,
616
+ });
617
+
618
+ expect(status.schedulerRegistered).toBeNull();
619
+ expect(status.schedulerNextRunAt).toBeUndefined();
620
+ });
621
+
622
+ test("every queue probe that throws becomes null without disturbing the others", async () => {
623
+ const boom: () => Promise<never> = (): Promise<never> => {
624
+ return Promise.reject(
625
+ new Error("redis://user:secret@redis:6379 refused"),
626
+ );
627
+ };
628
+
629
+ const status: ConnectorPlatformStatus =
630
+ await ConnectorPlatformHealth.getPlatformStatus({
631
+ queueOverride: makeQueue({
632
+ getWorkersCount: boom,
633
+ getJobSchedulers: boom,
634
+ getWaitingCount: boom,
635
+ getFailedCount: boom,
636
+ }),
637
+ storageProbeOverride: storageUp,
638
+ });
639
+
640
+ expect(status).toEqual({
641
+ workerConsumers: null,
642
+ schedulerRegistered: null,
643
+ queueWaiting: null,
644
+ queueFailed: null,
645
+ storageReachable: true,
646
+ });
647
+ });
648
+
649
+ test("a single throwing probe does not take the answering ones with it", async () => {
650
+ const status: ConnectorPlatformStatus =
651
+ await ConnectorPlatformHealth.getPlatformStatus({
652
+ queueOverride: makeQueue({
653
+ getWaitingCount: (): Promise<number> => {
654
+ return Promise.reject(new Error("timeout"));
655
+ },
656
+ }),
657
+ storageProbeOverride: storageUp,
658
+ });
659
+
660
+ expect(status.queueWaiting).toBeNull();
661
+ expect(status.workerConsumers).toBe(2);
662
+ expect(status.schedulerRegistered).toBe(true);
663
+ expect(status.queueFailed).toBe(1);
664
+ });
665
+
666
+ test("a storage probe that throws reads as unreachable, never as unknown or healthy", async () => {
667
+ /*
668
+ * The other probes answer "unknown" on a throw because the thing being
669
+ * probed (Redis) is not the thing being reported on. Here the probe IS
670
+ * the database that has to accept the imported rows, so an exception
671
+ * from it is the failure itself.
672
+ */
673
+ const status: ConnectorPlatformStatus =
674
+ await ConnectorPlatformHealth.getPlatformStatus({
675
+ queueOverride: makeQueue(),
676
+ storageProbeOverride: (): Promise<boolean> => {
677
+ return Promise.reject(new Error("ECONNREFUSED"));
678
+ },
679
+ });
680
+
681
+ expect(status.storageReachable).toBe(false);
682
+ });
683
+
684
+ test("a storage probe answering false is reported as is", async () => {
685
+ const status: ConnectorPlatformStatus =
686
+ await ConnectorPlatformHealth.getPlatformStatus({
687
+ queueOverride: makeQueue(),
688
+ storageProbeOverride: (): Promise<boolean> => {
689
+ return Promise.resolve(false);
690
+ },
691
+ });
692
+
693
+ expect(status.storageReachable).toBe(false);
694
+ });
695
+
696
+ test("a Worker queue that cannot even be opened leaves every queue value unknown", async () => {
697
+ getJestSpyOn(Queue, "getQueue").mockImplementation((): never => {
698
+ throw new Error("Redis is not configured");
699
+ });
700
+
701
+ const status: ConnectorPlatformStatus =
702
+ await ConnectorPlatformHealth.getPlatformStatus({
703
+ storageProbeOverride: storageUp,
704
+ });
705
+
706
+ expect(status).toEqual({
707
+ workerConsumers: null,
708
+ schedulerRegistered: null,
709
+ queueWaiting: null,
710
+ queueFailed: null,
711
+ storageReachable: true,
712
+ });
713
+ });
714
+
715
+ test("uses the Worker queue when no override is supplied", async () => {
716
+ const getQueue: ReturnType<typeof getJestSpyOn> = getJestSpyOn(
717
+ Queue,
718
+ "getQueue",
719
+ ).mockReturnValue(makeQueue() as never);
720
+
721
+ const status: ConnectorPlatformStatus =
722
+ await ConnectorPlatformHealth.getPlatformStatus({
723
+ storageProbeOverride: storageUp,
724
+ });
725
+
726
+ expect(getQueue).toHaveBeenCalledWith("Worker");
727
+ expect(status.workerConsumers).toBe(2);
728
+ });
729
+ });
730
+
731
+ describe("ConnectorPlatformHealth.toPlatformChecks", () => {
732
+ test("emits the three deployment checks in a stable order", () => {
733
+ const checks: Array<SecurityConnectorCheck> =
734
+ ConnectorPlatformHealth.toPlatformChecks(healthyStatus());
735
+
736
+ expect(
737
+ checks.map((check: SecurityConnectorCheck): string => {
738
+ return check.key;
739
+ }),
740
+ ).toEqual(["worker-consumers", "scheduler", "storage"]);
741
+ expect(
742
+ checks.every((check: SecurityConnectorCheck): boolean => {
743
+ return check.status === "pass";
744
+ }),
745
+ ).toBe(true);
746
+ });
747
+
748
+ test("zero worker consumers fails with the DISABLE_QUEUE_WORKERS / Helm remediation", () => {
749
+ const check: SecurityConnectorCheck = findCheck(
750
+ ConnectorPlatformHealth.toPlatformChecks({
751
+ ...healthyStatus(),
752
+ workerConsumers: 0,
753
+ }),
754
+ "worker-consumers",
755
+ );
756
+
757
+ expect(check.status).toBe("fail");
758
+ expect(check.message).toContain("No process is consuming the Worker queue");
759
+ expect(check.remediation).toContain("DISABLE_QUEUE_WORKERS=false");
760
+ expect(check.remediation).toContain("worker.enabled: true");
761
+ expect(check.details).toEqual({ workerConsumers: 0 });
762
+ });
763
+
764
+ test("an unknown worker count warns instead of failing or passing", () => {
765
+ const check: SecurityConnectorCheck = findCheck(
766
+ ConnectorPlatformHealth.toPlatformChecks({
767
+ ...healthyStatus(),
768
+ workerConsumers: null,
769
+ }),
770
+ "worker-consumers",
771
+ );
772
+
773
+ expect(check.status).toBe("warn");
774
+ expect(check.message).toContain("Could not determine");
775
+ expect(check.remediation).toContain("Redis");
776
+ });
777
+
778
+ test("a healthy worker count passes and carries the queue depths as details", () => {
779
+ const check: SecurityConnectorCheck = findCheck(
780
+ ConnectorPlatformHealth.toPlatformChecks({
781
+ ...healthyStatus(),
782
+ workerConsumers: 2,
783
+ queueWaiting: 4,
784
+ queueFailed: 7,
785
+ }),
786
+ "worker-consumers",
787
+ );
788
+
789
+ expect(check.status).toBe("pass");
790
+ expect(check.message).toBe("2 processes consuming the Worker queue.");
791
+ expect(check.details).toEqual({
792
+ workerConsumers: 2,
793
+ queueWaiting: 4,
794
+ queueFailed: 7,
795
+ });
796
+ expect(check.remediation).toBeUndefined();
797
+ });
798
+
799
+ test("a single consumer is described in the singular and unknown depths are omitted", () => {
800
+ const check: SecurityConnectorCheck = findCheck(
801
+ ConnectorPlatformHealth.toPlatformChecks({
802
+ ...healthyStatus(),
803
+ workerConsumers: 1,
804
+ queueWaiting: null,
805
+ queueFailed: null,
806
+ }),
807
+ "worker-consumers",
808
+ );
809
+
810
+ expect(check.message).toBe("1 process consuming the Worker queue.");
811
+ expect(check.details).toEqual({ workerConsumers: 1 });
812
+ });
813
+
814
+ test("a missing scheduler fails and blames the Workers feature set", () => {
815
+ const check: SecurityConnectorCheck = findCheck(
816
+ ConnectorPlatformHealth.toPlatformChecks({
817
+ ...healthyStatus(),
818
+ schedulerRegistered: false,
819
+ }),
820
+ "scheduler",
821
+ );
822
+
823
+ expect(check.status).toBe("fail");
824
+ expect(check.message).toContain("poll scheduler is not registered");
825
+ expect(check.remediation).toContain("Workers feature set");
826
+ });
827
+
828
+ test("an unknown scheduler warns", () => {
829
+ const check: SecurityConnectorCheck = findCheck(
830
+ ConnectorPlatformHealth.toPlatformChecks({
831
+ ...healthyStatus(),
832
+ schedulerRegistered: null,
833
+ }),
834
+ "scheduler",
835
+ );
836
+
837
+ expect(check.status).toBe("warn");
838
+ expect(check.remediation).toContain("Redis");
839
+ });
840
+
841
+ test("a registered scheduler passes and shows its next tick when known", () => {
842
+ const withNext: SecurityConnectorCheck = findCheck(
843
+ ConnectorPlatformHealth.toPlatformChecks(healthyStatus()),
844
+ "scheduler",
845
+ );
846
+
847
+ expect(withNext.status).toBe("pass");
848
+ expect(withNext.message).toContain(new Date(NEXT_TICK_MS).toISOString());
849
+ expect(withNext.details).toEqual({
850
+ nextRunAt: new Date(NEXT_TICK_MS).toISOString(),
851
+ });
852
+
853
+ const withoutNext: SecurityConnectorCheck = findCheck(
854
+ ConnectorPlatformHealth.toPlatformChecks({
855
+ ...healthyStatus(),
856
+ schedulerNextRunAt: undefined,
857
+ }),
858
+ "scheduler",
859
+ );
860
+
861
+ expect(withoutNext.status).toBe("pass");
862
+ expect(withoutNext.message).toBe("Registered.");
863
+ expect(withoutNext.details).toBeUndefined();
864
+ });
865
+
866
+ test("unreachable storage fails and points at the CLICKHOUSE_* settings", () => {
867
+ const check: SecurityConnectorCheck = findCheck(
868
+ ConnectorPlatformHealth.toPlatformChecks({
869
+ ...healthyStatus(),
870
+ storageReachable: false,
871
+ }),
872
+ "storage",
873
+ );
874
+
875
+ expect(check.status).toBe("fail");
876
+ expect(check.message).toContain("did not answer");
877
+ expect(check.remediation).toContain("CLICKHOUSE_");
878
+ });
879
+
880
+ test("an unprobed storage warns and reachable storage passes", () => {
881
+ expect(
882
+ findCheck(
883
+ ConnectorPlatformHealth.toPlatformChecks({
884
+ ...healthyStatus(),
885
+ storageReachable: null,
886
+ }),
887
+ "storage",
888
+ ).status,
889
+ ).toBe("warn");
890
+
891
+ const pass: SecurityConnectorCheck = findCheck(
892
+ ConnectorPlatformHealth.toPlatformChecks(healthyStatus()),
893
+ "storage",
894
+ );
895
+
896
+ expect(pass.status).toBe("pass");
897
+ expect(pass.message).toBe("The analytics database answered.");
898
+ });
899
+
900
+ test("every check carries a non-negative duration and a message", () => {
901
+ for (const check of ConnectorPlatformHealth.toPlatformChecks({
902
+ workerConsumers: null,
903
+ schedulerRegistered: null,
904
+ queueWaiting: null,
905
+ queueFailed: null,
906
+ storageReachable: null,
907
+ })) {
908
+ expect(check.durationMs).toBeGreaterThanOrEqual(0);
909
+ expect(check.message.trim()).not.toBe("");
910
+ expect(check.name.trim()).not.toBe("");
911
+ }
912
+ });
913
+ });
914
+
915
+ describe("ConnectorPlatformHealth.toScheduleCheck", () => {
916
+ test("the grace period is two scheduler ticks", () => {
917
+ expect(CONNECTOR_OVERDUE_GRACE_IN_MS).toBe(2 * 60 * 1000);
918
+ });
919
+
920
+ test("a disabled connection warns and says on-demand runs still work", () => {
921
+ const check: SecurityConnectorCheck =
922
+ ConnectorPlatformHealth.toScheduleCheck(
923
+ facts({ isEnabled: false, lastError: "ignored while disabled" }),
924
+ NOW,
925
+ );
926
+
927
+ expect(check.key).toBe("connection-schedule");
928
+ expect(check.status).toBe("warn");
929
+ expect(check.message).toContain("disabled");
930
+ expect(check.remediation).toContain("On-demand runs");
931
+ });
932
+
933
+ test("never polled and created moments ago passes as 'not polled yet'", () => {
934
+ const check: SecurityConnectorCheck =
935
+ ConnectorPlatformHealth.toScheduleCheck(
936
+ facts({ createdAt: new Date(NOW.getTime() - 60_000) }),
937
+ NOW,
938
+ );
939
+
940
+ expect(check.status).toBe("pass");
941
+ expect(check.message).toContain("Not polled yet");
942
+ });
943
+
944
+ test("never polled with no creation timestamp is treated as fresh", () => {
945
+ expect(ConnectorPlatformHealth.toScheduleCheck(facts(), NOW).status).toBe(
946
+ "pass",
947
+ );
948
+ });
949
+
950
+ test("never polled and older than the grace period fails with the age in minutes", () => {
951
+ const check: SecurityConnectorCheck =
952
+ ConnectorPlatformHealth.toScheduleCheck(
953
+ facts({ createdAt: new Date(NOW.getTime() - 45 * 60_000) }),
954
+ NOW,
955
+ );
956
+
957
+ expect(check.status).toBe("fail");
958
+ expect(check.message).toContain("created 45 minutes ago");
959
+ expect(check.message).toContain("never been polled");
960
+ expect(check.remediation).toContain("Run now");
961
+ });
962
+
963
+ test("exactly at the grace boundary is still fresh", () => {
964
+ const check: SecurityConnectorCheck =
965
+ ConnectorPlatformHealth.toScheduleCheck(
966
+ facts({
967
+ createdAt: new Date(NOW.getTime() - CONNECTOR_OVERDUE_GRACE_IN_MS),
968
+ }),
969
+ NOW,
970
+ );
971
+
972
+ expect(check.status).toBe("pass");
973
+ });
974
+
975
+ test("a poll later than interval plus grace is overdue", () => {
976
+ const lastPolledAt: Date = new Date(NOW.getTime() - 8 * 60_000);
977
+ const check: SecurityConnectorCheck =
978
+ ConnectorPlatformHealth.toScheduleCheck(
979
+ facts({ pollIntervalInMinutes: 5, lastPolledAt }),
980
+ NOW,
981
+ );
982
+
983
+ expect(check.status).toBe("fail");
984
+ expect(check.message).toContain(lastPolledAt.toISOString());
985
+ expect(check.message).toContain("5 minute interval");
986
+ expect(check.remediation).toContain("Background workers");
987
+ expect(check.details).toEqual({
988
+ lastPolledAt: lastPolledAt.toISOString(),
989
+ intervalMinutes: 5,
990
+ });
991
+ });
992
+
993
+ test("a poll inside interval plus grace is not overdue", () => {
994
+ const check: SecurityConnectorCheck =
995
+ ConnectorPlatformHealth.toScheduleCheck(
996
+ facts({
997
+ pollIntervalInMinutes: 5,
998
+ lastPolledAt: new Date(NOW.getTime() - 6 * 60_000),
999
+ }),
1000
+ NOW,
1001
+ );
1002
+
1003
+ expect(check.status).toBe("pass");
1004
+ });
1005
+
1006
+ test("a zero interval is read as the five minute default", () => {
1007
+ const check: SecurityConnectorCheck =
1008
+ ConnectorPlatformHealth.toScheduleCheck(
1009
+ facts({
1010
+ pollIntervalInMinutes: 0,
1011
+ lastPolledAt: new Date(NOW.getTime() - 6 * 60_000),
1012
+ }),
1013
+ NOW,
1014
+ );
1015
+
1016
+ expect(check.status).toBe("pass");
1017
+ });
1018
+
1019
+ test("a queued run older than the grace period fails and names the stale run", () => {
1020
+ const pendingRunCreatedAt: Date = new Date(NOW.getTime() - 3 * 60_000);
1021
+ const check: SecurityConnectorCheck =
1022
+ ConnectorPlatformHealth.toScheduleCheck(
1023
+ facts({
1024
+ lastPolledAt: new Date(NOW.getTime() - 60_000),
1025
+ pendingRunCreatedAt,
1026
+ }),
1027
+ NOW,
1028
+ );
1029
+
1030
+ expect(check.status).toBe("fail");
1031
+ expect(check.message).toContain(pendingRunCreatedAt.toISOString());
1032
+ expect(check.message).toContain("no worker has picked it up");
1033
+ expect(check.remediation).toContain("Background workers");
1034
+ });
1035
+
1036
+ test("a recently queued run is not a problem", () => {
1037
+ const check: SecurityConnectorCheck =
1038
+ ConnectorPlatformHealth.toScheduleCheck(
1039
+ facts({
1040
+ lastPolledAt: new Date(NOW.getTime() - 60_000),
1041
+ pendingRunCreatedAt: new Date(NOW.getTime() - 30_000),
1042
+ }),
1043
+ NOW,
1044
+ );
1045
+
1046
+ expect(check.status).toBe("pass");
1047
+ });
1048
+
1049
+ test("a stuck queued run outranks a recorded error, because it explains it", () => {
1050
+ const check: SecurityConnectorCheck =
1051
+ ConnectorPlatformHealth.toScheduleCheck(
1052
+ facts({
1053
+ lastPolledAt: new Date(NOW.getTime() - 60_000),
1054
+ lastError: "Okta token exchange failed (HTTP 401)",
1055
+ pendingRunCreatedAt: new Date(NOW.getTime() - 10 * 60_000),
1056
+ }),
1057
+ NOW,
1058
+ );
1059
+
1060
+ expect(check.status).toBe("fail");
1061
+ expect(check.message).toContain("queued since");
1062
+ });
1063
+
1064
+ test("a recent poll that failed surfaces lastError verbatim", () => {
1065
+ const lastPolledAt: Date = new Date(NOW.getTime() - 60_000);
1066
+ const lastSuccessfulPollAt: Date = new Date(NOW.getTime() - 11 * 60_000);
1067
+ const check: SecurityConnectorCheck =
1068
+ ConnectorPlatformHealth.toScheduleCheck(
1069
+ facts({
1070
+ lastPolledAt,
1071
+ lastSuccessfulPollAt,
1072
+ lastError: "Splunk search failed (HTTP 403): insufficient permission",
1073
+ }),
1074
+ NOW,
1075
+ );
1076
+
1077
+ expect(check.status).toBe("fail");
1078
+ expect(check.message).toBe(
1079
+ "The last poll attempt failed: Splunk search failed (HTTP 403): insufficient permission",
1080
+ );
1081
+ expect(check.remediation).toContain("error prefix");
1082
+ expect(check.details).toEqual({
1083
+ lastPolledAt: lastPolledAt.toISOString(),
1084
+ lastSuccessfulPollAt: lastSuccessfulPollAt.toISOString(),
1085
+ });
1086
+ });
1087
+
1088
+ test("healthy with an ingested event names both timestamps", () => {
1089
+ const lastPolledAt: Date = new Date(NOW.getTime() - 60_000);
1090
+ const lastSuccessfulPollAt: Date = lastPolledAt;
1091
+ const lastEventIngestedAt: Date = new Date(NOW.getTime() - 4 * 60_000);
1092
+ const check: SecurityConnectorCheck =
1093
+ ConnectorPlatformHealth.toScheduleCheck(
1094
+ facts({ lastPolledAt, lastSuccessfulPollAt, lastEventIngestedAt }),
1095
+ NOW,
1096
+ );
1097
+
1098
+ expect(check.status).toBe("pass");
1099
+ expect(check.message).toContain(`last poll ${lastPolledAt.toISOString()}`);
1100
+ expect(check.message).toContain(
1101
+ `last event imported ${lastEventIngestedAt.toISOString()}`,
1102
+ );
1103
+ expect(check.details).toEqual({
1104
+ lastPolledAt: lastPolledAt.toISOString(),
1105
+ lastSuccessfulPollAt: lastSuccessfulPollAt.toISOString(),
1106
+ lastEventIngestedAt: lastEventIngestedAt.toISOString(),
1107
+ });
1108
+ expect(check.remediation).toBeUndefined();
1109
+ });
1110
+
1111
+ test("healthy without any ingested event says so is expected", () => {
1112
+ const lastPolledAt: Date = new Date(NOW.getTime() - 60_000);
1113
+ const check: SecurityConnectorCheck =
1114
+ ConnectorPlatformHealth.toScheduleCheck(facts({ lastPolledAt }), NOW);
1115
+
1116
+ expect(check.status).toBe("pass");
1117
+ expect(check.message).toContain("No event has been imported yet");
1118
+ expect(check.details).toEqual({ lastPolledAt: lastPolledAt.toISOString() });
1119
+ });
1120
+
1121
+ test("defaults `now` to the current clock", () => {
1122
+ const check: SecurityConnectorCheck =
1123
+ ConnectorPlatformHealth.toScheduleCheck(
1124
+ facts({ lastPolledAt: new Date(Date.now() - 30_000) }),
1125
+ );
1126
+
1127
+ expect(check.status).toBe("pass");
1128
+ });
1129
+ });