@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
@@ -52,9 +52,37 @@ type CapturedFormStep = {
52
52
  title: string;
53
53
  };
54
54
 
55
+ /*
56
+ * The list half of the table's configuration, captured for the same reason the
57
+ * form half is: the Scan column, the filters and the row actions are all plain
58
+ * props, so a refactor can drop one without breaking a type or a render.
59
+ */
60
+ type CapturedColumn = {
61
+ field?: Record<string, unknown> | undefined;
62
+ title?: string | undefined;
63
+ getElement?:
64
+ | ((item: NetworkDeviceDiscoveryScan) => React.ReactElement)
65
+ | undefined;
66
+ };
67
+
68
+ type CapturedFilter = {
69
+ field?: Record<string, unknown> | undefined;
70
+ title?: string | undefined;
71
+ };
72
+
73
+ type CapturedActionButton = {
74
+ title?: string | undefined;
75
+ isVisible?: ((item: NetworkDeviceDiscoveryScan) => boolean) | undefined;
76
+ };
77
+
55
78
  type CapturedTableProps = {
56
79
  formFields?: Array<CapturedFormField>;
57
80
  formSteps?: Array<CapturedFormStep>;
81
+ columns?: Array<CapturedColumn>;
82
+ filters?: Array<CapturedFilter>;
83
+ actionButtons?: Array<CapturedActionButton>;
84
+ selectMoreFields?: Record<string, boolean>;
85
+ isEditable?: boolean | undefined;
58
86
  };
59
87
 
60
88
  let capturedTableProps: CapturedTableProps | null = null;
@@ -74,7 +102,11 @@ import ProbeUtil from "../../../../App/FeatureSet/Dashboard/src/Utils/Probe";
74
102
  import Project from "../../../Models/DatabaseModels/Project";
75
103
  import Probe from "../../../Models/DatabaseModels/Probe";
76
104
  import ProjectUtil from "../../../UI/Utils/Project";
105
+ import PermissionUtil from "../../../UI/Utils/Permission";
106
+ import Permission from "../../../Types/Permission";
77
107
  import ScanTargetUtil from "../../../Utils/NetworkDiscovery/ScanTargetUtil";
108
+ import ScanNameUtil from "../../../Utils/NetworkDiscovery/ScanNameUtil";
109
+ import NetworkDeviceDiscoveryScan from "../../../Models/DatabaseModels/NetworkDeviceDiscoveryScan";
78
110
  import ObjectID from "../../../Types/ObjectID";
79
111
  import Route from "../../../Types/API/Route";
80
112
 
@@ -105,6 +137,43 @@ function fieldNamed(key: string): CapturedFormField {
105
137
  return field;
106
138
  }
107
139
 
140
+ function columnNamed(key: string): CapturedColumn {
141
+ const column: CapturedColumn | undefined = capturedTableProps?.columns?.find(
142
+ (tableColumn: CapturedColumn): boolean => {
143
+ return Object.keys(tableColumn.field || {})[0] === key;
144
+ },
145
+ );
146
+
147
+ if (!column) {
148
+ throw new Error(`Discovery scans table column "${key}" not found`);
149
+ }
150
+
151
+ return column;
152
+ }
153
+
154
+ /*
155
+ * What the Scan column actually puts on screen for a given row. Rendered
156
+ * rather than inspected: the fallback that matters here is a rendering
157
+ * decision (name on the first line, target underneath, target ALONE when there
158
+ * is no name), and reading it off the element tree would pin the markup rather
159
+ * than what an operator sees.
160
+ */
161
+ function renderScanCell(scan: Partial<NetworkDeviceDiscoveryScan>): string {
162
+ const column: CapturedColumn = columnNamed("name");
163
+
164
+ if (!column.getElement) {
165
+ throw new Error("The Scan column renders no element");
166
+ }
167
+
168
+ const { container } = render(
169
+ <MemoryRouter>
170
+ {column.getElement(scan as NetworkDeviceDiscoveryScan)}
171
+ </MemoryRouter>,
172
+ );
173
+
174
+ return container.textContent || "";
175
+ }
176
+
108
177
  function validate(key: string, values: Record<string, unknown>): string | null {
109
178
  const field: CapturedFormField = fieldNamed(key);
110
179
 
@@ -406,3 +475,217 @@ describe("SNMP Port is bounded on the SNMP Credentials step", () => {
406
475
  expect(validate("snmpPort", {})).toBeNull();
407
476
  });
408
477
  });
