@oneuptime/common 12.0.22 → 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 (345) hide show
  1. package/Models/DatabaseModels/DetectionRule.ts +55 -0
  2. package/Models/DatabaseModels/Index.ts +2 -0
  3. package/Models/DatabaseModels/NetworkDevice.ts +44 -0
  4. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +584 -0
  5. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +105 -0
  6. package/Models/DatabaseModels/Project.ts +68 -0
  7. package/Models/DatabaseModels/User.ts +68 -0
  8. package/Server/API/TelemetryAPI.ts +29 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.ts +60 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.ts +26 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.ts +26 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.ts +28 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.ts +49 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.ts +33 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
  16. package/Server/Middleware/GzipRequestBody.ts +311 -0
  17. package/Server/Middleware/MultipartFormData.ts +87 -3
  18. package/Server/Services/DetectionRuleService.ts +73 -6
  19. package/Server/Services/Index.ts +207 -0
  20. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +917 -0
  21. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +181 -0
  22. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +59 -0
  23. package/Server/Services/NetworkDeviceService.ts +148 -0
  24. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +65 -0
  25. package/Server/Services/OnCallDutyPolicyFeedService.ts +1 -1
  26. package/Server/Services/ProjectService.ts +29 -19
  27. package/Server/Services/SecurityEventService.ts +90 -13
  28. package/Server/Services/StatusPageResourceService.ts +223 -0
  29. package/Server/Services/TelemetryAttributeService.ts +17 -0
  30. package/Server/Services/UserService.ts +4 -6
  31. package/Server/Types/Markdown.ts +161 -67
  32. package/Server/Utils/AI/Toolbox/OnCallTools.ts +12 -4
  33. package/Server/Utils/AnalyticsDatabase/Statement.ts +13 -1
  34. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +297 -6
  35. package/Server/Utils/Attribution.ts +4 -0
  36. package/Server/Utils/Marketing/MarketingEventUtil.ts +45 -7
  37. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +39 -1
  38. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +55 -3
  39. package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +21 -0
  40. package/Server/Utils/StartServer.ts +12 -32
  41. package/Server/Utils/Telemetry/LlmCostBudgetEvaluator.ts +101 -4
  42. package/Server/Utils/Telemetry/LlmMetricSpend.ts +130 -0
  43. package/Server/Views/Partials/AnalyticsConsent.ejs +159 -102
  44. package/Server/Views/Partials/Head.ejs +2 -1
  45. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +776 -38
  46. package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +359 -0
  47. package/Tests/App/Dashboard/CorrelateGraph.test.tsx +865 -0
  48. package/Tests/App/Dashboard/CorrelationGraph.test.ts +346 -0
  49. package/Tests/App/Dashboard/CriteriaFilterConditionDropdown.test.tsx +256 -0
  50. package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +738 -0
  51. package/Tests/App/Dashboard/CriteriaFilterMonitorTypeChange.test.ts +1122 -0
  52. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +283 -0
  53. package/Tests/App/Dashboard/ExternalStatusPageCriteriaFilter.test.ts +407 -0
  54. package/Tests/App/Dashboard/MetricSeriesInvestigateMenu.test.tsx +5 -14
  55. package/Tests/App/Dashboard/MonitorCriteriaActionToggles.test.tsx +426 -0
  56. package/Tests/App/Dashboard/MonitorStepsCriteriaAlignmentWiring.test.tsx +352 -0
  57. package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +278 -0
  58. package/Tests/App/Dashboard/OnCallLayerShiftPreviewOverrides.test.ts +237 -0
  59. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +2 -2
  60. package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +460 -0
  61. package/Tests/App/Dashboard/SecurityEventAttributeUtil.test.ts +171 -0
  62. package/Tests/App/Dashboard/SecurityEventCorrelation.test.ts +857 -0
  63. package/Tests/App/Dashboard/SecurityEventDetailObservables.test.tsx +194 -0
  64. package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +124 -0
  65. package/Tests/App/Dashboard/SecurityEventsMonitorStepForm.test.tsx +79 -19
  66. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +382 -0
  67. package/Tests/App/StatusPage/BulkAddStatusPageMonitors.test.ts +216 -0
  68. package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +590 -11
  69. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +757 -0
  70. package/Tests/Models/DiscoveryScanNameColumn.test.ts +293 -0
  71. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +564 -0
  72. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +120 -4
  73. package/Tests/Server/Middleware/GzipRequestBody.test.ts +725 -0
  74. package/Tests/Server/Middleware/MultipartFormData.test.ts +298 -0
  75. package/Tests/Server/Services/AddDetectionRuleDistinctCountColumnsMigration.test.ts +311 -0
  76. package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +205 -0
  77. package/Tests/Server/Services/DetectionRuleService.test.ts +134 -2
  78. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +7 -1
  79. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +131 -0
  80. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +933 -0
  81. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +194 -0
  82. package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +800 -0
  83. package/Tests/Server/Services/OnCallScheduleAttachRosterRefresh.test.ts +244 -0
  84. package/Tests/Server/Services/SecurityEventService.test.ts +376 -0
  85. package/Tests/Server/Services/StatusPageResourceDuplicates.test.ts +703 -0
  86. package/Tests/Server/Services/TelemetryAttributeServiceSecurityEvent.test.ts +256 -0
  87. package/Tests/Server/Types/Workflow/Components/ComponentRegistryParity.test.ts +417 -0
  88. package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWhereOperators.test.ts +677 -0
  89. package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +43 -0
  90. package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +15 -11
  91. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +97 -1
  92. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +369 -8
  93. package/Tests/Server/Utils/SecurityEvent/SigmaClickhouseCompiler.test.ts +35 -0
  94. package/Tests/Server/Utils/Telemetry/LlmCostBudgetEvaluator.test.ts +368 -4
  95. package/Tests/Server/Utils/Telemetry/LlmMetricSpend.test.ts +245 -0
  96. package/Tests/Server/Views/AnalyticsConsentPartial.test.ts +48 -5
  97. package/Tests/Types/Code/YamlSyntax.test.ts +396 -0
  98. package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +957 -0
  99. package/Tests/Types/Monitor/MonitorCriteriaActionValidation.test.ts +598 -0
  100. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +49 -0
  101. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +6 -6
  102. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +4 -4
  103. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +4 -3
  104. package/Tests/Types/Telemetry/LlmMetricConventions.test.ts +193 -0
  105. package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +0 -12
  106. package/Tests/UI/Components/CardModelDetailEdit.test.tsx +1 -17
  107. package/Tests/UI/Components/CodeEditor.test.tsx +474 -10
  108. package/Tests/UI/Components/Detail/YamlField.test.tsx +105 -0
  109. package/Tests/UI/Components/EntityDropdownLabelsBulkAdd.test.tsx +319 -0
  110. package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +231 -0
  111. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +1 -0
  112. package/Tests/UI/Components/Forms/ValidationYAML.test.ts +234 -0
  113. package/Tests/UI/Components/ModelTable/AttributeColumns.test.tsx +573 -0
  114. package/Tests/UI/Components/ModelTable/BaseModelTableAttributeColumns.test.tsx +824 -0
  115. package/Tests/UI/Components/ModelTable/ColumnCustomizationModalAddableColumns.test.tsx +707 -0
  116. package/Tests/UI/Components/SideOver.test.tsx +1 -1
  117. package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +294 -0
  118. package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +436 -0
  119. package/Tests/UI/Components/TableBulkCsvExport.test.tsx +6 -2
  120. package/Tests/UI/Components/Toggle.test.tsx +25 -0
  121. package/Tests/UI/Components/YamlEditor.test.tsx +847 -0
  122. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +252 -0
  123. package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +516 -0
  124. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +272 -0
  125. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +221 -0
  126. package/Tests/Utils/NetworkDiscovery/ScanNameUtil.test.ts +312 -0
  127. package/Tests/Utils/NetworkDiscovery/ScanTargetUtil.test.ts +164 -0
  128. package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +468 -0
  129. package/Tests/Utils/Telemetry/LlmMetricQuery.test.ts +472 -0
  130. package/Types/Code/YamlSyntax.ts +396 -0
  131. package/Types/Exception/ExceptionCode.ts +1 -0
  132. package/Types/Exception/PayloadTooLargeException.ts +8 -0
  133. package/Types/Marketing/Attribution.ts +10 -0
  134. package/Types/Marketing/MarketingEvent.ts +4 -0
  135. package/Types/Monitor/MonitorCriteriaInstance.ts +116 -56
  136. package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +2 -1
  137. package/Types/NetworkAutomation/RuleRunResult.ts +84 -0
  138. package/Types/Permission.ts +47 -0
  139. package/Types/SecurityEvent/DetectionFindingConstants.ts +11 -0
  140. package/Types/Telemetry/LlmMetricConventions.ts +124 -0
  141. package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +3 -0
  142. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +10 -1
  143. package/UI/Components/CodeEditor/CodeEditor.tsx +241 -79
  144. package/UI/Components/CodeEditor/YamlEditor.tsx +369 -0
  145. package/UI/Components/Detail/Detail.tsx +10 -0
  146. package/UI/Components/EntityDropdown/EntityDropdown.tsx +33 -0
  147. package/UI/Components/Forms/Fields/FormField.tsx +31 -0
  148. package/UI/Components/Forms/Types/Field.ts +8 -0
  149. package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
  150. package/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.ts +2 -0
  151. package/UI/Components/Forms/Validation.ts +46 -0
  152. package/UI/Components/Input/Input.tsx +3 -0
  153. package/UI/Components/ModelTable/AttributeColumns.tsx +321 -0
  154. package/UI/Components/ModelTable/BaseModelTable.tsx +263 -14
  155. package/UI/Components/ModelTable/Column.ts +8 -0
  156. package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +310 -0
  157. package/UI/Components/ModelTable/ColumnPreference.ts +13 -1
  158. package/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.tsx +2 -2
  159. package/UI/Components/SideOver/SideOver.tsx +5 -5
  160. package/UI/Components/StatusPage/ResourceGrid.tsx +82 -2
  161. package/UI/Components/StatusPage/ResourceList.tsx +197 -38
  162. package/UI/Components/Toggle/Toggle.tsx +9 -1
  163. package/UI/Components/Types/FieldType.ts +1 -0
  164. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +73 -1
  165. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +257 -0
  166. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +183 -0
  167. package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +95 -0
  168. package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +66 -0
  169. package/Utils/NetworkDiscovery/ScanNameUtil.ts +181 -0
  170. package/Utils/NetworkDiscovery/ScanTargetUtil.ts +82 -0
  171. package/Utils/StatusPage/ResourceExplorer.ts +258 -0
  172. package/Utils/Telemetry/LlmMetricQuery.ts +204 -0
  173. package/build/dist/Models/DatabaseModels/DetectionRule.js +57 -0
  174. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  175. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  176. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  177. package/build/dist/Models/DatabaseModels/NetworkDevice.js +45 -0
  178. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  179. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +609 -0
  180. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -0
  181. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +97 -0
  182. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  183. package/build/dist/Models/DatabaseModels/Project.js +76 -0
  184. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  185. package/build/dist/Models/DatabaseModels/User.js +76 -0
  186. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  187. package/build/dist/Server/API/TelemetryAPI.js +17 -0
  188. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  189. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.js +35 -0
  190. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.js.map +1 -0
  191. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.js +19 -0
  192. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.js.map +1 -0
  193. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.js +19 -0
  194. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.js.map +1 -0
  195. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js +21 -0
  196. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js.map +1 -0
  197. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js +42 -0
  198. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js.map +1 -0
  199. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js +22 -0
  200. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js.map +1 -0
  201. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
  202. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  203. package/build/dist/Server/Middleware/GzipRequestBody.js +224 -0
  204. package/build/dist/Server/Middleware/GzipRequestBody.js.map +1 -0
  205. package/build/dist/Server/Middleware/MultipartFormData.js +71 -2
  206. package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
  207. package/build/dist/Server/Services/DetectionRuleService.js +49 -4
  208. package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
  209. package/build/dist/Server/Services/Index.js +206 -0
  210. package/build/dist/Server/Services/Index.js.map +1 -1
  211. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +711 -0
  212. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -0
  213. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +155 -0
  214. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -0
  215. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +50 -0
  216. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  217. package/build/dist/Server/Services/NetworkDeviceService.js +124 -0
  218. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  219. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +68 -13
  220. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  221. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js +1 -1
  222. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js.map +1 -1
  223. package/build/dist/Server/Services/ProjectService.js +25 -45
  224. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  225. package/build/dist/Server/Services/SecurityEventService.js +57 -5
  226. package/build/dist/Server/Services/SecurityEventService.js.map +1 -1
  227. package/build/dist/Server/Services/StatusPageResourceService.js +140 -0
  228. package/build/dist/Server/Services/StatusPageResourceService.js.map +1 -1
  229. package/build/dist/Server/Services/TelemetryAttributeService.js +17 -0
  230. package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
  231. package/build/dist/Server/Services/UserService.js +2 -12
  232. package/build/dist/Server/Services/UserService.js.map +1 -1
  233. package/build/dist/Server/Types/Markdown.js +147 -61
  234. package/build/dist/Server/Types/Markdown.js.map +1 -1
  235. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +12 -4
  236. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -1
  237. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +12 -1
  238. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  239. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +246 -9
  240. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  241. package/build/dist/Server/Utils/Attribution.js.map +1 -1
  242. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +27 -7
  243. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
  244. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +26 -0
  245. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  246. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +42 -7
  247. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  248. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +18 -0
  249. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
  250. package/build/dist/Server/Utils/StartServer.js +12 -21
  251. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  252. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js +76 -5
  253. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js.map +1 -1
  254. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js +102 -0
  255. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js.map +1 -0
  256. package/build/dist/Types/Code/YamlSyntax.js +212 -0
  257. package/build/dist/Types/Code/YamlSyntax.js.map +1 -0
  258. package/build/dist/Types/Exception/ExceptionCode.js +1 -0
  259. package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
  260. package/build/dist/Types/Exception/PayloadTooLargeException.js +8 -0
  261. package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -0
  262. package/build/dist/Types/Marketing/Attribution.js +10 -0
  263. package/build/dist/Types/Marketing/Attribution.js.map +1 -1
  264. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +112 -51
  265. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  266. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +2 -1
  267. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
  268. package/build/dist/Types/NetworkAutomation/RuleRunResult.js +24 -0
  269. package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -1
  270. package/build/dist/Types/Permission.js +41 -0
  271. package/build/dist/Types/Permission.js.map +1 -1
  272. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +9 -0
  273. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
  274. package/build/dist/Types/Telemetry/LlmMetricConventions.js +98 -0
  275. package/build/dist/Types/Telemetry/LlmMetricConventions.js.map +1 -0
  276. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +1 -1
  277. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
  278. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +5 -2
  279. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  280. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +206 -76
  281. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  282. package/build/dist/UI/Components/CodeEditor/YamlEditor.js +201 -0
  283. package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -0
  284. package/build/dist/UI/Components/Detail/Detail.js +9 -0
  285. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  286. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +16 -1
  287. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  288. package/build/dist/UI/Components/Forms/Fields/FormField.js +14 -1
  289. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  290. package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
  291. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
  292. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
  293. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js +2 -0
  294. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js.map +1 -1
  295. package/build/dist/UI/Components/Forms/Validation.js +27 -0
  296. package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
  297. package/build/dist/UI/Components/Input/Input.js +1 -1
  298. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  299. package/build/dist/UI/Components/ModelTable/AttributeColumns.js +159 -0
  300. package/build/dist/UI/Components/ModelTable/AttributeColumns.js.map +1 -0
  301. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +179 -17
  302. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  303. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +133 -2
  304. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -1
  305. package/build/dist/UI/Components/ModelTable/ColumnPreference.js +7 -1
  306. package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -1
  307. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js +2 -2
  308. package/build/dist/UI/Components/SideOver/SideOver.js +5 -5
  309. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +28 -2
  310. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
  311. package/build/dist/UI/Components/StatusPage/ResourceList.js +87 -20
  312. package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
  313. package/build/dist/UI/Components/Toggle/Toggle.js +9 -1
  314. package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
  315. package/build/dist/UI/Components/Types/FieldType.js +1 -0
  316. package/build/dist/UI/Components/Types/FieldType.js.map +1 -1
  317. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +37 -1
  318. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
  319. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +149 -0
  320. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -0
  321. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +121 -0
  322. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -0
  323. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +75 -0
  324. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -0
  325. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +59 -0
  326. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -0
  327. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js +120 -0
  328. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js.map +1 -0
  329. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +60 -0
  330. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -1
  331. package/build/dist/Utils/StatusPage/ResourceExplorer.js +171 -0
  332. package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -1
  333. package/build/dist/Utils/Telemetry/LlmMetricQuery.js +119 -0
  334. package/build/dist/Utils/Telemetry/LlmMetricQuery.js.map +1 -0
  335. package/jest.config.json +2 -0
  336. package/package.json +1 -1
  337. package/tsconfig.json +2 -1
  338. package/Tests/UI/Components/Toast.test.tsx +0 -197
  339. package/Tests/UI/Components/ToastStacking.test.tsx +0 -198
  340. package/UI/Components/Toast/Toast.tsx +0 -189
  341. package/UI/Components/Toast/ToastInit.tsx +0 -110
  342. package/build/dist/UI/Components/Toast/Toast.js +0 -123
  343. package/build/dist/UI/Components/Toast/Toast.js.map +0 -1
  344. package/build/dist/UI/Components/Toast/ToastInit.js +0 -53
  345. package/build/dist/UI/Components/Toast/ToastInit.js.map +0 -1
