@oneuptime/common 12.0.32 → 12.0.33

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 (597) hide show
  1. package/Models/AnalyticsModels/Span.ts +14 -0
  2. package/Models/DatabaseModels/EnterpriseLicense.ts +56 -0
  3. package/Models/DatabaseModels/Index.ts +10 -0
  4. package/Models/DatabaseModels/Monitor.ts +76 -0
  5. package/Models/DatabaseModels/NetworkAlertPolicy.ts +690 -0
  6. package/Models/DatabaseModels/NetworkDevice.ts +176 -1
  7. package/Models/DatabaseModels/NetworkSite.ts +201 -2
  8. package/Models/DatabaseModels/NetworkSiteType.ts +102 -3
  9. package/Models/DatabaseModels/NetworkSnmpCredentialProfile.ts +841 -0
  10. package/Models/DatabaseModels/TelemetryException.ts +119 -0
  11. package/Models/DatabaseModels/UserNotificationEmailRollupBatch.ts +334 -0
  12. package/Models/DatabaseModels/UserNotificationEmailRollupItem.ts +370 -0
  13. package/Models/DatabaseModels/UserNotificationEmailRollupSetting.ts +282 -0
  14. package/Server/API/EnterpriseLicenseAPI.ts +391 -64
  15. package/Server/API/LlmProviderAPI.ts +137 -22
  16. package/Server/EnvironmentConfig.ts +14 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.ts +55 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.ts +31 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.ts +124 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.ts +132 -0
  21. package/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.ts +79 -0
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.ts +191 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +12 -0
  24. package/Server/Infrastructure/QueueWorker.ts +38 -8
  25. package/Server/Middleware/BearerTokenAuthorization.ts +12 -0
  26. package/Server/Middleware/ProjectAuthorization.ts +11 -0
  27. package/Server/Middleware/SCIMAuthorization.ts +12 -0
  28. package/Server/Middleware/TelemetryIngest.ts +11 -0
  29. package/Server/Services/AIBillingService.ts +101 -27
  30. package/Server/Services/EnterpriseLicenseInstanceService.ts +197 -0
  31. package/Server/Services/EnterpriseLicenseService.ts +55 -0
  32. package/Server/Services/Index.ts +10 -0
  33. package/Server/Services/MonitorService.ts +143 -21
  34. package/Server/Services/MonitorStatusTimelineService.ts +150 -8
  35. package/Server/Services/MonitorTemplateService.ts +217 -1
  36. package/Server/Services/NetworkAlertPolicyEngineService.ts +2159 -0
  37. package/Server/Services/NetworkAlertPolicyService.ts +944 -0
  38. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +9 -10
  39. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +60 -15
  40. package/Server/Services/NetworkDeviceService.ts +1032 -73
  41. package/Server/Services/NetworkSiteService.ts +1502 -129
  42. package/Server/Services/NetworkSiteTypeService.ts +1216 -0
  43. package/Server/Services/NetworkSnmpCredentialProfileService.ts +238 -0
  44. package/Server/Services/NotificationService.ts +118 -28
  45. package/Server/Services/ProjectService.ts +105 -48
  46. package/Server/Services/StatusPagePrivateUserService.ts +103 -3
  47. package/Server/Services/UserNotificationEmailRollupBatchService.ts +78 -0
  48. package/Server/Services/UserNotificationEmailRollupItemService.ts +79 -0
  49. package/Server/Services/UserNotificationEmailRollupSettingService.ts +113 -0
  50. package/Server/Services/UserNotificationSettingService.ts +62 -25
  51. package/Server/Services/UserService.ts +95 -0
  52. package/Server/Types/Database/QueryHelper.ts +2 -2
  53. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +14 -3
  54. package/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.ts +10 -0
  55. package/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.ts +10 -0
  56. package/Server/Utils/AI/SRE/Insights/InsightTriageRunner.ts +62 -1
  57. package/Server/Utils/AI/Toolbox/AlertTools.ts +15 -1
  58. package/Server/Utils/Billing/BillingFailureNoticeThrottle.ts +80 -0
  59. package/Server/Utils/DataSource/HttpFetch.ts +9 -2
  60. package/Server/Utils/EmailRollup/EmailRollupConstants.ts +98 -0
  61. package/Server/Utils/EmailRollup/EmailRollupFlushRunner.ts +872 -0
  62. package/Server/Utils/EmailRollup/EmailRollupRenderer.ts +781 -0
  63. package/Server/Utils/EmailRollup/EmailRollupWriter.ts +368 -0
  64. package/Server/Utils/LLM/LLMService.ts +78 -0
  65. package/Server/Utils/LogRedaction.ts +8 -0
  66. package/Server/Utils/Logger.ts +79 -1
  67. package/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.ts +190 -0
  68. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +9 -2
  69. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +61 -1
  70. package/Server/Utils/Monitor/MonitorCriteriaDataExtractor.ts +14 -0
  71. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +49 -0
  72. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +255 -4
  73. package/Server/Utils/Monitor/MonitorMetricUtil.ts +41 -0
  74. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +43 -0
  75. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +499 -19
  76. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +66 -10
  77. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +238 -44
  78. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +146 -39
  79. package/Server/Utils/NetworkDevice/DeviceHealthAggregation.ts +31 -18
  80. package/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.ts +213 -0
  81. package/Server/Utils/OutboundUserAgent.ts +152 -0
  82. package/Server/Utils/StartServer.ts +51 -19
  83. package/Server/Utils/Telemetry/CaptureSpan.ts +32 -8
  84. package/Server/Utils/Telemetry/ErrorClassResolver.ts +120 -0
  85. package/Server/Utils/Telemetry/SpanUtil.ts +33 -0
  86. package/Server/Utils/Telemetry.ts +198 -51
  87. package/Server/Views/Partials/SensitiveUrlToken.ejs +140 -0
  88. package/Tests/App/Dashboard/AddNeighborToMonitoringModal.test.tsx +134 -33
  89. package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +279 -0
  90. package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +517 -0
  91. package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +26 -0
  92. package/Tests/App/Dashboard/DeviceStatusHero.test.tsx +588 -0
  93. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +18 -9
  94. package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +632 -0
  95. package/Tests/App/Dashboard/MonitorRecommendationCreateProgress.test.tsx +682 -0
  96. package/Tests/App/Dashboard/MonitorTypePicker.test.tsx +4 -2
  97. package/Tests/App/Dashboard/NetworkDeviceCreateFormMonitorBinding.test.tsx +676 -0
  98. package/Tests/App/Dashboard/NetworkDeviceCreateFormPingMonitor.test.tsx +791 -0
  99. package/Tests/App/Dashboard/NetworkDeviceCreateFormProbeAndSnmp.test.tsx +833 -0
  100. package/Tests/App/Dashboard/NetworkDeviceCriteriaFilter.test.ts +161 -0
  101. package/Tests/App/Dashboard/NetworkDeviceSettingsMonitoringSection.test.tsx +458 -0
  102. package/Tests/App/Dashboard/NetworkSideMenu.test.tsx +41 -5
  103. package/Tests/App/Dashboard/PingMonitorProvisioning.test.ts +368 -0
  104. package/Tests/App/Dashboard/RecommendationCard.test.tsx +796 -0
  105. package/Tests/App/Dashboard/RecommendationToolbar.test.tsx +519 -0
  106. package/Tests/App/Dashboard/RecommendationsList.test.tsx +661 -0
  107. package/Tests/App/Dashboard/UseBulkCreatePingMonitors.test.tsx +899 -0
  108. package/Tests/App/Dashboard/UseBulkSnmpCredentialProfileActions.test.tsx +732 -0
  109. package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +256 -0
  110. package/Tests/App/StatusPage/StatusPageIndexPageRobotsMeta.test.ts +11 -1
  111. package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +9 -4
  112. package/Tests/Models/NetworkSiteHierarchy.test.ts +41 -4
  113. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +951 -7
  114. package/Tests/Server/API/LlmProviderConnectionTest.test.ts +522 -0
  115. package/Tests/Server/Infrastructure/Postgres/NetworkSnmpCredentialProfilesAndAlertPoliciesMigration.test.ts +854 -0
  116. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +18 -0
  117. package/Tests/Server/Infrastructure/Postgres/UserNotificationEmailRollupTableMigration.test.ts +535 -0
  118. package/Tests/Server/Services/AIChatPrivacyPin.test.ts +560 -0
  119. package/Tests/Server/Services/BillingRechargeOwnerEmailGuards.test.ts +783 -0
  120. package/Tests/Server/Services/EnterpriseLicenseInstanceServiceDeletionUsage.test.ts +707 -0
  121. package/Tests/Server/Services/EnterpriseLicenseServiceUsageAggregationLock.test.ts +329 -0
  122. package/Tests/Server/Services/MonitorServiceDeleteNetworkDeviceCleanup.test.ts +294 -0
  123. package/Tests/Server/Services/MonitorStatusBridgeProbePath.test.ts +802 -0
  124. package/Tests/Server/Services/MonitorStatusTimelineService.test.ts +72 -2
  125. package/Tests/Server/Services/NetworkAlertPolicyEngineHooks.test.ts +752 -0
  126. package/Tests/Server/Services/NetworkAlertPolicyEngineService.test.ts +1849 -0
  127. package/Tests/Server/Services/NetworkAlertPolicyModel.test.ts +1793 -0
  128. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +47 -4
  129. package/Tests/Server/Services/NetworkDeviceAutoImportRuleService.test.ts +97 -12
  130. package/Tests/Server/Services/NetworkDeviceAutoMonitorLifecycle.test.ts +148 -3
  131. package/Tests/Server/Services/NetworkDeviceMonitorBindingUpdateGuard.test.ts +514 -0
  132. package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +447 -58
  133. package/Tests/Server/Services/NetworkDeviceMonitoringMethodTransition.test.ts +739 -0
  134. package/Tests/Server/Services/NetworkDevicePollingTenancy.test.ts +501 -0
  135. package/Tests/Server/Services/NetworkDeviceSiteDefaultProbe.test.ts +432 -0
  136. package/Tests/Server/Services/NetworkSiteMonitoringDefaults.test.ts +498 -0
  137. package/Tests/Server/Services/NetworkSiteRollupPolicyAndMaintenance.test.ts +337 -55
  138. package/Tests/Server/Services/NetworkSiteService.test.ts +1868 -131
  139. package/Tests/Server/Services/NetworkSiteTypeService.test.ts +1109 -0
  140. package/Tests/Server/Services/NetworkSnmpCredentialProfileModel.test.ts +926 -0
  141. package/Tests/Server/Services/NetworkSnmpCredentialProfileService.test.ts +796 -0
  142. package/Tests/Server/Services/ProjectServiceNetworkSiteTypeDefaults.test.ts +214 -0
  143. package/Tests/Server/Services/StatusPagePrivateUserEmailChangePasswordResetExpiry.test.ts +269 -0
  144. package/Tests/Server/Services/UserEmailChangePasswordResetExpiry.test.ts +472 -0
  145. package/Tests/Server/Services/UserNotificationEmailRollupModels.test.ts +569 -0
  146. package/Tests/Server/Services/UserNotificationEmailRollupSettingModel.test.ts +314 -0
  147. package/Tests/Server/Services/UserNotificationEmailRollupSettingService.test.ts +409 -0
  148. package/Tests/Server/Services/UserNotificationSettingRollupRouting.test.ts +856 -0
  149. package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +102 -1
  150. package/Tests/Server/Types/Database/Permissions/DashboardAccessPermission.test.ts +321 -0
  151. package/Tests/Server/Types/Database/QueryHelperOperators.test.ts +17 -0
  152. package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +124 -0
  153. package/Tests/Server/Utils/AI/Insights/InsightTriageRunner.test.ts +208 -0
  154. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +235 -0
  155. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +253 -0
  156. package/Tests/Server/Utils/Captcha.test.ts +422 -0
  157. package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +96 -2
  158. package/Tests/Server/Utils/Database/MigrationFailureLog.test.ts +466 -0
  159. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerBehaviour.test.ts +1096 -0
  160. package/Tests/Server/Utils/EmailRollup/EmailRollupFlushRunnerClaim.test.ts +466 -0
  161. package/Tests/Server/Utils/EmailRollup/EmailRollupRenderer.test.ts +1428 -0
  162. package/Tests/Server/Utils/EmailRollup/EmailRollupTestHarness.ts +752 -0
  163. package/Tests/Server/Utils/EmailRollup/EmailRollupWriter.test.ts +864 -0
  164. package/Tests/Server/Utils/LoggerFaultDemotion.test.ts +346 -0
  165. package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +633 -0
  166. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +196 -0
  167. package/Tests/Server/Utils/Monitor/DatabaseMetricWrite.test.ts +367 -0
  168. package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +100 -0
  169. package/Tests/Server/Utils/Monitor/MonitorStepResourceIdentity.test.ts +5 -0
  170. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +512 -31
  171. package/Tests/Server/Utils/Monitor/NetworkDeviceMetricUtil.test.ts +252 -0
  172. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +479 -42
  173. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +351 -5
  174. package/Tests/Server/Utils/NetworkDevice/DeviceHealthAggregation.test.ts +136 -12
  175. package/Tests/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.test.ts +306 -0
  176. package/Tests/Server/Utils/OutboundUserAgent.test.ts +266 -0
  177. package/Tests/Server/Utils/SecurityEvent/ThreatIntel/TaxiiClientUserAgent.test.ts +141 -0
  178. package/Tests/Server/Utils/Telemetry/ErrorClassResolver.test.ts +298 -0
  179. package/Tests/Server/Utils/Telemetry.test.ts +456 -66
  180. package/Tests/Types/Monitor/DatabaseMetricCatalog.test.ts +388 -0
  181. package/Tests/Types/Monitor/MonitorStepDatabaseMonitor.test.ts +243 -0
  182. package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +1 -0
  183. package/Tests/Types/Monitor/MonitorType.test.ts +1 -0
  184. package/Tests/Types/Monitor/MonitorTypeKeywords.test.ts +16 -7
  185. package/Tests/Types/Monitor/NetworkDeviceAlertPack.test.ts +60 -0
  186. package/Tests/Types/NetworkDevice/NetworkAlertPolicyScope.test.ts +655 -0
  187. package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +115 -26
  188. package/Tests/Types/NetworkSite/DefaultNetworkSiteType.test.ts +39 -0
  189. package/Tests/Types/NotificationSetting/NotificationEmailRollupPolicy.test.ts +299 -0
  190. package/Tests/Types/Telemetry/ErrorClass.test.ts +483 -0
  191. package/Tests/UI/Components/BasicRadioButtons.test.tsx +336 -0
  192. package/Tests/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.test.ts +15 -0
  193. package/Tests/UI/Components/ProgressBar.test.tsx +38 -2
  194. package/Tests/UI/Components/SideMenuItem.test.tsx +226 -4
  195. package/Tests/UI/Components/SideMenuSection.test.tsx +310 -0
  196. package/Tests/UI/Components/SideOverSubmitState.test.tsx +335 -0
  197. package/Tests/UI/Utils/PageScrollLock.test.tsx +377 -0
  198. package/Tests/UI/Utils/PermissionGate.test.ts +78 -0
  199. package/Tests/UI/Utils/SensitiveUrlToken.test.ts +140 -0
  200. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +69 -0
  201. package/Tests/Utils/EnterpriseLicenseSync.test.ts +7 -1
  202. package/Tests/Utils/EnterpriseLicenseUsage.test.ts +433 -2
  203. package/Tests/Utils/Monitor/MonitorMetricType.test.ts +280 -1
  204. package/Tests/Utils/Monitor/MonitorSummarySnapshotUtil.test.ts +1 -0
  205. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +38 -0
  206. package/Tests/Utils/NetworkDevice/DeviceHealthStateUtil.test.ts +284 -23
  207. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +177 -0
  208. package/Tests/Utils/NetworkDevice/MonitoringMethodThreadedClassifiers.test.ts +992 -0
  209. package/Tests/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.test.ts +427 -0
  210. package/Tests/Utils/NetworkDevice/ReachabilityStampConsistency.test.ts +185 -0
  211. package/Tests/Utils/NetworkDevice/SnmpCredentialUtil.test.ts +268 -0
  212. package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +55 -5
  213. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +98 -21
  214. package/Tests/Utils/NetworkDiscovery/DiscoveryImportEligibility.test.ts +98 -20
  215. package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +8 -7
  216. package/Tests/Utils/NetworkDiscovery/PingMonitorBuilderForAddress.test.ts +274 -0
  217. package/Tests/Utils/NetworkSite/SiteStatusRollupUtil.test.ts +230 -51
  218. package/Tests/Utils/NetworkSite/TypeHierarchyUtil.test.ts +209 -0
  219. package/Tests/Utils/Telemetry/CaptureSpanExportGating.test.ts +145 -0
  220. package/Types/AI/ExceptionAIClassification.ts +10 -24
  221. package/Types/Email/EmailTemplateType.ts +2 -0
  222. package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +5 -0
  223. package/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.ts +13 -0
  224. package/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.ts +6 -0
  225. package/Types/Exception/ApiException.ts +10 -0
  226. package/Types/Exception/BadDataException.ts +11 -0
  227. package/Types/Exception/BadRequestException.ts +11 -0
  228. package/Types/Exception/Exception.ts +65 -0
  229. package/Types/Exception/ForbiddenException.ts +10 -0
  230. package/Types/Exception/NotAuthenticatedException.ts +10 -0
  231. package/Types/Exception/NotAuthorizedException.ts +10 -0
  232. package/Types/Exception/NotFoundException.ts +11 -0
  233. package/Types/Exception/PayloadTooLargeException.ts +11 -0
  234. package/Types/Exception/PaymentRequiredException.ts +10 -0
  235. package/Types/Exception/ServiceUnavailableException.ts +10 -0
  236. package/Types/Exception/SsoAuthorizationException.ts +10 -0
  237. package/Types/Exception/TenantNotFoundException.ts +11 -0
  238. package/Types/Exception/TimeoutException.ts +10 -0
  239. package/Types/Exception/TooManyRequestsException.ts +10 -0
  240. package/Types/Exception/UnableToReachServer.ts +10 -0
  241. package/Types/Exception/WebsiteRequestException.ts +10 -0
  242. package/Types/Monitor/CriteriaFilter.ts +60 -2
  243. package/Types/Monitor/DatabaseMetricCatalog.ts +693 -0
  244. package/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.ts +83 -0
  245. package/Types/Monitor/MonitorCriteriaInstance.ts +76 -0
  246. package/Types/Monitor/MonitorMetricType.ts +71 -0
  247. package/Types/Monitor/MonitorStep.ts +76 -0
  248. package/Types/Monitor/MonitorStepDatabaseMonitor.ts +171 -0
  249. package/Types/Monitor/MonitorStepSqlMonitor.ts +2 -20
  250. package/Types/Monitor/MonitorType.ts +47 -1
  251. package/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.ts +22 -1
  252. package/Types/Monitor/SqlConnectionConfig.ts +31 -0
  253. package/Types/NetworkDevice/NetworkAlertPolicyScope.ts +343 -0
  254. package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +42 -22
  255. package/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.ts +30 -0
  256. package/Types/NotificationSetting/NotificationEmailRollupCategory.ts +255 -0
  257. package/Types/NotificationSetting/NotificationEmailRollupPolicy.ts +104 -0
  258. package/Types/Permission.ts +90 -0
  259. package/Types/Probe/ProbeMonitorResponse.ts +16 -0
  260. package/Types/Telemetry/ErrorClass.ts +274 -0
  261. package/Types/Telemetry/UnitOfWork.ts +59 -0
  262. package/UI/Components/CommandPalette/CommandPalette.tsx +2 -8
  263. package/UI/Components/EditionLabel/EditionLabel.tsx +4 -0
  264. package/UI/Components/Modal/Modal.tsx +2 -8
  265. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +44 -0
  266. package/UI/Components/ProgressBar/ProgressBar.tsx +12 -1
  267. package/UI/Components/RadioButtons/BasicRadioButtons.tsx +37 -7
  268. package/UI/Components/SideMenu/SideMenu.tsx +123 -5
  269. package/UI/Components/SideMenu/SideMenuItem.tsx +76 -84
  270. package/UI/Components/SideMenu/SideMenuSection.tsx +55 -23
  271. package/UI/Components/SideOver/SideOver.tsx +21 -20
  272. package/UI/Utils/PageScrollLock.ts +79 -3
  273. package/UI/Utils/PermissionGate.ts +61 -0
  274. package/UI/Utils/SensitiveUrlToken.ts +112 -0
  275. package/UI/Utils/TestLLMProvider.ts +11 -0
  276. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +16 -0
  277. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +191 -11
  278. package/Utils/Monitor/MonitorMetricType.ts +153 -1
  279. package/Utils/Monitor/NetworkTopologyUtil.ts +23 -3
  280. package/Utils/NetworkDevice/DeviceHealthStateUtil.ts +65 -14
  281. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +43 -14
  282. package/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.ts +247 -0
  283. package/Utils/NetworkDevice/SnmpCredentialUtil.ts +68 -0
  284. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +15 -7
  285. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +52 -17
  286. package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +55 -23
  287. package/Utils/NetworkDiscovery/PingMonitorBuilder.ts +115 -13
  288. package/Utils/NetworkSite/SiteStatusRollupUtil.ts +66 -20
  289. package/Utils/NetworkSite/TypeHierarchyUtil.ts +313 -0
  290. package/build/dist/Models/AnalyticsModels/Span.js +14 -0
  291. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  292. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +59 -0
  293. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
  294. package/build/dist/Models/DatabaseModels/Index.js +10 -0
  295. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  296. package/build/dist/Models/DatabaseModels/Monitor.js +75 -0
  297. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  298. package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js +713 -0
  299. package/build/dist/Models/DatabaseModels/NetworkAlertPolicy.js.map +1 -0
  300. package/build/dist/Models/DatabaseModels/NetworkDevice.js +180 -1
  301. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  302. package/build/dist/Models/DatabaseModels/NetworkSite.js +200 -2
  303. package/build/dist/Models/DatabaseModels/NetworkSite.js.map +1 -1
  304. package/build/dist/Models/DatabaseModels/NetworkSiteType.js +102 -3
  305. package/build/dist/Models/DatabaseModels/NetworkSiteType.js.map +1 -1
  306. package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js +878 -0
  307. package/build/dist/Models/DatabaseModels/NetworkSnmpCredentialProfile.js.map +1 -0
  308. package/build/dist/Models/DatabaseModels/TelemetryException.js +123 -0
  309. package/build/dist/Models/DatabaseModels/TelemetryException.js.map +1 -1
  310. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js +363 -0
  311. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupBatch.js.map +1 -0
  312. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js +402 -0
  313. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupItem.js.map +1 -0
  314. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js +296 -0
  315. package/build/dist/Models/DatabaseModels/UserNotificationEmailRollupSetting.js.map +1 -0
  316. package/build/dist/Server/API/EnterpriseLicenseAPI.js +273 -60
  317. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
  318. package/build/dist/Server/API/LlmProviderAPI.js +108 -13
  319. package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
  320. package/build/dist/Server/EnvironmentConfig.js +12 -0
  321. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  322. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js +24 -0
  323. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790700000000-AddNetworkSiteTypeParentHierarchy.js.map +1 -0
  324. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js +16 -0
  325. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddEnterpriseLicenseUsageProvenance.js.map +1 -0
  326. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js +111 -0
  327. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790900000000-AddTelemetryExceptionErrorClass.js.map +1 -0
  328. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js +77 -0
  329. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791000000000-AddUserNotificationEmailRollup.js.map +1 -0
  330. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js +50 -0
  331. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791100000000-AddUserNotificationEmailRollupSetting.js.map +1 -0
  332. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js +83 -0
  333. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1791200000000-AddNetworkSnmpCredentialProfilesAndAlertPolicies.js.map +1 -0
  334. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +12 -0
  335. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  336. package/build/dist/Server/Infrastructure/QueueWorker.js +33 -5
  337. package/build/dist/Server/Infrastructure/QueueWorker.js.map +1 -1
  338. package/build/dist/Server/Middleware/BearerTokenAuthorization.js +12 -0
  339. package/build/dist/Server/Middleware/BearerTokenAuthorization.js.map +1 -1
  340. package/build/dist/Server/Middleware/ProjectAuthorization.js +11 -0
  341. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  342. package/build/dist/Server/Middleware/SCIMAuthorization.js +12 -0
  343. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +1 -1
  344. package/build/dist/Server/Middleware/TelemetryIngest.js +11 -0
  345. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  346. package/build/dist/Server/Services/AIBillingService.js +70 -16
  347. package/build/dist/Server/Services/AIBillingService.js.map +1 -1
  348. package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js +167 -0
  349. package/build/dist/Server/Services/EnterpriseLicenseInstanceService.js.map +1 -1
  350. package/build/dist/Server/Services/EnterpriseLicenseService.js +39 -0
  351. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  352. package/build/dist/Server/Services/Index.js +10 -0
  353. package/build/dist/Server/Services/Index.js.map +1 -1
  354. package/build/dist/Server/Services/MonitorService.js +119 -21
  355. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  356. package/build/dist/Server/Services/MonitorStatusTimelineService.js +127 -8
  357. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  358. package/build/dist/Server/Services/MonitorTemplateService.js +162 -0
  359. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  360. package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js +1683 -0
  361. package/build/dist/Server/Services/NetworkAlertPolicyEngineService.js.map +1 -0
  362. package/build/dist/Server/Services/NetworkAlertPolicyService.js +732 -0
  363. package/build/dist/Server/Services/NetworkAlertPolicyService.js.map +1 -0
  364. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +10 -9
  365. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  366. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +54 -11
  367. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
  368. package/build/dist/Server/Services/NetworkDeviceService.js +841 -70
  369. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  370. package/build/dist/Server/Services/NetworkSiteService.js +1145 -107
  371. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  372. package/build/dist/Server/Services/NetworkSiteTypeService.js +863 -0
  373. package/build/dist/Server/Services/NetworkSiteTypeService.js.map +1 -1
  374. package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js +217 -0
  375. package/build/dist/Server/Services/NetworkSnmpCredentialProfileService.js.map +1 -0
  376. package/build/dist/Server/Services/NotificationService.js +80 -17
  377. package/build/dist/Server/Services/NotificationService.js.map +1 -1
  378. package/build/dist/Server/Services/ProjectService.js +66 -30
  379. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  380. package/build/dist/Server/Services/StatusPagePrivateUserService.js +92 -2
  381. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  382. package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js +76 -0
  383. package/build/dist/Server/Services/UserNotificationEmailRollupBatchService.js.map +1 -0
  384. package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js +77 -0
  385. package/build/dist/Server/Services/UserNotificationEmailRollupItemService.js.map +1 -0
  386. package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js +111 -0
  387. package/build/dist/Server/Services/UserNotificationEmailRollupSettingService.js.map +1 -0
  388. package/build/dist/Server/Services/UserNotificationSettingService.js +46 -20
  389. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  390. package/build/dist/Server/Services/UserService.js +90 -0
  391. package/build/dist/Server/Services/UserService.js.map +1 -1
  392. package/build/dist/Server/Types/Database/QueryHelper.js +1 -1
  393. package/build/dist/Server/Types/Database/QueryHelper.js.map +1 -1
  394. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +14 -3
  395. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
  396. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js +10 -0
  397. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/ExceptionSpikeDetector.js.map +1 -1
  398. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js +10 -0
  399. package/build/dist/Server/Utils/AI/SRE/Insights/Detectors/NewExceptionDetector.js.map +1 -1
  400. package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js +54 -1
  401. package/build/dist/Server/Utils/AI/SRE/Insights/InsightTriageRunner.js.map +1 -1
  402. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +18 -4
  403. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
  404. package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js +59 -0
  405. package/build/dist/Server/Utils/Billing/BillingFailureNoticeThrottle.js.map +1 -0
  406. package/build/dist/Server/Utils/DataSource/HttpFetch.js +2 -1
  407. package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
  408. package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js +91 -0
  409. package/build/dist/Server/Utils/EmailRollup/EmailRollupConstants.js.map +1 -0
  410. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js +691 -0
  411. package/build/dist/Server/Utils/EmailRollup/EmailRollupFlushRunner.js.map +1 -0
  412. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js +497 -0
  413. package/build/dist/Server/Utils/EmailRollup/EmailRollupRenderer.js.map +1 -0
  414. package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js +257 -0
  415. package/build/dist/Server/Utils/EmailRollup/EmailRollupWriter.js.map +1 -0
  416. package/build/dist/Server/Utils/LLM/LLMService.js +64 -1
  417. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  418. package/build/dist/Server/Utils/LogRedaction.js +8 -0
  419. package/build/dist/Server/Utils/LogRedaction.js.map +1 -1
  420. package/build/dist/Server/Utils/Logger.js +63 -1
  421. package/build/dist/Server/Utils/Logger.js.map +1 -1
  422. package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js +141 -0
  423. package/build/dist/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.js.map +1 -0
  424. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  425. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  426. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +51 -1
  427. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  428. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js +7 -0
  429. package/build/dist/Server/Utils/Monitor/MonitorCriteriaDataExtractor.js.map +1 -1
  430. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +37 -0
  431. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  432. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +158 -6
  433. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  434. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +33 -0
  435. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  436. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +32 -0
  437. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  438. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +330 -21
  439. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  440. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +55 -10
  441. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
  442. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +178 -49
  443. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
  444. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +119 -29
  445. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  446. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js +30 -17
  447. package/build/dist/Server/Utils/NetworkDevice/DeviceHealthAggregation.js.map +1 -1
  448. package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js +158 -0
  449. package/build/dist/Server/Utils/NetworkSite/NetworkSiteHierarchyLock.js.map +1 -0
  450. package/build/dist/Server/Utils/OutboundUserAgent.js +123 -0
  451. package/build/dist/Server/Utils/OutboundUserAgent.js.map +1 -0
  452. package/build/dist/Server/Utils/StartServer.js +38 -14
  453. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  454. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js +28 -8
  455. package/build/dist/Server/Utils/Telemetry/CaptureSpan.js.map +1 -1
  456. package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js +95 -0
  457. package/build/dist/Server/Utils/Telemetry/ErrorClassResolver.js.map +1 -0
  458. package/build/dist/Server/Utils/Telemetry/SpanUtil.js +29 -0
  459. package/build/dist/Server/Utils/Telemetry/SpanUtil.js.map +1 -1
  460. package/build/dist/Server/Utils/Telemetry.js +162 -46
  461. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  462. package/build/dist/Types/AI/ExceptionAIClassification.js +10 -24
  463. package/build/dist/Types/AI/ExceptionAIClassification.js.map +1 -1
  464. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  465. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  466. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js +2 -0
  467. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUsageSnapshot.js.map +1 -0
  468. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js +7 -0
  469. package/build/dist/Types/EnterpriseLicense/EnterpriseLicenseUserCountSource.js.map +1 -0
  470. package/build/dist/Types/Exception/ApiException.js +9 -0
  471. package/build/dist/Types/Exception/ApiException.js.map +1 -1
  472. package/build/dist/Types/Exception/BadDataException.js +10 -0
  473. package/build/dist/Types/Exception/BadDataException.js.map +1 -1
  474. package/build/dist/Types/Exception/BadRequestException.js +10 -0
  475. package/build/dist/Types/Exception/BadRequestException.js.map +1 -1
  476. package/build/dist/Types/Exception/Exception.js +56 -0
  477. package/build/dist/Types/Exception/Exception.js.map +1 -1
  478. package/build/dist/Types/Exception/ForbiddenException.js +9 -0
  479. package/build/dist/Types/Exception/ForbiddenException.js.map +1 -1
  480. package/build/dist/Types/Exception/NotAuthenticatedException.js +9 -0
  481. package/build/dist/Types/Exception/NotAuthenticatedException.js.map +1 -1
  482. package/build/dist/Types/Exception/NotAuthorizedException.js +9 -0
  483. package/build/dist/Types/Exception/NotAuthorizedException.js.map +1 -1
  484. package/build/dist/Types/Exception/NotFoundException.js +10 -0
  485. package/build/dist/Types/Exception/NotFoundException.js.map +1 -1
  486. package/build/dist/Types/Exception/PayloadTooLargeException.js +10 -0
  487. package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -1
  488. package/build/dist/Types/Exception/PaymentRequiredException.js +9 -0
  489. package/build/dist/Types/Exception/PaymentRequiredException.js.map +1 -1
  490. package/build/dist/Types/Exception/ServiceUnavailableException.js +9 -0
  491. package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -1
  492. package/build/dist/Types/Exception/SsoAuthorizationException.js +9 -0
  493. package/build/dist/Types/Exception/SsoAuthorizationException.js.map +1 -1
  494. package/build/dist/Types/Exception/TenantNotFoundException.js +10 -0
  495. package/build/dist/Types/Exception/TenantNotFoundException.js.map +1 -1
  496. package/build/dist/Types/Exception/TimeoutException.js +9 -0
  497. package/build/dist/Types/Exception/TimeoutException.js.map +1 -1
  498. package/build/dist/Types/Exception/TooManyRequestsException.js +9 -0
  499. package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -1
  500. package/build/dist/Types/Exception/UnableToReachServer.js +9 -0
  501. package/build/dist/Types/Exception/UnableToReachServer.js.map +1 -1
  502. package/build/dist/Types/Exception/WebsiteRequestException.js +9 -0
  503. package/build/dist/Types/Exception/WebsiteRequestException.js.map +1 -1
  504. package/build/dist/Types/Monitor/CriteriaFilter.js +45 -2
  505. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  506. package/build/dist/Types/Monitor/DatabaseMetricCatalog.js +594 -0
  507. package/build/dist/Types/Monitor/DatabaseMetricCatalog.js.map +1 -0
  508. package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js +21 -0
  509. package/build/dist/Types/Monitor/DatabaseMonitor/DatabaseMonitorResponse.js.map +1 -0
  510. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +70 -0
  511. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  512. package/build/dist/Types/Monitor/MonitorMetricType.js +61 -0
  513. package/build/dist/Types/Monitor/MonitorMetricType.js.map +1 -1
  514. package/build/dist/Types/Monitor/MonitorStep.js +54 -0
  515. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  516. package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js +122 -0
  517. package/build/dist/Types/Monitor/MonitorStepDatabaseMonitor.js.map +1 -0
  518. package/build/dist/Types/Monitor/MonitorStepSqlMonitor.js.map +1 -1
  519. package/build/dist/Types/Monitor/MonitorType.js +45 -1
  520. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  521. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js +21 -1
  522. package/build/dist/Types/Monitor/SnmpMonitor/NetworkDeviceAlertPack.js.map +1 -1
  523. package/build/dist/Types/Monitor/SqlConnectionConfig.js +2 -0
  524. package/build/dist/Types/Monitor/SqlConnectionConfig.js.map +1 -0
  525. package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js +172 -0
  526. package/build/dist/Types/NetworkDevice/NetworkAlertPolicyScope.js.map +1 -0
  527. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +40 -22
  528. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -1
  529. package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js +26 -0
  530. package/build/dist/Types/NetworkSite/DefaultNetworkSiteTypeHierarchy.js.map +1 -0
  531. package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js +186 -0
  532. package/build/dist/Types/NotificationSetting/NotificationEmailRollupCategory.js.map +1 -0
  533. package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js +87 -0
  534. package/build/dist/Types/NotificationSetting/NotificationEmailRollupPolicy.js.map +1 -0
  535. package/build/dist/Types/Permission.js +80 -0
  536. package/build/dist/Types/Permission.js.map +1 -1
  537. package/build/dist/Types/Telemetry/ErrorClass.js +216 -0
  538. package/build/dist/Types/Telemetry/ErrorClass.js.map +1 -0
  539. package/build/dist/Types/Telemetry/UnitOfWork.js +59 -0
  540. package/build/dist/Types/Telemetry/UnitOfWork.js.map +1 -0
  541. package/build/dist/UI/Components/CommandPalette/CommandPalette.js +2 -7
  542. package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
  543. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +3 -0
  544. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  545. package/build/dist/UI/Components/Modal/Modal.js +2 -7
  546. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  547. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +39 -0
  548. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  549. package/build/dist/UI/Components/ProgressBar/ProgressBar.js +12 -1
  550. package/build/dist/UI/Components/ProgressBar/ProgressBar.js.map +1 -1
  551. package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js +6 -6
  552. package/build/dist/UI/Components/RadioButtons/BasicRadioButtons.js.map +1 -1
  553. package/build/dist/UI/Components/SideMenu/SideMenu.js +67 -5
  554. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  555. package/build/dist/UI/Components/SideMenu/SideMenuItem.js +49 -53
  556. package/build/dist/UI/Components/SideMenu/SideMenuItem.js.map +1 -1
  557. package/build/dist/UI/Components/SideMenu/SideMenuSection.js +25 -7
  558. package/build/dist/UI/Components/SideMenu/SideMenuSection.js.map +1 -1
  559. package/build/dist/UI/Components/SideOver/SideOver.js +5 -20
  560. package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
  561. package/build/dist/UI/Utils/PageScrollLock.js +31 -3
  562. package/build/dist/UI/Utils/PageScrollLock.js.map +1 -1
  563. package/build/dist/UI/Utils/PermissionGate.js +42 -1
  564. package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
  565. package/build/dist/UI/Utils/SensitiveUrlToken.js +97 -0
  566. package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -0
  567. package/build/dist/UI/Utils/TestLLMProvider.js +4 -5
  568. package/build/dist/UI/Utils/TestLLMProvider.js.map +1 -1
  569. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +15 -0
  570. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -1
  571. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +111 -9
  572. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  573. package/build/dist/Utils/Monitor/MonitorMetricType.js +109 -1
  574. package/build/dist/Utils/Monitor/MonitorMetricType.js.map +1 -1
  575. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +8 -3
  576. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  577. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js +27 -7
  578. package/build/dist/Utils/NetworkDevice/DeviceHealthStateUtil.js.map +1 -1
  579. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +7 -5
  580. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
  581. package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js +180 -0
  582. package/build/dist/Utils/NetworkDevice/NetworkAlertPolicyBootstrapUtil.js.map +1 -0
  583. package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js +12 -0
  584. package/build/dist/Utils/NetworkDevice/SnmpCredentialUtil.js.map +1 -0
  585. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +15 -5
  586. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
  587. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +44 -15
  588. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
  589. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +52 -23
  590. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -1
  591. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js +85 -13
  592. package/build/dist/Utils/NetworkDiscovery/PingMonitorBuilder.js.map +1 -1
  593. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js +30 -15
  594. package/build/dist/Utils/NetworkSite/SiteStatusRollupUtil.js.map +1 -1
  595. package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js +191 -0
  596. package/build/dist/Utils/NetworkSite/TypeHierarchyUtil.js.map +1 -0
  597. package/package.json +2 -2
