@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
@@ -13,10 +13,49 @@ import { getQuerySettings } from "../Utils/AnalyticsDatabase/QuerySettingsHelper
13
13
  export interface DetectionMatchGroup {
14
14
  groupValue: string;
15
15
  matchCount: number;
16
+ /*
17
+ * uniqExact of the rule's distinctCountField over the group's matches;
18
+ * 0 whenever the rule has no distinct-count field (the query emits a
19
+ * constant, not an aggregate, in that case).
20
+ */
21
+ distinctCount: number;
16
22
  sampleMessage: string;
17
23
  sampleObservables: Array<string>;
18
24
  }
19
25
 
26
+ export interface FindDetectionMatchesData {
27
+ projectId: ObjectID;
28
+ startTime: Date;
29
+ endTime: Date;
30
+ whereFragment: Statement;
31
+ groupByExpression: Statement | null;
32
+ distinctCountExpression: Statement | null;
33
+ minMatchCount: number;
34
+ maxGroups: number;
35
+ }
36
+
37
+ /*
38
+ * The in-process twin of the HAVING clause findDetectionMatches emits —
39
+ * exported so the evaluator's re-filter and the SQL builder live in one
40
+ * file, and a change to either side of the firing predicate is reviewed
41
+ * next to the other.
42
+ */
43
+ export function doesGroupMeetDetectionThreshold(data: {
44
+ group: DetectionMatchGroup;
45
+ usesDistinctCount: boolean;
46
+ minMatchCount: number;
47
+ }): boolean {
48
+ if (data.group.matchCount <= 0) {
49
+ return false;
50
+ }
51
+
52
+ const effectiveCount: number = data.usesDistinctCount
53
+ ? data.group.distinctCount
54
+ : data.group.matchCount;
55
+
56
+ return effectiveCount >= Math.max(1, data.minMatchCount);
57
+ }
58
+
20
59
  export class SecurityEventService extends AnalyticsDatabaseService<SecurityEvent> {
21
60
  public constructor(clickhouseDatabase?: ClickhouseDatabase | undefined) {
22
61
  super({ modelType: SecurityEvent, database: clickhouseDatabase });
@@ -24,18 +63,21 @@ export class SecurityEventService extends AnalyticsDatabaseService<SecurityEvent
24
63
 
25
64
  /*
26
65
  * Detection-engine query: count matching events in a window, grouped by
27
- * an optional field expression. `whereFragment` and
28
- * `groupByExpression` are Statements built by SigmaClickhouseCompiler —
29
- * every rule-controlled value inside them is a bound parameter.
66
+ * an optional field expression. `whereFragment`, `groupByExpression`
67
+ * and `distinctCountExpression` are Statements built by
68
+ * SigmaClickhouseCompiler — every rule-controlled value inside them is
69
+ * a bound parameter.
70
+ *
71
+ * When distinctCountExpression is set, the threshold applies to
72
+ * uniqExact of that field, not the raw match count — and empty values
73
+ * are excluded via nullIf, so "5 distinct usernames" never counts rows
74
+ * that carry no username. The threshold is enforced in HAVING so the
75
+ * maxGroups LIMIT keeps only qualifying groups instead of letting
76
+ * noisy-but-under-threshold groups crowd out real ones.
30
77
  */
31
- public async findDetectionMatches(data: {
32
- projectId: ObjectID;
33
- startTime: Date;
34
- endTime: Date;
35
- whereFragment: Statement;
36
- groupByExpression: Statement | null;
37
- maxGroups: number;
38
- }): Promise<Array<DetectionMatchGroup>> {
78
+ public async findDetectionMatches(
79
+ data: FindDetectionMatchesData,
80
+ ): Promise<Array<DetectionMatchGroup>> {
39
81
  if (!this.database) {
40
82
  this.useDefaultDatabase();
41
83
  }
@@ -51,8 +93,18 @@ export class SecurityEventService extends AnalyticsDatabaseService<SecurityEvent
51
93
  statement.append("''");
52
94
  }
53
95
 
96
+ statement.append(" AS groupValue, count() AS matchCount, ");
97
+
98
+ if (data.distinctCountExpression) {
99
+ statement.append("uniqExact(nullIf(");
100
+ statement.append(data.distinctCountExpression);
101
+ statement.append(", ''))");
102
+ } else {
103
+ statement.append("0");
104
+ }
105
+
54
106
  statement.append(
55
- ` AS groupValue, count() AS matchCount, any(message) AS sampleMessage, arrayDistinct(arrayFlatten(groupArray(20)(observables))) AS sampleObservables FROM ${databaseName}.${this.model.tableName} WHERE `,
107
+ ` AS distinctCount, any(message) AS sampleMessage, arrayDistinct(arrayFlatten(groupArray(20)(observables))) AS sampleObservables FROM ${databaseName}.${this.model.tableName} WHERE `,
56
108
  );
57
109
 
58
110
  statement.append(
@@ -69,7 +121,31 @@ export class SecurityEventService extends AnalyticsDatabaseService<SecurityEvent
69
121
  );
70
122
 
71
123
  statement.append(data.whereFragment);
72
- statement.append(") GROUP BY groupValue ORDER BY matchCount DESC LIMIT ");
124
+ statement.append(") GROUP BY groupValue");
125
+
126
+ /*
127
+ * The effective count — what the rule's threshold means — is the
128
+ * distinct count when a distinct expression was given, else the raw
129
+ * match count. A distinct-count rule always gets a HAVING clause,
130
+ * even at threshold 1: a group whose matches all lack the counted
131
+ * field has distinctCount 0 and must not fire.
132
+ */
133
+ const effectiveCountColumn: string = data.distinctCountExpression
134
+ ? "distinctCount"
135
+ : "matchCount";
136
+ const minMatchCount: number = Math.max(1, data.minMatchCount);
137
+
138
+ if (data.distinctCountExpression || minMatchCount > 1) {
139
+ statement.append(` HAVING ${effectiveCountColumn} >= `);
140
+ statement.append(
141
+ SQL`${{
142
+ type: TableColumnType.Number,
143
+ value: minMatchCount,
144
+ }}`,
145
+ );
146
+ }
147
+
148
+ statement.append(` ORDER BY ${effectiveCountColumn} DESC LIMIT `);
73
149
  statement.append(
74
150
  SQL`${{
75
151
  type: TableColumnType.Number,
@@ -88,6 +164,7 @@ export class SecurityEventService extends AnalyticsDatabaseService<SecurityEvent
88
164
  return {
89
165
  groupValue: String(row["groupValue"] ?? ""),
90
166
  matchCount: Number(row["matchCount"] || 0),
167
+ distinctCount: Number(row["distinctCount"] || 0),
91
168
  sampleMessage: String(row["sampleMessage"] ?? ""),
92
169
  sampleObservables: Array.isArray(row["sampleObservables"])
93
170
  ? (row["sampleObservables"] as Array<unknown>).map(
@@ -17,6 +17,82 @@ import Model from "../../Models/DatabaseModels/StatusPageResource";
17
17
  import Monitor from "../../Models/DatabaseModels/Monitor";
18
18
  import MonitorGroupResource from "../../Models/DatabaseModels/MonitorGroupResource";
19
19
 
20
+ /**
21
+ * The ways a create or update can name the resource's target. Everything
22
+ * server side sets the foreign key column, but the dashboard's resource form
23
+ * posts the relation - and the relation does NOT arrive in the same shape on
24
+ * both write paths:
25
+ *
26
+ * - create goes through BaseAPI.createItem, which revives the body with
27
+ * BaseModel.fromJSON, so `monitor` is a real Monitor and `monitor.id` is
28
+ * an ObjectID;
29
+ * - update goes through BaseAPI.updateItem, which only runs
30
+ * JSONFunctions.deserialize. That revives ObjectID/DateTime values, but
31
+ * never nested models, so `monitor` stays the plain `{ _id: "<uuid>" }`
32
+ * the browser sent and has no `id` at all.
33
+ *
34
+ * Reading only `.id` therefore silently saw nothing on every edit-form save,
35
+ * which is the whole path the update guard exists for - so this accepts the
36
+ * id however it arrives.
37
+ */
38
+ type StatusPageResourceTargetValue =
39
+ | ObjectID
40
+ | string
41
+ | { id?: unknown; _id?: unknown }
42
+ | null
43
+ | undefined;
44
+
45
+ interface StatusPageResourceTargetInput {
46
+ monitorId?: StatusPageResourceTargetValue;
47
+ monitor?: StatusPageResourceTargetValue;
48
+ monitorGroupId?: StatusPageResourceTargetValue;
49
+ monitorGroup?: StatusPageResourceTargetValue;
50
+ }
51
+
52
+ function toTargetObjectID(
53
+ value: StatusPageResourceTargetValue,
54
+ ): ObjectID | null {
55
+ if (!value) {
56
+ return null;
57
+ }
58
+
59
+ if (value instanceof ObjectID) {
60
+ return value;
61
+ }
62
+
63
+ if (typeof value === "string") {
64
+ return new ObjectID(value);
65
+ }
66
+
67
+ if (typeof value === "object") {
68
+ return (
69
+ toTargetObjectID(value.id as StatusPageResourceTargetValue) ||
70
+ toTargetObjectID(value._id as StatusPageResourceTargetValue)
71
+ );
72
+ }
73
+
74
+ return null;
75
+ }
76
+
77
+ interface StatusPageResourceTarget {
78
+ monitorId: ObjectID | null;
79
+ monitorGroupId: ObjectID | null;
80
+ }
81
+
82
+ /**
83
+ * Named after what the operator sees rather than what the column is, because
84
+ * this reads back to them on the resource form.
85
+ */
86
+ function duplicateResourceException(
87
+ target: StatusPageResourceTarget,
88
+ ): BadDataException {
89
+ const thing: string = target.monitorId ? "monitor" : "monitor group";
90
+
91
+ return new BadDataException(
92
+ `This ${thing} is already added to this status page. A ${thing} can only be added once so it is not shown twice to your customers.`,
93
+ );
94
+ }
95
+
20
96
  export class Service extends DatabaseService<Model> {
21
97
  public constructor() {
22
98
  super(Model);
@@ -115,6 +191,76 @@ export class Service extends DatabaseService<Model> {
115
191
  return statusPageResources;
116
192
  }
117
193
 
194
+ /**
195
+ * The id of the thing a resource points at, whichever way the caller
196
+ * expressed it. The dashboard's resource form posts the relation
197
+ * (`monitor: { _id }`) while everything server side sets the foreign key
198
+ * column, and both mean the same resource.
199
+ */
200
+ private getResourceMonitorTarget(
201
+ data: StatusPageResourceTargetInput,
202
+ ): StatusPageResourceTarget {
203
+ return {
204
+ monitorId:
205
+ toTargetObjectID(data.monitorId) || toTargetObjectID(data.monitor),
206
+ monitorGroupId:
207
+ toTargetObjectID(data.monitorGroupId) ||
208
+ toTargetObjectID(data.monitorGroup),
209
+ };
210
+ }
211
+
212
+ /**
213
+ * A status page lists a monitor once.
214
+ *
215
+ * Nothing stopped the same monitor being added twice, so re-adding a label's
216
+ * monitors after a new one joined that label created a second resource for
217
+ * every monitor already there, and the public page listed each of them twice
218
+ * (issue #3420). The rule engine has always refused to add a monitor that is
219
+ * already on the page for exactly this reason; this makes the same promise
220
+ * hold for every other way a resource is created - the resource form, the
221
+ * bulk add modal, and the API.
222
+ *
223
+ * The check is status-page-wide rather than per group: a monitor in two
224
+ * groups is still a monitor a visitor sees twice.
225
+ */
226
+ @CaptureSpan()
227
+ public async isResourceAlreadyOnStatusPage(data: {
228
+ statusPageId: ObjectID;
229
+ monitorId?: ObjectID | null | undefined;
230
+ monitorGroupId?: ObjectID | null | undefined;
231
+ excludeResourceId?: ObjectID | null | undefined;
232
+ }): Promise<boolean> {
233
+ if (!data.monitorId && !data.monitorGroupId) {
234
+ return false;
235
+ }
236
+
237
+ const query: Query<Model> = {
238
+ statusPageId: data.statusPageId,
239
+ };
240
+
241
+ if (data.monitorId) {
242
+ query.monitorId = data.monitorId;
243
+ } else {
244
+ query.monitorGroupId = data.monitorGroupId!;
245
+ }
246
+
247
+ if (data.excludeResourceId) {
248
+ query._id = QueryHelper.notEquals(data.excludeResourceId.toString());
249
+ }
250
+
251
+ const existingResource: Model | null = await this.findOneBy({
252
+ query: query,
253
+ select: {
254
+ _id: true,
255
+ },
256
+ props: {
257
+ isRoot: true,
258
+ },
259
+ });
260
+
261
+ return Boolean(existingResource);
262
+ }
263
+
118
264
  @CaptureSpan()
119
265
  protected override async onBeforeCreate(
120
266
  createBy: CreateBy<Model>,
@@ -125,6 +271,20 @@ export class Service extends DatabaseService<Model> {
125
271
  );
126
272
  }
127
273
 
274
+ const target: StatusPageResourceTarget = this.getResourceMonitorTarget(
275
+ createBy.data as unknown as StatusPageResourceTargetInput,
276
+ );
277
+
278
+ if (
279
+ await this.isResourceAlreadyOnStatusPage({
280
+ statusPageId: createBy.data.statusPageId,
281
+ monitorId: target.monitorId,
282
+ monitorGroupId: target.monitorGroupId,
283
+ })
284
+ ) {
285
+ throw duplicateResourceException(target);
286
+ }
287
+
128
288
  if (!createBy.data.order) {
129
289
  const query: Query<Model> = {
130
290
  statusPageId: createBy.data.statusPageId,
@@ -222,6 +382,69 @@ export class Service extends DatabaseService<Model> {
222
382
  protected override async onBeforeUpdate(
223
383
  updateBy: UpdateBy<Model>,
224
384
  ): Promise<OnUpdate<Model>> {
385
+ /*
386
+ * Pointing an existing resource at a monitor the page already lists is the
387
+ * same duplicate onBeforeCreate refuses, just reached from the edit form.
388
+ */
389
+ const updatedTarget: StatusPageResourceTarget =
390
+ this.getResourceMonitorTarget(
391
+ updateBy.data as unknown as StatusPageResourceTargetInput,
392
+ );
393
+
394
+ if (
395
+ (updatedTarget.monitorId || updatedTarget.monitorGroupId) &&
396
+ updateBy.query._id
397
+ ) {
398
+ const resourceBeingUpdated: Model | null = await this.findOneBy({
399
+ query: {
400
+ _id: updateBy.query._id!,
401
+ },
402
+ props: {
403
+ isRoot: true,
404
+ },
405
+ select: {
406
+ _id: true,
407
+ statusPageId: true,
408
+ monitorId: true,
409
+ monitorGroupId: true,
410
+ },
411
+ });
412
+
413
+ const currentTarget: StatusPageResourceTarget =
414
+ this.getResourceMonitorTarget(
415
+ (resourceBeingUpdated ||
416
+ {}) as unknown as StatusPageResourceTargetInput,
417
+ );
418
+
419
+ /*
420
+ * The edit form is a ModelForm, so it posts every field it collects -
421
+ * the monitor included - even when all the operator changed was the
422
+ * display name. Checking an unchanged target would refuse those saves
423
+ * on a status page that already carries a duplicate from before this
424
+ * rule existed, which would leave both of its rows uneditable.
425
+ */
426
+ const isTargetUnchanged: boolean =
427
+ (!updatedTarget.monitorId ||
428
+ updatedTarget.monitorId.toString() ===
429
+ currentTarget.monitorId?.toString()) &&
430
+ (!updatedTarget.monitorGroupId ||
431
+ updatedTarget.monitorGroupId.toString() ===
432
+ currentTarget.monitorGroupId?.toString());
433
+
434
+ if (
435
+ resourceBeingUpdated?.statusPageId &&
436
+ !isTargetUnchanged &&
437
+ (await this.isResourceAlreadyOnStatusPage({
438
+ statusPageId: resourceBeingUpdated.statusPageId,
439
+ monitorId: updatedTarget.monitorId,
440
+ monitorGroupId: updatedTarget.monitorGroupId,
441
+ excludeResourceId: resourceBeingUpdated.id,
442
+ }))
443
+ ) {
444
+ throw duplicateResourceException(updatedTarget);
445
+ }
446
+ }
447
+
225
448
  if (updateBy.data.order && !updateBy.props.isRoot && updateBy.query._id) {
226
449
  const resource: Model | null = await this.findOneBy({
227
450
  query: {
@@ -4,6 +4,7 @@ import LogDatabaseService from "./LogService";
4
4
  import MetricDatabaseService from "./MetricService";
5
5
  import SpanDatabaseService from "./SpanService";
6
6
  import ExceptionInstanceService from "./ExceptionInstanceService";
7
+ import SecurityEventService from "./SecurityEventService";
7
8
  import MutableMetricDatabaseService, {
8
9
  MutableMetricService as MutableMetricServiceClass,
9
10
  } from "./MutableMetricService";
@@ -101,6 +102,22 @@ export class TelemetryAttributeService {
101
102
  attributeKeysColumn: "attributeKeys",
102
103
  timeColumn: "time",
103
104
  };
105
+ /*
106
+ * Security events carry the whole source payload flattened into
107
+ * `attributes`, which is where every field the OCSF schema does not
108
+ * have a typed column for ends up (device.hostname,
109
+ * finding_info.title, metadata.product.name, ...). The security
110
+ * events table offers those as optional columns, and this is the
111
+ * list it offers.
112
+ */
113
+ case TelemetryType.SecurityEvent:
114
+ return {
115
+ service: SecurityEventService,
116
+ tableName: SecurityEventService.model.tableName,
117
+ attributesColumn: "attributes",
118
+ attributeKeysColumn: "attributeKeys",
119
+ timeColumn: "time",
120
+ };
104
121
  default:
105
122
  return null;
106
123
  }
@@ -42,7 +42,9 @@ import TeamMember from "../../Models/DatabaseModels/TeamMember";
42
42
  import Model from "../../Models/DatabaseModels/User";
43
43
  import SlackUtil from "../Utils/Workspace/Slack/Slack";
44
44
  import ProductAnalytics from "../Utils/ProductAnalytics";
45
- import MarketingEventUtil from "../Utils/Marketing/MarketingEventUtil";
45
+ import MarketingEventUtil, {
46
+ utmAnalyticsProperties,
47
+ } from "../Utils/Marketing/MarketingEventUtil";
46
48
  import { MarketingEventType } from "../../Types/Marketing/MarketingEvent";
47
49
  import UserTotpAuthService from "./UserTotpAuthService";
48
50
  import UserTwoFactorBackupCodeService from "./UserTwoFactorBackupCodeService";
@@ -242,11 +244,7 @@ export class Service extends DatabaseService<Model> {
242
244
  distinctId: createdItem.email.toString(),
243
245
  properties: {
244
246
  has_password: Boolean(createdItem.password),
245
- utm_source: createdItem.utmSource || "",
246
- utm_medium: createdItem.utmMedium || "",
247
- utm_campaign: createdItem.utmCampaign || "",
248
- utm_term: createdItem.utmTerm || "",
249
- utm_content: createdItem.utmContent || "",
247
+ ...utmAnalyticsProperties(createdItem as unknown as JSONObject),
250
248
  utm_url: createdItem.utmUrl || "",
251
249
  click_ids: createdItem.clickIds || {},
252
250
  first_touch: createdItem.firstTouchAttribution || {},