@oneuptime/common 12.0.23 → 12.0.24

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 (294) hide show
  1. package/Models/DatabaseModels/DetectionRule.ts +55 -0
  2. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +27 -7
  3. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +67 -0
  4. package/Models/DatabaseModels/Project.ts +68 -0
  5. package/Models/DatabaseModels/User.ts +68 -0
  6. package/Server/API/TelemetryAPI.ts +29 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.ts +28 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.ts +49 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.ts +33 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  11. package/Server/Middleware/GzipRequestBody.ts +311 -0
  12. package/Server/Middleware/MultipartFormData.ts +87 -3
  13. package/Server/Services/DetectionRuleService.ts +73 -6
  14. package/Server/Services/Index.ts +205 -0
  15. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +59 -0
  16. package/Server/Services/NetworkDeviceService.ts +148 -0
  17. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +65 -0
  18. package/Server/Services/OnCallDutyPolicyFeedService.ts +1 -1
  19. package/Server/Services/ProjectService.ts +29 -19
  20. package/Server/Services/SecurityEventService.ts +90 -13
  21. package/Server/Services/StatusPageResourceService.ts +223 -0
  22. package/Server/Services/TelemetryAttributeService.ts +17 -0
  23. package/Server/Services/UserService.ts +4 -6
  24. package/Server/Types/Markdown.ts +161 -67
  25. package/Server/Utils/AI/Toolbox/OnCallTools.ts +12 -4
  26. package/Server/Utils/AnalyticsDatabase/Statement.ts +13 -1
  27. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +297 -6
  28. package/Server/Utils/Attribution.ts +4 -0
  29. package/Server/Utils/Marketing/MarketingEventUtil.ts +45 -7
  30. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +55 -3
  31. package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +21 -0
  32. package/Server/Utils/StartServer.ts +12 -32
  33. package/Server/Utils/Telemetry/LlmCostBudgetEvaluator.ts +101 -4
  34. package/Server/Utils/Telemetry/LlmMetricSpend.ts +130 -0
  35. package/Server/Views/Partials/AnalyticsConsent.ejs +159 -102
  36. package/Server/Views/Partials/Head.ejs +2 -1
  37. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +776 -38
  38. package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +359 -0
  39. package/Tests/App/Dashboard/CorrelateGraph.test.tsx +865 -0
  40. package/Tests/App/Dashboard/CorrelationGraph.test.ts +346 -0
  41. package/Tests/App/Dashboard/CriteriaFilterConditionDropdown.test.tsx +256 -0
  42. package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +738 -0
  43. package/Tests/App/Dashboard/CriteriaFilterMonitorTypeChange.test.ts +1122 -0
  44. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +283 -0
  45. package/Tests/App/Dashboard/ExternalStatusPageCriteriaFilter.test.ts +407 -0
  46. package/Tests/App/Dashboard/MetricSeriesInvestigateMenu.test.tsx +5 -14
  47. package/Tests/App/Dashboard/MonitorCriteriaActionToggles.test.tsx +426 -0
  48. package/Tests/App/Dashboard/MonitorStepsCriteriaAlignmentWiring.test.tsx +352 -0
  49. package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +278 -0
  50. package/Tests/App/Dashboard/OnCallLayerShiftPreviewOverrides.test.ts +237 -0
  51. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +2 -2
  52. package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +460 -0
  53. package/Tests/App/Dashboard/SecurityEventAttributeUtil.test.ts +171 -0
  54. package/Tests/App/Dashboard/SecurityEventCorrelation.test.ts +857 -0
  55. package/Tests/App/Dashboard/SecurityEventDetailObservables.test.tsx +194 -0
  56. package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +124 -0
  57. package/Tests/App/Dashboard/SecurityEventsMonitorStepForm.test.tsx +79 -19
  58. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +382 -0
  59. package/Tests/App/StatusPage/BulkAddStatusPageMonitors.test.ts +216 -0
  60. package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +590 -11
  61. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +757 -0
  62. package/Tests/Models/DiscoveryScanNameColumn.test.ts +293 -0
  63. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +564 -0
  64. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +120 -4
  65. package/Tests/Server/Middleware/GzipRequestBody.test.ts +725 -0
  66. package/Tests/Server/Middleware/MultipartFormData.test.ts +298 -0
  67. package/Tests/Server/Services/AddDetectionRuleDistinctCountColumnsMigration.test.ts +311 -0
  68. package/Tests/Server/Services/DetectionRuleService.test.ts +134 -2
  69. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +7 -1
  70. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +131 -0
  71. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +194 -0
  72. package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +800 -0
  73. package/Tests/Server/Services/OnCallScheduleAttachRosterRefresh.test.ts +244 -0
  74. package/Tests/Server/Services/SecurityEventService.test.ts +376 -0
  75. package/Tests/Server/Services/StatusPageResourceDuplicates.test.ts +703 -0
  76. package/Tests/Server/Services/TelemetryAttributeServiceSecurityEvent.test.ts +256 -0
  77. package/Tests/Server/Types/Workflow/Components/ComponentRegistryParity.test.ts +417 -0
  78. package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWhereOperators.test.ts +677 -0
  79. package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +43 -0
  80. package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +15 -11
  81. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +369 -8
  82. package/Tests/Server/Utils/SecurityEvent/SigmaClickhouseCompiler.test.ts +35 -0
  83. package/Tests/Server/Utils/Telemetry/LlmCostBudgetEvaluator.test.ts +368 -4
  84. package/Tests/Server/Utils/Telemetry/LlmMetricSpend.test.ts +245 -0
  85. package/Tests/Server/Views/AnalyticsConsentPartial.test.ts +48 -5
  86. package/Tests/Types/Code/YamlSyntax.test.ts +396 -0
  87. package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +957 -0
  88. package/Tests/Types/Monitor/MonitorCriteriaActionValidation.test.ts +598 -0
  89. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +49 -0
  90. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +6 -6
  91. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +4 -4
  92. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +4 -3
  93. package/Tests/Types/Telemetry/LlmMetricConventions.test.ts +193 -0
  94. package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +0 -12
  95. package/Tests/UI/Components/CardModelDetailEdit.test.tsx +1 -17
  96. package/Tests/UI/Components/CodeEditor.test.tsx +474 -10
  97. package/Tests/UI/Components/Detail/YamlField.test.tsx +105 -0
  98. package/Tests/UI/Components/EntityDropdownLabelsBulkAdd.test.tsx +319 -0
  99. package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +231 -0
  100. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +1 -0
  101. package/Tests/UI/Components/Forms/ValidationYAML.test.ts +234 -0
  102. package/Tests/UI/Components/ModelTable/AttributeColumns.test.tsx +573 -0
  103. package/Tests/UI/Components/ModelTable/BaseModelTableAttributeColumns.test.tsx +824 -0
  104. package/Tests/UI/Components/ModelTable/ColumnCustomizationModalAddableColumns.test.tsx +707 -0
  105. package/Tests/UI/Components/SideOver.test.tsx +1 -1
  106. package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +294 -0
  107. package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +436 -0
  108. package/Tests/UI/Components/TableBulkCsvExport.test.tsx +6 -2
  109. package/Tests/UI/Components/Toggle.test.tsx +25 -0
  110. package/Tests/UI/Components/YamlEditor.test.tsx +847 -0
  111. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +252 -0
  112. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +221 -0
  113. package/Tests/Utils/NetworkDiscovery/ScanNameUtil.test.ts +312 -0
  114. package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +468 -0
  115. package/Tests/Utils/Telemetry/LlmMetricQuery.test.ts +472 -0
  116. package/Types/Code/YamlSyntax.ts +396 -0
  117. package/Types/Exception/ExceptionCode.ts +1 -0
  118. package/Types/Exception/PayloadTooLargeException.ts +8 -0
  119. package/Types/Marketing/Attribution.ts +10 -0
  120. package/Types/Marketing/MarketingEvent.ts +4 -0
  121. package/Types/Monitor/MonitorCriteriaInstance.ts +116 -56
  122. package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +2 -1
  123. package/Types/SecurityEvent/DetectionFindingConstants.ts +11 -0
  124. package/Types/Telemetry/LlmMetricConventions.ts +124 -0
  125. package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +3 -0
  126. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +10 -1
  127. package/UI/Components/CodeEditor/CodeEditor.tsx +241 -79
  128. package/UI/Components/CodeEditor/YamlEditor.tsx +369 -0
  129. package/UI/Components/Detail/Detail.tsx +10 -0
  130. package/UI/Components/EntityDropdown/EntityDropdown.tsx +33 -0
  131. package/UI/Components/Forms/Fields/FormField.tsx +31 -0
  132. package/UI/Components/Forms/Types/Field.ts +8 -0
  133. package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
  134. package/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.ts +2 -0
  135. package/UI/Components/Forms/Validation.ts +46 -0
  136. package/UI/Components/Input/Input.tsx +3 -0
  137. package/UI/Components/ModelTable/AttributeColumns.tsx +321 -0
  138. package/UI/Components/ModelTable/BaseModelTable.tsx +263 -14
  139. package/UI/Components/ModelTable/Column.ts +8 -0
  140. package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +310 -0
  141. package/UI/Components/ModelTable/ColumnPreference.ts +13 -1
  142. package/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.tsx +2 -2
  143. package/UI/Components/SideOver/SideOver.tsx +5 -5
  144. package/UI/Components/StatusPage/ResourceGrid.tsx +82 -2
  145. package/UI/Components/StatusPage/ResourceList.tsx +197 -38
  146. package/UI/Components/Toggle/Toggle.tsx +9 -1
  147. package/UI/Components/Types/FieldType.ts +1 -0
  148. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +73 -1
  149. package/Utils/NetworkDiscovery/ScanNameUtil.ts +181 -0
  150. package/Utils/StatusPage/ResourceExplorer.ts +258 -0
  151. package/Utils/Telemetry/LlmMetricQuery.ts +204 -0
  152. package/build/dist/Models/DatabaseModels/DetectionRule.js +57 -0
  153. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  154. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +27 -7
  155. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
  156. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +69 -0
  157. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  158. package/build/dist/Models/DatabaseModels/Project.js +76 -0
  159. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  160. package/build/dist/Models/DatabaseModels/User.js +76 -0
  161. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  162. package/build/dist/Server/API/TelemetryAPI.js +17 -0
  163. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  164. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js +21 -0
  165. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js.map +1 -0
  166. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js +42 -0
  167. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js.map +1 -0
  168. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js +22 -0
  169. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js.map +1 -0
  170. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  171. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  172. package/build/dist/Server/Middleware/GzipRequestBody.js +224 -0
  173. package/build/dist/Server/Middleware/GzipRequestBody.js.map +1 -0
  174. package/build/dist/Server/Middleware/MultipartFormData.js +71 -2
  175. package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
  176. package/build/dist/Server/Services/DetectionRuleService.js +49 -4
  177. package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
  178. package/build/dist/Server/Services/Index.js +204 -0
  179. package/build/dist/Server/Services/Index.js.map +1 -1
  180. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +50 -0
  181. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  182. package/build/dist/Server/Services/NetworkDeviceService.js +124 -0
  183. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  184. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +68 -13
  185. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  186. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js +1 -1
  187. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js.map +1 -1
  188. package/build/dist/Server/Services/ProjectService.js +25 -45
  189. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  190. package/build/dist/Server/Services/SecurityEventService.js +57 -5
  191. package/build/dist/Server/Services/SecurityEventService.js.map +1 -1
  192. package/build/dist/Server/Services/StatusPageResourceService.js +140 -0
  193. package/build/dist/Server/Services/StatusPageResourceService.js.map +1 -1
  194. package/build/dist/Server/Services/TelemetryAttributeService.js +17 -0
  195. package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
  196. package/build/dist/Server/Services/UserService.js +2 -12
  197. package/build/dist/Server/Services/UserService.js.map +1 -1
  198. package/build/dist/Server/Types/Markdown.js +147 -61
  199. package/build/dist/Server/Types/Markdown.js.map +1 -1
  200. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +12 -4
  201. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -1
  202. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +12 -1
  203. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  204. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +246 -9
  205. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  206. package/build/dist/Server/Utils/Attribution.js.map +1 -1
  207. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +27 -7
  208. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
  209. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +42 -7
  210. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  211. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +18 -0
  212. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
  213. package/build/dist/Server/Utils/StartServer.js +12 -21
  214. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  215. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js +76 -5
  216. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js.map +1 -1
  217. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js +102 -0
  218. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js.map +1 -0
  219. package/build/dist/Types/Code/YamlSyntax.js +212 -0
  220. package/build/dist/Types/Code/YamlSyntax.js.map +1 -0
  221. package/build/dist/Types/Exception/ExceptionCode.js +1 -0
  222. package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
  223. package/build/dist/Types/Exception/PayloadTooLargeException.js +8 -0
  224. package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -0
  225. package/build/dist/Types/Marketing/Attribution.js +10 -0
  226. package/build/dist/Types/Marketing/Attribution.js.map +1 -1
  227. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +112 -51
  228. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  229. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +2 -1
  230. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
  231. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +9 -0
  232. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
  233. package/build/dist/Types/Telemetry/LlmMetricConventions.js +98 -0
  234. package/build/dist/Types/Telemetry/LlmMetricConventions.js.map +1 -0
  235. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +1 -1
  236. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
  237. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +5 -2
  238. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  239. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +206 -76
  240. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  241. package/build/dist/UI/Components/CodeEditor/YamlEditor.js +201 -0
  242. package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -0
  243. package/build/dist/UI/Components/Detail/Detail.js +9 -0
  244. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  245. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +16 -1
  246. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  247. package/build/dist/UI/Components/Forms/Fields/FormField.js +14 -1
  248. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  249. package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
  250. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
  251. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
  252. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js +2 -0
  253. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js.map +1 -1
  254. package/build/dist/UI/Components/Forms/Validation.js +27 -0
  255. package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
  256. package/build/dist/UI/Components/Input/Input.js +1 -1
  257. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  258. package/build/dist/UI/Components/ModelTable/AttributeColumns.js +159 -0
  259. package/build/dist/UI/Components/ModelTable/AttributeColumns.js.map +1 -0
  260. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +179 -17
  261. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  262. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +133 -2
  263. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -1
  264. package/build/dist/UI/Components/ModelTable/ColumnPreference.js +7 -1
  265. package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -1
  266. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js +2 -2
  267. package/build/dist/UI/Components/SideOver/SideOver.js +5 -5
  268. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +28 -2
  269. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
  270. package/build/dist/UI/Components/StatusPage/ResourceList.js +87 -20
  271. package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
  272. package/build/dist/UI/Components/Toggle/Toggle.js +9 -1
  273. package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
  274. package/build/dist/UI/Components/Types/FieldType.js +1 -0
  275. package/build/dist/UI/Components/Types/FieldType.js.map +1 -1
  276. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +37 -1
  277. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
  278. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js +120 -0
  279. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js.map +1 -0
  280. package/build/dist/Utils/StatusPage/ResourceExplorer.js +171 -0
  281. package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -1
  282. package/build/dist/Utils/Telemetry/LlmMetricQuery.js +119 -0
  283. package/build/dist/Utils/Telemetry/LlmMetricQuery.js.map +1 -0
  284. package/jest.config.json +2 -0
  285. package/package.json +1 -1
  286. package/tsconfig.json +2 -1
  287. package/Tests/UI/Components/Toast.test.tsx +0 -197
  288. package/Tests/UI/Components/ToastStacking.test.tsx +0 -198
  289. package/UI/Components/Toast/Toast.tsx +0 -189
  290. package/UI/Components/Toast/ToastInit.tsx +0 -110
  291. package/build/dist/UI/Components/Toast/Toast.js +0 -123
  292. package/build/dist/UI/Components/Toast/Toast.js.map +0 -1
  293. package/build/dist/UI/Components/Toast/ToastInit.js +0 -53
  294. package/build/dist/UI/Components/Toast/ToastInit.js.map +0 -1
