@oneuptime/common 12.0.30 → 12.0.31

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 (489) hide show
  1. package/Models/AnalyticsModels/SecurityEvent.ts +48 -16
  2. package/Models/AnalyticsModels/ThreatIntelIndicator.ts +10 -5
  3. package/Models/DatabaseModels/AlertSeverity.ts +44 -0
  4. package/Models/DatabaseModels/DetectionRule.ts +16 -5
  5. package/Models/DatabaseModels/GoogleSecOpsConnection.ts +14 -5
  6. package/Models/DatabaseModels/IncidentSeverity.ts +44 -0
  7. package/Models/DatabaseModels/Index.ts +2 -0
  8. package/Models/DatabaseModels/NetworkDevice.ts +113 -3
  9. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +88 -0
  10. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +22 -0
  11. package/Models/DatabaseModels/NetworkDeviceOidTemplate.ts +499 -0
  12. package/Models/DatabaseModels/ThreatIntelFeed.ts +16 -5
  13. package/Server/API/GlobalConfigAPI.ts +362 -183
  14. package/Server/API/TelemetryAPI.ts +42 -4
  15. package/Server/EnvironmentConfig.ts +112 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.ts +59 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.ts +25 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  19. package/Server/Middleware/MultipartFormData.ts +118 -32
  20. package/Server/Services/AlertEpisodeLabelRuleEngineService.ts +9 -1
  21. package/Server/Services/AlertEpisodeOnCallRuleEngineService.ts +9 -1
  22. package/Server/Services/AlertEpisodeOwnerRuleEngineService.ts +9 -1
  23. package/Server/Services/AlertEpisodePrivacyRuleEngineService.ts +9 -1
  24. package/Server/Services/AlertGroupingEngineService.ts +9 -1
  25. package/Server/Services/AlertLabelRuleEngineService.ts +9 -1
  26. package/Server/Services/AlertOnCallRuleEngineService.ts +9 -1
  27. package/Server/Services/AlertOwnerRuleEngineService.ts +9 -1
  28. package/Server/Services/AlertPrivacyRuleEngineService.ts +9 -1
  29. package/Server/Services/AlertReminderRuleService.ts +9 -1
  30. package/Server/Services/AutoRemediationRuleEngineService.ts +9 -1
  31. package/Server/Services/CephClusterLabelRuleEngineService.ts +9 -1
  32. package/Server/Services/CephClusterOwnerRuleEngineService.ts +9 -1
  33. package/Server/Services/CloudResourceLabelRuleEngineService.ts +9 -1
  34. package/Server/Services/CloudResourceOwnerRuleEngineService.ts +9 -1
  35. package/Server/Services/DashboardLabelRuleEngineService.ts +9 -1
  36. package/Server/Services/DashboardOwnerRuleEngineService.ts +9 -1
  37. package/Server/Services/DockerHostLabelRuleEngineService.ts +9 -1
  38. package/Server/Services/DockerHostOwnerRuleEngineService.ts +9 -1
  39. package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +9 -1
  40. package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +9 -1
  41. package/Server/Services/HostLabelRuleEngineService.ts +9 -1
  42. package/Server/Services/HostOwnerRuleEngineService.ts +9 -1
  43. package/Server/Services/IncidentEpisodeLabelRuleEngineService.ts +9 -1
  44. package/Server/Services/IncidentEpisodeOnCallRuleEngineService.ts +9 -1
  45. package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +9 -1
  46. package/Server/Services/IncidentEpisodePrivacyRuleEngineService.ts +9 -1
  47. package/Server/Services/IncidentGroupingEngineService.ts +9 -1
  48. package/Server/Services/IncidentLabelRuleEngineService.ts +9 -1
  49. package/Server/Services/IncidentOnCallRuleEngineService.ts +9 -1
  50. package/Server/Services/IncidentOwnerRuleEngineService.ts +9 -1
  51. package/Server/Services/IncidentPrivacyRuleEngineService.ts +9 -1
  52. package/Server/Services/IncidentReminderRuleService.ts +9 -1
  53. package/Server/Services/IncidentSlaRuleService.ts +9 -1
  54. package/Server/Services/IncomingCallPolicyLabelRuleEngineService.ts +9 -1
  55. package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +9 -1
  56. package/Server/Services/Index.ts +2 -0
  57. package/Server/Services/IoTFleetLabelRuleEngineService.ts +9 -1
  58. package/Server/Services/IoTFleetOwnerRuleEngineService.ts +9 -1
  59. package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +9 -1
  60. package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +9 -1
  61. package/Server/Services/KubernetesResourceService.ts +5 -1
  62. package/Server/Services/MonitorLabelRuleEngineService.ts +9 -1
  63. package/Server/Services/MonitorOwnerRuleEngineService.ts +9 -1
  64. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +35 -0
  65. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +96 -0
  66. package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +9 -1
  67. package/Server/Services/NetworkDeviceOidTemplateService.ts +201 -0
  68. package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +9 -1
  69. package/Server/Services/NetworkDeviceService.ts +209 -1
  70. package/Server/Services/OnCallDutyPolicyLabelRuleEngineService.ts +9 -1
  71. package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +9 -1
  72. package/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.ts +9 -1
  73. package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +9 -1
  74. package/Server/Services/PodmanHostLabelRuleEngineService.ts +9 -1
  75. package/Server/Services/PodmanHostOwnerRuleEngineService.ts +9 -1
  76. package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +9 -1
  77. package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +9 -1
  78. package/Server/Services/RumApplicationLabelRuleEngineService.ts +9 -1
  79. package/Server/Services/RumApplicationOwnerRuleEngineService.ts +9 -1
  80. package/Server/Services/RunbookLabelRuleEngineService.ts +9 -1
  81. package/Server/Services/RunbookOwnerRuleEngineService.ts +9 -1
  82. package/Server/Services/RunbookRuleEngineService.ts +9 -1
  83. package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +9 -1
  84. package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +9 -1
  85. package/Server/Services/ScheduledMaintenanceReminderRuleService.ts +9 -1
  86. package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +9 -1
  87. package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +9 -1
  88. package/Server/Services/ServiceLabelRuleEngineService.ts +9 -1
  89. package/Server/Services/ServiceOwnerRuleEngineService.ts +9 -1
  90. package/Server/Services/StatusPageLabelRuleEngineService.ts +9 -1
  91. package/Server/Services/StatusPageMonitorRuleEngineService.ts +7 -0
  92. package/Server/Services/StatusPageOwnerRuleEngineService.ts +9 -1
  93. package/Server/Services/TelemetrySourceMapService.ts +266 -23
  94. package/Server/Services/UserService.ts +27 -0
  95. package/Server/Services/WorkflowLabelRuleEngineService.ts +9 -1
  96. package/Server/Services/WorkflowOwnerRuleEngineService.ts +9 -1
  97. package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +186 -0
  98. package/Server/Utils/Monitor/CapturedMetricAttributeUtil.ts +245 -0
  99. package/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.ts +21 -2
  100. package/Server/Utils/Monitor/MonitorMetricUtil.ts +55 -21
  101. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +32 -0
  102. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +15 -2
  103. package/Server/Utils/Monitor/NetworkDeviceWalkUtil.ts +18 -1
  104. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +10 -0
  105. package/Server/Utils/Monitor/SeriesResourceLabels.ts +34 -0
  106. package/Server/Utils/Rules/RuleEngineRuleRead.ts +48 -0
  107. package/Server/Utils/Telemetry/ExceptionSanitizer.ts +14 -1
  108. package/Server/Utils/Telemetry/LogExceptionExtractor.ts +14 -2
  109. package/Server/Utils/Telemetry/SourceMapResolver.ts +16 -5
  110. package/Server/Utils/Telemetry/StackTraceParser.ts +399 -0
  111. package/Tests/App/Dashboard/EventOverlayHook.test.tsx +125 -0
  112. package/Tests/App/Dashboard/HeaderImageAssets.test.tsx +93 -0
  113. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +3 -3
  114. package/Tests/App/Dashboard/UserElementEmail.test.tsx +12 -4
  115. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +1 -1
  116. package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +14 -0
  117. package/Tests/Models/DatabaseModels/ModelRegistryInvariants.test.ts +469 -0
  118. package/Tests/Models/SecurityDomainAccessControl.test.ts +429 -0
  119. package/Tests/Server/API/GlobalConfigLicense.test.ts +657 -0
  120. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +84 -6
  121. package/Tests/Server/API/TelemetryResolveStackTraceAPI.test.ts +805 -0
  122. package/Tests/Server/Infrastructure/Postgres/AddOnCallCalendarFeedsMigration.test.ts +32 -7
  123. package/Tests/Server/Middleware/IdentityRateLimit.test.ts +1144 -0
  124. package/Tests/Server/Middleware/MultipartFormData.test.ts +618 -3
  125. package/Tests/Server/Services/MonitorLabelRuleEngineScale.test.ts +520 -0
  126. package/Tests/Server/Services/NetworkDeviceOidTemplateService.test.ts +332 -0
  127. package/Tests/Server/Services/NetworkDeviceOidTemplateWriteGuards.test.ts +409 -0
  128. package/Tests/Server/Services/RuleEngineRuleFetchLimit.test.ts +239 -0
  129. package/Tests/Server/Services/TelemetrySourceMapService.test.ts +1210 -2
  130. package/Tests/Server/Services/UserServiceSeatLimit.test.ts +182 -0
  131. package/Tests/Server/Types/AnalyticsDatabase/SecurityEventModelPermission.test.ts +255 -0
  132. package/Tests/Server/Types/Database/Permissions/ReadBlockPermission.test.ts +212 -0
  133. package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +413 -0
  134. package/Tests/Server/Utils/CodeRepository.test.ts +689 -0
  135. package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +495 -0
  136. package/Tests/Server/Utils/ExceptionSanitizer.test.ts +77 -0
  137. package/Tests/Server/Utils/Monitor/CapturedMetricAttributeUtil.test.ts +284 -0
  138. package/Tests/Server/Utils/Monitor/MonitorCustomMetricAttributes.test.ts +503 -0
  139. package/Tests/Server/Utils/Monitor/MonitorTemplatePrototypePollution.test.ts +106 -0
  140. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkLogWritePath.test.ts +33 -4
  141. package/Tests/Server/Utils/Monitor/NetworkDeviceWalkUtil.test.ts +14 -4
  142. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +44 -0
  143. package/Tests/Server/Utils/OpenAPISpec.test.ts +536 -0
  144. package/Tests/Server/Utils/Rules/RuleEngineRuleRead.test.ts +115 -0
  145. package/Tests/Server/Utils/StackTraceParser.test.ts +610 -0
  146. package/Tests/Server/Utils/Telemetry/LogExceptionExtractor.test.ts +0 -0
  147. package/Tests/Server/Utils/Telemetry/SourceMapLimits.test.ts +656 -0
  148. package/Tests/Server/Utils/Telemetry/SourceMapResolver.test.ts +100 -0
  149. package/Tests/Types/Monitor/SnmpMonitor/SnmpOidListUtil.test.ts +454 -0
  150. package/Tests/Types/SecurityRolePermissions.test.ts +193 -0
  151. package/Tests/UI/Components/Charts/AnnotationLayout.test.ts +773 -0
  152. package/Tests/UI/Components/Charts/ChartAnnotationRail.test.tsx +789 -0
  153. package/Tests/UI/Components/Charts/ChartBucketIdentity.test.ts +254 -0
  154. package/Tests/UI/Components/Charts/TimeAnnotation.test.ts +471 -0
  155. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +405 -0
  156. package/Tests/UI/Components/ErrorMessageRefreshControl.test.tsx +83 -0
  157. package/Tests/UI/Components/MarkdownConverters.test.ts +686 -0
  158. package/Tests/UI/Components/ModelTable/BaseModelTableDeleteAndEmptyStates.test.tsx +341 -0
  159. package/Tests/UI/Components/OrderedStatesList.test.tsx +5 -5
  160. package/Tests/UI/Components/PendingProjectInvitations.test.tsx +1 -1
  161. package/Tests/UI/Components/TableSortAndMobileColumns.test.tsx +195 -0
  162. package/Tests/UI/Components/XAxis.test.ts +270 -5
  163. package/Tests/UI/Components/XAxisDaylightSaving.test.ts +113 -0
  164. package/Tests/UI/Styles/ChartFocusRing.test.ts +153 -0
  165. package/Tests/UI/Styles/ChartFocusRingCoverage.test.tsx +377 -0
  166. package/Tests/UI/Styles/ThemeStylesheet.ts +162 -0
  167. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +507 -0
  168. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +951 -1
  169. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +238 -0
  170. package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +1056 -0
  171. package/Tests/Utils/NetworkDiscovery/ReverseDnsNameUtil.test.ts +882 -0
  172. package/Types/Date.ts +39 -0
  173. package/Types/Monitor/SnmpMonitor/SnmpOidListUtil.ts +333 -0
  174. package/Types/Permission.ts +96 -0
  175. package/Types/Rum/SessionReplay.ts +21 -0
  176. package/Types/Telemetry/SourceMap.ts +8 -0
  177. package/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.tsx +176 -0
  178. package/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.ts +745 -0
  179. package/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.tsx +576 -0
  180. package/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.tsx +204 -0
  181. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +491 -544
  182. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +324 -372
  183. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +487 -540
  184. package/UI/Components/Charts/ChartLibrary/Types/FormattedReferenceRegion.ts +7 -3
  185. package/UI/Components/Charts/ChartLibrary/Types/FormattedTimeReferenceLine.ts +14 -3
  186. package/UI/Components/Charts/Types/ChartEventKind.ts +13 -0
  187. package/UI/Components/Charts/Types/ReferenceRegionProps.ts +6 -0
  188. package/UI/Components/Charts/Types/TimeReferenceLineProps.ts +20 -3
  189. package/UI/Components/Charts/Utils/TimeAnnotation.ts +69 -35
  190. package/UI/Components/Charts/Utils/XAxis.ts +125 -18
  191. package/UI/Components/EditionLabel/EditionLabel.tsx +280 -26
  192. package/UI/Components/ErrorMessage/ErrorMessage.tsx +21 -10
  193. package/UI/Components/Feed/FeedItem.tsx +4 -5
  194. package/UI/Components/Header/HeaderIconDropdownButton.tsx +1 -2
  195. package/UI/Components/Header/UserProfile/UserProfile.tsx +1 -2
  196. package/UI/Components/Image/Image.tsx +20 -3
  197. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  198. package/UI/Components/MemberRoleAssignment/MemberRoleAssignment.tsx +1 -2
  199. package/UI/Components/ModelTable/BaseModelTable.tsx +150 -24
  200. package/UI/Components/Table/TableHeader.tsx +64 -48
  201. package/UI/Components/Table/TableRow.tsx +13 -3
  202. package/UI/Styles/Theme.css +38 -0
  203. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +271 -0
  204. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +6 -0
  205. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +141 -10
  206. package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +55 -3
  207. package/Utils/NetworkDiscovery/ReverseDnsNameUtil.ts +151 -0
  208. package/Utils/Rules/RuleEngineLimits.ts +32 -0
  209. package/build/dist/Models/AnalyticsModels/SecurityEvent.js +48 -16
  210. package/build/dist/Models/AnalyticsModels/SecurityEvent.js.map +1 -1
  211. package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js +10 -5
  212. package/build/dist/Models/AnalyticsModels/ThreatIntelIndicator.js.map +1 -1
  213. package/build/dist/Models/DatabaseModels/AlertSeverity.js +46 -1
  214. package/build/dist/Models/DatabaseModels/AlertSeverity.js.map +1 -1
  215. package/build/dist/Models/DatabaseModels/DetectionRule.js +16 -5
  216. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  217. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +14 -5
  218. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +1 -1
  219. package/build/dist/Models/DatabaseModels/IncidentSeverity.js +46 -1
  220. package/build/dist/Models/DatabaseModels/IncidentSeverity.js.map +1 -1
  221. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  222. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  223. package/build/dist/Models/DatabaseModels/NetworkDevice.js +115 -3
  224. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  225. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +88 -0
  226. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
  227. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  228. package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js +519 -0
  229. package/build/dist/Models/DatabaseModels/NetworkDeviceOidTemplate.js.map +1 -0
  230. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +16 -5
  231. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js.map +1 -1
  232. package/build/dist/Server/API/GlobalConfigAPI.js +293 -176
  233. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  234. package/build/dist/Server/API/TelemetryAPI.js +31 -3
  235. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  236. package/build/dist/Server/EnvironmentConfig.js +83 -0
  237. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  238. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.js +26 -0
  239. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790500000000-AddNetworkDeviceOidTemplate.js.map +1 -0
  240. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.js +14 -0
  241. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790600000000-AddAutoImportRuleOidTemplate.js.map +1 -0
  242. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  243. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  244. package/build/dist/Server/Middleware/MultipartFormData.js +93 -28
  245. package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
  246. package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js +8 -1
  247. package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js.map +1 -1
  248. package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js +8 -1
  249. package/build/dist/Server/Services/AlertEpisodeOnCallRuleEngineService.js.map +1 -1
  250. package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js +8 -1
  251. package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js.map +1 -1
  252. package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js +8 -1
  253. package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js.map +1 -1
  254. package/build/dist/Server/Services/AlertGroupingEngineService.js +8 -1
  255. package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
  256. package/build/dist/Server/Services/AlertLabelRuleEngineService.js +8 -1
  257. package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
  258. package/build/dist/Server/Services/AlertOnCallRuleEngineService.js +8 -1
  259. package/build/dist/Server/Services/AlertOnCallRuleEngineService.js.map +1 -1
  260. package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +8 -1
  261. package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
  262. package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js +8 -1
  263. package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js.map +1 -1
  264. package/build/dist/Server/Services/AlertReminderRuleService.js +8 -1
  265. package/build/dist/Server/Services/AlertReminderRuleService.js.map +1 -1
  266. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +8 -1
  267. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
  268. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +8 -1
  269. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
  270. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +8 -1
  271. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
  272. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +8 -1
  273. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
  274. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +8 -1
  275. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
  276. package/build/dist/Server/Services/DashboardLabelRuleEngineService.js +8 -1
  277. package/build/dist/Server/Services/DashboardLabelRuleEngineService.js.map +1 -1
  278. package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +8 -1
  279. package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
  280. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +8 -1
  281. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
  282. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +8 -1
  283. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
  284. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +8 -1
  285. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
  286. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +8 -1
  287. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
  288. package/build/dist/Server/Services/HostLabelRuleEngineService.js +8 -1
  289. package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
  290. package/build/dist/Server/Services/HostOwnerRuleEngineService.js +8 -1
  291. package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
  292. package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js +8 -1
  293. package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js.map +1 -1
  294. package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js +8 -1
  295. package/build/dist/Server/Services/IncidentEpisodeOnCallRuleEngineService.js.map +1 -1
  296. package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +8 -1
  297. package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
  298. package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js +8 -1
  299. package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js.map +1 -1
  300. package/build/dist/Server/Services/IncidentGroupingEngineService.js +8 -1
  301. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  302. package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +8 -1
  303. package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
  304. package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js +8 -1
  305. package/build/dist/Server/Services/IncidentOnCallRuleEngineService.js.map +1 -1
  306. package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +8 -1
  307. package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
  308. package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js +8 -1
  309. package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js.map +1 -1
  310. package/build/dist/Server/Services/IncidentReminderRuleService.js +8 -1
  311. package/build/dist/Server/Services/IncidentReminderRuleService.js.map +1 -1
  312. package/build/dist/Server/Services/IncidentSlaRuleService.js +8 -1
  313. package/build/dist/Server/Services/IncidentSlaRuleService.js.map +1 -1
  314. package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js +8 -1
  315. package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js.map +1 -1
  316. package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +8 -1
  317. package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
  318. package/build/dist/Server/Services/Index.js +2 -0
  319. package/build/dist/Server/Services/Index.js.map +1 -1
  320. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +8 -1
  321. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -1
  322. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +8 -1
  323. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
  324. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +8 -1
  325. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
  326. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +8 -1
  327. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
  328. package/build/dist/Server/Services/KubernetesResourceService.js +5 -1
  329. package/build/dist/Server/Services/KubernetesResourceService.js.map +1 -1
  330. package/build/dist/Server/Services/MonitorLabelRuleEngineService.js +8 -1
  331. package/build/dist/Server/Services/MonitorLabelRuleEngineService.js.map +1 -1
  332. package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js +8 -1
  333. package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js.map +1 -1
  334. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +30 -21
  335. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  336. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +64 -0
  337. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -1
  338. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +8 -1
  339. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
  340. package/build/dist/Server/Services/NetworkDeviceOidTemplateService.js +180 -0
  341. package/build/dist/Server/Services/NetworkDeviceOidTemplateService.js.map +1 -0
  342. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +8 -1
  343. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
  344. package/build/dist/Server/Services/NetworkDeviceService.js +154 -1
  345. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  346. package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js +8 -1
  347. package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js.map +1 -1
  348. package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +8 -1
  349. package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
  350. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js +8 -1
  351. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js.map +1 -1
  352. package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +8 -1
  353. package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
  354. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +8 -1
  355. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
  356. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +8 -1
  357. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
  358. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +8 -1
  359. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
  360. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +8 -1
  361. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
  362. package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +8 -1
  363. package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -1
  364. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +8 -1
  365. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
  366. package/build/dist/Server/Services/RunbookLabelRuleEngineService.js +8 -1
  367. package/build/dist/Server/Services/RunbookLabelRuleEngineService.js.map +1 -1
  368. package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +8 -1
  369. package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
  370. package/build/dist/Server/Services/RunbookRuleEngineService.js +8 -1
  371. package/build/dist/Server/Services/RunbookRuleEngineService.js.map +1 -1
  372. package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +8 -1
  373. package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
  374. package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +8 -1
  375. package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
  376. package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js +8 -1
  377. package/build/dist/Server/Services/ScheduledMaintenanceReminderRuleService.js.map +1 -1
  378. package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +8 -1
  379. package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -1
  380. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +8 -1
  381. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
  382. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +8 -1
  383. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
  384. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +8 -1
  385. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
  386. package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js +8 -1
  387. package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js.map +1 -1
  388. package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js +6 -0
  389. package/build/dist/Server/Services/StatusPageMonitorRuleEngineService.js.map +1 -1
  390. package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js +8 -1
  391. package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js.map +1 -1
  392. package/build/dist/Server/Services/TelemetrySourceMapService.js +213 -19
  393. package/build/dist/Server/Services/TelemetrySourceMapService.js.map +1 -1
  394. package/build/dist/Server/Services/UserService.js +25 -0
  395. package/build/dist/Server/Services/UserService.js.map +1 -1
  396. package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js +8 -1
  397. package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js.map +1 -1
  398. package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +8 -1
  399. package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
  400. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +145 -0
  401. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +1 -0
  402. package/build/dist/Server/Utils/Monitor/CapturedMetricAttributeUtil.js +201 -0
  403. package/build/dist/Server/Utils/Monitor/CapturedMetricAttributeUtil.js.map +1 -0
  404. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js +19 -2
  405. package/build/dist/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.js.map +1 -1
  406. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js +42 -23
  407. package/build/dist/Server/Utils/Monitor/MonitorMetricUtil.js.map +1 -1
  408. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +29 -0
  409. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  410. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +11 -2
  411. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
  412. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js +16 -1
  413. package/build/dist/Server/Utils/Monitor/NetworkDeviceWalkUtil.js.map +1 -1
  414. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +10 -0
  415. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  416. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +33 -0
  417. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  418. package/build/dist/Server/Utils/Rules/RuleEngineRuleRead.js +37 -0
  419. package/build/dist/Server/Utils/Rules/RuleEngineRuleRead.js.map +1 -0
  420. package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js +12 -1
  421. package/build/dist/Server/Utils/Telemetry/ExceptionSanitizer.js.map +1 -1
  422. package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js +14 -2
  423. package/build/dist/Server/Utils/Telemetry/LogExceptionExtractor.js.map +1 -1
  424. package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js +15 -5
  425. package/build/dist/Server/Utils/Telemetry/SourceMapResolver.js.map +1 -1
  426. package/build/dist/Server/Utils/Telemetry/StackTraceParser.js +307 -0
  427. package/build/dist/Server/Utils/Telemetry/StackTraceParser.js.map +1 -1
  428. package/build/dist/Types/Date.js +27 -0
  429. package/build/dist/Types/Date.js.map +1 -1
  430. package/build/dist/Types/Monitor/SnmpMonitor/SnmpOidListUtil.js +253 -0
  431. package/build/dist/Types/Monitor/SnmpMonitor/SnmpOidListUtil.js.map +1 -0
  432. package/build/dist/Types/Permission.js +86 -0
  433. package/build/dist/Types/Permission.js.map +1 -1
  434. package/build/dist/Types/Rum/SessionReplay.js +19 -0
  435. package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
  436. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.js +83 -0
  437. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationHoverCard.js.map +1 -0
  438. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.js +531 -0
  439. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/AnnotationLayout.js.map +1 -0
  440. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.js +264 -0
  441. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/ChartAnnotationLayer.js.map +1 -0
  442. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.js +122 -0
  443. package/build/dist/UI/Components/Charts/ChartLibrary/Annotations/UseChartAnnotations.js.map +1 -0
  444. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +213 -233
  445. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  446. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +139 -152
  447. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  448. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +212 -232
  449. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  450. package/build/dist/UI/Components/Charts/Types/ChartEventKind.js +14 -0
  451. package/build/dist/UI/Components/Charts/Types/ChartEventKind.js.map +1 -0
  452. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js +57 -28
  453. package/build/dist/UI/Components/Charts/Utils/TimeAnnotation.js.map +1 -1
  454. package/build/dist/UI/Components/Charts/Utils/XAxis.js +103 -17
  455. package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
  456. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +198 -23
  457. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  458. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +15 -5
  459. package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
  460. package/build/dist/UI/Components/Feed/FeedItem.js +4 -5
  461. package/build/dist/UI/Components/Feed/FeedItem.js.map +1 -1
  462. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +1 -2
  463. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
  464. package/build/dist/UI/Components/Header/UserProfile/UserProfile.js.map +1 -1
  465. package/build/dist/UI/Components/Image/Image.js +6 -1
  466. package/build/dist/UI/Components/Image/Image.js.map +1 -1
  467. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  468. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  469. package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js +1 -2
  470. package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js.map +1 -1
  471. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +104 -23
  472. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  473. package/build/dist/UI/Components/Table/TableHeader.js +20 -22
  474. package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
  475. package/build/dist/UI/Components/Table/TableRow.js +13 -4
  476. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  477. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +153 -0
  478. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +1 -0
  479. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -1
  480. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +127 -7
  481. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
  482. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +50 -3
  483. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
  484. package/build/dist/Utils/NetworkDiscovery/ReverseDnsNameUtil.js +132 -0
  485. package/build/dist/Utils/NetworkDiscovery/ReverseDnsNameUtil.js.map +1 -0
  486. package/build/dist/Utils/Rules/RuleEngineLimits.js +31 -0
  487. package/build/dist/Utils/Rules/RuleEngineLimits.js.map +1 -0
  488. package/jest.config.json +1 -0
  489. package/package.json +2 -2
