@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
@@ -13,6 +13,7 @@ import {
13
13
  fireEvent,
14
14
  render,
15
15
  screen,
16
+ within,
16
17
  } from "@testing-library/react";
17
18
  import * as React from "react";
18
19
  import getJestMockFunction, { MockFunction } from "../../MockType";
@@ -30,6 +31,7 @@ const getFriendlyMessageMock: MockFunction = getJestMockFunction();
30
31
  const getCommonHeadersMock: MockFunction = getJestMockFunction();
31
32
  const markdownViewerMock: MockFunction = getJestMockFunction();
32
33
  const activityFeedMock: MockFunction = getJestMockFunction();
34
+ const widgetRendererMock: MockFunction = getJestMockFunction();
33
35
 
34
36
  jest.mock("../../../UI/Utils/API/API", () => {
35
37
  return {
@@ -59,6 +61,8 @@ jest.mock("../../../UI/Utils/ModelAPI/ModelAPI", () => {
59
61
  /*
60
62
  * Record MarkdownViewer's props so safeMode remains an asserted part of the
61
63
  * contract even when the Common Jest config replaces its markdown renderer.
64
+ * The recorded `inlineReferences` are the panel's own chip/link renderers, so
65
+ * tests can call them and render what they return.
62
66
  */
63
67
  jest.mock("../../../UI/Components/Markdown.tsx/LazyMarkdownViewer", () => {
64
68
  return {
@@ -83,6 +87,20 @@ jest.mock("../../../UI/Components/Markdown.tsx/LazyMarkdownViewer", () => {
83
87
  */
84
88
  const hasRenderableActivityMock: MockFunction = getJestMockFunction();
85
89
 
90
+ // Evidence rows render through the chat widgets; their output is not under test.
91
+ jest.mock(
92
+ "../../../../App/FeatureSet/Dashboard/src/Components/AIChat/Widgets/WidgetRenderer",
93
+ () => {
94
+ return {
95
+ __esModule: true,
96
+ default: (props: { widgets: Array<JSONObject> }): React.ReactElement => {
97
+ widgetRendererMock(props);
98
+ return React.createElement("div", { "data-testid": "evidence-widget" });
99
+ },
100
+ };
101
+ },
102
+ );
103
+
86
104
  jest.mock(
87
105
  "../../../../App/FeatureSet/Dashboard/src/Components/AIChat/ChatActivityFeed",
88
106
  () => {
@@ -111,10 +129,12 @@ import AIRunEventType from "../../../Types/AI/AIRunEventType";
111
129
  import AIRunStatus from "../../../Types/AI/AIRunStatus";
112
130
  import { JSONArray, JSONObject } from "../../../Types/JSON";
113
131
  import ObjectID from "../../../Types/ObjectID";
132
+ import type { MarkdownInlineReferenceRenderers } from "../../../UI/Components/Markdown.tsx/InlineReferences";
114
133
 
115
134
  interface MarkdownViewerProps {
116
135
  text: string;
117
136
  safeMode?: boolean | undefined;
137
+ inlineReferences?: MarkdownInlineReferenceRenderers | undefined;
118
138
  }
119
139
 
120
140
  interface ActivityFeedProps {
@@ -138,6 +158,8 @@ interface InvestigationPayloadOptions {
138
158
  humanVerdict?: string | null | undefined;
139
159
  codeFixRecommendation?: AIRunCodeFixRecommendation | undefined;
140
160
  completedAt?: string | undefined;
161
+ evidence?: JSONArray | undefined;
162
+ references?: JSONArray | undefined;
141
163
  }
142
164
 
143
165
  interface ApiResponse {
@@ -203,13 +225,27 @@ function investigationPayload(
203
225
  run["completedAt"] = options.completedAt;
204
226
  }
205
227
 
206
- return {
228
+ const payload: JSONObject = {
207
229
  run,
208
230
  events: options.events || [],
209
231
  analysisMarkdown: options.analysisMarkdown ?? null,
210
232
  analysisTldr: options.analysisTldr ?? null,
211
233
  isAnalysisPending: options.isAnalysisPending === true,
212
234
  };
235
+
236
+ /*
237
+ * Older API replicas omit these keys entirely, so they are only present
238
+ * when a test asks for them.
239
+ */
240
+ if (options.evidence !== undefined) {
241
+ payload["evidence"] = options.evidence;
242
+ }
243
+
244
+ if (options.references !== undefined) {
245
+ payload["references"] = options.references;
246
+ }
247
+
248
+ return payload;
213
249
  }
214
250
 
215
251
  function successfulResponse(payload: JSONObject): ApiResponse {
@@ -264,6 +300,7 @@ function renderPanel(data?: {
264
300
  subjectId?: ObjectID | undefined;
265
301
  onAnalysisAvailable?: (() => void) | undefined;
266
302
  onStatusChange?: ((status: AIRunStatus | null) => void) | undefined;
303
+ onReportSummaryChange?: ((summary: string | null) => void) | undefined;
267
304
  }): ReturnType<typeof render> {
268
305
  return render(
269
306
  <InvestigationPanel
@@ -271,6 +308,7 @@ function renderPanel(data?: {
271
308
  subjectId={data?.subjectId || INCIDENT_ID}
272
309
  onAnalysisAvailable={data?.onAnalysisAvailable}
273
310
  onStatusChange={data?.onStatusChange}
311
+ onReportSummaryChange={data?.onReportSummaryChange}
274
312
  />,
275
313
  );
276
314
  }
@@ -371,6 +409,7 @@ afterEach(() => {
371
409
  markdownViewerMock.mockReset();
372
410
  activityFeedMock.mockReset();
373
411
  hasRenderableActivityMock.mockReset();
412
+ widgetRendererMock.mockReset();
374
413
  });
375
414
 
376
415
  describe("InvestigationPanel report lifecycle", () => {
@@ -432,10 +471,22 @@ describe("InvestigationPanel report lifecycle", () => {
432
471
  expect(screen.getByTestId("investigation-markdown")).toHaveTextContent(
433
472
  "The database connection pool was exhausted.",
434
473
  );
474
+ /*
475
+ * The report renders section by section: the "## Root cause" heading
476
+ * becomes the section's own title and its body goes through the safe
477
+ * viewer together with the panel's inline reference renderers.
478
+ */
435
479
  expect(markdownViewerMock).toHaveBeenCalledWith({
436
- text: ANALYSIS,
480
+ text: "The database connection pool was exhausted.",
437
481
  safeMode: true,
482
+ inlineReferences: expect.objectContaining({
483
+ renderCitation: expect.any(Function),
484
+ renderEventReference: expect.any(Function),
485
+ }),
438
486
  });
487
+ expect(
488
+ screen.getByRole("heading", { level: 4, name: "Root cause" }),
489
+ ).toBeInTheDocument();
439
490
  expect(screen.getByText("Investigation activity")).toBeInTheDocument();
440
491
  expect(lastActivityProps()).toEqual(
441
492
  expect.objectContaining({
@@ -845,10 +896,10 @@ describe("InvestigationPanel TL;DR", () => {
845
896
  // The summary is never routed through the markdown renderer.
846
897
  expect(markdownTexts().length).toBeGreaterThan(0);
847
898
  expect(
848
- markdownTexts().every((text: string): boolean => {
849
- return text === ANALYSIS;
899
+ markdownTexts().some((text: string): boolean => {
900
+ return text.includes(TLDR);
850
901
  }),
851
- ).toBe(true);
902
+ ).toBe(false);
852
903
 
853
904
  // It sits above the report it summarizes.
854
905
  const report: HTMLElement = screen.getByLabelText("Investigation report");
@@ -1021,10 +1072,10 @@ describe("InvestigationPanel TL;DR", () => {
1021
1072
  ).toBeUndefined();
1022
1073
  // The summary never reaches the markdown renderer.
1023
1074
  expect(
1024
- markdownTexts().every((text: string): boolean => {
1025
- return text === ANALYSIS;
1075
+ markdownTexts().some((text: string): boolean => {
1076
+ return text.includes("__pwned");
1026
1077
  }),
1027
- ).toBe(true);
1078
+ ).toBe(false);
1028
1079
  });
1029
1080
 
1030
1081
  test("drops the previous subject's summary the moment the subject changes", async () => {
@@ -1693,3 +1744,820 @@ describe("InvestigationPanel completed actions", () => {
1693
1744
  expect(screen.getByRole("button", { name: "Confirmed" })).toBeEnabled();
1694
1745
  });
1695
1746
  });
1747
+
1748
+ /*
1749
+ * The completed report is laid out for a responder: its Summary in a section
1750
+ * of its own, the report section by section, and every query the AI ran with
1751
+ * the rows behind it one click away. The payload's `evidence` and
1752
+ * `references` drive the interactive parts; older API replicas omit them and
1753
+ * the panel must fall back to the markdown alone.
1754
+ */
1755
+ const PRIOR_INCIDENT_ID: string = "66666666-6666-4666-8666-666666666666";
1756
+ const PRIOR_ALERT_ID: string = "77777777-7777-4777-8777-777777777777";
1757
+ const REPORT_SUMMARY: string =
1758
+ "the connection pool ran dry after the 18:00 deploy.";
1759
+
1760
+ const STRUCTURED_REPORT: string = [
1761
+ "## \u{1F9E0} AI — Automated Root Cause Analysis",
1762
+ "",
1763
+ "**Summary** — the connection pool ran dry after the 18:00 deploy [C1].",
1764
+ "",
1765
+ "**Most likely root cause** — the deploy halved the pool size; this matches prior #6954 [C2].",
1766
+ "",
1767
+ "**Suggested next steps**",
1768
+ "- Roll back the deploy",
1769
+ "",
1770
+ "**Evidence checked**",
1771
+ "- **[C1]** Active incidents (7 total) — 7 row(s)",
1772
+ "- **[C2]** Logs 17:20 – 18:20 (1 shown) — 1 row(s)",
1773
+ "",
1774
+ "---",
1775
+ "*Investigated automatically by OneUptime AI — read-only, 2 queries run across your own telemetry using gpt-5. This is an AI-generated first pass; verify before acting.*",
1776
+ ].join("\n");
1777
+
1778
+ const EVIDENCE_ITEMS: JSONArray = [
1779
+ {
1780
+ citationId: "C1",
1781
+ toolName: "query_incidents",
1782
+ label: "Active incidents (7 total)",
1783
+ rowCount: 7,
1784
+ durationInMs: 812,
1785
+ queryArguments: { state: "active" },
1786
+ target: { type: "Incidents" },
1787
+ executedAt: "2026-08-07T11:58:00.000Z",
1788
+ canLoadRows: true,
1789
+ },
1790
+ {
1791
+ citationId: "C2",
1792
+ toolName: "search_logs",
1793
+ label: "Logs 17:20 – 18:20 (1 shown)",
1794
+ rowCount: 1,
1795
+ queryArguments: { bodySearchText: "pool timeout" },
1796
+ target: { type: "Logs" },
1797
+ executedAt: "2026-08-07T11:59:00.000Z",
1798
+ canLoadRows: true,
1799
+ },
1800
+ ];
1801
+
1802
+ const REFERENCES: JSONArray = [
1803
+ {
1804
+ kind: "incident",
1805
+ number: 6954,
1806
+ id: PRIOR_INCIDENT_ID,
1807
+ displayNumber: "INC-6954",
1808
+ title: "Checkout pool exhausted",
1809
+ stateName: "Resolved",
1810
+ },
1811
+ {
1812
+ kind: "alert",
1813
+ number: 6954,
1814
+ id: PRIOR_ALERT_ID,
1815
+ displayNumber: "#6954",
1816
+ title: "Webhook failures",
1817
+ },
1818
+ ];
1819
+
1820
+ interface EvidencePostRequest extends PostRequest {
1821
+ headers?: JSONObject | undefined;
1822
+ }
1823
+
1824
+ function structuredResponse(
1825
+ overrides: Partial<InvestigationPayloadOptions> = {},
1826
+ ): ApiResponse {
1827
+ return completedResponse({
1828
+ analysisMarkdown: STRUCTURED_REPORT,
1829
+ evidence: EVIDENCE_ITEMS,
1830
+ references: REFERENCES,
1831
+ ...overrides,
1832
+ });
1833
+ }
1834
+
1835
+ function evidenceRowsResponse(citationId: string, text: string): ApiResponse {
1836
+ return successfulResponse({
1837
+ citationId,
1838
+ toolName: "query_incidents",
1839
+ label: "Active incidents (7 total)",
1840
+ rowCount: 7,
1841
+ isTruncated: false,
1842
+ executedAt: COMPLETED_AT,
1843
+ isPinnedToInvestigationTime: false,
1844
+ text,
1845
+ });
1846
+ }
1847
+
1848
+ /*
1849
+ * Investigation polls and evidence re-runs share API.post, so route by URL:
1850
+ * the investigation handler answers the panel's own endpoint and the evidence
1851
+ * handler (default: never resolves) answers /ai-investigation/evidence.
1852
+ */
1853
+ function routePosts(handlers: {
1854
+ investigation: (request: EvidencePostRequest) => unknown;
1855
+ evidence?: ((request: EvidencePostRequest) => unknown) | undefined;
1856
+ }): void {
1857
+ postMock.mockImplementation((request: unknown): unknown => {
1858
+ const typedRequest: EvidencePostRequest = request as EvidencePostRequest;
1859
+
1860
+ if (typedRequest.url.toString().includes("/ai-investigation/evidence")) {
1861
+ return handlers.evidence
1862
+ ? handlers.evidence(typedRequest)
1863
+ : new Promise<never>(() => {});
1864
+ }
1865
+
1866
+ return handlers.investigation(typedRequest);
1867
+ });
1868
+ }
1869
+
1870
+ function evidencePosts(): Array<EvidencePostRequest> {
1871
+ return (postMock.mock.calls as Array<Array<EvidencePostRequest>>)
1872
+ .map((call: Array<EvidencePostRequest>): EvidencePostRequest => {
1873
+ return call[0]!;
1874
+ })
1875
+ .filter((request: EvidencePostRequest): boolean => {
1876
+ return request.url.toString().includes("/ai-investigation/evidence");
1877
+ });
1878
+ }
1879
+
1880
+ function investigationPostCount(): number {
1881
+ return postMock.mock.calls.length - evidencePosts().length;
1882
+ }
1883
+
1884
+ function lastInlineReferences(): MarkdownInlineReferenceRenderers {
1885
+ const calls: Array<Array<MarkdownViewerProps>> = markdownViewerMock.mock
1886
+ .calls as Array<Array<MarkdownViewerProps>>;
1887
+ return calls[calls.length - 1]![0]!.inlineReferences!;
1888
+ }
1889
+
1890
+ function allMarkdownProps(): Array<MarkdownViewerProps> {
1891
+ return (
1892
+ markdownViewerMock.mock.calls as Array<Array<MarkdownViewerProps>>
1893
+ ).map((call: Array<MarkdownViewerProps>): MarkdownViewerProps => {
1894
+ return call[0]!;
1895
+ });
1896
+ }
1897
+
1898
+ describe("InvestigationPanel structured report", () => {
1899
+ const scrollIntoViewMock: MockFunction = getJestMockFunction();
1900
+
1901
+ beforeEach(() => {
1902
+ Object.defineProperty(Element.prototype, "scrollIntoView", {
1903
+ configurable: true,
1904
+ writable: true,
1905
+ value: scrollIntoViewMock,
1906
+ });
1907
+ });
1908
+
1909
+ afterEach(() => {
1910
+ scrollIntoViewMock.mockReset();
1911
+ delete (Element.prototype as unknown as { scrollIntoView?: unknown })
1912
+ .scrollIntoView;
1913
+ });
1914
+
1915
+ test("lifts the report's Summary into its own section above the report", async () => {
1916
+ postMock.mockResolvedValue(structuredResponse() as never);
1917
+
1918
+ renderPanel();
1919
+ await flush();
1920
+
1921
+ const summary: HTMLElement = screen.getByRole("region", {
1922
+ name: "Investigation summary",
1923
+ });
1924
+ expect(summary).toHaveTextContent(
1925
+ "the connection pool ran dry after the 18:00 deploy [C1].",
1926
+ );
1927
+ expect(within(summary).queryByText("TL;DR")).toBeNull();
1928
+
1929
+ const report: HTMLElement = screen.getByRole("region", {
1930
+ name: "Investigation report",
1931
+ });
1932
+ expect(
1933
+ within(report)
1934
+ .getAllByRole("heading", { level: 4 })
1935
+ .map((heading: HTMLElement): string => {
1936
+ return heading.textContent || "";
1937
+ }),
1938
+ ).toEqual(["Most likely root cause", "Suggested next steps"]);
1939
+ expect(report).not.toHaveTextContent("the connection pool ran dry");
1940
+ expect(
1941
+ summary.compareDocumentPosition(report) &
1942
+ Node.DOCUMENT_POSITION_FOLLOWING,
1943
+ ).toBeTruthy();
1944
+
1945
+ for (const props of allMarkdownProps()) {
1946
+ expect(props.safeMode).toBe(true);
1947
+ expect(props.text).not.toContain("Automated Root Cause Analysis");
1948
+ expect(props.text).not.toContain("Evidence checked");
1949
+ expect(props.text).not.toContain("Investigated automatically");
1950
+ }
1951
+ });
1952
+
1953
+ test("renders the evidence the API returns, below the report", async () => {
1954
+ postMock.mockResolvedValue(structuredResponse() as never);
1955
+
1956
+ renderPanel();
1957
+ await flush();
1958
+
1959
+ const evidence: HTMLElement = screen.getByRole("region", {
1960
+ name: "Evidence checked",
1961
+ });
1962
+ expect(within(evidence).getByText("2 queries")).toBeVisible();
1963
+ expect(
1964
+ within(evidence).getByRole("button", { name: /Active incidents/ }),
1965
+ ).toHaveAttribute("aria-expanded", "false");
1966
+ expect(
1967
+ screen
1968
+ .getByLabelText("Investigation report")
1969
+ .compareDocumentPosition(evidence) & Node.DOCUMENT_POSITION_FOLLOWING,
1970
+ ).toBeTruthy();
1971
+ // Rendering evidence never re-runs anything by itself.
1972
+ expect(evidencePosts()).toHaveLength(0);
1973
+ expect(jest.getTimerCount()).toBe(1);
1974
+ });
1975
+
1976
+ test("expanding a query POSTs its citation once and shows the rows", async () => {
1977
+ routePosts({
1978
+ investigation: (): unknown => {
1979
+ return Promise.resolve(structuredResponse());
1980
+ },
1981
+ evidence: (): unknown => {
1982
+ return Promise.resolve(
1983
+ evidenceRowsResponse("C1", "id | title\n1 | Checkout down"),
1984
+ );
1985
+ },
1986
+ });
1987
+
1988
+ renderPanel();
1989
+ await flush();
1990
+
1991
+ const toggle: HTMLElement = screen.getByRole("button", {
1992
+ name: /Active incidents \(7 total\)/,
1993
+ });
1994
+ fireEvent.click(toggle);
1995
+ await flush();
1996
+
1997
+ expect(evidencePosts()).toHaveLength(1);
1998
+ expect(evidencePosts()[0]!.data).toEqual({
1999
+ subjectType: "incident",
2000
+ subjectId: INCIDENT_ID.toString(),
2001
+ investigationRunId: RUN_ID,
2002
+ citationId: "C1",
2003
+ });
2004
+ expect(screen.getByText(/Checkout down/)).toBeVisible();
2005
+
2006
+ // Collapse and re-open: served from the cache.
2007
+ fireEvent.click(toggle);
2008
+ fireEvent.click(toggle);
2009
+ await flush();
2010
+
2011
+ expect(evidencePosts()).toHaveLength(1);
2012
+ expect(investigationPostCount()).toBe(1);
2013
+ });
2014
+
2015
+ test("falls back to the report's own Evidence checked list for an older API", async () => {
2016
+ postMock.mockResolvedValue(
2017
+ completedResponse({ analysisMarkdown: STRUCTURED_REPORT }) as never,
2018
+ );
2019
+
2020
+ renderPanel();
2021
+ await flush();
2022
+
2023
+ const evidence: HTMLElement = screen.getByRole("region", {
2024
+ name: "Evidence checked",
2025
+ });
2026
+ expect(evidence).toHaveTextContent("Active incidents (7 total)");
2027
+ expect(evidence).toHaveTextContent("Logs 17:20 – 18:20 (1 shown)");
2028
+ expect(within(evidence).queryAllByRole("button")).toHaveLength(0);
2029
+ // No references from an older API, so numbers stay plain text.
2030
+ expect(
2031
+ lastInlineReferences().renderEventReference!({
2032
+ kind: null,
2033
+ number: 6954,
2034
+ text: "#6954",
2035
+ }),
2036
+ ).toBeNull();
2037
+ });
2038
+
2039
+ test("picks up evidence that arrives on a later poll", async () => {
2040
+ postMock
2041
+ .mockResolvedValueOnce(
2042
+ completedResponse({ analysisMarkdown: STRUCTURED_REPORT }) as never,
2043
+ )
2044
+ .mockResolvedValue(structuredResponse() as never);
2045
+
2046
+ renderPanel();
2047
+ await flush();
2048
+ expect(
2049
+ within(screen.getByLabelText("Evidence checked")).queryAllByRole(
2050
+ "button",
2051
+ ),
2052
+ ).toHaveLength(0);
2053
+
2054
+ await tick(SETTLED_POLL_INTERVAL_MS);
2055
+
2056
+ expect(
2057
+ within(screen.getByLabelText("Evidence checked")).getAllByRole("button"),
2058
+ ).toHaveLength(2);
2059
+ });
2060
+
2061
+ test("never shows evidence without the report it belongs to", async () => {
2062
+ postMock.mockResolvedValue(
2063
+ completedResponse({
2064
+ analysisMarkdown: null,
2065
+ isAnalysisPending: true,
2066
+ evidence: EVIDENCE_ITEMS,
2067
+ references: REFERENCES,
2068
+ }) as never,
2069
+ );
2070
+
2071
+ renderPanel();
2072
+ await flush();
2073
+
2074
+ expect(screen.getByText("Preparing the final report")).toBeVisible();
2075
+ expect(screen.queryByLabelText("Evidence checked")).toBeNull();
2076
+ });
2077
+
2078
+ test("drops evidence when the report disappears on a later poll", async () => {
2079
+ postMock
2080
+ .mockResolvedValueOnce(structuredResponse() as never)
2081
+ .mockResolvedValue(
2082
+ structuredResponse({ analysisMarkdown: null }) as never,
2083
+ );
2084
+
2085
+ renderPanel();
2086
+ await flush();
2087
+ expect(screen.getByLabelText("Evidence checked")).toBeInTheDocument();
2088
+
2089
+ await tick(SETTLED_POLL_INTERVAL_MS);
2090
+
2091
+ expect(screen.queryByLabelText("Evidence checked")).toBeNull();
2092
+ expect(
2093
+ screen.getByText("No investigation report was published."),
2094
+ ).toBeVisible();
2095
+ });
2096
+
2097
+ test("ignores malformed evidence and references from the API", async () => {
2098
+ postMock.mockResolvedValue(
2099
+ completedResponse({
2100
+ analysisMarkdown: STRUCTURED_REPORT,
2101
+ evidence: [
2102
+ { citationId: "not-a-citation", toolName: "search_logs" },
2103
+ { citationId: "C1" },
2104
+ ] as unknown as JSONArray,
2105
+ references: [
2106
+ { kind: "incident", number: 6954, id: "javascript:alert(1)" },
2107
+ ] as unknown as JSONArray,
2108
+ }) as never,
2109
+ );
2110
+
2111
+ renderPanel();
2112
+ await flush();
2113
+
2114
+ // Nothing valid survived, so the legacy list and plain numbers are used.
2115
+ expect(
2116
+ within(screen.getByLabelText("Evidence checked")).queryAllByRole(
2117
+ "button",
2118
+ ),
2119
+ ).toHaveLength(0);
2120
+ expect(
2121
+ lastInlineReferences().renderEventReference!({
2122
+ kind: "incident",
2123
+ number: 6954,
2124
+ text: "#6954",
2125
+ }),
2126
+ ).toBeNull();
2127
+ });
2128
+
2129
+ test("a citation chip expands, scrolls to and highlights its evidence row", async () => {
2130
+ routePosts({
2131
+ investigation: (): unknown => {
2132
+ return Promise.resolve(structuredResponse());
2133
+ },
2134
+ });
2135
+
2136
+ renderPanel();
2137
+ await flush();
2138
+ expect(jest.getTimerCount()).toBe(1);
2139
+
2140
+ const chip: React.ReactElement | null =
2141
+ lastInlineReferences().renderCitation!("C2");
2142
+ expect(chip).not.toBeNull();
2143
+ render(chip!);
2144
+
2145
+ const chipButton: HTMLElement = screen.getByRole("button", {
2146
+ name: "Citation C2: Logs 17:20 – 18:20 (1 shown)",
2147
+ });
2148
+ expect(chipButton).toHaveAttribute("title", "Logs 17:20 – 18:20 (1 shown)");
2149
+
2150
+ fireEvent.click(chipButton);
2151
+ await flush();
2152
+
2153
+ const toggle: HTMLElement = within(
2154
+ screen.getByLabelText("Evidence checked"),
2155
+ ).getByRole("button", { name: /Logs 17:20/ });
2156
+ expect(toggle).toHaveAttribute("aria-expanded", "true");
2157
+ expect(toggle.closest("li")).toHaveAttribute("data-highlighted", "true");
2158
+ expect(scrollIntoViewMock).toHaveBeenCalledWith({
2159
+ block: "nearest",
2160
+ behavior: "smooth",
2161
+ });
2162
+ expect(evidencePosts()).toHaveLength(1);
2163
+ expect(evidencePosts()[0]!.data["citationId"]).toBe("C2");
2164
+ // The settled poll plus the single highlight timer.
2165
+ expect(jest.getTimerCount()).toBe(2);
2166
+
2167
+ await tick(2000);
2168
+
2169
+ expect(toggle.closest("li")).not.toHaveAttribute("data-highlighted");
2170
+ expect(jest.getTimerCount()).toBe(1);
2171
+ });
2172
+
2173
+ test("leaves a citation that is not in the evidence as plain text", async () => {
2174
+ postMock.mockResolvedValue(structuredResponse() as never);
2175
+
2176
+ renderPanel();
2177
+ await flush();
2178
+
2179
+ expect(lastInlineReferences().renderCitation!("C9")).toBeNull();
2180
+ expect(lastInlineReferences().renderCitation!("C1")).not.toBeNull();
2181
+ });
2182
+
2183
+ test("links a referenced incident number to that incident", async () => {
2184
+ postMock.mockResolvedValue(structuredResponse() as never);
2185
+
2186
+ renderPanel();
2187
+ await flush();
2188
+
2189
+ const link: React.ReactElement | null = lastInlineReferences()
2190
+ .renderEventReference!({
2191
+ kind: null,
2192
+ number: 6954,
2193
+ text: "#6954",
2194
+ });
2195
+ expect(link).not.toBeNull();
2196
+ render(link!);
2197
+
2198
+ const anchor: HTMLElement = screen.getByRole("link", {
2199
+ name: "INC-6954 · Checkout pool exhausted · Resolved",
2200
+ });
2201
+ expect(anchor).toHaveTextContent("#6954");
2202
+ expect(anchor.getAttribute("href")).toMatch(
2203
+ new RegExp(`/incidents/${PRIOR_INCIDENT_ID}$`),
2204
+ );
2205
+ expect(
2206
+ lastInlineReferences().renderEventReference!({
2207
+ kind: "incident",
2208
+ number: 1,
2209
+ text: "#1",
2210
+ }),
2211
+ ).toBeNull();
2212
+ });
2213
+
2214
+ test("resolves an unqualified number as an alert on an alert investigation", async () => {
2215
+ postMock.mockResolvedValue(structuredResponse() as never);
2216
+
2217
+ renderPanel({ subjectType: "alert", subjectId: ALERT_ID });
2218
+ await flush();
2219
+
2220
+ const link: React.ReactElement | null = lastInlineReferences()
2221
+ .renderEventReference!({
2222
+ kind: null,
2223
+ number: 6954,
2224
+ text: "#6954",
2225
+ });
2226
+ render(link!);
2227
+
2228
+ expect(
2229
+ screen
2230
+ .getByRole("link", { name: "#6954 · Webhook failures" })
2231
+ .getAttribute("href"),
2232
+ ).toMatch(new RegExp(`/alerts/${PRIOR_ALERT_ID}$`));
2233
+ });
2234
+
2235
+ test("ignores evidence rows that resolve after navigating to another subject", async () => {
2236
+ const staleRows: Deferred<ApiResponse> = createDeferred<ApiResponse>();
2237
+ let evidenceCalls: number = 0;
2238
+ routePosts({
2239
+ investigation: (request: EvidencePostRequest): unknown => {
2240
+ return Promise.resolve(
2241
+ request.data["alertId"]
2242
+ ? structuredResponse({ runId: NEXT_RUN_ID })
2243
+ : structuredResponse(),
2244
+ );
2245
+ },
2246
+ evidence: (): unknown => {
2247
+ evidenceCalls += 1;
2248
+ return evidenceCalls === 1
2249
+ ? staleRows.promise
2250
+ : Promise.resolve(
2251
+ evidenceRowsResponse("C1", "id | title\n9 | Alert subject rows"),
2252
+ );
2253
+ },
2254
+ });
2255
+
2256
+ const view: ReturnType<typeof render> = renderPanel();
2257
+ await flush();
2258
+ fireEvent.click(
2259
+ screen.getByRole("button", { name: /Active incidents \(7 total\)/ }),
2260
+ );
2261
+ await flush();
2262
+ expect(evidencePosts()).toHaveLength(1);
2263
+
2264
+ view.rerender(
2265
+ <InvestigationPanel subjectType="alert" subjectId={ALERT_ID} />,
2266
+ );
2267
+ await flush();
2268
+ await resolveDeferred(
2269
+ staleRows,
2270
+ evidenceRowsResponse("C1", "id | title\n1 | Previous subject rows"),
2271
+ );
2272
+
2273
+ expect(screen.queryByText(/Previous subject rows/)).toBeNull();
2274
+ const toggle: HTMLElement = screen.getByRole("button", {
2275
+ name: /Active incidents \(7 total\)/,
2276
+ });
2277
+ expect(toggle).toHaveAttribute("aria-expanded", "false");
2278
+
2279
+ fireEvent.click(toggle);
2280
+ await flush();
2281
+
2282
+ expect(screen.getByText(/Alert subject rows/)).toBeVisible();
2283
+ expect(screen.queryByText(/Previous subject rows/)).toBeNull();
2284
+ expect(evidencePosts()[1]!.data).toEqual({
2285
+ subjectType: "alert",
2286
+ subjectId: ALERT_ID.toString(),
2287
+ investigationRunId: NEXT_RUN_ID,
2288
+ citationId: "C1",
2289
+ });
2290
+ });
2291
+
2292
+ test("renders a hostile report only through the safe viewer", async () => {
2293
+ const hostile: string = [
2294
+ '**Summary** — <img src=x onerror="window.__panelPwned = true"> [click](https://evil.example)',
2295
+ "",
2296
+ "**Most likely root cause** — ![pixel](https://evil.example/p.png) [C1]",
2297
+ "",
2298
+ "[C1]: https://evil.example/exfil",
2299
+ ].join("\n");
2300
+ postMock.mockResolvedValue(
2301
+ structuredResponse({ analysisMarkdown: hostile }) as never,
2302
+ );
2303
+
2304
+ const { container } = renderPanel();
2305
+ await flush();
2306
+
2307
+ expect(allMarkdownProps().length).toBeGreaterThan(0);
2308
+ for (const props of allMarkdownProps()) {
2309
+ expect(props.safeMode).toBe(true);
2310
+ }
2311
+ expect(container.querySelector("img")).toBeNull();
2312
+ expect(container.querySelector("a")).toBeNull();
2313
+ expect(
2314
+ (window as unknown as { __panelPwned?: boolean }).__panelPwned,
2315
+ ).toBeUndefined();
2316
+ });
2317
+
2318
+ test("names the model and asks for verification in the usage strip", async () => {
2319
+ postMock.mockResolvedValue(structuredResponse() as never);
2320
+
2321
+ renderPanel();
2322
+ await flush();
2323
+
2324
+ const usage: HTMLElement = screen.getByLabelText("Investigation usage");
2325
+ expect(usage).toHaveTextContent("Model gpt-5");
2326
+ expect(usage).toHaveTextContent(
2327
+ "AI-generated first pass — verify before acting.",
2328
+ );
2329
+ expect(usage).toHaveTextContent("2 telemetry queries");
2330
+ });
2331
+
2332
+ test("does not ask to verify a report that does not exist", async () => {
2333
+ postMock.mockResolvedValue(
2334
+ successfulResponse(
2335
+ investigationPayload({
2336
+ status: AIRunStatus.Error,
2337
+ errorMessage: "The provider timed out.",
2338
+ toolCallCount: 3,
2339
+ }),
2340
+ ) as never,
2341
+ );
2342
+
2343
+ renderPanel();
2344
+ await flush();
2345
+
2346
+ const usage: HTMLElement = screen.getByLabelText("Investigation usage");
2347
+ expect(usage).not.toHaveTextContent("verify before acting");
2348
+ expect(usage).not.toHaveTextContent("Model");
2349
+ });
2350
+
2351
+ test("titles the act and rate blocks with headings instead of icon-in-paragraph", async () => {
2352
+ postMock.mockResolvedValue(completedResponse() as never);
2353
+
2354
+ const { container } = renderPanel();
2355
+ await flush();
2356
+
2357
+ expect(
2358
+ screen.getByRole("heading", { name: "Act on this investigation" }),
2359
+ ).toBeVisible();
2360
+ expect(
2361
+ screen.getByRole("heading", { name: "Rate this investigation" }),
2362
+ ).toBeVisible();
2363
+ expect(container.querySelectorAll("p div")).toHaveLength(0);
2364
+ });
2365
+ });
2366
+
2367
+ describe("InvestigationPanel report summary callback", () => {
2368
+ function nonNullCalls(callback: MockFunction): Array<unknown> {
2369
+ return callback.mock.calls
2370
+ .map((call: Array<unknown>): unknown => {
2371
+ return call[0];
2372
+ })
2373
+ .filter((value: unknown): boolean => {
2374
+ return value !== null;
2375
+ });
2376
+ }
2377
+
2378
+ test("reports the TL;DR of a completed report", async () => {
2379
+ const onReportSummaryChange: MockFunction = getJestMockFunction();
2380
+ postMock.mockResolvedValue(
2381
+ structuredResponse({ analysisTldr: TLDR }) as never,
2382
+ );
2383
+
2384
+ renderPanel({ onReportSummaryChange });
2385
+ await flush();
2386
+
2387
+ expect(onReportSummaryChange).toHaveBeenLastCalledWith(TLDR);
2388
+ expect(nonNullCalls(onReportSummaryChange)).toEqual([TLDR]);
2389
+ });
2390
+
2391
+ test("falls back to the report's Summary as plain text without a TL;DR", async () => {
2392
+ const onReportSummaryChange: MockFunction = getJestMockFunction();
2393
+ postMock.mockResolvedValue(structuredResponse() as never);
2394
+
2395
+ renderPanel({ onReportSummaryChange });
2396
+ await flush();
2397
+
2398
+ expect(onReportSummaryChange).toHaveBeenLastCalledWith(REPORT_SUMMARY);
2399
+ });
2400
+
2401
+ test("bounds a long Summary", async () => {
2402
+ const onReportSummaryChange: MockFunction = getJestMockFunction();
2403
+ postMock.mockResolvedValue(
2404
+ completedResponse({
2405
+ analysisMarkdown: `**Summary** — ${"pool exhausted ".repeat(60)}\n\n**Root cause** — a deploy.`,
2406
+ }) as never,
2407
+ );
2408
+
2409
+ renderPanel({ onReportSummaryChange });
2410
+ await flush();
2411
+
2412
+ const summary: string = nonNullCalls(onReportSummaryChange)[0] as string;
2413
+ expect(summary.length).toBeLessThanOrEqual(280);
2414
+ expect(summary.endsWith("…")).toBe(true);
2415
+ });
2416
+
2417
+ test("reports null when a report has neither a TL;DR nor a Summary", async () => {
2418
+ const onReportSummaryChange: MockFunction = getJestMockFunction();
2419
+ postMock.mockResolvedValue(completedResponse() as never);
2420
+
2421
+ renderPanel({ onReportSummaryChange });
2422
+ await flush();
2423
+
2424
+ expect(onReportSummaryChange).toHaveBeenCalledWith(null);
2425
+ expect(nonNullCalls(onReportSummaryChange)).toEqual([]);
2426
+ });
2427
+
2428
+ test("reports null while the run is active or the report is pending", async () => {
2429
+ const onReportSummaryChange: MockFunction = getJestMockFunction();
2430
+ postMock
2431
+ .mockResolvedValueOnce(
2432
+ successfulResponse(
2433
+ investigationPayload({
2434
+ status: AIRunStatus.Running,
2435
+ analysisTldr: TLDR,
2436
+ }),
2437
+ ) as never,
2438
+ )
2439
+ .mockResolvedValueOnce(
2440
+ completedResponse({
2441
+ analysisMarkdown: null,
2442
+ analysisTldr: TLDR,
2443
+ isAnalysisPending: true,
2444
+ }) as never,
2445
+ )
2446
+ .mockResolvedValue(structuredResponse({ analysisTldr: TLDR }) as never);
2447
+
2448
+ renderPanel({ onReportSummaryChange });
2449
+ await flush();
2450
+ await advanceFastPolls();
2451
+
2452
+ expect(nonNullCalls(onReportSummaryChange)).toEqual([]);
2453
+
2454
+ await advanceFastPolls();
2455
+
2456
+ expect(onReportSummaryChange).toHaveBeenLastCalledWith(TLDR);
2457
+ });
2458
+
2459
+ test("does not repeat an unchanged summary across polls", async () => {
2460
+ const onReportSummaryChange: MockFunction = getJestMockFunction();
2461
+ postMock.mockResolvedValue(
2462
+ structuredResponse({ analysisTldr: TLDR }) as never,
2463
+ );
2464
+
2465
+ renderPanel({ onReportSummaryChange });
2466
+ await flush();
2467
+ const callsAfterLoad: number = onReportSummaryChange.mock.calls.length;
2468
+
2469
+ await tick(SETTLED_POLL_INTERVAL_MS);
2470
+ await tick(SETTLED_POLL_INTERVAL_MS);
2471
+
2472
+ expect(investigationPostCount()).toBe(3);
2473
+ expect(onReportSummaryChange).toHaveBeenCalledTimes(callsAfterLoad);
2474
+ });
2475
+
2476
+ test("reports null the moment the subject changes, then the new summary", async () => {
2477
+ const onReportSummaryChange: MockFunction = getJestMockFunction();
2478
+ const nextSubject: Deferred<ApiResponse> = createDeferred<ApiResponse>();
2479
+ const nextTldr: string = "The webhook signer rotated its key.";
2480
+ postMock
2481
+ .mockResolvedValueOnce(
2482
+ structuredResponse({ analysisTldr: TLDR }) as never,
2483
+ )
2484
+ .mockReturnValueOnce(nextSubject.promise as never);
2485
+
2486
+ const view: ReturnType<typeof render> = renderPanel({
2487
+ onReportSummaryChange,
2488
+ });
2489
+ await flush();
2490
+ expect(onReportSummaryChange).toHaveBeenLastCalledWith(TLDR);
2491
+
2492
+ view.rerender(
2493
+ <InvestigationPanel
2494
+ subjectType="alert"
2495
+ subjectId={ALERT_ID}
2496
+ onReportSummaryChange={onReportSummaryChange}
2497
+ />,
2498
+ );
2499
+ await flush();
2500
+
2501
+ expect(onReportSummaryChange).toHaveBeenLastCalledWith(null);
2502
+
2503
+ await resolveDeferred(
2504
+ nextSubject,
2505
+ structuredResponse({ runId: NEXT_RUN_ID, analysisTldr: nextTldr }),
2506
+ );
2507
+
2508
+ expect(onReportSummaryChange).toHaveBeenLastCalledWith(nextTldr);
2509
+ });
2510
+
2511
+ test("reports null when the report disappears", async () => {
2512
+ const onReportSummaryChange: MockFunction = getJestMockFunction();
2513
+ postMock
2514
+ .mockResolvedValueOnce(
2515
+ structuredResponse({ analysisTldr: TLDR }) as never,
2516
+ )
2517
+ .mockResolvedValue(
2518
+ structuredResponse({
2519
+ analysisMarkdown: null,
2520
+ analysisTldr: TLDR,
2521
+ }) as never,
2522
+ );
2523
+
2524
+ renderPanel({ onReportSummaryChange });
2525
+ await flush();
2526
+ expect(onReportSummaryChange).toHaveBeenLastCalledWith(TLDR);
2527
+
2528
+ await tick(SETTLED_POLL_INTERVAL_MS);
2529
+
2530
+ expect(onReportSummaryChange).toHaveBeenLastCalledWith(null);
2531
+ });
2532
+
2533
+ test("uses the latest callback without re-reporting", async () => {
2534
+ const first: MockFunction = getJestMockFunction();
2535
+ const second: MockFunction = getJestMockFunction();
2536
+ postMock.mockResolvedValue(
2537
+ structuredResponse({ analysisTldr: TLDR }) as never,
2538
+ );
2539
+
2540
+ const view: ReturnType<typeof render> = renderPanel({
2541
+ onReportSummaryChange: first,
2542
+ });
2543
+ await flush();
2544
+ expect(first).toHaveBeenLastCalledWith(TLDR);
2545
+
2546
+ view.rerender(
2547
+ <InvestigationPanel
2548
+ subjectType="incident"
2549
+ subjectId={INCIDENT_ID}
2550
+ onReportSummaryChange={second}
2551
+ />,
2552
+ );
2553
+ await flush();
2554
+ expect(second).not.toHaveBeenCalled();
2555
+
2556
+ postMock.mockResolvedValue(
2557
+ structuredResponse({ analysisTldr: "A newer summary." }) as never,
2558
+ );
2559
+ await tick(SETTLED_POLL_INTERVAL_MS);
2560
+
2561
+ expect(second).toHaveBeenLastCalledWith("A newer summary.");
2562
+ });
2563
+ });