@@ -0,0 +1,426 @@
1
+ import "@testing-library/jest-dom";
2
+ import { cleanup, fireEvent, render, screen } from "@testing-library/react";
3
+ import React, { FunctionComponent, ReactElement } from "react";
4
+ import { afterEach, describe, expect, test } from "@jest/globals";
5
+
6
+ import MonitorCriteriaInstanceElement from "../../../../App/FeatureSet/Dashboard/src/Components/Form/Monitor/MonitorCriteriaInstance";
7
+ import FilterCondition from "../../../Types/Filter/FilterCondition";
8
+ import { CheckOn, FilterType } from "../../../Types/Monitor/CriteriaFilter";
9
+ import MonitorCriteria from "../../../Types/Monitor/MonitorCriteria";
10
+ import MonitorCriteriaInstance from "../../../Types/Monitor/MonitorCriteriaInstance";
11
+ import MonitorStep from "../../../Types/Monitor/MonitorStep";
12
+ import MonitorType from "../../../Types/Monitor/MonitorType";
13
+ import ObjectID from "../../../Types/ObjectID";
14
+ import { DropdownOption } from "../../../UI/Components/Dropdown/Dropdown";
15
+
16
+ /*
17
+ * Issues #3410 and #3413, driven through the real criteria form.
18
+ *
19
+ * The unit suite (Common/Tests/Types/Monitor/MonitorCriteriaActionValidation)
20
+ * pins what getValidationError does with a given criteria. This file pins the
21
+ * half that produced the bug reports: what the form actually puts INTO the
22
+ * criteria as the user clicks. Both defects lived in that gap —
23
+ *
24
+ * - flipping a switch on seeds a blank incident / alert row, and flipping it
25
+ * back off used to leave that row behind while hiding the fields to fix it;
26
+ * - the same seeding block ran on the way OFF too, so switching off an action
27
+ * that had no rows yet *added* one;
28
+ * - Toggle called its consumer's onChange twice per click, so the seeding
29
+ * ran twice.
30
+ *
31
+ * None of that is reachable from a type test, so it is driven here through the
32
+ * component the user clicks, with the parent's clone-on-change behaviour
33
+ * reproduced by the harness (MonitorCriteria.tsx rebuilds the array through
34
+ * MonitorCriteria.fromJSON on every change, which is what makes the child's
35
+ * props a fresh object on every keystroke).
36
+ */
37
+
38
+ const MONITOR_STATUS_ID: ObjectID = new ObjectID(
39
+ "11111111-1111-4111-8111-111111111111",
40
+ );
41
+ const OFFLINE_STATUS_ID: ObjectID = new ObjectID(
42
+ "44444444-4444-4444-8444-444444444444",
43
+ );
44
+ const INCIDENT_SEVERITY_ID: ObjectID = new ObjectID(
45
+ "22222222-2222-4222-8222-222222222222",
46
+ );
47
+ const ALERT_SEVERITY_ID: ObjectID = new ObjectID(
48
+ "33333333-3333-4333-8333-333333333333",
49
+ );
50
+
51
+ const CRITERIA_NAME: string = "Check if AWS Status Page is operational";
52
+
53
+ const MONITOR_STATUS_OPTIONS: Array<DropdownOption> = [
54
+ { value: MONITOR_STATUS_ID.toString(), label: "Operational" },
55
+ { value: OFFLINE_STATUS_ID.toString(), label: "Offline" },
56
+ ];
57
+
58
+ const INCIDENT_SEVERITY_OPTIONS: Array<DropdownOption> = [
59
+ { value: INCIDENT_SEVERITY_ID.toString(), label: "Critical" },
60
+ ];
61
+
62
+ const ALERT_SEVERITY_OPTIONS: Array<DropdownOption> = [
63
+ { value: ALERT_SEVERITY_ID.toString(), label: "Warning" },
64
+ ];
65
+
66
+ // The shape the ExternalStatusPage online criteria ships with.
67
+ function buildCriteria(
68
+ overrides?: Partial<NonNullable<MonitorCriteriaInstance["data"]>>,
69
+ ): MonitorCriteriaInstance {
70
+ const instance: MonitorCriteriaInstance = new MonitorCriteriaInstance();
71
+ instance.data = {
72
+ id: ObjectID.generate().toString(),
73
+ monitorStatusId: MONITOR_STATUS_ID,
74
+ filterCondition: FilterCondition.All,
75
+ filters: [
76
+ {
77
+ checkOn: CheckOn.IsOnline,
78
+ filterType: FilterType.True,
79
+ value: undefined,
80
+ },
81
+ ],
82
+ incidents: [],
83
+ alerts: [],
84
+ changeMonitorStatus: true,
85
+ createIncidents: false,
86
+ createAlerts: false,
87
+ isEnabled: true,
88
+ name: CRITERIA_NAME,
89
+ description: "Checks whether the external status page is healthy",
90
+ ...(overrides || {}),
91
+ };
92
+ return instance;
93
+ }
94
+
95
+ interface Harness {
96
+ // The criteria as the form last handed it up, i.e. what would be submitted.
97
+ latest: () => MonitorCriteriaInstance;
98
+ // The error the create form's customValidation would surface right now.
99
+ error: () => string | null;
100
+ }
101
+
102
+ function renderCriteria(initial: MonitorCriteriaInstance): Harness {
103
+ let latest: MonitorCriteriaInstance = initial;
104
+
105
+ const Wrapper: FunctionComponent = (): ReactElement => {
106
+ const [value, setValue] = React.useState<MonitorCriteriaInstance>(initial);
107
+
108
+ return (
109
+ <MonitorCriteriaInstanceElement
110
+ monitorType={MonitorType.Ping}
111
+ monitorStep={new MonitorStep()}
112
+ monitorStatusDropdownOptions={MONITOR_STATUS_OPTIONS}
113
+ incidentSeverityDropdownOptions={INCIDENT_SEVERITY_OPTIONS}
114
+ alertSeverityDropdownOptions={ALERT_SEVERITY_OPTIONS}
115
+ onCallPolicyDropdownOptions={[]}
116
+ labelDropdownOptions={[]}
117
+ teamDropdownOptions={[]}
118
+ userDropdownOptions={[]}
119
+ value={value}
120
+ onChange={(changed: MonitorCriteriaInstance) => {
121
+ /*
122
+ * MonitorCriteria.tsx does exactly this on every change: it rebuilds
123
+ * the criteria array through MonitorCriteria.fromJSON. Passing live
124
+ * instances makes that hop a pass-through (fromJSON returns its
125
+ * argument unchanged when it is already an instance), but keeping it
126
+ * means this harness is the real parent's code path rather than a
127
+ * simplified stand-in for it.
128
+ */
129
+ const rebuilt: MonitorCriteria = MonitorCriteria.fromJSON({
130
+ _type: "MonitorCriteria",
131
+ value: {
132
+ monitorCriteriaInstanceArray: [changed],
133
+ },
134
+ } as never);
135
+
136
+ latest = rebuilt.data!.monitorCriteriaInstanceArray[0]!;
137
+ setValue(latest);
138
+ }}
139
+ />
140
+ );
141
+ };
142
+
143
+ render(<Wrapper />);
144
+
145
+ return {
146
+ latest: (): MonitorCriteriaInstance => {
147
+ return latest;
148
+ },
149
+ error: (): string | null => {
150
+ return MonitorCriteriaInstance.getValidationError(
151
+ latest,
152
+ MonitorType.Ping,
153
+ );
154
+ },
155
+ };
156
+ }
157
+
158
+ function switchFor(name: RegExp): HTMLElement {
159
+ return screen.getByRole("switch", { name: name });
160
+ }
161
+
162
+ /*
163
+ * Picks an option out of the shared Dropdown, which wraps react-select: find
164
+ * the control by its placeholder, open the menu off its hidden text input, and
165
+ * click the option (react-select portals the menu, so screen. rather than
166
+ * within()).
167
+ */
168
+ function pickFromDropdown(placeholder: string, optionLabel: string): void {
169
+ const control: HTMLElement | null = screen
170
+ .getByText(placeholder)
171
+ .closest("div[class]");
172
+
173
+ if (!control) {
174
+ throw new Error(`No dropdown control found for placeholder ${placeholder}`);
175
+ }
176
+
177
+ const input: HTMLInputElement | null = control
178
+ .closest("div")
179
+ ?.parentElement?.querySelector("input") as HTMLInputElement | null;
180
+
181
+ if (!input) {
182
+ throw new Error(`No dropdown input found for placeholder ${placeholder}`);
183
+ }
184
+
185
+ fireEvent.keyDown(input, { key: "ArrowDown", code: "ArrowDown" });
186
+ fireEvent.click(screen.getByText(optionLabel));
187
+ }
188
+
189
+ const ALERT_SWITCH: RegExp = /When filters match, create an alert/;
190
+ const INCIDENT_SWITCH: RegExp = /When filters match, declare an incident/;
191
+ const STATUS_SWITCH: RegExp = /When filters match, change monitor status/;
192
+
193
+ describe("Monitor criteria action switches", () => {
194
+ afterEach(() => {
195
+ cleanup();
196
+ });
197
+
198
+ describe("issue #3413 - an action that is switched off must not block Next", () => {
199
+ test("declare an incident: on, then off, leaves the criteria valid", () => {
200
+ const harness: Harness = renderCriteria(buildCriteria());
201
+ expect(harness.error()).toBeNull();
202
+
203
+ fireEvent.click(switchFor(INCIDENT_SWITCH));
204
+ // Switching on seeds a blank row, which is what Next should block on.
205
+ expect(harness.latest().data?.createIncidents).toBe(true);
206
+ expect(harness.error()).toBe(
207
+ `Incident title is required for criteria "${CRITERIA_NAME}"`,
208
+ );
209
+
210
+ fireEvent.click(switchFor(INCIDENT_SWITCH));
211
+ expect(harness.latest().data?.createIncidents).toBe(false);
212
+ expect(harness.error()).toBeNull();
213
+ });
214
+
215
+ test("create an alert: on, then off, leaves the criteria valid", () => {
216
+ const harness: Harness = renderCriteria(buildCriteria());
217
+
218
+ fireEvent.click(switchFor(ALERT_SWITCH));
219
+ expect(harness.latest().data?.createAlerts).toBe(true);
220
+ expect(harness.error()).toBe(
221
+ `Alert title is required for criteria "${CRITERIA_NAME}"`,
222
+ );
223
+
224
+ fireEvent.click(switchFor(ALERT_SWITCH));
225
+ expect(harness.latest().data?.createAlerts).toBe(false);
226
+ expect(harness.error()).toBeNull();
227
+ });
228
+
229
+ test("the row the user typed survives switching off and back on", () => {
230
+ /*
231
+ * The rows are deliberately retained rather than cleared, so that a
232
+ * mis-click does not throw away what was typed. That retention is the
233
+ * reason the validator has to be gated instead.
234
+ */
235
+ const harness: Harness = renderCriteria(buildCriteria());
236
+
237
+ fireEvent.click(switchFor(ALERT_SWITCH));
238
+ fireEvent.change(screen.getByPlaceholderText(/is degraded/), {
239
+ target: { value: "UND66DWANRTR01 is offline" },
240
+ });
241
+
242
+ fireEvent.click(switchFor(ALERT_SWITCH));
243
+ expect(harness.error()).toBeNull();
244
+ expect(harness.latest().data?.alerts[0]?.title).toBe(
245
+ "UND66DWANRTR01 is offline",
246
+ );
247
+
248
+ fireEvent.click(switchFor(ALERT_SWITCH));
249
+ expect(harness.latest().data?.alerts[0]?.title).toBe(
250
+ "UND66DWANRTR01 is offline",
251
+ );
252
+ });
253
+
254
+ test("both actions off with rows retained is valid", () => {
255
+ const harness: Harness = renderCriteria(buildCriteria());
256
+
257
+ fireEvent.click(switchFor(ALERT_SWITCH));
258
+ fireEvent.click(switchFor(INCIDENT_SWITCH));
259
+ fireEvent.click(switchFor(ALERT_SWITCH));
260
+ fireEvent.click(switchFor(INCIDENT_SWITCH));
261
+
262
+ expect(harness.latest().data?.createAlerts).toBe(false);
263
+ expect(harness.latest().data?.createIncidents).toBe(false);
264
+ expect(harness.latest().data?.alerts).toHaveLength(1);
265
+ expect(harness.latest().data?.incidents).toHaveLength(1);
266
+ expect(harness.error()).toBeNull();
267
+ });
268
+ });
269
+
270
+ describe("issue #3410 - filling the fields must clear the error", () => {
271
+ test("title plus severity is enough; the description stays optional", () => {
272
+ /*
273
+ * The reporter filled the Alert Title and the form stayed blocked,
274
+ * because validation moved on to the description — a field that lives
275
+ * inside a section the form itself labels "Optional alert description"
276
+ * and renders collapsed. Title and Severity are the two the form marks
277
+ * required, and they are now the two it checks.
278
+ */
279
+ const harness: Harness = renderCriteria(buildCriteria());
280
+
281
+ fireEvent.click(switchFor(ALERT_SWITCH));
282
+ expect(harness.error()).toContain("Alert title is required");
283
+
284
+ fireEvent.change(screen.getByPlaceholderText(/is degraded/), {
285
+ target: { value: "UND66DWANRTR01 is offline" },
286
+ });
287
+ expect(harness.error()).toBe(
288
+ `Alert severity is required for criteria "${CRITERIA_NAME}"`,
289
+ );
290
+
291
+ pickFromDropdown("Select Severity", "Warning");
292
+
293
+ expect(
294
+ harness.latest().data?.alerts[0]?.alertSeverityId?.toString(),
295
+ ).toBe(ALERT_SEVERITY_ID.toString());
296
+ // Never touched, still empty, and no longer an obstacle.
297
+ expect(harness.latest().data?.alerts[0]?.description).toBe("");
298
+ expect(harness.error()).toBeNull();
299
+ });
300
+
301
+ test("the same for an incident", () => {
302
+ const harness: Harness = renderCriteria(buildCriteria());
303
+
304
+ fireEvent.click(switchFor(INCIDENT_SWITCH));
305
+ fireEvent.change(screen.getByPlaceholderText(/is down/), {
306
+ target: { value: "AWS Status Page has an active incident" },
307
+ });
308
+ expect(harness.error()).toBe(
309
+ `Incident severity is required for criteria "${CRITERIA_NAME}"`,
310
+ );
311
+
312
+ pickFromDropdown("Select Severity", "Critical");
313
+
314
+ expect(
315
+ harness.latest().data?.incidents[0]?.incidentSeverityId?.toString(),
316
+ ).toBe(INCIDENT_SEVERITY_ID.toString());
317
+ expect(harness.latest().data?.incidents[0]?.description).toBe("");
318
+ expect(harness.error()).toBeNull();
319
+ });
320
+ });
321
+
322
+ describe("the switch seeds a row on the way on only", () => {
323
+ test("switching an action off does not create a row it never had", () => {
324
+ /*
325
+ * NetworkDeviceAlertPackUtil ships criteria with the create flag on and
326
+ * an empty array, and MonitorCriteriaIncidentsForm renders that as zero
327
+ * rows rather than seeding one. Switching the action off used to run the
328
+ * seeding block anyway and add a blank row on the way OUT — invisible,
329
+ * because the sub-form is rendered only while the switch is on.
330
+ */
331
+ const harness: Harness = renderCriteria(
332
+ buildCriteria({ createIncidents: true, incidents: [] }),
333
+ );
334
+
335
+ fireEvent.click(switchFor(INCIDENT_SWITCH));
336
+
337
+ expect(harness.latest().data?.createIncidents).toBe(false);
338
+ expect(harness.latest().data?.incidents).toHaveLength(0);
339
+ expect(harness.error()).toBeNull();
340
+ });
341
+
342
+ test("switching an action on seeds exactly one row, not two", () => {
343
+ /*
344
+ * Toggle used to call onChange twice per click. The second pass found a
345
+ * non-empty array and skipped, so this held by luck; it is pinned here
346
+ * because the seeding block is what would break if that changed.
347
+ * Toggle's own call count is pinned in Common/Tests/UI/Components/Toggle.
348
+ */
349
+ const harness: Harness = renderCriteria(buildCriteria());
350
+
351
+ fireEvent.click(switchFor(INCIDENT_SWITCH));
352
+
353
+ expect(harness.latest().data?.incidents).toHaveLength(1);
354
+ });
355
+
356
+ test("an alert sub-form opened on an empty array seeds one row, and it is inert once switched off", () => {
357
+ /*
358
+ * MonitorCriteriaAlertsForm - unlike the incident one - seeds a row on
359
+ * mount when the array is empty, so the user has something to fill in.
360
+ * That row is retained when the switch goes off, which is exactly the
361
+ * state #3413 reported; it must not block.
362
+ */
363
+ const harness: Harness = renderCriteria(
364
+ buildCriteria({ createAlerts: true, alerts: [] }),
365
+ );
366
+
367
+ expect(harness.latest().data?.alerts).toHaveLength(1);
368
+ expect(harness.error()).toContain("Alert title is required");
369
+
370
+ fireEvent.click(switchFor(ALERT_SWITCH));
371
+
372
+ expect(harness.latest().data?.createAlerts).toBe(false);
373
+ expect(harness.latest().data?.alerts).toHaveLength(1);
374
+ expect(harness.error()).toBeNull();
375
+ });
376
+ });
377
+
378
+ describe("the change-monitor-status switch reflects its own flag", () => {
379
+ test("shows on for a criteria whose flag is on but whose status was never picked", () => {
380
+ /*
381
+ * Read from monitorStatusId alone, this switch showed OFF for a criteria
382
+ * that does change the monitor status — the same "the form says this
383
+ * action is off" confusion the two issues are about.
384
+ */
385
+ renderCriteria(
386
+ buildCriteria({
387
+ changeMonitorStatus: true,
388
+ monitorStatusId: undefined,
389
+ }),
390
+ );
391
+
392
+ expect(switchFor(STATUS_SWITCH)).toHaveAttribute("aria-checked", "true");
393
+ });
394
+
395
+ test("still shows on for a criteria saved before the flag existed", () => {
396
+ renderCriteria(
397
+ buildCriteria({
398
+ changeMonitorStatus: false,
399
+ monitorStatusId: MONITOR_STATUS_ID,
400
+ }),
401
+ );
402
+
403
+ expect(switchFor(STATUS_SWITCH)).toHaveAttribute("aria-checked", "true");
404
+ });
405
+
406
+ test("shows off for a criteria that does not change status at all", () => {
407
+ renderCriteria(
408
+ buildCriteria({
409
+ changeMonitorStatus: false,
410
+ monitorStatusId: undefined,
411
+ }),
412
+ );
413
+
414
+ expect(switchFor(STATUS_SWITCH)).toHaveAttribute("aria-checked", "false");
415
+ });
416
+
417
+ test("switching it off clears the status id and the flag together", () => {
418
+ const harness: Harness = renderCriteria(buildCriteria());
419
+
420
+ fireEvent.click(switchFor(STATUS_SWITCH));
421
+
422
+ expect(harness.latest().data?.changeMonitorStatus).toBe(false);
423
+ expect(harness.latest().data?.monitorStatusId).toBeUndefined();
424
+ });
425
+ });
426
+ });