@@ -0,0 +1,312 @@
1
+ import ScanNameUtil, {
2
+ DiscoveryScanIdentity,
3
+ } from "../../../Utils/NetworkDiscovery/ScanNameUtil";
4
+ import ColumnLength from "../../../Types/Database/ColumnLength";
5
+ import { describe, expect, it } from "@jest/globals";
6
+
7
+ /*
8
+ * Contract under test: the optional name on a Network Device Discovery Scan
9
+ * (issue #3391).
10
+ *
11
+ * Three rules are pinned here, because four different layers depend on all
12
+ * three agreeing — the create form, the server's write hooks, the Discovery
13
+ * Scans list, and the probe's own log lines:
14
+ *
15
+ * 1. what gets STORED (normalize): one line, trimmed, and nothing at all
16
+ * rather than an empty string. A scan is either named or it is not;
17
+ * "" is a third state that every `name ?` in the product would read as
18
+ * the first one and render as a blank line above the scan target.
19
+ * 2. what is REJECTED (getValidationError): only two things — a value that
20
+ * is not text, and one that would not fit the varchar(100) column. The
21
+ * field is optional, so absence and blankness are not errors anywhere.
22
+ * 3. what a scan is CALLED (getScanLabel): its name and its target
23
+ * together, falling back to whichever one it has. Every scan that
24
+ * existed before this column did has no name, so the fallback is the
25
+ * common case, not the edge case.
26
+ */
27
+
28
+ function scan(name?: unknown, cidr?: unknown): DiscoveryScanIdentity {
29
+ return {
30
+ name: name as string | null | undefined,
31
+ cidr: cidr as string | null | undefined,
32
+ };
33
+ }
34
+
35
+ const MAX: number = ScanNameUtil.MAX_SCAN_NAME_LENGTH;
36
+
37
+ describe("ScanNameUtil", () => {
38
+ /*
39
+ * The ceiling is the column, not a number this module invented. A name that
40
+ * passes validation and then fails the INSERT would be the worst of both.
41
+ */
42
+ it("caps names at the width of the ShortText column they are stored in", () => {
43
+ expect(MAX).toBe(ColumnLength.ShortText);
44
+ expect(MAX).toBe(100);
45
+ });
46
+
47
+ describe("normalize", () => {
48
+ it("returns null when there is no name", () => {
49
+ expect(ScanNameUtil.normalize(undefined)).toBeNull();
50
+ expect(ScanNameUtil.normalize(null)).toBeNull();
51
+ });
52
+
53
+ /*
54
+ * The distinction that matters most: an operator who typed nothing and one
55
+ * who typed a space have said the same thing, and the column stores the
56
+ * same thing for both.
57
+ */
58
+ it("returns null for a blank name rather than an empty string", () => {
59
+ expect(ScanNameUtil.normalize("")).toBeNull();
60
+ expect(ScanNameUtil.normalize(" ")).toBeNull();
61
+ expect(ScanNameUtil.normalize(" ")).toBeNull();
62
+ expect(ScanNameUtil.normalize("\t")).toBeNull();
63
+ expect(ScanNameUtil.normalize("\n\n")).toBeNull();
64
+ // A non-breaking space pasted out of a document is still a blank box.
65
+ expect(ScanNameUtil.normalize("\u00A0")).toBeNull();
66
+ });
67
+
68
+ it("keeps an ordinary name exactly as it was typed", () => {
69
+ expect(ScanNameUtil.normalize("Router Discovery - Region 1100")).toBe(
70
+ "Router Discovery - Region 1100",
71
+ );
72
+ });
73
+
74
+ it("trims the ends", () => {
75
+ expect(ScanNameUtil.normalize(" Switch Discovery ")).toBe(
76
+ "Switch Discovery",
77
+ );
78
+ });
79
+
80
+ /*
81
+ * A name is rendered in one table cell and inlined into log lines. A value
82
+ * pasted out of a spreadsheet cell arrives with a newline in it, and
83
+ * nothing downstream would ever repair that.
84
+ */
85
+ it("folds a multi-line name onto one line", () => {
86
+ expect(ScanNameUtil.normalize("Router\nDiscovery")).toBe(
87
+ "Router Discovery",
88
+ );
89
+ expect(ScanNameUtil.normalize("Router\r\nDiscovery")).toBe(
90
+ "Router Discovery",
91
+ );
92
+ expect(ScanNameUtil.normalize("Router\tDiscovery")).toBe(
93
+ "Router Discovery",
94
+ );
95
+ });
96
+
97
+ it("collapses every run of whitespace to a single space", () => {
98
+ expect(ScanNameUtil.normalize("Router Discovery")).toBe(
99
+ "Router Discovery",
100
+ );
101
+ expect(ScanNameUtil.normalize(" WB \n\t Units ")).toBe("WB Units");
102
+ });
103
+
104
+ it("strips control characters, including ones with no whitespace meaning", () => {
105
+ expect(ScanNameUtil.normalize("Router\u0000Discovery")).toBe(
106
+ "Router Discovery",
107
+ );
108
+ expect(ScanNameUtil.normalize("Router\u007FDiscovery")).toBe(
109
+ "Router Discovery",
110
+ );
111
+ expect(ScanNameUtil.normalize("\u0001\u0002")).toBeNull();
112
+ });
113
+
114
+ it("leaves punctuation, accents and symbols alone", () => {
115
+ expect(ScanNameUtil.normalize("Switch Discovery — WB Units (v2)")).toBe(
116
+ "Switch Discovery — WB Units (v2)",
117
+ );
118
+ expect(ScanNameUtil.normalize("Zürich / Køge · 10%")).toBe(
119
+ "Zürich / Køge · 10%",
120
+ );
121
+ });
122
+
123
+ /*
124
+ * The value arrives straight from request JSON, so it is genuinely not
125
+ * guaranteed to be a string. normalize() answers "what would be stored",
126
+ * and the answer for a non-string is "nothing" — rejecting it is
127
+ * getValidationError's job, not this one's.
128
+ */
129
+ it("returns null for anything that is not a string", () => {
130
+ expect(ScanNameUtil.normalize(1100)).toBeNull();
131
+ expect(ScanNameUtil.normalize(0)).toBeNull();
132
+ expect(ScanNameUtil.normalize(true)).toBeNull();
133
+ expect(ScanNameUtil.normalize({ name: "Router" })).toBeNull();
134
+ expect(ScanNameUtil.normalize(["Router"])).toBeNull();
135
+ expect(ScanNameUtil.normalize(NaN)).toBeNull();
136
+ });
137
+
138
+ // Normalizing is what gets STORED, so it must not also be a length gate.
139
+ it("does not truncate a name that is too long to store", () => {
140
+ const tooLong: string = "a".repeat(MAX + 50);
141
+
142
+ expect(ScanNameUtil.normalize(tooLong)).toBe(tooLong);
143
+ });
144
+
145
+ it("is idempotent, so a stored name re-read is left alone", () => {
146
+ const messy: string = " Router \n Discovery — Region 1100 ";
147
+ const once: string | null = ScanNameUtil.normalize(messy);
148
+
149
+ expect(ScanNameUtil.normalize(once)).toBe(once);
150
+ });
151
+ });
152
+
153
+ describe("getValidationError", () => {
154
+ it("says nothing about a missing name, because the field is optional", () => {
155
+ expect(ScanNameUtil.getValidationError(undefined)).toBeNull();
156
+ expect(ScanNameUtil.getValidationError(null)).toBeNull();
157
+ });
158
+
159
+ it("says nothing about a blank name either", () => {
160
+ expect(ScanNameUtil.getValidationError("")).toBeNull();
161
+ expect(ScanNameUtil.getValidationError(" ")).toBeNull();
162
+ expect(ScanNameUtil.getValidationError("\n\t")).toBeNull();
163
+ });
164
+
165
+ it("accepts an ordinary name", () => {
166
+ expect(
167
+ ScanNameUtil.getValidationError("Router Discovery - Region 1100"),
168
+ ).toBeNull();
169
+ });
170
+
171
+ it("accepts a name of exactly the column width", () => {
172
+ expect(ScanNameUtil.getValidationError("a".repeat(MAX))).toBeNull();
173
+ });
174
+
175
+ it("rejects a name one character past the column width", () => {
176
+ const error: string | null = ScanNameUtil.getValidationError(
177
+ "a".repeat(MAX + 1),
178
+ );
179
+
180
+ expect(error).not.toBeNull();
181
+ expect(error).toContain(String(MAX));
182
+ expect(error).toContain(String(MAX + 1));
183
+ });
184
+
185
+ /*
186
+ * Length is measured on what would be STORED. Rejecting a value this
187
+ * module was about to shorten by trimming would be refusing to save
188
+ * something perfectly storable.
189
+ */
190
+ it("measures the normalized name, not the raw one", () => {
191
+ expect(
192
+ ScanNameUtil.getValidationError(` ${"a".repeat(MAX)} \n`),
193
+ ).toBeNull();
194
+
195
+ const collapsible: string = `${"a".repeat(MAX - 2)} b`;
196
+
197
+ expect(collapsible.length).toBeGreaterThan(MAX);
198
+ expect(ScanNameUtil.getValidationError(collapsible)).toBeNull();
199
+ });
200
+
201
+ it("rejects a value that is not text at all", () => {
202
+ for (const value of [1100, true, { name: "Router" }, ["Router"]]) {
203
+ const error: string | null = ScanNameUtil.getValidationError(value);
204
+
205
+ expect(error).not.toBeNull();
206
+ expect(error).toContain("text");
207
+ }
208
+ });
209
+
210
+ /*
211
+ * A non-string is reported rather than silently dropped: a client sending
212
+ * `{"name": 1100}` has made a type error, and quietly storing no name at
213
+ * all would hide it until someone noticed the scan was unnamed.
214
+ */
215
+ it("does not accept a non-string merely because it normalizes to nothing", () => {
216
+ expect(ScanNameUtil.normalize(1100)).toBeNull();
217
+ expect(ScanNameUtil.getValidationError(1100)).not.toBeNull();
218
+ });
219
+ });
220
+
221
+ describe("getDisplayName", () => {
222
+ it("is the normalized name", () => {
223
+ expect(ScanNameUtil.getDisplayName(scan(" Router Discovery "))).toBe(
224
+ "Router Discovery",
225
+ );
226
+ });
227
+
228
+ /*
229
+ * Normalized on the way OUT as well as in, because rows written before the
230
+ * column existed — and any writer that bypasses the hooks — are not
231
+ * guaranteed to have been through normalize().
232
+ */
233
+ it("is null for a scan with no usable name, whatever the row holds", () => {
234
+ expect(ScanNameUtil.getDisplayName(scan(undefined))).toBeNull();
235
+ expect(ScanNameUtil.getDisplayName(scan(null))).toBeNull();
236
+ expect(ScanNameUtil.getDisplayName(scan(""))).toBeNull();
237
+ expect(ScanNameUtil.getDisplayName(scan(" "))).toBeNull();
238
+ expect(ScanNameUtil.getDisplayName(scan(1100))).toBeNull();
239
+ });
240
+
241
+ it("ignores the scan target entirely", () => {
242
+ expect(
243
+ ScanNameUtil.getDisplayName(scan(undefined, "10.15.128.0-255")),
244
+ ).toBeNull();
245
+ });
246
+
247
+ it("reads a row that selected no name column at all", () => {
248
+ expect(ScanNameUtil.getDisplayName({})).toBeNull();
249
+ });
250
+ });
251
+
252
+ describe("getScanLabel", () => {
253
+ it("names a named scan and says what it sweeps", () => {
254
+ expect(
255
+ ScanNameUtil.getScanLabel(
256
+ scan("Router Discovery - Region 1100", "10.15.128.0-255"),
257
+ ),
258
+ ).toBe("Router Discovery - Region 1100 (10.15.128.0-255)");
259
+ });
260
+
261
+ // Exactly what every log line and modal said before names existed.
262
+ it("falls back to the target for an unnamed scan", () => {
263
+ expect(
264
+ ScanNameUtil.getScanLabel(scan(undefined, "10.15.128.0-255")),
265
+ ).toBe("10.15.128.0-255");
266
+ expect(ScanNameUtil.getScanLabel(scan("", "192.168.1.0/24"))).toBe(
267
+ "192.168.1.0/24",
268
+ );
269
+ expect(ScanNameUtil.getScanLabel(scan(" ", "192.168.1.0/24"))).toBe(
270
+ "192.168.1.0/24",
271
+ );
272
+ });
273
+
274
+ it("uses the name alone when the target was not selected", () => {
275
+ expect(ScanNameUtil.getScanLabel(scan("Router Discovery"))).toBe(
276
+ "Router Discovery",
277
+ );
278
+ });
279
+
280
+ /*
281
+ * Returned empty rather than invented: the only caller that can see this
282
+ * is one that selected neither column, and each of them appends its own
283
+ * fallback (the scan id).
284
+ */
285
+ it("is empty when the row carries neither", () => {
286
+ expect(ScanNameUtil.getScanLabel({})).toBe("");
287
+ expect(ScanNameUtil.getScanLabel(scan(null, null))).toBe("");
288
+ expect(ScanNameUtil.getScanLabel(scan(" ", " "))).toBe("");
289
+ });
290
+
291
+ it("normalizes both halves", () => {
292
+ expect(
293
+ ScanNameUtil.getScanLabel(scan(" Router\nDiscovery ", " 10.0.0.0/24 ")),
294
+ ).toBe("Router Discovery (10.0.0.0/24)");
295
+ });
296
+
297
+ it("ignores a target that is not text", () => {
298
+ expect(ScanNameUtil.getScanLabel(scan("Router Discovery", 10))).toBe(
299
+ "Router Discovery",
300
+ );
301
+ expect(ScanNameUtil.getScanLabel(scan(undefined, 10))).toBe("");
302
+ });
303
+
304
+ it("does not truncate, so a log line always names the whole scan", () => {
305
+ const long: string = "a".repeat(MAX);
306
+
307
+ expect(ScanNameUtil.getScanLabel(scan(long, "10.0.0.0/24"))).toBe(
308
+ `${long} (10.0.0.0/24)`,
309
+ );
310
+ });
311
+ });
312
+ });
@@ -581,3 +581,167 @@ describe("ScanTargetUtil.isValid", () => {
581
581
  expect(ScanTargetUtil.isValid("")).toBe(false);
582
582
  });