478
+
479
+ /*
480
+ * The name (issue #3391).
481
+ *
482
+ * A discovery scan was identified everywhere by its target alone, so a list of
483
+ * them read as a column of octet ranges with no way to tell the router sweep
484
+ * from the switch range. These tests pin the three places the name has to
485
+ * appear for that to be fixed — the wizard that collects it, the list column
486
+ * that shows it, and the filters that find it — plus the fallback that keeps
487
+ * every scan created before the column existed looking exactly as it did.
488
+ */
489
+ describe("Name is collected by the wizard", () => {
490
+ beforeEach(() => {
491
+ capturedTableProps = null;
492
+ jest.spyOn(ProjectUtil, "getCurrentProjectId").mockReturnValue(PROJECT_ID);
493
+ jest.spyOn(ProbeUtil, "getAllProbes").mockResolvedValue([] as never);
494
+ });
495
+
496
+ afterEach(() => {
497
+ cleanup();
498
+ jest.restoreAllMocks();
499
+ capturedTableProps = null;
500
+ });
501
+
502
+ test("is the first thing the wizard asks for, on the first step", async () => {
503
+ await renderPage();
504
+
505
+ const fields: Array<CapturedFormField> =
506
+ capturedTableProps?.formFields || [];
507
+
508
+ expect(fieldKeyOf(fields[0] as CapturedFormField)).toBe("name");
509
+ expect(fieldNamed("name").stepId).toBe(STEP_SCAN_TARGET);
510
+ });
511
+
512
+ /*
513
+ * Optional on purpose. Requiring it would put a wall in front of the
514
+ * operator sweeping one subnet once, which is the case the page was built
515
+ * for.
516
+ */
517
+ test("is optional", async () => {
518
+ await renderPage();
519
+
520
+ expect(fieldNamed("name").required).toBeFalsy();
521
+ });
522
+
523
+ test("carries the shared validator, so the form and the server agree", async () => {
524
+ await renderPage();
525
+
526
+ expect(typeof fieldNamed("name").customValidation).toBe("function");
527
+
528
+ for (const value of [
529
+ "Router Discovery - Region 1100",
530
+ "",
531
+ " ",
532
+ "a".repeat(ScanNameUtil.MAX_SCAN_NAME_LENGTH + 1),
533
+ 1100,
534
+ ]) {
535
+ expect(validate("name", { name: value })).toBe(
536
+ ScanNameUtil.getValidationError(value),
537
+ );
538
+ }
539
+ });
540
+
541
+ test("says nothing about an empty box, so Next is never blocked by it", async () => {
542
+ await renderPage();
543
+
544
+ expect(validate("name", {})).toBeNull();
545
+ expect(validate("name", { name: "" })).toBeNull();
546
+ });
547
+ });
548
+
549
+ describe("Name identifies the scan in the list", () => {
550
+ beforeEach(() => {
551
+ capturedTableProps = null;
552
+ jest.spyOn(ProjectUtil, "getCurrentProjectId").mockReturnValue(PROJECT_ID);
553
+ jest.spyOn(ProbeUtil, "getAllProbes").mockResolvedValue([] as never);
554
+ });
555
+
556
+ afterEach(() => {
557
+ cleanup();
558
+ jest.restoreAllMocks();
559
+ capturedTableProps = null;
560
+ });
561
+
562
+ test("a named scan leads with its name and still shows its target", async () => {
563
+ await renderPage();
564
+
565
+ const cell: string = renderScanCell({
566
+ name: "Router Discovery - Region 1100",
567
+ cidr: "10.15.128.0-255",
568
+ });
569
+
570
+ expect(cell).toContain("Router Discovery - Region 1100");
571
+ expect(cell).toContain("10.15.128.0-255");
572
+ });
573
+
574
+ /*
575
+ * The case that has to keep working: every scan that existed before this
576
+ * column did. It reads exactly as it did before — the target, on the first
577
+ * line, with nothing above it.
578
+ */
579
+ test("an unnamed scan reads exactly as it did before names existed", async () => {
580
+ await renderPage();
581
+
582
+ expect(renderScanCell({ cidr: "10.114.167.11-38" })).toBe(
583
+ "10.114.167.11-38",
584
+ );
585
+ expect(renderScanCell({ name: "", cidr: "10.114.167.11-38" })).toBe(
586
+ "10.114.167.11-38",
587
+ );
588
+ expect(renderScanCell({ name: " ", cidr: "10.114.167.11-38" })).toBe(
589
+ "10.114.167.11-38",
590
+ );
591
+ });
592
+
593
+ test("a blank name never renders as an empty line above the target", async () => {
594
+ await renderPage();
595
+
596
+ const cell: string = renderScanCell({
597
+ name: " ",
598
+ cidr: "192.168.1.0/24",
599
+ });
600
+
601
+ expect(cell.trim()).toBe("192.168.1.0/24");
602
+ });
603
+
604
+ test("a stored name is tidied up on the way out, not rendered raw", async () => {
605
+ await renderPage();
606
+
607
+ expect(
608
+ renderScanCell({ name: "Router\nDiscovery", cidr: "10.0.0.0/24" }),
609
+ ).toContain("Router Discovery");
610
+ });
611
+
612
+ /*
613
+ * The column renders `cidr` while being keyed on `name`, so the target has
614
+ * to be DECLARED on the column — not merely selected alongside it. Declaring
615
+ * it is what fetches it for the second line AND what puts it in the CSV
616
+ * export, which builds its row out of a column's declared fields alone
617
+ * (Common/UI/Components/ModelTable/ExportFromColumns.ts). Reaching the
618
+ * target through selectMoreFields instead exported an empty cell for every
619
+ * scan without a name.
620
+ */
621
+ test("the target is declared on the column, so it is fetched and exported", async () => {
622
+ await renderPage();
623
+
624
+ expect(Object.keys(columnNamed("name").field || {})).toEqual([
625
+ "name",
626
+ "cidr",
627
+ ]);
628
+ });
629
+
630
+ test("both halves of the identity are searchable", async () => {
631
+ await renderPage();
632
+
633
+ const filtered: Array<string> = (capturedTableProps?.filters || []).map(
634
+ (filter: CapturedFilter): string => {
635
+ return Object.keys(filter.field || {})[0] as string;
636
+ },
637
+ );
638
+
639
+ expect(filtered).toContain("name");
640
+ expect(filtered).toContain("cidr");
641
+ });
642
+
643
+ /*
644
+ * A name that cannot be corrected is worse than no name: "Region 1100" on
645
+ * the wrong range misleads everyone who reads the list afterwards, and the
646
+ * only other way to fix it would be deleting the scan and its results.
647
+ */
648
+ test("a scan can be renamed after it was created", async () => {
649
+ await renderPage();
650
+
651
+ const actions: Array<string> = (
652
+ capturedTableProps?.actionButtons || []
653
+ ).map((button: CapturedActionButton): string => {
654
+ return button.title || "";
655
+ });
656
+
657
+ expect(actions).toContain("Rename");
658
+ });
659
+
660
+ /*
661
+ * The table is not editable, so this button is the page's only edit
662
+ * affordance and nothing else gates it. Offered to a reader, it would open a
663
+ * dialog whose one field ModelForm has already dropped for want of the
664
+ * update permission — a box that cannot be saved and does not say why.
665
+ */
666
+ test("renaming is offered only to someone who could save it", async () => {
667
+ await renderPage();
668
+
669
+ const rename: CapturedActionButton | undefined = (
670
+ capturedTableProps?.actionButtons || []
671
+ ).find((button: CapturedActionButton): boolean => {
672
+ return button.title === "Rename";
673
+ });
674
+
675
+ const scan: NetworkDeviceDiscoveryScan = {
676
+ cidr: "10.0.0.0/24",
677
+ } as NetworkDeviceDiscoveryScan;
678
+
679
+ jest
680
+ .spyOn(PermissionUtil, "getAllPermissions")
681
+ .mockReturnValue([Permission.Viewer]);
682
+
683
+ expect(rename?.isVisible?.(scan)).toBe(false);
684
+
685
+ jest
686
+ .spyOn(PermissionUtil, "getAllPermissions")
687
+ .mockReturnValue([Permission.ProjectAdmin]);
688
+
689
+ expect(rename?.isVisible?.(scan)).toBe(true);
690
+ });
691
+ });