@@ -0,0 +1,409 @@
1
+ import NetworkDeviceOidTemplateService from "../../../Server/Services/NetworkDeviceOidTemplateService";
2
+ import { Service as NetworkDeviceServiceType } from "../../../Server/Services/NetworkDeviceService";
3
+ import CreateBy from "../../../Server/Types/Database/CreateBy";
4
+ import UpdateBy from "../../../Server/Types/Database/UpdateBy";
5
+ import { OnCreate, OnUpdate } from "../../../Server/Types/Database/Hooks";
6
+ import NetworkDevice from "../../../Models/DatabaseModels/NetworkDevice";
7
+ import NetworkDeviceOidTemplate from "../../../Models/DatabaseModels/NetworkDeviceOidTemplate";
8
+ import BadDataException from "../../../Types/Exception/BadDataException";
9
+ import SnmpOid from "../../../Types/Monitor/SnmpMonitor/SnmpOid";
10
+ import {
11
+ MAX_DEVICE_SPECIFIC_OIDS,
12
+ MAX_EFFECTIVE_OIDS_PER_DEVICE,
13
+ } from "../../../Types/Monitor/SnmpMonitor/SnmpOidListUtil";
14
+ import ObjectID from "../../../Types/ObjectID";
15
+ import { beforeEach, describe, expect, jest, test } from "@jest/globals";
16
+
17
+ /*
18
+ * WHAT THIS FILE IS DEFENDING
19
+ *
20
+ * Two write guards on NetworkDevice, and specifically that they RUN.
21
+ *
22
+ * onBeforeUpdate has an early return: a write that changes neither the
23
+ * device's site nor its identity columns bails out before the expensive read
24
+ * it does not need. Both new guards were originally added below that return —
25
+ * which made them dead code for exactly the writes they exist for, because
26
+ * linking a template or editing snmpOids touches neither site nor identity.
27
+ * Nothing failed; the guards simply never ran, which is the worst shape a
28
+ * security check can take.
29
+ *
30
+ * So these tests do not just assert "a cross-project template is refused".
31
+ * They assert it through the real hook, on a payload that trips the early
32
+ * return, in both spellings the UI actually posts.
33
+ */
34
+
35
+ const PROJECT_ID: ObjectID = new ObjectID(
36
+ "11111111-1111-4111-8111-111111111111",
37
+ );
38
+ const OTHER_PROJECT_ID: ObjectID = new ObjectID(
39
+ "22222222-2222-4222-8222-222222222222",
40
+ );
41
+ const TEMPLATE_ID: ObjectID = new ObjectID(
42
+ "33333333-3333-4333-8333-333333333333",
43
+ );
44
+ const DEVICE_ID: ObjectID = new ObjectID(
45
+ "44444444-4444-4444-8444-444444444444",
46
+ );
47
+
48
+ type DeviceServiceInternals = {
49
+ onBeforeCreate: (
50
+ createBy: CreateBy<NetworkDevice>,
51
+ ) => Promise<OnCreate<NetworkDevice>>;
52
+ onBeforeUpdate: (
53
+ updateBy: UpdateBy<NetworkDevice>,
54
+ ) => Promise<OnUpdate<NetworkDevice>>;
55
+ };
56
+
57
+ function buildDeviceService(): {
58
+ service: NetworkDeviceServiceType;
59
+ internals: DeviceServiceInternals;
60
+ } {
61
+ const service: NetworkDeviceServiceType = new NetworkDeviceServiceType();
62
+ return {
63
+ service,
64
+ internals: service as unknown as DeviceServiceInternals,
65
+ };
66
+ }
67
+
68
+ /*
69
+ * The device the update matches. Its projectId is what the guard compares the
70
+ * template against.
71
+ */
72
+ function matchedDevice(): NetworkDevice {
73
+ const device: NetworkDevice = new NetworkDevice(DEVICE_ID);
74
+ device.projectId = PROJECT_ID;
75
+ return device;
76
+ }
77
+
78
+ function templateInProject(projectId: ObjectID): NetworkDeviceOidTemplate {
79
+ const template: NetworkDeviceOidTemplate = new NetworkDeviceOidTemplate(
80
+ TEMPLATE_ID,
81
+ );
82
+ template.projectId = projectId;
83
+ template.name = "Cisco Catalyst 9300";
84
+ return template;
85
+ }
86
+
87
+ /*
88
+ * A payload that links a template and NOTHING else — no site, no hostname, no
89
+ * name, no sysName. This is the shape the device settings form and the bulk
90
+ * action actually post, and it is precisely the shape that trips
91
+ * onBeforeUpdate's early return.
92
+ */
93
+ function templateOnlyUpdate(
94
+ spelling: "id" | "relation",
95
+ ): UpdateBy<NetworkDevice> {
96
+ const data: Record<string, unknown> =
97
+ spelling === "id"
98
+ ? { oidTemplateId: TEMPLATE_ID }
99
+ : { oidTemplate: templateInProject(PROJECT_ID) };
100
+
101
+ return {
102
+ query: { _id: DEVICE_ID.toString() },
103
+ data: data,
104
+ props: { isRoot: true },
105
+ } as unknown as UpdateBy<NetworkDevice>;
106
+ }
107
+
108
+ describe("linking a device to an OID Collection Template is tenant-checked", () => {
109
+ /*
110
+ * Typed loosely: jest.spyOn's SpiedFunction and this repo's @types/jest
111
+ * disagree about the optionality of mock.lastCall, and these assertions
112
+ * only need mockResolvedValue and the call count.
113
+ */
114
+ let templateFindSpy: {
115
+ mockResolvedValue: (value: never) => unknown;
116
+ mock: { calls: Array<Array<unknown>> };
117
+ };
118
+
119
+ beforeEach(() => {
120
+ jest.restoreAllMocks();
121
+ templateFindSpy = jest.spyOn(
122
+ NetworkDeviceOidTemplateService,
123
+ "findOneById",
124
+ ) as unknown as typeof templateFindSpy;
125
+ });
126
+
127
+ /*
128
+ * THE regression test. If the guard drifts back below the early return this
129
+ * resolves cleanly and the cross-project link is persisted, so the assertion
130
+ * has to be that the hook REJECTS — not merely that some code path exists.
131
+ */
132
+ test.each(["id", "relation"] as const)(
133
+ "refuses a template from another project when the payload writes only the %s",
134
+ async (spelling: "id" | "relation") => {
135
+ const { service, internals } = buildDeviceService();
136
+
137
+ jest
138
+ .spyOn(service, "findBy")
139
+ .mockResolvedValue([matchedDevice()] as never);
140
+ templateFindSpy.mockResolvedValue(
141
+ templateInProject(OTHER_PROJECT_ID) as never,
142
+ );
143
+
144
+ await expect(
145
+ internals.onBeforeUpdate(templateOnlyUpdate(spelling)),
146
+ ).rejects.toThrow(/must belong to the same project/);
147
+ },
148
+ );
149
+
150
+ test("allows a template from the device's own project", async () => {
151
+ const { service, internals } = buildDeviceService();
152
+
153
+ jest.spyOn(service, "findBy").mockResolvedValue([matchedDevice()] as never);
154
+ templateFindSpy.mockResolvedValue(templateInProject(PROJECT_ID) as never);
155
+
156
+ await expect(
157
+ internals.onBeforeUpdate(templateOnlyUpdate("id")),
158
+ ).resolves.toBeDefined();
159
+ });
160
+
161
+ /*
162
+ * The guard must actually reach the database rather than being skipped. A
163
+ * hook that returns early looks identical to a hook that passed, so assert
164
+ * the lookup happened.
165
+ */
166
+ test("actually looks the template up, rather than returning early", async () => {
167
+ const { service, internals } = buildDeviceService();
168
+
169
+ jest.spyOn(service, "findBy").mockResolvedValue([matchedDevice()] as never);
170
+ templateFindSpy.mockResolvedValue(templateInProject(PROJECT_ID) as never);
171
+
172
+ await internals.onBeforeUpdate(templateOnlyUpdate("id"));
173
+
174
+ expect(templateFindSpy.mock.calls.length).toBeGreaterThan(0);
175
+ });
176
+
177
+ test("refuses a template that does not exist at all", async () => {
178
+ const { service, internals } = buildDeviceService();
179
+
180
+ jest.spyOn(service, "findBy").mockResolvedValue([matchedDevice()] as never);
181
+ templateFindSpy.mockResolvedValue(null as never);
182
+
183
+ await expect(
184
+ internals.onBeforeUpdate(templateOnlyUpdate("id")),
185
+ ).rejects.toThrow(BadDataException);
186
+ });
187
+
188
+ test("does no template lookup for an update that links nothing", async () => {
189
+ const { internals } = buildDeviceService();
190
+
191
+ await internals.onBeforeUpdate({
192
+ query: { _id: DEVICE_ID.toString() },
193
+ data: { pollingIntervalInMinutes: 10 },
194
+ props: { isRoot: true },
195
+ } as unknown as UpdateBy<NetworkDevice>);
196
+
197
+ expect(templateFindSpy.mock.calls).toHaveLength(0);
198
+ });
199
+
200
+ test("checks the template on create too", async () => {
201
+ const { internals } = buildDeviceService();
202
+
203
+ templateFindSpy.mockResolvedValue(
204
+ templateInProject(OTHER_PROJECT_ID) as never,
205
+ );
206
+
207
+ const device: NetworkDevice = new NetworkDevice();
208
+ device.projectId = PROJECT_ID;
209
+ device.oidTemplateId = TEMPLATE_ID;
210
+
211
+ await expect(
212
+ internals.onBeforeCreate({
213
+ data: device,
214
+ props: { isRoot: true },
215
+ } as CreateBy<NetworkDevice>),
216
+ ).rejects.toThrow(/must belong to the same project/);
217
+ });
218
+ });
219
+
220
+ describe("device-specific OID validation runs on the write that carries it", () => {
221
+ function oidOnlyUpdate(oids: Array<SnmpOid>): UpdateBy<NetworkDevice> {
222
+ return {
223
+ query: { _id: DEVICE_ID.toString() },
224
+ data: { snmpOids: oids },
225
+ props: { isRoot: true },
226
+ } as unknown as UpdateBy<NetworkDevice>;
227
+ }
228
+
229
+ beforeEach(() => {
230
+ jest.restoreAllMocks();
231
+ });
232
+
233
+ /*
234
+ * Same dead-code hazard as above: a snmpOids-only write changes neither
235
+ * site nor identity, so validation placed after the early return would
236
+ * never run on the only write that carries an OID list.
237
+ */
238
+ test("refuses a malformed OID on an snmpOids-only update", async () => {
239
+ const { service, internals } = buildDeviceService();
240
+
241
+ jest.spyOn(service, "findBy").mockResolvedValue([matchedDevice()] as never);
242
+
243
+ await expect(
244
+ internals.onBeforeUpdate(oidOnlyUpdate([{ oid: "sysUpTime.0" }])),
245
+ ).rejects.toThrow(/is not a numeric OID/);
246
+ });
247
+
248
+ function oidList(length: number): Array<SnmpOid> {
249
+ return Array.from({ length: length }, (_unused: unknown, index: number) => {
250
+ return { oid: `1.3.6.1.4.1.${index}` };
251
+ });
252
+ }
253
+
254
+ function linkedDevice(): NetworkDevice {
255
+ const device: NetworkDevice = matchedDevice();
256
+ device.oidTemplateId = TEMPLATE_ID;
257
+ return device;
258
+ }
259
+
260
+ /*
261
+ * The tight per-device budget is what ADOPTING a template costs, not a
262
+ * retroactive limit on every device that already exists.
263
+ *
264
+ * Enforcing it unconditionally would have locked a device that predates
265
+ * this feature, carrying a long hand-built list, out of saving ANY polling
266
+ * setting — the fleet in #3507 being the likeliest example, since it is the
267
+ * one with a hundred OIDs on it.
268
+ */
269
+ test("a device with no template may carry more than the device-specific budget", async () => {
270
+ const { service, internals } = buildDeviceService();
271
+
272
+ jest.spyOn(service, "findBy").mockResolvedValue([matchedDevice()] as never);
273
+
274
+ const result: OnUpdate<NetworkDevice> = await internals.onBeforeUpdate(
275
+ oidOnlyUpdate(oidList(MAX_DEVICE_SPECIFIC_OIDS + 1)),
276
+ );
277
+
278
+ expect(result.updateBy.data.snmpOids).toHaveLength(
279
+ MAX_DEVICE_SPECIFIC_OIDS + 1,
280
+ );
281
+ });
282
+
283
+ test("but never more than a device may effectively poll", async () => {
284
+ const { service, internals } = buildDeviceService();
285
+
286
+ jest.spyOn(service, "findBy").mockResolvedValue([matchedDevice()] as never);
287
+
288
+ await expect(
289
+ internals.onBeforeUpdate(
290
+ oidOnlyUpdate(oidList(MAX_EFFECTIVE_OIDS_PER_DEVICE + 1)),
291
+ ),
292
+ ).rejects.toThrow(
293
+ new RegExp(`more than the limit of ${MAX_EFFECTIVE_OIDS_PER_DEVICE}`),
294
+ );
295
+ });
296
+
297
+ /*
298
+ * Once a template IS linked, the two halves have to compose: the template
299
+ * budget plus the device-specific budget is the effective ceiling, so the
300
+ * device-specific half is what gives.
301
+ */
302
+ test("a LINKED device is held to the device-specific budget", async () => {
303
+ const { service, internals } = buildDeviceService();
304
+
305
+ jest.spyOn(service, "findBy").mockResolvedValue([linkedDevice()] as never);
306
+
307
+ await expect(
308
+ internals.onBeforeUpdate(
309
+ oidOnlyUpdate(oidList(MAX_DEVICE_SPECIFIC_OIDS + 1)),
310
+ ),
311
+ ).rejects.toThrow(
312
+ new RegExp(`more than the limit of ${MAX_DEVICE_SPECIFIC_OIDS}`),
313
+ );
314
+ });
315
+
316
+ /*
317
+ * And the same write that adopts a template is held to it immediately —
318
+ * otherwise the budget could be dodged by linking and editing in one call.
319
+ */
320
+ test("adopting a template in the same write applies the tighter budget at once", async () => {
321
+ const { service, internals } = buildDeviceService();
322
+
323
+ jest.spyOn(service, "findBy").mockResolvedValue([matchedDevice()] as never);
324
+ jest
325
+ .spyOn(NetworkDeviceOidTemplateService, "findOneById")
326
+ .mockResolvedValue(templateInProject(PROJECT_ID) as never);
327
+
328
+ await expect(
329
+ internals.onBeforeUpdate({
330
+ query: { _id: DEVICE_ID.toString() },
331
+ data: {
332
+ oidTemplateId: TEMPLATE_ID,
333
+ snmpOids: oidList(MAX_DEVICE_SPECIFIC_OIDS + 1),
334
+ },
335
+ props: { isRoot: true },
336
+ } as unknown as UpdateBy<NetworkDevice>),
337
+ ).rejects.toThrow(
338
+ new RegExp(`more than the limit of ${MAX_DEVICE_SPECIFIC_OIDS}`),
339
+ );
340
+ });
341
+
342
+ test("normalizes what it stores, so criteria can match with equality", async () => {
343
+ const { service, internals } = buildDeviceService();
344
+
345
+ jest.spyOn(service, "findBy").mockResolvedValue([matchedDevice()] as never);
346
+
347
+ const result: OnUpdate<NetworkDevice> = await internals.onBeforeUpdate(
348
+ oidOnlyUpdate([{ oid: ".1.3.6.1.4.1.9.1", name: "cpu" }]),
349
+ );
350
+
351
+ expect((result.updateBy.data.snmpOids as Array<SnmpOid>)[0]!.oid).toBe(
352
+ "1.3.6.1.4.1.9.1",
353
+ );
354
+ });
355
+
356
+ /*
357
+ * Linking a device whose STORED list already exceeds the device-specific
358
+ * budget would push the merge over the effective ceiling, and truncation
359
+ * drops from the end — so the operator's own OIDs would silently stop being
360
+ * polled, on a write that never mentioned them. Refuse the link instead,
361
+ * and say how many to trim.
362
+ */
363
+ test("refuses to link a device whose existing list already exceeds the linked budget", async () => {
364
+ const { service, internals } = buildDeviceService();
365
+
366
+ const crowdedDevice: NetworkDevice = matchedDevice();
367
+ crowdedDevice.snmpOids = oidList(MAX_DEVICE_SPECIFIC_OIDS + 5);
368
+
369
+ jest.spyOn(service, "findBy").mockResolvedValue([crowdedDevice] as never);
370
+ jest
371
+ .spyOn(NetworkDeviceOidTemplateService, "findOneById")
372
+ .mockResolvedValue(templateInProject(PROJECT_ID) as never);
373
+
374
+ await expect(
375
+ internals.onBeforeUpdate(templateOnlyUpdate("id")),
376
+ ).rejects.toThrow(/Remove 5 of them/);
377
+ });
378
+
379
+ test("allows the link when the existing list fits", async () => {
380
+ const { service, internals } = buildDeviceService();
381
+
382
+ const tidyDevice: NetworkDevice = matchedDevice();
383
+ tidyDevice.snmpOids = oidList(3);
384
+
385
+ jest.spyOn(service, "findBy").mockResolvedValue([tidyDevice] as never);
386
+ jest
387
+ .spyOn(NetworkDeviceOidTemplateService, "findOneById")
388
+ .mockResolvedValue(templateInProject(PROJECT_ID) as never);
389
+
390
+ await expect(
391
+ internals.onBeforeUpdate(templateOnlyUpdate("id")),
392
+ ).resolves.toBeDefined();
393
+ });
394
+
395
+ test("validates on create as well", async () => {
396
+ const { internals } = buildDeviceService();
397
+
398
+ const device: NetworkDevice = new NetworkDevice();
399
+ device.projectId = PROJECT_ID;
400
+ device.snmpOids = [{ oid: "not-an-oid" }];
401
+
402
+ await expect(
403
+ internals.onBeforeCreate({
404
+ data: device,
405
+ props: { isRoot: true },
406
+ } as CreateBy<NetworkDevice>),
407
+ ).rejects.toThrow(BadDataException);
408
+ });
409
+ });
@@ -0,0 +1,239 @@
1
+ import { MAX_RULES_EVALUATED_PER_PROJECT } from "../../../Utils/Rules/RuleEngineLimits";
2
+ import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
3
+ import { describe, expect, it } from "@jest/globals";
4
+ import fs from "fs";
5
+ import path from "path";
6
+
7
+ /*
8
+ * Every rule engine asks the same question when a resource is created -
9
+ * "which of this project's enabled rules match it?" - and every one of them
10
+ * used to ask it with `limit: 100, skip: 0`. That is not a page of a paged
11
+ * walk; it is the entire evaluation. A project with more rules than the cap
12
+ * silently never consulted the rest, which is how 1,243 monitor label rules
13
+ * produced roughly 50-100 labelled monitors out of 1,000+
14
+ * (OneUptime/oneuptime#3506).
15
+ *
16
+ * The fix is one shared constant, and this is the guard on it: the bug was a
17
+ * copy-paste that spread across 62 files, so the next engine copied from a
18
+ * sibling has to inherit the fix rather than the cap. Scanning the directory
19
+ * catches a new engine; asserting on the constant catches the cap being
20
+ * reintroduced under a different number.
21
+ *
22
+ * Raising the cap is only half of it. A read of `limit: <cap>, skip: 0` with
23
+ * no second page still cannot tell "that is all of them" from "that is all I
24
+ * was allowed to ask for", so an engine that reads rules must also REPORT
25
+ * hitting the ceiling. Without that, 10,000 is not a ceiling - it is the same
26
+ * cliff, further away. Both halves are asserted below.
27
+ */
28
+
29
+ const SERVICES_DIRECTORY: string = path.resolve(
30
+ __dirname,
31
+ "..",
32
+ "..",
33
+ "..",
34
+ "Server",
35
+ "Services",
36
+ );
37
+
38
+ interface RuleEngineSource {
39
+ /** Repo-relative-ish, so a failure message names something greppable. */
40
+ name: string;
41
+ contents: string;
42
+ }
43
+
44
+ /*
45
+ * Reads of a project's hand-authored rule config that do NOT carry the
46
+ * *RuleEngineService.ts suffix, and so were missed the first time the cap was
47
+ * lifted by filename. Five hang off IncidentService/AlertService
48
+ * onCreateSuccess and one off ScheduledMaintenanceService's - the same
49
+ * create-time chain, the same `limit: 100, skip: 0` shape, the same defect.
50
+ *
51
+ * Listed explicitly rather than matched by pattern: there is no naming
52
+ * convention that separates these from the hundreds of legitimate paged reads
53
+ * in the same directory, and a wrong pattern here would be a test that
54
+ * silently checks nothing.
55
+ */
56
+ const OTHER_PROJECT_RULE_READS: Array<string> = [
57
+ "IncidentGroupingEngineService.ts",
58
+ "AlertGroupingEngineService.ts",
59
+ "IncidentSlaRuleService.ts",
60
+ "IncidentReminderRuleService.ts",
61
+ "AlertReminderRuleService.ts",
62
+ "ScheduledMaintenanceReminderRuleService.ts",
63
+ ];
64
+
65
+ function readSource(fileName: string): RuleEngineSource {
66
+ return {
67
+ name: fileName,
68
+ contents: fs.readFileSync(path.join(SERVICES_DIRECTORY, fileName), "utf8"),
69
+ };
70
+ }
71
+
72
+ /*
73
+ * The engines that evaluate a project's configured rules. Named by
74
+ * convention, and the convention is what a new engine will be named too.
75
+ */
76
+ function readRuleEngineSources(): Array<RuleEngineSource> {
77
+ return fs
78
+ .readdirSync(SERVICES_DIRECTORY)
79
+ .filter((fileName: string) => {
80
+ return fileName.endsWith("RuleEngineService.ts");
81
+ })
82
+ .map(readSource);
83
+ }
84
+
85
+ /*
86
+ * A file that reads a project's rules at all, and the shape of a limit that
87
+ * reads all of them. Hoisted rather than written inline: `/x/.test(y)` is a
88
+ * lint fight between `wrap-regex`, which wants parentheses, and prettier,
89
+ * which takes them straight back off.
90
+ */
91
+ const RULE_FETCH_CALL: RegExp = /RuleService\.findBy\(|this\.findBy\(/;
92
+ const WHOLE_PROJECT_LIMIT: RegExp =
93
+ /limit:\s*(MAX_RULES_EVALUATED_PER_PROJECT|LIMIT_PER_PROJECT|LIMIT_MAX)/;
94
+ /*
95
+ * A read that advances an offset rather than always starting at zero, i.e.
96
+ * one that pages. Such a read cannot truncate, so it needs no ceiling report.
97
+ */
98
+ const PAGED_READ: RegExp = /skip:\s*skip,/;
99
+
100
+ /*
101
+ * Every `limit: <literal number>` in the file. Limits written as a named
102
+ * constant - MAX_RULES_EVALUATED_PER_PROJECT, LIMIT_PER_PROJECT, LIMIT_MAX,
103
+ * or a page size the file defines and documents - are deliberate; a bare
104
+ * number in a rule read is the shape of the bug.
105
+ */
106
+ function numericLimits(source: string): Array<number> {
107
+ const matches: Array<string> = source.match(/limit:\s*\d+/g) || [];
108
+
109
+ return matches.map((match: string) => {
110
+ return Number(match.replace(/limit:\s*/, ""));
111
+ });
112
+ }
113
+
114
+ describe("MAX_RULES_EVALUATED_PER_PROJECT", () => {
115
+ it("is the codebase's existing whole-project bound", () => {
116
+ expect(MAX_RULES_EVALUATED_PER_PROJECT).toBe(LIMIT_PER_PROJECT);
117
+ });
118
+
119
+ /*
120
+ * 1,243 is the reporter's rule count. A ceiling that a real project has
121
+ * already walked up to is not a ceiling.
122
+ */
123
+ it("leaves room well past the rule counts that broke", () => {
124
+ expect(MAX_RULES_EVALUATED_PER_PROJECT).toBeGreaterThanOrEqual(10000);
125
+ });
126
+ });
127
+
128
+ describe("rule engines read every enabled rule in the project", () => {
129
+ const sources: Array<RuleEngineSource> = readRuleEngineSources();
130
+
131
+ it("finds the rule engines to check", () => {
132
+ expect(sources.length).toBeGreaterThan(50);
133
+ });
134
+
135
+ it.each(
136
+ sources.map((source: RuleEngineSource) => {
137
+ return [source.name, source] as [string, RuleEngineSource];
138
+ }),
139
+ )(
140
+ "%s does not cap its rule read at a bare number",
141
+ (_name: string, source: RuleEngineSource) => {
142
+ /*
143
+ * `limit: 1` is a single-row existence probe, not a rule evaluation, and
144
+ * a couple of engines legitimately use one. Anything else written as a
145
+ * literal is a cap on how much configuration gets evaluated.
146
+ */
147
+ const suspiciousLimits: Array<number> = numericLimits(
148
+ source.contents,
149
+ ).filter((limit: number) => {
150
+ return limit > 1 && limit < LIMIT_PER_PROJECT;
151
+ });
152
+
153
+ expect(suspiciousLimits).toEqual([]);
154
+ },
155
+ );
156
+
157
+ /*
158
+ * The read is `limit: <cap>, skip: 0` - there is no second page - so the
159
+ * cap has to be the whole-project one. An engine that fetches rules must
160
+ * say so with the shared constant.
161
+ */
162
+ it.each(
163
+ sources
164
+ .filter((source: RuleEngineSource) => {
165
+ return RULE_FETCH_CALL.test(source.contents);
166
+ })
167
+ .map((source: RuleEngineSource) => {
168
+ return [source.name, source] as [string, RuleEngineSource];
169
+ }),
170
+ )(
171
+ "%s fetches its rules with a whole-project limit",
172
+ (_name: string, source: RuleEngineSource) => {
173
+ expect(WHOLE_PROJECT_LIMIT.test(source.contents)).toBe(true);
174
+ },
175
+ );
176
+
177
+ /*
178
+ * The half that turns a cliff into a ceiling. `limit: <cap>, skip: 0`
179
+ * returns a full page whether or not more rows exist, so an engine that
180
+ * does not report the full page has merely relocated #3506 to a higher
181
+ * number.
182
+ *
183
+ * Two ways to satisfy that, and both are fine. Page to exhaustion, as
184
+ * NetworkDeviceAutoImportRuleEngineService.loadEnabledRules does - a read
185
+ * that keeps going until a short page proves the end has nothing left to
186
+ * truncate. Or read once and report a full result, which is what every
187
+ * other engine does. What is not fine is a single capped read that says
188
+ * nothing.
189
+ */
190
+ it.each(
191
+ sources
192
+ .filter((source: RuleEngineSource) => {
193
+ return RULE_FETCH_CALL.test(source.contents);
194
+ })
195
+ .map((source: RuleEngineSource) => {
196
+ return [source.name, source] as [string, RuleEngineSource];
197
+ }),
198
+ )(
199
+ "%s either pages its rule read to exhaustion or reports hitting the ceiling",
200
+ (_name: string, source: RuleEngineSource) => {
201
+ const pagesToExhaustion: boolean = PAGED_READ.test(source.contents);
202
+ const reportsCeiling: boolean =
203
+ source.contents.includes("logIfRuleReadWasTruncated({") &&
204
+ source.contents.includes("rulesRead:");
205
+
206
+ expect(pagesToExhaustion || reportsCeiling).toBe(true);
207
+ },
208
+ );
209
+ });
210
+
211
+ /*
212
+ * The same two properties for the rule reads that do not carry the
213
+ * *RuleEngineService.ts suffix. These were missed when the cap was first
214
+ * lifted, precisely because the fix was scoped by filename - which is the
215
+ * argument for listing them here by name rather than trusting a pattern.
216
+ */
217
+ describe("project rule reads outside the *RuleEngineService.ts naming", () => {
218
+ const sources: Array<RuleEngineSource> =
219
+ OTHER_PROJECT_RULE_READS.map(readSource);
220
+
221
+ it.each(
222
+ sources.map((source: RuleEngineSource) => {
223
+ return [source.name, source] as [string, RuleEngineSource];
224
+ }),
225
+ )(
226
+ "%s reads its rules with a whole-project limit and reports the ceiling",
227
+ (_name: string, source: RuleEngineSource) => {
228
+ const suspiciousLimits: Array<number> = numericLimits(
229
+ source.contents,
230
+ ).filter((limit: number) => {
231
+ return limit > 1 && limit < LIMIT_PER_PROJECT;
232
+ });
233
+
234
+ expect(suspiciousLimits).toEqual([]);
235
+ expect(WHOLE_PROJECT_LIMIT.test(source.contents)).toBe(true);
236
+ expect(source.contents).toContain("logIfRuleReadWasTruncated({");
237
+ },
238
+ );
239
+ });