@@ -0,0 +1,569 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { describe, expect, test } from "@jest/globals";
4
+ import { getMetadataArgsStorage } from "typeorm";
5
+ import { IndexMetadataArgs } from "typeorm/metadata-args/IndexMetadataArgs";
6
+ import { RelationMetadataArgs } from "typeorm/metadata-args/RelationMetadataArgs";
7
+ import AllModelTypes from "../../../Models/DatabaseModels/Index";
8
+ import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
9
+ import UserNotificationEmailRollupBatch from "../../../Models/DatabaseModels/UserNotificationEmailRollupBatch";
10
+ import UserNotificationEmailRollupItem from "../../../Models/DatabaseModels/UserNotificationEmailRollupItem";
11
+ import Services from "../../../Server/Services/Index";
12
+ import UserNotificationEmailRollupBatchService from "../../../Server/Services/UserNotificationEmailRollupBatchService";
13
+ import UserNotificationEmailRollupItemService from "../../../Server/Services/UserNotificationEmailRollupItemService";
14
+ import CreateBy from "../../../Server/Types/Database/CreateBy";
15
+ import DeleteBy from "../../../Server/Types/Database/DeleteBy";
16
+ import UpdateBy from "../../../Server/Types/Database/UpdateBy";
17
+ import {
18
+ CLAIM_EPOCH_MINUTES,
19
+ FLUSH_AFTER_MINUTES,
20
+ ROLLUP_BATCH_RETENTION_DAYS,
21
+ ROLLUP_ITEM_RETENTION_DAYS,
22
+ } from "../../../Server/Utils/EmailRollup/EmailRollupConstants";
23
+ import { ColumnAccessControl } from "../../../Types/BaseDatabase/AccessControl";
24
+ import Dictionary from "../../../Types/Dictionary";
25
+ import NotAuthorizedException from "../../../Types/Exception/NotAuthorizedException";
26
+ import GenericFunction from "../../../Types/GenericFunction";
27
+ import ObjectID from "../../../Types/ObjectID";
28
+
29
+ /*
30
+ * The rollup tables carry almost no behaviour. Everything that makes them
31
+ * safe lives in decorator metadata and in three registration files, and none
32
+ * of it is exercised by a functional test — which is exactly why it is worth
33
+ * pinning here. What breaks in production if any of this regresses:
34
+ *
35
+ * 1. AN OPEN ACCESS LIST IS A NOTIFICATION KILL SWITCH. Both tables are
36
+ * root-only in every direction. A pending item row is the only record
37
+ * that a deferred notification is owed to somebody, and a batch row is
38
+ * what stops a second replica sending the same rollup. Grant create on
39
+ * the batch table and a caller can pre-claim an epoch so the real flush
40
+ * is refused; grant delete on the item table and a caller can drop
41
+ * another member's queued notifications on the floor. Empty lists are
42
+ * also why the feature needs no new Permission enum members at all — the
43
+ * assertion below is direct, so PermissionCatalogueCoverage can never be
44
+ * triggered by these two models in the first place.
45
+ *
46
+ * 2. THE UNIQUE INDEX IS THE EXACTLY-ONCE MECHANISM. Not the Redis
47
+ * semaphore, and not the "is it still pending?" predicate on the stamping
48
+ * update — DatabaseService resolves an update predicate in a separate
49
+ * read, so that is a check-then-act race, not a compare-and-swap. Lose
50
+ * the four-column UNIQUE index on the batch table, or reorder it, and two
51
+ * replicas both claim and the flooded recipient gets the rollup twice.
52
+ *
53
+ * 3. rollupBatchId MUST NOT BECOME A FOREIGN KEY. A CASCADE would delete
54
+ * queue items when their batch is pruned at thirty days, destroying the
55
+ * volume record; a SET NULL would un-stamp them and hand a month-old
56
+ * rollup back to the sweep as pending work. Somebody "tidying up" the
57
+ * model by adding the obvious @ManyToOne is the regression this pins.
58
+ *
59
+ * 4. UNREGISTERED IS INERT. A model missing from AllModelTypes gets no
60
+ * table; a service missing from the Services array is never swept by the
61
+ * HardDelete cron, so the queue grows without bound on the exact install
62
+ * that generates the most rows. Both are silent.
63
+ *
64
+ * Nothing here touches a database: the models are instantiated and read for
65
+ * their decorator metadata, the services are read for their retention
66
+ * settings and their root guards, and the wiring that lives in the App
67
+ * workspace is read off the source as text.
68
+ */
69
+
70
+ const ITEM_SERVICE_SOURCE: string = fs.readFileSync(
71
+ path.join(
72
+ __dirname,
73
+ "../../../Server/Services/UserNotificationEmailRollupItemService.ts",
74
+ ),
75
+ "utf8",
76
+ );
77
+
78
+ const BATCH_SERVICE_SOURCE: string = fs.readFileSync(
79
+ path.join(
80
+ __dirname,
81
+ "../../../Server/Services/UserNotificationEmailRollupBatchService.ts",
82
+ ),
83
+ "utf8",
84
+ );
85
+
86
+ /*
87
+ * The routers live in the App workspace, which this suite cannot import, so
88
+ * the mount is asserted by reading the source — the same thing the other
89
+ * wiring tests in this directory do. It breaks on reformatting, which is the
90
+ * price of asserting on the registration itself rather than on a re-export
91
+ * somebody could add to make it pass.
92
+ */
93
+ const BASE_API_INDEX_SOURCE: string = fs.readFileSync(
94
+ path.join(__dirname, "../../../../App/FeatureSet/BaseAPI/Index.ts"),
95
+ "utf8",
96
+ );
97
+
98
+ const PROJECT_ID: ObjectID = new ObjectID(
99
+ "22222222-2222-4222-8222-222222222222",
100
+ );
101
+
102
+ const USER_ID: ObjectID = new ObjectID("33333333-3333-4333-8333-333333333333");
103
+
104
+ interface ModelUnderTest {
105
+ name: string;
106
+ modelType: { new (): BaseModel };
107
+ crudApiPath: string;
108
+ }
109
+
110
+ const ROLLUP_MODELS: Array<ModelUnderTest> = [
111
+ {
112
+ name: "UserNotificationEmailRollupItem",
113
+ modelType: UserNotificationEmailRollupItem,
114
+ crudApiPath: "/user-notification-email-rollup-item",
115
+ },
116
+ {
117
+ name: "UserNotificationEmailRollupBatch",
118
+ modelType: UserNotificationEmailRollupBatch,
119
+ crudApiPath: "/user-notification-email-rollup-batch",
120
+ },
121
+ ];
122
+
123
+ /*
124
+ * The three root guards are `protected`, which is a compile-time notion only.
125
+ * Calling them through create()/updateBy()/deleteBy() instead would drag the
126
+ * whole ORM in for no extra assurance about the one check under test.
127
+ */
128
+ interface RootGuardedServiceInternals {
129
+ onBeforeCreate: (createBy: CreateBy<BaseModel>) => Promise<unknown>;
130
+ onBeforeUpdate: (updateBy: UpdateBy<BaseModel>) => Promise<unknown>;
131
+ onBeforeDelete: (deleteBy: DeleteBy<BaseModel>) => Promise<unknown>;
132
+ }
133
+
134
+ interface RetentionService {
135
+ hardDeleteItemByColumnName: string;
136
+ hardDeleteItemsOlderThanDays: number;
137
+ }
138
+
139
+ interface ServiceUnderTest {
140
+ name: string;
141
+ service: unknown;
142
+ source: string;
143
+ retentionInDays: number;
144
+ }
145
+
146
+ const ROLLUP_SERVICES: Array<ServiceUnderTest> = [
147
+ {
148
+ name: "UserNotificationEmailRollupItemService",
149
+ service: UserNotificationEmailRollupItemService,
150
+ source: ITEM_SERVICE_SOURCE,
151
+ retentionInDays: ROLLUP_ITEM_RETENTION_DAYS,
152
+ },
153
+ {
154
+ name: "UserNotificationEmailRollupBatchService",
155
+ service: UserNotificationEmailRollupBatchService,
156
+ source: BATCH_SERVICE_SOURCE,
157
+ retentionInDays: ROLLUP_BATCH_RETENTION_DAYS,
158
+ },
159
+ ];
160
+
161
+ function relationArgs(
162
+ target: GenericFunction,
163
+ propertyName: string,
164
+ ): RelationMetadataArgs | undefined {
165
+ return getMetadataArgsStorage().relations.find(
166
+ (relation: RelationMetadataArgs): boolean => {
167
+ return (
168
+ relation.target === target && relation.propertyName === propertyName
169
+ );
170
+ },
171
+ );
172
+ }
173
+
174
+ /*
175
+ * A property-level @Index() is stored as a one-column index, so the composite
176
+ * class-level ones are the entries with more than one named column.
177
+ */
178
+ function compositeIndexes(target: GenericFunction): Array<IndexMetadataArgs> {
179
+ return getMetadataArgsStorage().indices.filter(
180
+ (index: IndexMetadataArgs): boolean => {
181
+ return (
182
+ index.target === target &&
183
+ Array.isArray(index.columns) &&
184
+ index.columns.length > 1
185
+ );
186
+ },
187
+ );
188
+ }
189
+
190
+ function indexColumns(index: IndexMetadataArgs): Array<string> {
191
+ return index.columns as Array<string>;
192
+ }
193
+
194
+ function findIndexOver(
195
+ target: GenericFunction,
196
+ columns: Array<string>,
197
+ ): IndexMetadataArgs | undefined {
198
+ return compositeIndexes(target).find((index: IndexMetadataArgs): boolean => {
199
+ return indexColumns(index).join(",") === columns.join(",");
200
+ });
201
+ }
202
+
203
+ function internals(service: unknown): RootGuardedServiceInternals {
204
+ return service as RootGuardedServiceInternals;
205
+ }
206
+
207
+ function retention(service: unknown): RetentionService {
208
+ return service as RetentionService;
209
+ }
210
+
211
+ describe("the rollup tables are tenant-scoped and addressable like every other model", () => {
212
+ test.each(ROLLUP_MODELS)(
213
+ "$name is scoped to a project by projectId",
214
+ (entry: ModelUnderTest) => {
215
+ /*
216
+ * The tenant column is what makes every read, write and permission
217
+ * check project-scoped by default. Without it the flush sweep's own
218
+ * queries would be global in a way nothing downstream expects.
219
+ */
220
+ expect(new entry.modelType().getTenantColumn()).toBe("projectId");
221
+ },
222
+ );
223
+
224
+ test.each(ROLLUP_MODELS)(
225
+ "$name is served at its own CRUD path",
226
+ (entry: ModelUnderTest) => {
227
+ expect(new entry.modelType().getCrudApiPath()?.toString()).toBe(
228
+ entry.crudApiPath,
229
+ );
230
+ },
231
+ );
232
+
233
+ test.each(ROLLUP_MODELS)(
234
+ "$name is registered in Models/Index.ts",
235
+ (entry: ModelUnderTest) => {
236
+ /*
237
+ * Boot-time createTables() iterates that array. A model missing from it
238
+ * type-checks, imports fine, and simply has no table in Postgres — the
239
+ * write path's fail-open catch would then swallow every insert and the
240
+ * feature would be silently dead.
241
+ */
242
+ expect(AllModelTypes).toContain(entry.modelType);
243
+ },
244
+ );
245
+
246
+ test("both services are registered in Services/Index.ts", () => {
247
+ /*
248
+ * Registration is what subscribes a service to the HardDelete cron, which
249
+ * iterates the whole array. Unregistered means the queue is never pruned.
250
+ */
251
+ expect(Services).toContain(UserNotificationEmailRollupItemService);
252
+ expect(Services).toContain(UserNotificationEmailRollupBatchService);
253
+ });
254
+
255
+ test("both CRUD routers are mounted in the API", () => {
256
+ expect(BASE_API_INDEX_SOURCE).toContain(
257
+ 'import UserNotificationEmailRollupItem from "Common/Models/DatabaseModels/UserNotificationEmailRollupItem";',
258
+ );
259
+ expect(BASE_API_INDEX_SOURCE).toContain(
260
+ 'import UserNotificationEmailRollupBatch from "Common/Models/DatabaseModels/UserNotificationEmailRollupBatch";',
261
+ );
262
+ expect(BASE_API_INDEX_SOURCE).toContain(
263
+ " UserNotificationEmailRollupItem,\n" +
264
+ " UserNotificationEmailRollupItemServiceType\n" +
265
+ " >(\n" +
266
+ " UserNotificationEmailRollupItem,\n" +
267
+ " UserNotificationEmailRollupItemService,\n" +
268
+ " ).getRouter(),",
269
+ );
270
+ expect(BASE_API_INDEX_SOURCE).toContain(
271
+ " UserNotificationEmailRollupBatch,\n" +
272
+ " UserNotificationEmailRollupBatchServiceType\n" +
273
+ " >(\n" +
274
+ " UserNotificationEmailRollupBatch,\n" +
275
+ " UserNotificationEmailRollupBatchService,\n" +
276
+ " ).getRouter(),",
277
+ );
278
+ });
279
+ });
280
+
281
+ describe("both tables are root-only, which is why the feature needs no new permissions", () => {
282
+ test.each(ROLLUP_MODELS)(
283
+ "$name refuses create, read, update and delete to every permission",
284
+ (entry: ModelUnderTest) => {
285
+ const model: BaseModel = new entry.modelType();
286
+
287
+ expect(model.createRecordPermissions).toEqual([]);
288
+ expect(model.readRecordPermissions).toEqual([]);
289
+ expect(model.updateRecordPermissions).toEqual([]);
290
+ expect(model.deleteRecordPermissions).toEqual([]);
291
+ },
292
+ );
293
+
294
+ /*
295
+ * THE INVARIANT THIS BLOCK EXISTS FOR. Not one column may name a Permission
296
+ * member. That is both the security property — nothing about a mail ledger
297
+ * is a user-facing resource — and the reason PermissionCatalogueCoverage
298
+ * has nothing to sweep here: a permission these models referenced but the
299
+ * catalogue did not describe would gate the table and be ungrantable, and
300
+ * the only way to be sure of never hitting that is to reference none.
301
+ */
302
+ test.each(ROLLUP_MODELS)(
303
+ "$name names no permission on any column, not even a readable one",
304
+ (entry: ModelUnderTest) => {
305
+ const model: BaseModel = new entry.modelType();
306
+ const allColumns: Dictionary<ColumnAccessControl> =
307
+ model.getColumnAccessControlForAllColumns();
308
+ const columnNames: Array<string> = Object.keys(allColumns);
309
+
310
+ // Guards the loop below against passing on an empty dictionary.
311
+ expect(columnNames.length).toBeGreaterThan(10);
312
+
313
+ for (const columnName of columnNames) {
314
+ const accessControl: ColumnAccessControl = allColumns[
315
+ columnName
316
+ ] as ColumnAccessControl;
317
+
318
+ expect(accessControl.create).toEqual([]);
319
+ expect(accessControl.read).toEqual([]);
320
+ expect(accessControl.update).toEqual([]);
321
+ }
322
+ },
323
+ );
324
+ });
325
+
326
+ describe("deleting a project or a user takes its rollup rows with it", () => {
327
+ test.each(ROLLUP_MODELS)(
328
+ "$name cascades from both project and user",
329
+ (entry: ModelUnderTest) => {
330
+ /*
331
+ * CASCADE rather than SET NULL on both: a queue row whose project or
332
+ * recipient has been deleted is not a row to keep and re-send, and both
333
+ * id columns are NOT NULL, so SET NULL would fail the delete outright.
334
+ */
335
+ const project: RelationMetadataArgs | undefined = relationArgs(
336
+ entry.modelType,
337
+ "project",
338
+ );
339
+ const user: RelationMetadataArgs | undefined = relationArgs(
340
+ entry.modelType,
341
+ "user",
342
+ );
343
+
344
+ expect(project?.relationType).toBe("many-to-one");
345
+ expect(project?.options.onDelete).toBe("CASCADE");
346
+ expect(user?.relationType).toBe("many-to-one");
347
+ expect(user?.options.onDelete).toBe("CASCADE");
348
+ },
349
+ );
350
+
351
+ /*
352
+ * ...and rollupBatchId is the deliberate exception: a bare ObjectID column
353
+ * with no relation and therefore no foreign key. Adding the obvious
354
+ * @ManyToOne would give it a referential action, and both available actions
355
+ * are wrong — CASCADE deletes seven-day queue rows when their thirty-day
356
+ * batch is pruned, SET NULL un-stamps them and re-sends a month-old rollup.
357
+ */
358
+ test("rollupBatchId carries no relation, so no foreign key can be generated", () => {
359
+ expect(
360
+ relationArgs(UserNotificationEmailRollupItem, "rollupBatchId"),
361
+ ).toBeUndefined();
362
+ expect(
363
+ relationArgs(UserNotificationEmailRollupItem, "rollupBatch"),
364
+ ).toBeUndefined();
365
+
366
+ const relationsOnItem: Array<string> = getMetadataArgsStorage()
367
+ .relations.filter((relation: RelationMetadataArgs): boolean => {
368
+ return relation.target === UserNotificationEmailRollupItem;
369
+ })
370
+ .map((relation: RelationMetadataArgs): string => {
371
+ return relation.propertyName;
372
+ });
373
+
374
+ expect(relationsOnItem.sort()).toEqual(["project", "user"]);
375
+ });
376
+ });
377
+
378
+ describe("the indexes each table cannot work without", () => {
379
+ /*
380
+ * THE EXACTLY-ONCE MECHANISM. Four columns, in this order, UNIQUE. The
381
+ * order matters as much as the membership: claimEpochStartsAt has to be
382
+ * last so the leading three columns are the bucket key a lookup can also
383
+ * use, and the epoch is what turns "this address, now" into a value two
384
+ * replicas compute identically and therefore collide on.
385
+ */
386
+ test("the batch table claims under a UNIQUE index over exactly the bucket key plus the epoch", () => {
387
+ const claimIndex: IndexMetadataArgs | undefined = findIndexOver(
388
+ UserNotificationEmailRollupBatch,
389
+ ["projectId", "userId", "toEmail", "claimEpochStartsAt"],
390
+ );
391
+
392
+ expect(claimIndex).toBeDefined();
393
+ expect(claimIndex?.unique).toBe(true);
394
+ expect(indexColumns(claimIndex as IndexMetadataArgs)).toEqual([
395
+ "projectId",
396
+ "userId",
397
+ "toEmail",
398
+ "claimEpochStartsAt",
399
+ ]);
400
+ });
401
+
402
+ test("the item table declares all three of its composite indexes", () => {
403
+ /*
404
+ * The burst counter runs on the hot notification path and counts over the
405
+ * leading four columns with a createdAt range, so all five are in one
406
+ * index or the count is a scan of the tenant's whole queue.
407
+ */
408
+ expect(
409
+ findIndexOver(UserNotificationEmailRollupItem, [
410
+ "projectId",
411
+ "userId",
412
+ "toEmail",
413
+ "rollupCategory",
414
+ "createdAt",
415
+ ]),
416
+ ).toBeDefined();
417
+
418
+ /*
419
+ * The sweep's index: pending, oldest first, across every tenant. It is
420
+ * global by design and so cannot be scoped by projectId.
421
+ */
422
+ expect(
423
+ findIndexOver(UserNotificationEmailRollupItem, ["sentAt", "createdAt"]),
424
+ ).toBeDefined();
425
+
426
+ /*
427
+ * The read-back index. A flush stamps its claimed rows and then re-reads
428
+ * them by batch, so it renders exactly the rows it wrote.
429
+ */
430
+ const byBatch: IndexMetadataArgs | undefined =
431
+ getMetadataArgsStorage().indices.find(
432
+ (index: IndexMetadataArgs): boolean => {
433
+ return (
434
+ index.target === UserNotificationEmailRollupItem &&
435
+ Array.isArray(index.columns) &&
436
+ index.columns.join(",") === "rollupBatchId"
437
+ );
438
+ },
439
+ );
440
+
441
+ expect(byBatch).toBeDefined();
442
+ });
443
+
444
+ test("none of the item table's indexes is unique", () => {
445
+ /*
446
+ * The item table is an append-only ledger — the same address legitimately
447
+ * receives two notifications of the same type in the same second. A
448
+ * unique index anywhere on it would make the write path's fail-open catch
449
+ * swallow the second one.
450
+ */
451
+ for (const index of compositeIndexes(UserNotificationEmailRollupItem)) {
452
+ expect(index.unique).toBe(false);
453
+ }
454
+ });
455
+ });
456
+
457
+ describe("retention is registered unconditionally, on both services", () => {
458
+ test.each(ROLLUP_SERVICES)(
459
+ "$name prunes on createdAt",
460
+ (entry: ServiceUnderTest) => {
461
+ expect(retention(entry.service).hardDeleteItemByColumnName).toBe(
462
+ "createdAt",
463
+ );
464
+ expect(retention(entry.service).hardDeleteItemsOlderThanDays).toBe(
465
+ entry.retentionInDays,
466
+ );
467
+ },
468
+ );
469
+
470
+ test("the two retentions are seven days and thirty days", () => {
471
+ expect(ROLLUP_ITEM_RETENTION_DAYS).toBe(7);
472
+ expect(ROLLUP_BATCH_RETENTION_DAYS).toBe(30);
473
+ });
474
+
475
+ /*
476
+ * EmailLogService registers its retention only `if (IsBillingEnabled)`, and
477
+ * copying that here would be a real bug rather than a style choice: the
478
+ * HardDelete:HardDeleteOlderItemsInDatabase cron iterates every service in
479
+ * the Services array and honours whatever retention it declares, with no
480
+ * billing check anywhere in the loop. A gated call therefore prunes nothing
481
+ * at all on a self-hosted install — which is precisely the install that
482
+ * generates the most rows, because it is the one being flooded.
483
+ */
484
+ test.each(ROLLUP_SERVICES)(
485
+ "$name does not gate its retention on billing",
486
+ (entry: ServiceUnderTest) => {
487
+ const constructorBody: string = entry.source.slice(
488
+ entry.source.indexOf("public constructor()"),
489
+ entry.source.indexOf("@CaptureSpan()"),
490
+ );
491
+
492
+ expect(constructorBody).toContain("hardDeleteItemsOlderThanInDays(");
493
+ expect(constructorBody).toContain('"createdAt"');
494
+ /*
495
+ * No branch of any kind, and no billing flag, between super(Model) and
496
+ * the retention call. The import check is the stronger half: the flag
497
+ * lives in EnvironmentConfig and cannot be reached without importing
498
+ * it, whereas the whole-file text mentions IsBillingEnabled in the
499
+ * comment that explains why it is deliberately absent.
500
+ */
501
+ expect(constructorBody).not.toContain("if (");
502
+ expect(constructorBody).not.toContain("IsBillingEnabled");
503
+ expect(entry.source).not.toContain("EnvironmentConfig");
504
+ },
505
+ );
506
+ });
507
+
508
+ describe("nothing but the notification pipeline may write to either table", () => {
509
+ const NON_ROOT: { isRoot: boolean; tenantId: ObjectID } = {
510
+ isRoot: false,
511
+ tenantId: PROJECT_ID,
512
+ };
513
+
514
+ test.each(ROLLUP_SERVICES)(
515
+ "$name refuses a non-root create",
516
+ async (entry: ServiceUnderTest) => {
517
+ const item: UserNotificationEmailRollupItem =
518
+ new UserNotificationEmailRollupItem();
519
+ item.projectId = PROJECT_ID;
520
+ item.userId = USER_ID;
521
+
522
+ await expect(
523
+ internals(entry.service).onBeforeCreate({
524
+ data: item,
525
+ props: NON_ROOT,
526
+ } as unknown as CreateBy<BaseModel>),
527
+ ).rejects.toBeInstanceOf(NotAuthorizedException);
528
+ },
529
+ );
530
+
531
+ test.each(ROLLUP_SERVICES)(
532
+ "$name refuses a non-root update",
533
+ async (entry: ServiceUnderTest) => {
534
+ await expect(
535
+ internals(entry.service).onBeforeUpdate({
536
+ query: {},
537
+ data: {},
538
+ props: NON_ROOT,
539
+ } as unknown as UpdateBy<BaseModel>),
540
+ ).rejects.toBeInstanceOf(NotAuthorizedException);
541
+ },
542
+ );
543
+
544
+ test.each(ROLLUP_SERVICES)(
545
+ "$name refuses a non-root delete",
546
+ async (entry: ServiceUnderTest) => {
547
+ await expect(
548
+ internals(entry.service).onBeforeDelete({
549
+ query: {},
550
+ props: NON_ROOT,
551
+ } as unknown as DeleteBy<BaseModel>),
552
+ ).rejects.toBeInstanceOf(NotAuthorizedException);
553
+ },
554
+ );
555
+ });
556
+
557
+ /*
558
+ * The claim epoch and the flush delay are two constants that look independent
559
+ * and are not. A bucket becomes due only once its oldest pending item is
560
+ * FLUSH_AFTER_MINUTES old, and a flush stamps every pending row for that
561
+ * bucket, so a legitimate consecutive flush is always at least that long
562
+ * after the previous one. Only while the epoch is the same length does that
563
+ * guarantee "always a later epoch", and therefore "the UNIQUE index never
564
+ * refuses real work". Shorten the epoch and duplicate rollups become
565
+ * possible; lengthen it and a legitimate second flush is silently dropped.
566
+ */
567
+ test("the claim epoch is exactly as long as the flush delay", () => {
568
+ expect(CLAIM_EPOCH_MINUTES).toBe(FLUSH_AFTER_MINUTES);
569
+ });