583
583
  });
584
+
585
+ /*
586
+ * contains() is the matcher behind the auto-import rules' "Host IP is in"
587
+ * condition. It is CONTAINMENT, not membership of the sweep list — the two
588
+ * disagree at a CIDR block's network and broadcast addresses (in the block,
589
+ * never swept) — and an octet range is per-octet interval membership, not a
590
+ * numeric interval between the range's corners. Both distinctions are pinned
591
+ * here because either one, drifting, silently changes which hosts a rule
592
+ * imports.
593
+ */
594
+ describe("ScanTargetUtil.contains", () => {
595
+ describe("CIDR containment", () => {
596
+ it("contains addresses inside the block and not those outside", () => {
597
+ expect(ScanTargetUtil.contains("192.168.1.0/24", "192.168.1.1")).toBe(
598
+ true,
599
+ );
600
+ expect(ScanTargetUtil.contains("192.168.1.0/24", "192.168.1.254")).toBe(
601
+ true,
602
+ );
603
+ expect(ScanTargetUtil.contains("192.168.1.0/24", "192.168.2.1")).toBe(
604
+ false,
605
+ );
606
+ expect(ScanTargetUtil.contains("192.168.1.0/24", "192.167.1.1")).toBe(
607
+ false,
608
+ );
609
+ });
610
+
611
+ /*
612
+ * The deliberate divergence from expand(): a rule asking "is this address
613
+ * in 10.0.0.0/24" means the subnet, so the network and broadcast
614
+ * addresses are IN even though no sweep would ever probe them.
615
+ */
616
+ it("contains the network and broadcast addresses expand() excludes", () => {
617
+ expect(ScanTargetUtil.contains("192.168.1.0/24", "192.168.1.0")).toBe(
618
+ true,
619
+ );
620
+ expect(ScanTargetUtil.contains("192.168.1.0/24", "192.168.1.255")).toBe(
621
+ true,
622
+ );
623
+ expect(ScanTargetUtil.expand("192.168.1.0/24")).not.toContain(
624
+ "192.168.1.0",
625
+ );
626
+ expect(ScanTargetUtil.expand("192.168.1.0/24")).not.toContain(
627
+ "192.168.1.255",
628
+ );
629
+ });
630
+
631
+ it("treats a /32 as exactly one address", () => {
632
+ expect(ScanTargetUtil.contains("10.0.0.5/32", "10.0.0.5")).toBe(true);
633
+ expect(ScanTargetUtil.contains("10.0.0.5/32", "10.0.0.4")).toBe(false);
634
+ expect(ScanTargetUtil.contains("10.0.0.5/32", "10.0.0.6")).toBe(false);
635
+ });
636
+
637
+ it("treats a /31 as both of its addresses", () => {
638
+ expect(ScanTargetUtil.contains("10.0.0.0/31", "10.0.0.0")).toBe(true);
639
+ expect(ScanTargetUtil.contains("10.0.0.0/31", "10.0.0.1")).toBe(true);
640
+ expect(ScanTargetUtil.contains("10.0.0.0/31", "10.0.0.2")).toBe(false);
641
+ });
642
+
643
+ // Same masking rule as expand(): the block, not the address as typed.
644
+ it("masks a non-network address down to its subnet before matching", () => {
645
+ expect(ScanTargetUtil.contains("192.168.1.37/29", "192.168.1.32")).toBe(
646
+ true,
647
+ );
648
+ expect(ScanTargetUtil.contains("192.168.1.37/29", "192.168.1.39")).toBe(
649
+ true,
650
+ );
651
+ expect(ScanTargetUtil.contains("192.168.1.37/29", "192.168.1.40")).toBe(
652
+ false,
653
+ );
654
+ });
655
+
656
+ it("matches every address under /0", () => {
657
+ expect(ScanTargetUtil.contains("0.0.0.0/0", "0.0.0.0")).toBe(true);
658
+ expect(ScanTargetUtil.contains("0.0.0.0/0", "10.1.2.3")).toBe(true);
659
+ expect(ScanTargetUtil.contains("0.0.0.0/0", "255.255.255.255")).toBe(
660
+ true,
661
+ );
662
+ });
663
+
664
+ /*
665
+ * The high end of the address space, where every octet has the sign bit
666
+ * territory in play: signed arithmetic anywhere in the comparison would
667
+ * surface here first.
668
+ */
669
+ it("compares correctly at the top of the address space", () => {
670
+ expect(ScanTargetUtil.contains("255.255.255.0/24", "255.255.255.7")).toBe(
671
+ true,
672
+ );
673
+ expect(ScanTargetUtil.contains("255.255.255.0/24", "255.255.254.7")).toBe(
674
+ false,
675
+ );
676
+ });
677
+ });
678
+
679
+ describe("octet-range containment", () => {
680
+ /*
681
+ * A bare address parses as an octet range of four single values, so as a
682
+ * condition it means "exactly this host" — not a prefix, not a wildcard.
683
+ */
684
+ it("matches a bare-IP target only exactly", () => {
685
+ expect(ScanTargetUtil.contains("10.0.0.5", "10.0.0.5")).toBe(true);
686
+ expect(ScanTargetUtil.contains("10.0.0.5", "10.0.0.6")).toBe(false);
687
+ expect(ScanTargetUtil.contains("10.0.0.5", "10.0.0.50")).toBe(false);
688
+ expect(ScanTargetUtil.contains("10.0.0.5", "11.0.0.5")).toBe(false);
689
+ });
690
+
691
+ /*
692
+ * The distinction that makes octet ranges worth having: membership is
693
+ * per-octet, NOT "between the lowest and highest address". 10.17.5.10
694
+ * sits numerically between 10.16.0.51 and 10.22.255.66, but its fourth
695
+ * octet is outside 51-66, so it is not in the target — exactly as the
696
+ * sweep would never probe it.
697
+ */
698
+ it("matches per octet, not as a numeric interval", () => {
699
+ const target: string = "10.16-22.0-255.51-66";
700
+
701
+ expect(ScanTargetUtil.contains(target, "10.17.5.60")).toBe(true);
702
+ // Inside the interval's corners, outside the fourth octet's range.
703
+ expect(ScanTargetUtil.contains(target, "10.17.5.10")).toBe(false);
704
+ expect(ScanTargetUtil.contains(target, "10.17.5.67")).toBe(false);
705
+ });
706
+
707
+ it("respects the corners of every octet's range", () => {
708
+ const target: string = "10.16-22.0-255.51-66";
709
+
710
+ expect(ScanTargetUtil.contains(target, "10.16.0.51")).toBe(true);
711
+ expect(ScanTargetUtil.contains(target, "10.22.255.66")).toBe(true);
712
+ // One below / one above the second octet's bounds.
713
+ expect(ScanTargetUtil.contains(target, "10.15.0.60")).toBe(false);
714
+ expect(ScanTargetUtil.contains(target, "10.23.0.60")).toBe(false);
715
+ });
716
+
717
+ it("holds single-value octets exact while others range", () => {
718
+ const target: string = "10.16-22.0-255.51-66";
719
+
720
+ expect(ScanTargetUtil.contains(target, "11.17.5.60")).toBe(false);
721
+ expect(ScanTargetUtil.contains(target, "9.17.5.60")).toBe(false);
722
+ });
723
+ });
724
+
725
+ describe("malformed input", () => {
726
+ /*
727
+ * A condition that cannot parse matches nothing, same as the matcher's
728
+ * other conditions — never "matches everything".
729
+ */
730
+ it("returns false for a malformed target", () => {
731
+ expect(ScanTargetUtil.contains("", "10.0.0.5")).toBe(false);
732
+ expect(ScanTargetUtil.contains(" ", "10.0.0.5")).toBe(false);
733
+ expect(ScanTargetUtil.contains("abc", "10.0.0.5")).toBe(false);
734
+ expect(ScanTargetUtil.contains("10.0.0.0/99", "10.0.0.5")).toBe(false);
735
+ expect(ScanTargetUtil.contains("10.22-16.0.1", "10.20.0.1")).toBe(false);
736
+ });
737
+
738
+ it("returns false for a malformed address", () => {
739
+ expect(ScanTargetUtil.contains("10.0.0.0/24", "")).toBe(false);
740
+ expect(ScanTargetUtil.contains("10.0.0.0/24", "abc")).toBe(false);
741
+ expect(ScanTargetUtil.contains("10.0.0.0/24", "10.0.0")).toBe(false);
742
+ expect(ScanTargetUtil.contains("10.0.0.0/24", "10.0.0.1.5")).toBe(false);
743
+ expect(ScanTargetUtil.contains("10.0.0.0/24", "10.0.0.256")).toBe(false);
744
+ expect(ScanTargetUtil.contains("0.0.0.0/0", "not-an-ip")).toBe(false);
745
+ });
746
+ });
747
+ });