@oneuptime/common 13.0.5 → 13.0.7

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 (1566) hide show
  1. package/Models/AnalyticsModels/AuditLog.ts +81 -1
  2. package/Models/AnalyticsModels/SecurityEvent.ts +4 -4
  3. package/Models/DatabaseModels/AIAgentOwnerTeam.ts +6 -0
  4. package/Models/DatabaseModels/AIAgentOwnerUser.ts +6 -0
  5. package/Models/DatabaseModels/Alert.ts +74 -0
  6. package/Models/DatabaseModels/AlertEpisodeOwnerTeam.ts +6 -1
  7. package/Models/DatabaseModels/AlertEpisodeOwnerUser.ts +6 -1
  8. package/Models/DatabaseModels/AlertOwnerTeam.ts +6 -1
  9. package/Models/DatabaseModels/AlertOwnerUser.ts +6 -1
  10. package/Models/DatabaseModels/CephClusterOwnerTeam.ts +6 -0
  11. package/Models/DatabaseModels/CephClusterOwnerUser.ts +6 -0
  12. package/Models/DatabaseModels/CloudResourceOwnerTeam.ts +6 -0
  13. package/Models/DatabaseModels/CloudResourceOwnerUser.ts +6 -0
  14. package/Models/DatabaseModels/DashboardOwnerTeam.ts +6 -1
  15. package/Models/DatabaseModels/DashboardOwnerUser.ts +6 -1
  16. package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +8 -0
  17. package/Models/DatabaseModels/DockerHostOwnerTeam.ts +6 -0
  18. package/Models/DatabaseModels/DockerHostOwnerUser.ts +6 -0
  19. package/Models/DatabaseModels/DockerSwarmClusterOwnerTeam.ts +6 -0
  20. package/Models/DatabaseModels/DockerSwarmClusterOwnerUser.ts +6 -0
  21. package/Models/DatabaseModels/GlobalConfig.ts +1 -1
  22. package/Models/DatabaseModels/HostOwnerTeam.ts +6 -0
  23. package/Models/DatabaseModels/HostOwnerUser.ts +6 -0
  24. package/Models/DatabaseModels/Incident.ts +78 -0
  25. package/Models/DatabaseModels/IncidentEpisodeOwnerTeam.ts +6 -1
  26. package/Models/DatabaseModels/IncidentEpisodeOwnerUser.ts +6 -1
  27. package/Models/DatabaseModels/IncidentEpisodePublicNote.ts +74 -0
  28. package/Models/DatabaseModels/IncidentOwnerTeam.ts +6 -1
  29. package/Models/DatabaseModels/IncidentOwnerUser.ts +6 -1
  30. package/Models/DatabaseModels/IncidentPublicNote.ts +74 -0
  31. package/Models/DatabaseModels/IncidentTemplateOwnerTeam.ts +6 -0
  32. package/Models/DatabaseModels/IncidentTemplateOwnerUser.ts +6 -0
  33. package/Models/DatabaseModels/IncomingCallPolicyOwnerTeam.ts +6 -1
  34. package/Models/DatabaseModels/IncomingCallPolicyOwnerUser.ts +6 -1
  35. package/Models/DatabaseModels/Index.ts +6 -4
  36. package/Models/DatabaseModels/IoTFleetOwnerTeam.ts +6 -0
  37. package/Models/DatabaseModels/IoTFleetOwnerUser.ts +6 -0
  38. package/Models/DatabaseModels/KubernetesClusterOwnerTeam.ts +6 -0
  39. package/Models/DatabaseModels/KubernetesClusterOwnerUser.ts +6 -0
  40. package/Models/DatabaseModels/Monitor.ts +2 -3
  41. package/Models/DatabaseModels/MonitorGroupOwnerTeam.ts +6 -0
  42. package/Models/DatabaseModels/MonitorGroupOwnerUser.ts +6 -0
  43. package/Models/DatabaseModels/MonitorOwnerTeam.ts +6 -1
  44. package/Models/DatabaseModels/MonitorOwnerUser.ts +6 -1
  45. package/Models/DatabaseModels/MonitorTemplate.ts +2 -3
  46. package/Models/DatabaseModels/NetworkDevice.ts +67 -0
  47. package/Models/DatabaseModels/NetworkDeviceDiagnostic.ts +746 -0
  48. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +151 -0
  49. package/Models/DatabaseModels/NetworkDeviceOwnerTeam.ts +6 -0
  50. package/Models/DatabaseModels/NetworkDeviceOwnerUser.ts +6 -0
  51. package/Models/DatabaseModels/NetworkSiteAssignmentRule.ts +1 -1
  52. package/Models/DatabaseModels/OnCallDutyPolicyOwnerTeam.ts +6 -1
  53. package/Models/DatabaseModels/OnCallDutyPolicyOwnerUser.ts +6 -1
  54. package/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerTeam.ts +6 -1
  55. package/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerUser.ts +6 -1
  56. package/Models/DatabaseModels/PodmanHostOwnerTeam.ts +6 -0
  57. package/Models/DatabaseModels/PodmanHostOwnerUser.ts +6 -0
  58. package/Models/DatabaseModels/ProbeOwnerTeam.ts +6 -0
  59. package/Models/DatabaseModels/ProbeOwnerUser.ts +6 -0
  60. package/Models/DatabaseModels/Project.ts +41 -0
  61. package/Models/DatabaseModels/ProxmoxClusterOwnerTeam.ts +6 -0
  62. package/Models/DatabaseModels/ProxmoxClusterOwnerUser.ts +6 -0
  63. package/Models/DatabaseModels/RumApplicationOwnerTeam.ts +6 -0
  64. package/Models/DatabaseModels/RumApplicationOwnerUser.ts +6 -0
  65. package/Models/DatabaseModels/RunbookOwnerTeam.ts +6 -1
  66. package/Models/DatabaseModels/RunbookOwnerUser.ts +6 -1
  67. package/Models/DatabaseModels/RunnerOwnerTeam.ts +6 -1
  68. package/Models/DatabaseModels/RunnerOwnerUser.ts +6 -1
  69. package/Models/DatabaseModels/ScheduledMaintenanceOwnerTeam.ts +6 -1
  70. package/Models/DatabaseModels/ScheduledMaintenanceOwnerUser.ts +6 -1
  71. package/Models/DatabaseModels/ScheduledMaintenancePublicNote.ts +74 -0
  72. package/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerTeam.ts +8 -0
  73. package/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.ts +8 -0
  74. package/Models/DatabaseModels/SecurityEventConnection.ts +11 -11
  75. package/Models/DatabaseModels/ServerlessFunctionOwnerTeam.ts +6 -0
  76. package/Models/DatabaseModels/ServerlessFunctionOwnerUser.ts +6 -0
  77. package/Models/DatabaseModels/ServiceLevelObjective.ts +185 -8
  78. package/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.ts +746 -43
  79. package/Models/DatabaseModels/ServiceLevelObjectiveFeed.ts +575 -0
  80. package/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.ts +582 -0
  81. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.ts +22 -1
  82. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.ts +22 -1
  83. package/Models/DatabaseModels/ServiceOwnerTeam.ts +6 -0
  84. package/Models/DatabaseModels/ServiceOwnerUser.ts +6 -0
  85. package/Models/DatabaseModels/StatusPageAnnouncement.ts +75 -0
  86. package/Models/DatabaseModels/StatusPageOwnerTeam.ts +6 -1
  87. package/Models/DatabaseModels/StatusPageOwnerUser.ts +6 -1
  88. package/Models/DatabaseModels/ThreatIntelFeed.ts +1 -1
  89. package/Models/DatabaseModels/VMwareVCenterOwnerTeam.ts +6 -0
  90. package/Models/DatabaseModels/VMwareVCenterOwnerUser.ts +6 -0
  91. package/Models/DatabaseModels/WorkflowOwnerTeam.ts +6 -1
  92. package/Models/DatabaseModels/WorkflowOwnerUser.ts +6 -1
  93. package/Scripts/benchmark-fanin-capacity.js +2 -2
  94. package/Server/API/AIAgentDataAPI.ts +1 -1
  95. package/Server/API/AIChatAPI.ts +6 -4
  96. package/Server/API/AIInvestigationAPI.ts +7 -0
  97. package/Server/API/BaseAPI.ts +17 -0
  98. package/Server/API/BillingInvoiceAPI.ts +343 -30
  99. package/Server/API/BillingPaymentMethodAPI.ts +126 -5
  100. package/Server/API/DashboardAPI.ts +96 -2
  101. package/Server/API/SecurityEventConnectionAPI.ts +141 -11
  102. package/Server/API/StatusPageAPI.ts +321 -199
  103. package/Server/Infrastructure/Postgres/LocalMigrationGenerationDataSource.ts +1 -1
  104. package/Server/Infrastructure/Postgres/SchemaMigrations/1792800000000-AddNetworkDeviceDiagnostic.ts +83 -0
  105. package/Server/Infrastructure/Postgres/SchemaMigrations/1792900000000-AddNetworkDeviceDnsNameAndShortDeviceNames.ts +36 -0
  106. package/Server/Infrastructure/Postgres/SchemaMigrations/1793000000000-AddNetbiosLookupToNetworkDeviceDiscoveryScan.ts +29 -0
  107. package/Server/Infrastructure/Postgres/SchemaMigrations/1793100000000-SloProductOverhaul.ts +516 -0
  108. package/Server/Infrastructure/Postgres/SchemaMigrations/1793200000000-BackfillSloMonitorRulesAndAffectedResources.ts +98 -0
  109. package/Server/Infrastructure/Postgres/SchemaMigrations/1793300000000-AddDataResidencyToProject.ts +27 -0
  110. package/Server/Infrastructure/Postgres/SchemaMigrations/1793400000000-AddSubscriberUpdateNotificationStatus.ts +97 -0
  111. package/Server/Infrastructure/Postgres/SchemaMigrations/1793500000000-MakeOwnerRowsUnique.ts +1057 -0
  112. package/Server/Infrastructure/Postgres/SchemaMigrations/1793700000000-AddAIInvestigationDecision.ts +25 -0
  113. package/Server/Infrastructure/Postgres/SchemaMigrations/1793800000000-RemoveMonitorDescriptionLengthLimit.ts +31 -0
  114. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +20 -0
  115. package/Server/Infrastructure/Postgres/SchemaMigrations/Readme.md +6 -4
  116. package/Server/Middleware/IdentityRateLimit.ts +34 -1
  117. package/Server/Middleware/PublicDashboardRateLimit.ts +169 -39
  118. package/Server/Services/AlertEpisodeLabelRuleEngineService.ts +138 -67
  119. package/Server/Services/AlertEpisodeOwnerRuleEngineService.ts +213 -84
  120. package/Server/Services/AlertEpisodePrivacyRuleEngineService.ts +112 -35
  121. package/Server/Services/AlertEpisodeService.ts +13 -34
  122. package/Server/Services/AlertGroupingEngineService.ts +7 -4
  123. package/Server/Services/AlertLabelRuleEngineService.ts +299 -217
  124. package/Server/Services/AlertOwnerRuleEngineService.ts +572 -396
  125. package/Server/Services/AlertPrivacyRuleEngineService.ts +116 -40
  126. package/Server/Services/AlertService.ts +124 -36
  127. package/Server/Services/AuditLogService.ts +612 -59
  128. package/Server/Services/BillingInvoiceService.ts +112 -102
  129. package/Server/Services/BillingService.ts +539 -11
  130. package/Server/Services/CephClusterLabelRuleEngineService.ts +170 -109
  131. package/Server/Services/CephClusterOwnerRuleEngineService.ts +237 -111
  132. package/Server/Services/CloudResourceLabelRuleEngineService.ts +163 -100
  133. package/Server/Services/CloudResourceOwnerRuleEngineService.ts +240 -111
  134. package/Server/Services/DashboardLabelRuleEngineService.ts +145 -84
  135. package/Server/Services/DashboardOwnerRuleEngineService.ts +217 -91
  136. package/Server/Services/DatabaseService.ts +272 -22
  137. package/Server/Services/DockerHostLabelRuleEngineService.ts +171 -110
  138. package/Server/Services/DockerHostOwnerRuleEngineService.ts +237 -111
  139. package/Server/Services/DockerSwarmClusterLabelRuleEngineService.ts +181 -112
  140. package/Server/Services/DockerSwarmClusterOwnerRuleEngineService.ts +247 -114
  141. package/Server/Services/HostLabelRuleEngineService.ts +167 -106
  142. package/Server/Services/HostOwnerRuleEngineService.ts +233 -107
  143. package/Server/Services/IncidentEpisodeLabelRuleEngineService.ts +141 -67
  144. package/Server/Services/IncidentEpisodeOwnerRuleEngineService.ts +274 -72
  145. package/Server/Services/IncidentEpisodePrivacyRuleEngineService.ts +112 -35
  146. package/Server/Services/IncidentEpisodePublicNoteService.ts +24 -0
  147. package/Server/Services/IncidentEpisodeService.ts +15 -75
  148. package/Server/Services/IncidentGroupingEngineService.ts +7 -4
  149. package/Server/Services/IncidentLabelRuleEngineService.ts +279 -204
  150. package/Server/Services/IncidentOwnerRuleEngineService.ts +595 -425
  151. package/Server/Services/IncidentPrivacyRuleEngineService.ts +117 -44
  152. package/Server/Services/IncidentPublicNoteService.ts +24 -0
  153. package/Server/Services/IncidentService.ts +127 -35
  154. package/Server/Services/IncidentTemplateService.ts +13 -36
  155. package/Server/Services/IncomingCallPolicyLabelRuleEngineService.ts +147 -83
  156. package/Server/Services/IncomingCallPolicyOwnerRuleEngineService.ts +225 -96
  157. package/Server/Services/Index.ts +6 -4
  158. package/Server/Services/IoTFleetLabelRuleEngineService.ts +145 -84
  159. package/Server/Services/IoTFleetOwnerRuleEngineService.ts +217 -91
  160. package/Server/Services/KubernetesClusterLabelRuleEngineService.ts +181 -112
  161. package/Server/Services/KubernetesClusterOwnerRuleEngineService.ts +247 -114
  162. package/Server/Services/LabelService.ts +23 -28
  163. package/Server/Services/MonitorLabelRuleEngineService.ts +152 -92
  164. package/Server/Services/MonitorOwnerRuleEngineService.ts +220 -104
  165. package/Server/Services/MonitorProbeService.ts +20 -2
  166. package/Server/Services/MonitorService.ts +24 -41
  167. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +376 -5
  168. package/Server/Services/NetworkDeviceDiagnosticService.ts +417 -0
  169. package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +147 -83
  170. package/Server/Services/NetworkDeviceOwnerRuleEngineService.ts +222 -93
  171. package/Server/Services/NetworkDeviceService.ts +39 -2
  172. package/Server/Services/OnCallDutyPolicyLabelRuleEngineService.ts +151 -80
  173. package/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.ts +226 -93
  174. package/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.ts +154 -83
  175. package/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.ts +229 -96
  176. package/Server/Services/PodmanHostLabelRuleEngineService.ts +171 -110
  177. package/Server/Services/PodmanHostOwnerRuleEngineService.ts +239 -111
  178. package/Server/Services/ProjectService.ts +111 -10
  179. package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +174 -110
  180. package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +243 -112
  181. package/Server/Services/RumApplicationLabelRuleEngineService.ts +137 -73
  182. package/Server/Services/RumApplicationOwnerRuleEngineService.ts +204 -79
  183. package/Server/Services/RunbookLabelRuleEngineService.ts +146 -84
  184. package/Server/Services/RunbookOwnerRuleEngineService.ts +220 -91
  185. package/Server/Services/ScheduledMaintenanceLabelRuleEngineService.ts +324 -230
  186. package/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.ts +613 -428
  187. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +24 -0
  188. package/Server/Services/ScheduledMaintenanceService.ts +56 -48
  189. package/Server/Services/ScheduledMaintenanceTemplateService.ts +12 -34
  190. package/Server/Services/SecurityEventConnectionService.ts +56 -4
  191. package/Server/Services/ServerlessFunctionLabelRuleEngineService.ts +143 -74
  192. package/Server/Services/ServerlessFunctionOwnerRuleEngineService.ts +210 -81
  193. package/Server/Services/ServiceLabelRuleEngineService.ts +172 -110
  194. package/Server/Services/ServiceLevelObjectiveBurnRateRuleService.ts +1057 -18
  195. package/Server/Services/ServiceLevelObjectiveFeedService.ts +108 -0
  196. package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +793 -97
  197. package/Server/Services/ServiceLevelObjectiveMonitorRuleService.ts +1069 -0
  198. package/Server/Services/ServiceLevelObjectiveOwnerTeamService.ts +240 -1
  199. package/Server/Services/ServiceLevelObjectiveOwnerUserService.ts +257 -1
  200. package/Server/Services/ServiceLevelObjectiveService.ts +1356 -56
  201. package/Server/Services/ServiceOwnerRuleEngineService.ts +242 -112
  202. package/Server/Services/StatusPageAnnouncementService.ts +13 -0
  203. package/Server/Services/StatusPageLabelRuleEngineService.ts +146 -85
  204. package/Server/Services/StatusPageOwnerRuleEngineService.ts +210 -99
  205. package/Server/Services/StatusPagePrivateUserService.ts +38 -29
  206. package/Server/Services/StatusPagePrivateUserSessionService.ts +49 -1
  207. package/Server/Services/StatusPageService.ts +59 -36
  208. package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +28 -232
  209. package/Server/Services/StatusPageSubscriberService.ts +6 -0
  210. package/Server/Services/TelemetryUsageBillingService.ts +38 -7
  211. package/Server/Services/ThreatIntelFeedService.ts +1 -1
  212. package/Server/Services/UserSessionService.ts +6 -0
  213. package/Server/Services/VMwareVCenterLabelRuleEngineService.ts +173 -110
  214. package/Server/Services/VMwareVCenterOwnerRuleEngineService.ts +242 -112
  215. package/Server/Services/WorkflowLabelRuleEngineService.ts +145 -84
  216. package/Server/Services/WorkflowOwnerRuleEngineService.ts +219 -91
  217. package/Server/Static/Brand/README.md +7 -7
  218. package/Server/Static/Vendor/README.md +7 -7
  219. package/Server/Types/Database/Permissions/OwnedScopePermission.ts +18 -9
  220. package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +82 -0
  221. package/Server/Types/Database/UpdateByID.ts +3 -0
  222. package/Server/Types/Database/UpdateOneBy.ts +7 -0
  223. package/Server/Utils/AI/AlertAIContextBuilder.ts +19 -0
  224. package/Server/Utils/AI/Chat/ChatAgentRunner.ts +21 -8
  225. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +41 -4
  226. package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +1 -1
  227. package/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.ts +1 -1
  228. package/Server/Utils/AI/IncidentAIContextBuilder.ts +39 -0
  229. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +13 -5
  230. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +53 -13
  231. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +51 -14
  232. package/Server/Utils/AI/SRE/InvestigationEligibility.ts +292 -0
  233. package/Server/Utils/AI/SRE/InvestigationQueue.ts +25 -0
  234. package/Server/Utils/AI/Toolbox/AlertTools.ts +37 -1
  235. package/Server/Utils/AI/Toolbox/IncidentTools.ts +22 -1
  236. package/Server/Utils/AI/Toolbox/Index.ts +43 -13
  237. package/Server/Utils/AI/Toolbox/ResourceTools.ts +952 -0
  238. package/Server/Utils/AI/Toolbox/RumTools.ts +424 -0
  239. package/Server/Utils/AI/Toolbox/SloTools.ts +416 -51
  240. package/Server/Utils/AI/Toolbox/ToolTypes.ts +10 -0
  241. package/Server/Utils/AI/Toolbox/TraceTools.ts +2 -1
  242. package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +151 -13
  243. package/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.ts +17 -4
  244. package/Server/Utils/Dashboard/PublicDashboardSloWidget.ts +155 -8
  245. package/Server/Utils/Database/PostgresErrorTranslator.ts +14 -0
  246. package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +16 -0
  247. package/Server/Utils/Database/RelationValueUtil.ts +106 -0
  248. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +143 -127
  249. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +22 -27
  250. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +4 -1
  251. package/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.ts +3 -1
  252. package/Server/Utils/Monitor/MonitorStepsProjectValidator.ts +50 -20
  253. package/Server/Utils/Monitor/NetworkDeviceHydrationUtil.ts +13 -1
  254. package/Server/Utils/Monitor/NetworkDeviceMetricUtil.ts +6 -11
  255. package/Server/Utils/Rules/MonitorRulePatternValidator.ts +51 -0
  256. package/Server/Utils/Rules/OwnerRuleAssignment.ts +261 -0
  257. package/Server/Utils/Rules/RuleRun/RuleApplication.ts +81 -0
  258. package/Server/Utils/Rules/RuleRun/RuleRunPermission.ts +188 -0
  259. package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +803 -0
  260. package/Server/Utils/Rules/RuleRun/RuleRunner.ts +341 -0
  261. package/Server/Utils/SecurityEvent/ConnectorErrorMessage.ts +3 -2
  262. package/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.ts +6 -4
  263. package/Server/Utils/SecurityEvent/{GoogleSecOps → Connectors/GoogleSecOps}/GoogleSecOpsClient.ts +263 -16
  264. package/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.ts +2101 -0
  265. package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.ts +194 -14
  266. package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.ts +1 -2
  267. package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.ts +38 -7
  268. package/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.ts +2 -0
  269. package/Server/Utils/SecurityEvent/Connectors/Types.ts +242 -2
  270. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +1 -1
  271. package/Server/Utils/SecurityEvent/SecurityEventDedupe.ts +3 -3
  272. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +2 -2
  273. package/Server/Utils/SessionReplay/SessionReplayReadService.ts +217 -56
  274. package/Server/Utils/Slo/SloFeedUtil.ts +200 -0
  275. package/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.ts +173 -0
  276. package/Server/Utils/Slo/SloMetricUtil.ts +327 -0
  277. package/Server/Utils/Slo/SloOwnerReferenceValidator.ts +208 -0
  278. package/Server/Utils/Slo/SloRecordReferenceValidator.ts +169 -0
  279. package/Server/Utils/StatusPage/MonitorRulePatternValidator.ts +6 -43
  280. package/Server/Utils/StatusPageResource.ts +50 -5
  281. package/Server/Utils/Telemetry/TelemetryEntity.ts +205 -6
  282. package/SslCertificates/GlobalSign.crt +26 -0
  283. package/SslCertificates/Readme.md +3 -0
  284. package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +451 -0
  285. package/Tests/App/Dashboard/AIInsightsChatPanel.test.tsx +881 -0
  286. package/Tests/App/Dashboard/AIInsightsPageContext.test.ts +458 -0
  287. package/Tests/App/Dashboard/AIInsightsResourceCitations.test.ts +124 -0
  288. package/Tests/App/Dashboard/AIInsightsResourcePageContext.test.ts +798 -0
  289. package/Tests/App/Dashboard/AIInvestigationHeaderStatus.test.tsx +664 -15
  290. package/Tests/App/Dashboard/AddWidgetModal.test.tsx +4 -1
  291. package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +307 -0
  292. package/Tests/App/Dashboard/ArchiveResourceCard.test.tsx +289 -0
  293. package/Tests/App/Dashboard/AskAiSuggestedPrompts.test.ts +7 -0
  294. package/Tests/App/Dashboard/AuditLogsTable.test.tsx +598 -0
  295. package/Tests/App/Dashboard/BillingDefaultPaymentMethod.test.tsx +1046 -0
  296. package/Tests/App/Dashboard/BillingPaidUsageFlow.test.tsx +3 -0
  297. package/Tests/App/Dashboard/BillingPaymentMethodForm.test.tsx +201 -7
  298. package/Tests/App/Dashboard/BooleanSeriesCriteriaFilterText.test.ts +82 -0
  299. package/Tests/App/Dashboard/BreadcrumbCoverage.test.tsx +16 -1
  300. package/Tests/App/Dashboard/ChangeAlertStateAIHeader.test.tsx +116 -8
  301. package/Tests/App/Dashboard/ChatActivityFeed.test.tsx +168 -1
  302. package/Tests/App/Dashboard/ConnectionTestModal.test.tsx +1 -1
  303. package/Tests/App/Dashboard/ConnectorTestReportView.test.tsx +20 -3
  304. package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +1095 -1
  305. package/Tests/App/Dashboard/CorrelateFilterChips.test.tsx +910 -0
  306. package/Tests/App/Dashboard/CorrelateGraph.test.tsx +3747 -25
  307. package/Tests/App/Dashboard/CorrelateGraphHelpers.test.ts +1085 -0
  308. package/Tests/App/Dashboard/CorrelateInspector.test.tsx +1534 -0
  309. package/Tests/App/Dashboard/CorrelateNodeCard.test.tsx +965 -0
  310. package/Tests/App/Dashboard/CorrelateResultSummary.test.tsx +1525 -0
  311. package/Tests/App/Dashboard/CorrelationGraph.test.ts +1030 -0
  312. package/Tests/App/Dashboard/CorrelationGraphLayout.test.ts +526 -0
  313. package/Tests/App/Dashboard/DashboardChartWidgetZoom.test.tsx +104 -0
  314. package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +156 -64
  315. package/Tests/App/Dashboard/DeviceDiagnostics.test.tsx +787 -0
  316. package/Tests/App/Dashboard/DeviceLatencyTrend.test.tsx +278 -0
  317. package/Tests/App/Dashboard/DiscoveryReviewInventoryRefresh.test.tsx +279 -0
  318. package/Tests/App/Dashboard/DiscoveryScanEditForm.test.tsx +87 -0
  319. package/Tests/App/Dashboard/DiscoveryScanStatusMessage.test.tsx +970 -0
  320. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +849 -20
  321. package/Tests/App/Dashboard/EmbeddedMetricEventScope.test.tsx +358 -0
  322. package/Tests/App/Dashboard/EntityFilterDropdownArchivedSlos.test.tsx +340 -0
  323. package/Tests/App/Dashboard/ErrorPatternEventScope.test.tsx +148 -0
  324. package/Tests/App/Dashboard/EventOverlayAdditionalResourceScope.test.ts +255 -0
  325. package/Tests/App/Dashboard/EventOverlayScope.test.ts +845 -0
  326. package/Tests/App/Dashboard/EventOverlayScopeHook.test.tsx +903 -0
  327. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +98 -2
  328. package/Tests/App/Dashboard/ExceptionSegmentedControl.test.tsx +1020 -0
  329. package/Tests/App/Dashboard/ExternalStatusPageCriteriaFilter.test.ts +3 -3
  330. package/Tests/App/Dashboard/InvestigationDrawer.test.tsx +21 -0
  331. package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +268 -47
  332. package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +761 -0
  333. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +1122 -81
  334. package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +139 -9
  335. package/Tests/App/Dashboard/InvestigationReportView.test.tsx +279 -176
  336. package/Tests/App/Dashboard/InvestigationRunDetails.test.tsx +1166 -0
  337. package/Tests/App/Dashboard/InvoicesPayInvoice.test.tsx +437 -0
  338. package/Tests/App/Dashboard/MetricsViewerEventScopeNavigation.test.tsx +264 -0
  339. package/Tests/App/Dashboard/MonitorSummaryTestMonitorButton.test.tsx +342 -0
  340. package/Tests/App/Dashboard/MonitorTestForm.test.tsx +612 -0
  341. package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +301 -0
  342. package/Tests/App/Dashboard/NetworkDeviceBulkDelete.test.tsx +65 -0
  343. package/Tests/App/Dashboard/NetworkTopologyLiveView.test.tsx +5 -0
  344. package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +74 -0
  345. package/Tests/App/Dashboard/ResourceFeed.test.tsx +125 -5
  346. package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +8 -1
  347. package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +1764 -0
  348. package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +1000 -64
  349. package/Tests/App/Dashboard/SecurityEventConnectionsEmptyState.test.tsx +448 -0
  350. package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +739 -189
  351. package/Tests/App/Dashboard/SecurityEventSeverityPill.test.tsx +233 -0
  352. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +282 -0
  353. package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +74 -2
  354. package/Tests/App/Dashboard/SloActiveBurnEventsCard.test.tsx +538 -0
  355. package/Tests/App/Dashboard/SloBulkActionsArchive.test.tsx +252 -0
  356. package/Tests/App/Dashboard/SloDashboardTemplateWidgets.test.tsx +322 -518
  357. package/Tests/App/Dashboard/SloElement.test.tsx +194 -0
  358. package/Tests/App/Dashboard/SloFeed.test.tsx +289 -0
  359. package/Tests/App/Dashboard/SloHistoryCharts.test.tsx +471 -0
  360. package/Tests/App/Dashboard/SloHistorySeries.test.tsx +607 -0
  361. package/Tests/App/Dashboard/SloListWidget.test.tsx +783 -0
  362. package/Tests/App/Dashboard/SloMetricsPage.test.tsx +346 -0
  363. package/Tests/App/Dashboard/SloMonitorsPage.test.tsx +661 -0
  364. package/Tests/App/Dashboard/SloMonitorsSummaryCard.test.tsx +489 -0
  365. package/Tests/App/Dashboard/SloNavigationWiring.test.tsx +437 -0
  366. package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +305 -0
  367. package/Tests/App/Dashboard/SloOverviewData.test.tsx +563 -0
  368. package/Tests/App/Dashboard/SloOverviewHero.test.tsx +311 -0
  369. package/Tests/App/Dashboard/SloOverviewKpiStrip.test.tsx +426 -0
  370. package/Tests/App/Dashboard/SloOverviewSidebarCards.test.tsx +493 -0
  371. package/Tests/App/Dashboard/SloSettings.test.tsx +633 -0
  372. package/Tests/App/Dashboard/SloStatusSummaryCards.test.tsx +403 -0
  373. package/Tests/App/Dashboard/SloViewSideMenuCounts.test.tsx +373 -0
  374. package/Tests/App/Dashboard/SloWidgetVariableBinding.test.tsx +689 -0
  375. package/Tests/App/Dashboard/TextClampLayoutHarness.ts +224 -0
  376. package/Tests/App/Dashboard/TopologyConnectivitySection.test.tsx +206 -0
  377. package/Tests/App/Dashboard/TracesEntityNames.test.tsx +47 -15
  378. package/Tests/App/Dashboard/UseBulkShortenDeviceNames.test.tsx +1312 -0
  379. package/Tests/App/Dashboard/WidgetCatalog.test.ts +9 -1
  380. package/Tests/Models/AnalyticsModels/RumSessionReplayColumns.test.ts +14 -16
  381. package/Tests/Models/DatabaseModels/AuditLogModelConfiguration.test.ts +442 -0
  382. package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +9 -10
  383. package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +48 -1
  384. package/Tests/Models/DatabaseModels/SloOverhaulModels.test.ts +835 -0
  385. package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +3 -2
  386. package/Tests/Models/DiscoveryScanNetbiosLookupColumn.test.ts +328 -0
  387. package/Tests/Models/DiscoveryScanShortDeviceNamesColumn.test.ts +335 -0
  388. package/Tests/Models/InventoryItemNaming.test.ts +54 -0
  389. package/Tests/Models/NetworkDeviceDiagnosticContract.test.ts +194 -0
  390. package/Tests/Models/NetworkDeviceDnsNameColumn.test.ts +321 -0
  391. package/Tests/Models/ProjectDataResidencyColumn.test.ts +154 -0
  392. package/Tests/Models/SecurityDomainAccessControl.test.ts +181 -50
  393. package/Tests/Server/API/AIChatRouteAuthorization.test.ts +161 -0
  394. package/Tests/Server/API/AIInvestigationAPI.test.ts +14 -0
  395. package/Tests/Server/API/AIInvestigationAvailabilityAuthorization.test.ts +260 -0
  396. package/Tests/Server/API/BaseAPI.test.ts +6 -0
  397. package/Tests/Server/API/BaseAPIUpdateMiscDataProps.test.ts +217 -0
  398. package/Tests/Server/API/BillingInvoiceAPI.test.ts +7 -0
  399. package/Tests/Server/API/BillingInvoiceAPIPaymentStates.test.ts +990 -0
  400. package/Tests/Server/API/BillingPaymentMethodAPI.test.ts +498 -0
  401. package/Tests/Server/API/DashboardPublicSloAPI.test.ts +405 -0
  402. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +133 -0
  403. package/Tests/Server/API/SecurityEventConnectionAPI.test.ts +901 -7
  404. package/Tests/Server/API/SessionReplayAPI.test.ts +116 -0
  405. package/Tests/Server/API/StatusPageManageSubscriptionRecipient.test.ts +857 -0
  406. package/Tests/Server/API/StatusPageManageSubscriptionTemplateVariables.test.ts +1084 -0
  407. package/Tests/Server/API/StatusPageMasterPasswordRateLimit.test.ts +482 -0
  408. package/Tests/Server/EnvironmentConfigOnCallCalendarFeed.test.ts +1 -1
  409. package/Tests/Server/Infrastructure/ClickhouseKeepAliveOptions.test.ts +1 -1
  410. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +38 -16
  411. package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +106 -31
  412. package/Tests/Server/Infrastructure/ExampleDockerfiles.test.ts +46 -12
  413. package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +33 -3
  414. package/Tests/Server/Infrastructure/Postgres/AddDataResidencyToProjectMigration.test.ts +202 -0
  415. package/Tests/Server/Infrastructure/Postgres/AddNetbiosLookupToNetworkDeviceDiscoveryScanMigration.test.ts +330 -0
  416. package/Tests/Server/Infrastructure/Postgres/AddNetworkDeviceDnsNameAndShortDeviceNamesMigration.test.ts +340 -0
  417. package/Tests/Server/Infrastructure/Postgres/BackfillSloMonitorRulesAndAffectedResourcesMigration.test.ts +343 -0
  418. package/Tests/Server/Infrastructure/Postgres/MonitorDescriptionMigration.test.ts +422 -0
  419. package/Tests/Server/Infrastructure/Postgres/SloProductOverhaulMigration.test.ts +801 -0
  420. package/Tests/Server/Infrastructure/TelemetryExporterDeploymentConfig.test.ts +1 -1
  421. package/Tests/Server/Infrastructure/ValkeyDeploymentConfig.test.ts +25 -4
  422. package/Tests/Server/Middleware/IdentityRateLimit.test.ts +72 -0
  423. package/Tests/Server/Middleware/PublicDashboardRateLimit.test.ts +12 -12
  424. package/Tests/Server/Middleware/PublicDashboardRateLimitStatusPage.test.ts +800 -0
  425. package/Tests/Server/Services/AIInvestigationDecisionPostgres.test.ts +346 -0
  426. package/Tests/Server/Services/AddOwnersIdempotency.test.ts +471 -0
  427. package/Tests/Server/Services/AddSubscriberUpdateNotificationStatusMigration.test.ts +307 -0
  428. package/Tests/Server/Services/AuditLogService.test.ts +1124 -0
  429. package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +200 -1
  430. package/Tests/Server/Services/BillingInvoiceServiceMutexRelease.test.ts +254 -0
  431. package/Tests/Server/Services/BillingService.test.ts +70 -0
  432. package/Tests/Server/Services/BillingServicePayInvoiceStates.test.ts +723 -0
  433. package/Tests/Server/Services/BillingServicePaymentMethodReads.test.ts +14 -2
  434. package/Tests/Server/Services/BillingServiceSubscriptionPaymentMethodSync.test.ts +1634 -0
  435. package/Tests/Server/Services/DatabaseServiceAuditRelationDiff.test.ts +492 -0
  436. package/Tests/Server/Services/DatabaseServiceAutoOwnerOnCreate.test.ts +250 -0
  437. package/Tests/Server/Services/DatabaseServicePasswordFieldSecrets.test.ts +629 -0
  438. package/Tests/Server/Services/DatabaseServiceUniqueColumnsTogether.test.ts +622 -0
  439. package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +431 -0
  440. package/Tests/Server/Services/IncidentAlertSloReferenceGuard.test.ts +358 -0
  441. package/Tests/Server/Services/MonitorDescriptionValidation.test.ts +211 -0
  442. package/Tests/Server/Services/MonitorProbeServicePastDueMonitoring.test.ts +362 -0
  443. package/Tests/Server/Services/MonitorTemplateDescriptionPropagation.test.ts +269 -0
  444. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +1460 -1
  445. package/Tests/Server/Services/NetworkDeviceDiagnosticService.test.ts +962 -0
  446. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +106 -0
  447. package/Tests/Server/Services/NetworkDeviceRuleEngines.test.ts +10 -1
  448. package/Tests/Server/Services/NetworkDeviceServicePastDueMonitoring.test.ts +335 -0
  449. package/Tests/Server/Services/NetworkDeviceSiteRuleDnsName.test.ts +568 -0
  450. package/Tests/Server/Services/OwnerRowUniqueness.test.ts +504 -0
  451. package/Tests/Server/Services/ProjectDataResidencyPostgres.test.ts +344 -0
  452. package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +187 -0
  453. package/Tests/Server/Services/ProjectServiceDataResidency.test.ts +369 -0
  454. package/Tests/Server/Services/ProjectServiceDataResidencySelfHosted.test.ts +176 -0
  455. package/Tests/Server/Services/ProjectServicePastDueMonitoring.test.ts +289 -0
  456. package/Tests/Server/Services/ResourceFeedServices.test.ts +24 -8
  457. package/Tests/Server/Services/RuleRun/IncidentAlertMaintenanceRuleEnginesRun.test.ts +1396 -0
  458. package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupARun.test.ts +917 -0
  459. package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +1262 -0
  460. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupARun.test.ts +945 -0
  461. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +1163 -0
  462. package/Tests/Server/Services/RuleRun/PrivacyRuleEnginesRun.test.ts +843 -0
  463. package/Tests/Server/Services/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +465 -0
  464. package/Tests/Server/Services/SecurityEventConnectionService.test.ts +525 -4
  465. package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +77 -23
  466. package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleFeedWrites.test.ts +777 -0
  467. package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleOptions.test.ts +1399 -0
  468. package/Tests/Server/Services/ServiceLevelObjectiveBurnRateRuleService.test.ts +67 -74
  469. package/Tests/Server/Services/ServiceLevelObjectiveChildRowTenancy.test.ts +906 -0
  470. package/Tests/Server/Services/ServiceLevelObjectiveDeleteTenancy.test.ts +1029 -0
  471. package/Tests/Server/Services/ServiceLevelObjectiveFeedService.test.ts +313 -0
  472. package/Tests/Server/Services/ServiceLevelObjectiveFeedWrites.test.ts +1214 -0
  473. package/Tests/Server/Services/ServiceLevelObjectiveMarkdownLink.test.ts +289 -0
  474. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +1455 -430
  475. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleLegacyLabelAdoption.test.ts +634 -0
  476. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleService.test.ts +1193 -0
  477. package/Tests/Server/Services/{SloMonitorLabelRuleHooks.test.ts → ServiceLevelObjectiveMonitorRuleTriggers.test.ts} +135 -41
  478. package/Tests/Server/Services/ServiceLevelObjectiveOwnerFeedWrites.test.ts +671 -0
  479. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +180 -85
  480. package/Tests/Server/Services/ServiceLevelObjectiveServiceArchive.test.ts +537 -0
  481. package/Tests/Server/Services/ServiceLevelObjectiveServiceLegacyMonitorLabelWrite.test.ts +870 -0
  482. package/Tests/Server/Services/ServiceLevelObjectiveServiceMonitorRuleGuard.test.ts +343 -0
  483. package/Tests/Server/Services/ServiceLevelObjectiveServiceReEvaluation.test.ts +246 -0
  484. package/Tests/Server/Services/SessionRetention.test.ts +334 -0
  485. package/Tests/Server/Services/SloAffectedResourceCreatedFeed.test.ts +501 -0
  486. package/Tests/Server/Services/SloAffectedResourceLinkContract.test.ts +86 -0
  487. package/Tests/Server/Services/SloAffectedResourceMetricAttributes.test.ts +547 -0
  488. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +10 -4
  489. package/Tests/Server/Services/StatusPageMonitorRuleHooks.test.ts +7 -2
  490. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +172 -0
  491. package/Tests/Server/Services/StatusPagePrivateUserReadAccess.test.ts +178 -0
  492. package/Tests/Server/Services/StatusPagePrivateUserReadAccessPostgres.test.ts +311 -0
  493. package/Tests/Server/Services/StatusPagePrivateUserSessionService.test.ts +216 -1
  494. package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateCompile.test.ts +174 -0
  495. package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateServiceVariables.test.ts +40 -0
  496. package/Tests/Server/Services/SubscriberUpdateNotificationHooks.test.ts +541 -0
  497. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +1 -1
  498. package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +288 -0
  499. package/Tests/Server/Services/UserOnCallLogNoNotificationRules.test.ts +1 -1
  500. package/Tests/Server/TestingUtils/PastDueMonitoringClaimSql.ts +177 -0
  501. package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +51 -10
  502. package/Tests/Server/TestingUtils/__mocks__/Stripe.mock.ts +16 -1
  503. package/Tests/Server/Types/Database/EventOverlayScopePostgres.test.ts +626 -0
  504. package/Tests/Server/Types/Database/Permissions/InfrastructureOwnershipScope.test.ts +668 -0
  505. package/Tests/Server/Types/Database/Permissions/ProjectDataResidencyColumn.test.ts +386 -0
  506. package/Tests/Server/Types/Database/Permissions/SecurityRoleAccess.test.ts +26 -36
  507. package/Tests/Server/Types/Database/Permissions/SelectRejectionMessageContract.test.ts +1 -0
  508. package/Tests/Server/Types/Database/Permissions/UserNotificationRuleScoping.test.ts +1 -1
  509. package/Tests/Server/Utils/AI/AIIncidentGating.test.ts +16 -9
  510. package/Tests/Server/Utils/AI/ChatAgentRunner.test.ts +137 -1
  511. package/Tests/Server/Utils/AI/InvestigationEligibility.test.ts +697 -0
  512. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +105 -0
  513. package/Tests/Server/Utils/AI/RemediationHandoff.test.ts +16 -5
  514. package/Tests/Server/Utils/AI/ResourceTools.test.ts +1304 -0
  515. package/Tests/Server/Utils/AI/RumTools.test.ts +769 -0
  516. package/Tests/Server/Utils/AI/SloAffectedResourceAIContext.test.ts +445 -0
  517. package/Tests/Server/Utils/AI/SloTools.test.ts +423 -1
  518. package/Tests/Server/Utils/AI/SloToolsArchive.test.ts +294 -0
  519. package/Tests/Server/Utils/AI/SloToolsRuleReadPermissions.test.ts +297 -0
  520. package/Tests/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.test.ts +255 -10
  521. package/Tests/Server/Utils/Dashboard/SloTemplatePublicDashboard.test.ts +404 -750
  522. package/Tests/Server/Utils/Database/PostgresErrorTranslator.test.ts +63 -0
  523. package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +45 -0
  524. package/Tests/Server/Utils/Database/RelationValueUtil.test.ts +157 -0
  525. package/Tests/Server/Utils/Monitor/Criteria/APIRequestCriteriaEvaluateOverTime.test.ts +11 -9
  526. package/Tests/Server/Utils/Monitor/Criteria/BooleanSeriesEvaluateOverTime.test.ts +260 -0
  527. package/Tests/Server/Utils/Monitor/Criteria/CompareCriteria.test.ts +62 -45
  528. package/Tests/Server/Utils/Monitor/Criteria/CompareCriteriaAggregation.test.ts +25 -24
  529. package/Tests/Server/Utils/Monitor/Criteria/CompareCriteriaHumanMessages.test.ts +513 -0
  530. package/Tests/Server/Utils/Monitor/Criteria/CustomCodeMonitorCriteria.test.ts +2 -2
  531. package/Tests/Server/Utils/Monitor/Criteria/DatabaseMonitorCriteria.test.ts +181 -0
  532. package/Tests/Server/Utils/Monitor/Criteria/DnsMonitorCriteria.test.ts +1 -1
  533. package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +147 -30
  534. package/Tests/Server/Utils/Monitor/Criteria/ExternalStatusPageMonitorCriteria.test.ts +9 -9
  535. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.test.ts +7 -5
  536. package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +2 -2
  537. package/Tests/Server/Utils/Monitor/Criteria/ServerMonitorCriteria.test.ts +4 -3
  538. package/Tests/Server/Utils/Monitor/Criteria/SnmpMonitorCriteria.test.ts +2 -2
  539. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +3 -2
  540. package/Tests/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.test.ts +17 -0
  541. package/Tests/Server/Utils/Monitor/MonitorCriteriaHumanMessages.test.ts +529 -0
  542. package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidator.test.ts +136 -0
  543. package/Tests/Server/Utils/Monitor/MonitorStepsProjectValidatorLoadOrder.test.ts +472 -0
  544. package/Tests/Server/Utils/Monitor/NetworkDeviceHydrationUtil.test.ts +48 -2
  545. package/Tests/Server/Utils/Monitor/SloTemplateMetricEmitterContract.test.ts +435 -475
  546. package/Tests/Server/Utils/Rules/MonitorRulePatternValidator.test.ts +77 -0
  547. package/Tests/Server/Utils/Rules/OwnerRuleAssignment.test.ts +585 -0
  548. package/Tests/Server/Utils/Rules/RuleRun/RuleRunPermission.test.ts +365 -0
  549. package/Tests/Server/Utils/Rules/RuleRun/RuleRunRegistry.test.ts +173 -0
  550. package/Tests/Server/Utils/Rules/RuleRun/RuleRunner.test.ts +675 -0
  551. package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +8 -8
  552. package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorFetchSummary.test.ts +261 -0
  553. package/Tests/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.test.ts +68 -13
  554. package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsAuth.test.ts → Connectors/GoogleSecOps/GoogleSecOpsAuth.test.ts} +5 -5
  555. package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsClient.test.ts → Connectors/GoogleSecOps/GoogleSecOpsClient.test.ts} +4 -4
  556. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.test.ts +483 -0
  557. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorCuratedAndLateAlerts.test.ts +676 -0
  558. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorFetchEvents.test.ts +1994 -0
  559. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorFixtures.ts +332 -0
  560. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorHttpIntegration.test.ts +680 -0
  561. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorRequestContract.test.ts +1206 -0
  562. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorTestConnection.test.ts +1136 -0
  563. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsCuratedRuleCounts.test.ts +407 -0
  564. package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsErrorHandling.test.ts → Connectors/GoogleSecOps/GoogleSecOpsErrorHandling.test.ts} +5 -5
  565. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingAdaptiveCatchUp.test.ts +730 -0
  566. package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsClickhouseIntegration.test.ts → Connectors/GoogleSecOps/GoogleSecOpsPollingClickhouseIntegration.test.ts} +131 -36
  567. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingFailureTaxonomy.test.ts +772 -0
  568. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingFixtures.ts +648 -0
  569. package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsHttpIntegration.test.ts → Connectors/GoogleSecOps/GoogleSecOpsPollingHttpIntegration.test.ts} +230 -225
  570. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingIntegration.test.ts +1390 -0
  571. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingLoop.test.ts +981 -0
  572. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsPollingNothingImportedRegression.test.ts +290 -0
  573. package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsRequestContract.test.ts → Connectors/GoogleSecOps/GoogleSecOpsRequestContract.test.ts} +2 -2
  574. package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsResponseParsing.test.ts → Connectors/GoogleSecOps/GoogleSecOpsResponseParsing.test.ts} +5 -5
  575. package/Tests/Server/Utils/SecurityEvent/{GoogleSecOpsSearchDetections.test.ts → Connectors/GoogleSecOps/GoogleSecOpsSearchDetections.test.ts} +38 -5
  576. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsTesterIntegration.test.ts +421 -0
  577. package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.test.ts +1445 -3
  578. package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.test.ts +14 -4
  579. package/Tests/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.test.ts +313 -4
  580. package/Tests/Server/Utils/SessionReplay/SessionReplayReadServiceQueries.test.ts +352 -0
  581. package/Tests/Server/Utils/Slo/SloFeedUtil.test.ts +326 -0
  582. package/Tests/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.test.ts +260 -0
  583. package/Tests/Server/Utils/Slo/SloMetricUtil.test.ts +592 -0
  584. package/Tests/Server/Utils/Slo/SloRecordReferenceValidator.test.ts +311 -0
  585. package/Tests/Server/Utils/StatusPageResource.test.ts +91 -3
  586. package/Tests/Server/Utils/TailwindBuildCopy.test.ts +14 -2
  587. package/Tests/Server/Utils/Telemetry/HostAssetAttributesFromOtlp.test.ts +235 -0
  588. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +385 -2
  589. package/Tests/Server/Utils/VendorAssets.test.ts +17 -3
  590. package/Tests/Types/AI/AIChatPageContext.test.ts +0 -0
  591. package/Tests/Types/AI/AIResourceContext.test.ts +312 -0
  592. package/Tests/Types/Billing/SubscriptionStatus.test.ts +176 -0
  593. package/Tests/Types/Billing/SubscriptionStatusPastDueMonitoring.test.ts +187 -0
  594. package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +53 -7
  595. package/Tests/Types/Dashboard/SloDashboardTemplate.test.ts +816 -792
  596. package/Tests/Types/Database/UniqueColumnsTogether.test.ts +100 -0
  597. package/Tests/Types/Monitor/CriteriaFilter.test.ts +216 -24
  598. package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +4 -4
  599. package/Tests/Types/Monitor/MonitorStepDnssecMonitor.test.ts +14 -1
  600. package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +14 -1
  601. package/Tests/Types/Monitor/MonitorStepExternalStatusPageMonitor.test.ts +14 -1
  602. package/Tests/Types/Monitor/MonitorStepRetriesParsing.test.ts +201 -0
  603. package/Tests/Types/Monitor/MonitorStepRetryPersistence.test.ts +125 -0
  604. package/Tests/Types/Rules/RuleRun.test.ts +315 -0
  605. package/Tests/Types/Rum/SessionReplayApiContracts.test.ts +60 -0
  606. package/Tests/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.test.ts +29 -4
  607. package/Tests/Types/StatusPage/SubscriberNotificationTemplateVariables.test.ts +217 -0
  608. package/Tests/Types/StatusPage/SubscriberUpdateNotification.test.ts +200 -0
  609. package/Tests/Types/WebsiteRequest.test.ts +44 -0
  610. package/Tests/UI/Components/ActiveFilterChipsLockedFilters.test.tsx +141 -87
  611. package/Tests/UI/Components/AlertBanner.test.tsx +319 -0
  612. package/Tests/UI/Components/BulkArchiveActionsCopy.test.tsx +310 -0
  613. package/Tests/UI/Components/Detail/DetailIdIsUnique.test.tsx +87 -0
  614. package/Tests/UI/Components/Dropdown/DropdownClearable.test.tsx +393 -0
  615. package/Tests/UI/Components/Dropdown/DropdownMultiSelectChipAccessibleName.test.tsx +64 -0
  616. package/Tests/UI/Components/EmptyState/EmptyState.test.tsx +335 -4
  617. package/Tests/UI/Components/EmptyState/EmptyStateGuideLinks.test.tsx +337 -0
  618. package/Tests/UI/Components/Forms/ModelFormJsonColumns.test.tsx +21 -20
  619. package/Tests/UI/Components/Forms/MonitorDescriptionForm.test.tsx +410 -0
  620. package/Tests/UI/Components/LabelRuleImportExport.test.tsx +15 -2
  621. package/Tests/UI/Components/LockedFilterChip.test.tsx +281 -144
  622. package/Tests/UI/Components/ModelTable/BaseModelTableReadPermissions.test.tsx +439 -0
  623. package/Tests/UI/Components/MoreMenu.test.tsx +133 -0
  624. package/Tests/UI/Components/MoreMenuMotion.test.tsx +84 -3
  625. package/Tests/UI/Components/NavBarMenuSearch.test.tsx +372 -0
  626. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
  627. package/Tests/UI/Components/RuleRun/RuleDetailFields.test.tsx +336 -0
  628. package/Tests/UI/Components/RuleRun/RuleTable.test.tsx +304 -0
  629. package/Tests/UI/Components/RuleRun/RunRuleNowModal.test.tsx +231 -0
  630. package/Tests/UI/Components/RuleRun/RunRulesBulkAction.test.ts +213 -0
  631. package/Tests/UI/Components/TelemetryActiveFilterChipsLockedFilters.test.tsx +124 -61
  632. package/Tests/UI/EsbuildConfig.test.ts +1 -1
  633. package/Tests/UI/Monitor/MonitorStepRetrySettings.test.tsx +616 -0
  634. package/Tests/UI/ReactRouterSingletonBuild.test.ts +4 -2
  635. package/Tests/UI/Rum/ReplayEngine.test.ts +333 -0
  636. package/Tests/UI/Rum/ReplayHeader.test.tsx +257 -123
  637. package/Tests/UI/Rum/ReplayPinControl.test.tsx +122 -0
  638. package/Tests/UI/Rum/ReplayPlayerChrome.test.tsx +245 -0
  639. package/Tests/UI/Rum/ReplayRail.test.tsx +294 -0
  640. package/Tests/UI/Rum/ReplayScrubber.test.tsx +301 -1
  641. package/Tests/UI/Rum/ReplayStage.test.tsx +565 -172
  642. package/Tests/UI/Rum/ReplayStageOverlays.test.tsx +343 -3
  643. package/Tests/UI/Rum/ReplayTabSwitcher.test.tsx +1424 -0
  644. package/Tests/UI/Rum/ReplayTimeline.test.tsx +222 -0
  645. package/Tests/UI/Utils/DashboardStackingLayers.test.ts +8 -1
  646. package/Tests/UI/Utils/RuleRunClient.test.ts +303 -0
  647. package/Tests/UI/Utils/Telemetry/TelemetryEntityNames.test.ts +1 -0
  648. package/Tests/Utils/API.test.ts +96 -0
  649. package/Tests/Utils/Dashboard/Components/DashboardComponentDefaults.test.ts +2 -0
  650. package/Tests/Utils/Dashboard/Components/DashboardSloListComponent.test.ts +206 -0
  651. package/Tests/Utils/Dashboard/DashboardSloComponent.test.ts +36 -2
  652. package/Tests/Utils/Dashboard/SloTemplateVariableScoping.test.ts +409 -588
  653. package/Tests/Utils/Dashboard/SloWidgetSource.test.ts +351 -0
  654. package/Tests/Utils/HTTPResponseBodyReader.test.ts +188 -1
  655. package/Tests/Utils/Markdown/MarkdownEscape.test.ts +361 -0
  656. package/Tests/Utils/Metrics/MetricEventScopeUrl.test.ts +101 -0
  657. package/Tests/Utils/Monitor/MonitorTestAvailabilityUtil.test.ts +256 -0
  658. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +1425 -118
  659. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +188 -3
  660. package/Tests/Utils/NetworkDiscovery/DiscoveryReverseDnsChain.test.ts +661 -13
  661. package/Tests/Utils/NetworkDiscovery/NetbiosNameUtil.test.ts +349 -0
  662. package/Tests/Utils/NetworkDiscovery/RunImportedDeviceNaming.test.ts +656 -0
  663. package/Tests/Utils/NetworkDiscovery/ShortDeviceNamePlanner.test.ts +1020 -0
  664. package/Tests/Utils/NetworkDiscovery/ShortHostnameUtil.test.ts +619 -0
  665. package/Tests/Utils/NetworkSite/CidrMatchUtil.test.ts +317 -0
  666. package/Tests/Utils/Project/DataResidency.test.ts +198 -0
  667. package/Tests/Utils/Rules/RuleRunSummary.test.ts +394 -0
  668. package/Tests/Utils/Slo/SloAffectedResourceMarkdown.test.ts +302 -0
  669. package/Tests/Utils/Slo/SloBurnRateTemplate.test.ts +468 -0
  670. package/Tests/Utils/Slo/SloEvaluation.test.ts +20 -4
  671. package/Tests/Utils/Slo/SloFeedMarkdown.test.ts +1185 -0
  672. package/Tests/Utils/Slo/SloHealth.test.ts +262 -0
  673. package/Tests/Utils/Slo/SloHistoryMetricName.test.ts +102 -0
  674. package/Tests/Utils/Slo/SloListWidgetFormat.test.ts +522 -0
  675. package/Tests/Utils/Slo/SloMetricType.test.ts +355 -0
  676. package/Tests/Utils/Slo/SloMonitorRuleCriteria.test.ts +387 -0
  677. package/Tests/Utils/Slo/SloMonitorStatusSummary.test.ts +210 -0
  678. package/Tests/Utils/Slo/SloOverviewText.test.ts +226 -0
  679. package/Tests/Utils/Slo/SloProjection.test.ts +1039 -0
  680. package/Tests/Utils/Slo/SloWidgetFormat.test.ts +47 -0
  681. package/Tests/Utils/Telemetry/HostIpAddresses.test.ts +105 -0
  682. package/Tests/Utils/Telemetry/LockedFilterSearch.test.ts +1 -80
  683. package/Types/AI/AIChatPageContext.ts +87 -2
  684. package/Types/AI/AIChatTypes.ts +4 -0
  685. package/Types/AI/AIResourceContext.ts +198 -0
  686. package/Types/AI/InvestigationNotStartedReason.ts +30 -0
  687. package/Types/BaseDatabase/EnableAuditLogOn.ts +41 -0
  688. package/Types/Billing/SubscriptionStatus.ts +39 -4
  689. package/Types/Dashboard/DashboardComponentType.ts +1 -0
  690. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +5 -0
  691. package/Types/Dashboard/DashboardComponents/DashboardSloComponent.ts +10 -0
  692. package/Types/Dashboard/DashboardComponents/DashboardSloListComponent.ts +29 -0
  693. package/Types/Dashboard/DashboardTemplates.ts +290 -297
  694. package/Types/Database/EnableAuditLog.ts +23 -1
  695. package/Types/Database/UniqueColumnsTogether.ts +55 -0
  696. package/Types/Email/EmailTemplateType.ts +4 -0
  697. package/Types/Metrics/MetricQueryConfigData.ts +8 -0
  698. package/Types/Monitor/CriteriaFilter.ts +55 -8
  699. package/Types/Monitor/MonitorStep.ts +5 -2
  700. package/Types/Monitor/MonitorStepDnsMonitor.ts +3 -1
  701. package/Types/Monitor/MonitorStepDnssecMonitor.ts +3 -1
  702. package/Types/Monitor/MonitorStepDomainMonitor.ts +3 -1
  703. package/Types/Monitor/MonitorStepExternalStatusPageMonitor.ts +3 -1
  704. package/Types/Monitor/MonitorStepRetries.ts +59 -0
  705. package/Types/Monitor/MonitorStepSnmpMonitor.ts +9 -2
  706. package/Types/NetworkDevice/NetworkDeviceDiagnosticResult.ts +104 -0
  707. package/Types/NetworkDevice/NetworkDeviceDiagnosticStatus.ts +47 -0
  708. package/Types/NetworkDevice/NetworkDeviceDiagnosticType.ts +47 -0
  709. package/Types/NetworkDevice/NetworkDevicePingMetricNames.ts +20 -0
  710. package/Types/Permission.ts +127 -0
  711. package/Types/Rules/RuleCriteriaFieldRegistry.ts +5 -0
  712. package/Types/Rules/RuleRun.ts +518 -0
  713. package/Types/Rum/SessionReplayApi.ts +18 -0
  714. package/Types/Rum/WebVitals.ts +71 -0
  715. package/Types/SecurityEvent/Connectors/ConnectorDiagnostics.ts +6 -0
  716. package/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.ts +30 -4
  717. package/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.ts +108 -1
  718. package/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.ts +6 -2
  719. package/Types/ServiceLevelObjective/SloHistoryMetricName.ts +25 -0
  720. package/Types/ServiceLevelObjective/SloMetricType.ts +49 -0
  721. package/Types/StatusPage/StatusPageSubscriberNotificationEventType.ts +4 -0
  722. package/Types/StatusPage/SubscriberNotificationTemplateVariables.ts +331 -0
  723. package/Types/StatusPage/SubscriberNotificationTrigger.ts +12 -0
  724. package/Types/StatusPage/SubscriberUpdateNotification.ts +89 -0
  725. package/Types/Telemetry/LockedFilterDetail.ts +7 -28
  726. package/Types/Telemetry/ServiceType.ts +7 -0
  727. package/Types/WebsiteRequest.ts +2 -0
  728. package/Typings/Index.d.ts +53 -3
  729. package/UI/Components/AlertBanner/AlertBanner.tsx +85 -27
  730. package/UI/Components/BulkUpdate/BulkArchiveActions.tsx +21 -2
  731. package/UI/Components/Detail/Detail.tsx +9 -2
  732. package/UI/Components/Dropdown/Dropdown.tsx +64 -1
  733. package/UI/Components/EditionLabel/EditionLabel.tsx +7 -5
  734. package/UI/Components/EmptyState/EmptyState.tsx +27 -3
  735. package/UI/Components/EmptyState/EmptyStateGuideLinks.tsx +124 -0
  736. package/UI/Components/Forms/ModelForm.tsx +6 -5
  737. package/UI/Components/KeyboardShortcut/Screenshots/README.md +1 -1
  738. package/UI/Components/LabelRule/LabelRuleTable.tsx +8 -2
  739. package/UI/Components/LogsViewer/LogsViewer.tsx +2 -6
  740. package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +2 -13
  741. package/UI/Components/LogsViewer/types.ts +2 -2
  742. package/UI/Components/ModelTable/BaseModelTable.tsx +8 -0
  743. package/UI/Components/MoreMenu/MoreMenu.tsx +14 -3
  744. package/UI/Components/Navbar/NavBar.tsx +2 -0
  745. package/UI/Components/Navbar/NavBarMenuModal.tsx +6 -2
  746. package/UI/Components/RuleRun/RuleDetailFields.tsx +359 -0
  747. package/UI/Components/RuleRun/RuleTable.tsx +183 -0
  748. package/UI/Components/RuleRun/RuleView.tsx +170 -0
  749. package/UI/Components/RuleRun/RunRuleNowModal.tsx +147 -0
  750. package/UI/Components/RuleRun/RunRulesBulkAction.ts +103 -0
  751. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +2 -6
  752. package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +38 -104
  753. package/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.tsx +2 -18
  754. package/UI/Components/TelemetryViewer/types.ts +2 -2
  755. package/UI/Utils/Rules/RuleRunClient.ts +178 -0
  756. package/UI/Utils/Telemetry/TelemetryEntityNames.ts +8 -0
  757. package/UI/esbuild-config.js +4 -4
  758. package/Utils/API.ts +10 -1
  759. package/Utils/Dashboard/Components/DashboardSloComponent.ts +19 -2
  760. package/Utils/Dashboard/Components/DashboardSloListComponent.ts +126 -0
  761. package/Utils/Dashboard/Components/Index.ts +7 -0
  762. package/Utils/Dashboard/HtmlWidgetDocument.ts +1 -1
  763. package/Utils/Dashboard/SloWidgetSource.ts +188 -0
  764. package/Utils/HTTPResponseBodyReader.ts +64 -8
  765. package/Utils/Markdown/MarkdownEscape.ts +63 -0
  766. package/Utils/Metrics/MetricExplorerUrl.ts +19 -0
  767. package/Utils/Monitor/MonitorTestAvailabilityUtil.ts +92 -0
  768. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +161 -36
  769. package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +25 -0
  770. package/Utils/NetworkDiscovery/NetbiosNameUtil.ts +146 -0
  771. package/Utils/NetworkDiscovery/RunImportedDeviceNaming.ts +390 -0
  772. package/Utils/NetworkDiscovery/ShortDeviceNamePlanner.ts +291 -0
  773. package/Utils/NetworkDiscovery/ShortHostnameUtil.ts +91 -0
  774. package/Utils/NetworkSite/CidrMatchUtil.ts +37 -12
  775. package/Utils/Project/DataResidency.ts +63 -0
  776. package/Utils/Rules/RuleRunSummary.ts +323 -0
  777. package/Utils/Slo/SloAffectedResourceMarkdown.ts +123 -0
  778. package/Utils/Slo/SloBurnRateTemplate.ts +373 -0
  779. package/Utils/Slo/SloFeedMarkdown.ts +1507 -0
  780. package/Utils/Slo/SloHealth.ts +96 -9
  781. package/Utils/Slo/SloListWidgetFormat.ts +370 -0
  782. package/Utils/Slo/SloMetricType.ts +237 -0
  783. package/Utils/Slo/SloMonitorRuleCriteria.ts +364 -0
  784. package/Utils/Slo/SloMonitorStatusSummary.ts +210 -0
  785. package/Utils/Slo/SloOverviewText.ts +265 -0
  786. package/Utils/Slo/SloProjection.ts +967 -0
  787. package/Utils/Slo/SloWidgetFormat.ts +12 -2
  788. package/Utils/Telemetry/HostIpAddresses.ts +46 -2
  789. package/Utils/Telemetry/LockedFilterSearch.ts +3 -49
  790. package/build/dist/Models/AnalyticsModels/AuditLog.js +70 -1
  791. package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
  792. package/build/dist/Models/AnalyticsModels/SecurityEvent.js +4 -4
  793. package/build/dist/Models/DatabaseModels/AIAgentOwnerTeam.js +4 -1
  794. package/build/dist/Models/DatabaseModels/AIAgentOwnerTeam.js.map +1 -1
  795. package/build/dist/Models/DatabaseModels/AIAgentOwnerUser.js +4 -1
  796. package/build/dist/Models/DatabaseModels/AIAgentOwnerUser.js.map +1 -1
  797. package/build/dist/Models/DatabaseModels/Alert.js +72 -0
  798. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  799. package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerTeam.js +3 -1
  800. package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerTeam.js.map +1 -1
  801. package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerUser.js +3 -1
  802. package/build/dist/Models/DatabaseModels/AlertEpisodeOwnerUser.js.map +1 -1
  803. package/build/dist/Models/DatabaseModels/AlertOwnerTeam.js +3 -1
  804. package/build/dist/Models/DatabaseModels/AlertOwnerTeam.js.map +1 -1
  805. package/build/dist/Models/DatabaseModels/AlertOwnerUser.js +3 -1
  806. package/build/dist/Models/DatabaseModels/AlertOwnerUser.js.map +1 -1
  807. package/build/dist/Models/DatabaseModels/CephClusterOwnerTeam.js +4 -1
  808. package/build/dist/Models/DatabaseModels/CephClusterOwnerTeam.js.map +1 -1
  809. package/build/dist/Models/DatabaseModels/CephClusterOwnerUser.js +4 -1
  810. package/build/dist/Models/DatabaseModels/CephClusterOwnerUser.js.map +1 -1
  811. package/build/dist/Models/DatabaseModels/CloudResourceOwnerTeam.js +4 -1
  812. package/build/dist/Models/DatabaseModels/CloudResourceOwnerTeam.js.map +1 -1
  813. package/build/dist/Models/DatabaseModels/CloudResourceOwnerUser.js +4 -1
  814. package/build/dist/Models/DatabaseModels/CloudResourceOwnerUser.js.map +1 -1
  815. package/build/dist/Models/DatabaseModels/DashboardOwnerTeam.js +3 -1
  816. package/build/dist/Models/DatabaseModels/DashboardOwnerTeam.js.map +1 -1
  817. package/build/dist/Models/DatabaseModels/DashboardOwnerUser.js +3 -1
  818. package/build/dist/Models/DatabaseModels/DashboardOwnerUser.js.map +1 -1
  819. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +3 -0
  820. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
  821. package/build/dist/Models/DatabaseModels/DockerHostOwnerTeam.js +4 -1
  822. package/build/dist/Models/DatabaseModels/DockerHostOwnerTeam.js.map +1 -1
  823. package/build/dist/Models/DatabaseModels/DockerHostOwnerUser.js +4 -1
  824. package/build/dist/Models/DatabaseModels/DockerHostOwnerUser.js.map +1 -1
  825. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerTeam.js +4 -1
  826. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerTeam.js.map +1 -1
  827. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerUser.js +4 -1
  828. package/build/dist/Models/DatabaseModels/DockerSwarmClusterOwnerUser.js.map +1 -1
  829. package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
  830. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  831. package/build/dist/Models/DatabaseModels/HostOwnerTeam.js +4 -1
  832. package/build/dist/Models/DatabaseModels/HostOwnerTeam.js.map +1 -1
  833. package/build/dist/Models/DatabaseModels/HostOwnerUser.js +4 -1
  834. package/build/dist/Models/DatabaseModels/HostOwnerUser.js.map +1 -1
  835. package/build/dist/Models/DatabaseModels/Incident.js +76 -0
  836. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  837. package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerTeam.js +3 -1
  838. package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerTeam.js.map +1 -1
  839. package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerUser.js +3 -1
  840. package/build/dist/Models/DatabaseModels/IncidentEpisodeOwnerUser.js.map +1 -1
  841. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js +75 -0
  842. package/build/dist/Models/DatabaseModels/IncidentEpisodePublicNote.js.map +1 -1
  843. package/build/dist/Models/DatabaseModels/IncidentOwnerTeam.js +3 -1
  844. package/build/dist/Models/DatabaseModels/IncidentOwnerTeam.js.map +1 -1
  845. package/build/dist/Models/DatabaseModels/IncidentOwnerUser.js +3 -1
  846. package/build/dist/Models/DatabaseModels/IncidentOwnerUser.js.map +1 -1
  847. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js +75 -0
  848. package/build/dist/Models/DatabaseModels/IncidentPublicNote.js.map +1 -1
  849. package/build/dist/Models/DatabaseModels/IncidentTemplateOwnerTeam.js +4 -1
  850. package/build/dist/Models/DatabaseModels/IncidentTemplateOwnerTeam.js.map +1 -1
  851. package/build/dist/Models/DatabaseModels/IncidentTemplateOwnerUser.js +4 -1
  852. package/build/dist/Models/DatabaseModels/IncidentTemplateOwnerUser.js.map +1 -1
  853. package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerTeam.js +3 -1
  854. package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerTeam.js.map +1 -1
  855. package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerUser.js +3 -1
  856. package/build/dist/Models/DatabaseModels/IncomingCallPolicyOwnerUser.js.map +1 -1
  857. package/build/dist/Models/DatabaseModels/Index.js +6 -4
  858. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  859. package/build/dist/Models/DatabaseModels/IoTFleetOwnerTeam.js +4 -1
  860. package/build/dist/Models/DatabaseModels/IoTFleetOwnerTeam.js.map +1 -1
  861. package/build/dist/Models/DatabaseModels/IoTFleetOwnerUser.js +4 -1
  862. package/build/dist/Models/DatabaseModels/IoTFleetOwnerUser.js.map +1 -1
  863. package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerTeam.js +4 -1
  864. package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerTeam.js.map +1 -1
  865. package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerUser.js +4 -1
  866. package/build/dist/Models/DatabaseModels/KubernetesClusterOwnerUser.js.map +1 -1
  867. package/build/dist/Models/DatabaseModels/Monitor.js +2 -3
  868. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  869. package/build/dist/Models/DatabaseModels/MonitorGroupOwnerTeam.js +4 -1
  870. package/build/dist/Models/DatabaseModels/MonitorGroupOwnerTeam.js.map +1 -1
  871. package/build/dist/Models/DatabaseModels/MonitorGroupOwnerUser.js +4 -1
  872. package/build/dist/Models/DatabaseModels/MonitorGroupOwnerUser.js.map +1 -1
  873. package/build/dist/Models/DatabaseModels/MonitorOwnerTeam.js +3 -1
  874. package/build/dist/Models/DatabaseModels/MonitorOwnerTeam.js.map +1 -1
  875. package/build/dist/Models/DatabaseModels/MonitorOwnerUser.js +3 -1
  876. package/build/dist/Models/DatabaseModels/MonitorOwnerUser.js.map +1 -1
  877. package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -3
  878. package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
  879. package/build/dist/Models/DatabaseModels/NetworkDevice.js +68 -0
  880. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  881. package/build/dist/Models/DatabaseModels/NetworkDeviceDiagnostic.js +772 -0
  882. package/build/dist/Models/DatabaseModels/NetworkDeviceDiagnostic.js.map +1 -0
  883. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +140 -0
  884. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  885. package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerTeam.js +4 -1
  886. package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerTeam.js.map +1 -1
  887. package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerUser.js +4 -1
  888. package/build/dist/Models/DatabaseModels/NetworkDeviceOwnerUser.js.map +1 -1
  889. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js +1 -1
  890. package/build/dist/Models/DatabaseModels/NetworkSiteAssignmentRule.js.map +1 -1
  891. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerTeam.js +3 -1
  892. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerTeam.js.map +1 -1
  893. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerUser.js +3 -1
  894. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyOwnerUser.js.map +1 -1
  895. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerTeam.js +3 -1
  896. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerTeam.js.map +1 -1
  897. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerUser.js +3 -1
  898. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleOwnerUser.js.map +1 -1
  899. package/build/dist/Models/DatabaseModels/PodmanHostOwnerTeam.js +4 -1
  900. package/build/dist/Models/DatabaseModels/PodmanHostOwnerTeam.js.map +1 -1
  901. package/build/dist/Models/DatabaseModels/PodmanHostOwnerUser.js +4 -1
  902. package/build/dist/Models/DatabaseModels/PodmanHostOwnerUser.js.map +1 -1
  903. package/build/dist/Models/DatabaseModels/ProbeOwnerTeam.js +4 -1
  904. package/build/dist/Models/DatabaseModels/ProbeOwnerTeam.js.map +1 -1
  905. package/build/dist/Models/DatabaseModels/ProbeOwnerUser.js +4 -1
  906. package/build/dist/Models/DatabaseModels/ProbeOwnerUser.js.map +1 -1
  907. package/build/dist/Models/DatabaseModels/Project.js +42 -0
  908. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  909. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerTeam.js +4 -1
  910. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerTeam.js.map +1 -1
  911. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerUser.js +4 -1
  912. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerUser.js.map +1 -1
  913. package/build/dist/Models/DatabaseModels/RumApplicationOwnerTeam.js +4 -1
  914. package/build/dist/Models/DatabaseModels/RumApplicationOwnerTeam.js.map +1 -1
  915. package/build/dist/Models/DatabaseModels/RumApplicationOwnerUser.js +4 -1
  916. package/build/dist/Models/DatabaseModels/RumApplicationOwnerUser.js.map +1 -1
  917. package/build/dist/Models/DatabaseModels/RunbookOwnerTeam.js +3 -1
  918. package/build/dist/Models/DatabaseModels/RunbookOwnerTeam.js.map +1 -1
  919. package/build/dist/Models/DatabaseModels/RunbookOwnerUser.js +3 -1
  920. package/build/dist/Models/DatabaseModels/RunbookOwnerUser.js.map +1 -1
  921. package/build/dist/Models/DatabaseModels/RunnerOwnerTeam.js +3 -1
  922. package/build/dist/Models/DatabaseModels/RunnerOwnerTeam.js.map +1 -1
  923. package/build/dist/Models/DatabaseModels/RunnerOwnerUser.js +3 -1
  924. package/build/dist/Models/DatabaseModels/RunnerOwnerUser.js.map +1 -1
  925. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerTeam.js +3 -1
  926. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerTeam.js.map +1 -1
  927. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerUser.js +3 -1
  928. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceOwnerUser.js.map +1 -1
  929. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js +75 -0
  930. package/build/dist/Models/DatabaseModels/ScheduledMaintenancePublicNote.js.map +1 -1
  931. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerTeam.js +6 -1
  932. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerTeam.js.map +1 -1
  933. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.js +6 -1
  934. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser.js.map +1 -1
  935. package/build/dist/Models/DatabaseModels/SecurityEventConnection.js +11 -11
  936. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerTeam.js +4 -1
  937. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerTeam.js.map +1 -1
  938. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerUser.js +4 -1
  939. package/build/dist/Models/DatabaseModels/ServerlessFunctionOwnerUser.js.map +1 -1
  940. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js +192 -10
  941. package/build/dist/Models/DatabaseModels/ServiceLevelObjective.js.map +1 -1
  942. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js +798 -96
  943. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveBurnRateRule.js.map +1 -1
  944. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js +596 -0
  945. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js.map +1 -0
  946. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js +590 -0
  947. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js.map +1 -0
  948. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js +19 -1
  949. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerTeam.js.map +1 -1
  950. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js +19 -1
  951. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerUser.js.map +1 -1
  952. package/build/dist/Models/DatabaseModels/ServiceOwnerTeam.js +4 -1
  953. package/build/dist/Models/DatabaseModels/ServiceOwnerTeam.js.map +1 -1
  954. package/build/dist/Models/DatabaseModels/ServiceOwnerUser.js +4 -1
  955. package/build/dist/Models/DatabaseModels/ServiceOwnerUser.js.map +1 -1
  956. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js +75 -0
  957. package/build/dist/Models/DatabaseModels/StatusPageAnnouncement.js.map +1 -1
  958. package/build/dist/Models/DatabaseModels/StatusPageOwnerTeam.js +3 -1
  959. package/build/dist/Models/DatabaseModels/StatusPageOwnerTeam.js.map +1 -1
  960. package/build/dist/Models/DatabaseModels/StatusPageOwnerUser.js +3 -1
  961. package/build/dist/Models/DatabaseModels/StatusPageOwnerUser.js.map +1 -1
  962. package/build/dist/Models/DatabaseModels/ThreatIntelFeed.js +1 -1
  963. package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerTeam.js +4 -1
  964. package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerTeam.js.map +1 -1
  965. package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerUser.js +4 -1
  966. package/build/dist/Models/DatabaseModels/VMwareVCenterOwnerUser.js.map +1 -1
  967. package/build/dist/Models/DatabaseModels/WorkflowOwnerTeam.js +3 -1
  968. package/build/dist/Models/DatabaseModels/WorkflowOwnerTeam.js.map +1 -1
  969. package/build/dist/Models/DatabaseModels/WorkflowOwnerUser.js +3 -1
  970. package/build/dist/Models/DatabaseModels/WorkflowOwnerUser.js.map +1 -1
  971. package/build/dist/Server/API/AIAgentDataAPI.js +1 -1
  972. package/build/dist/Server/API/AIChatAPI.js +3 -1
  973. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  974. package/build/dist/Server/API/AIInvestigationAPI.js +3 -0
  975. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  976. package/build/dist/Server/API/BaseAPI.js +14 -0
  977. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  978. package/build/dist/Server/API/BillingInvoiceAPI.js +233 -19
  979. package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
  980. package/build/dist/Server/API/BillingPaymentMethodAPI.js +86 -5
  981. package/build/dist/Server/API/BillingPaymentMethodAPI.js.map +1 -1
  982. package/build/dist/Server/API/DashboardAPI.js +72 -2
  983. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  984. package/build/dist/Server/API/SecurityEventConnectionAPI.js +102 -10
  985. package/build/dist/Server/API/SecurityEventConnectionAPI.js.map +1 -1
  986. package/build/dist/Server/API/StatusPageAPI.js +245 -155
  987. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  988. package/build/dist/Server/Infrastructure/Postgres/LocalMigrationGenerationDataSource.js +1 -1
  989. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792800000000-AddNetworkDeviceDiagnostic.js +34 -0
  990. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792800000000-AddNetworkDeviceDiagnostic.js.map +1 -0
  991. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792900000000-AddNetworkDeviceDnsNameAndShortDeviceNames.js +24 -0
  992. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1792900000000-AddNetworkDeviceDnsNameAndShortDeviceNames.js.map +1 -0
  993. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793000000000-AddNetbiosLookupToNetworkDeviceDiscoveryScan.js +21 -0
  994. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793000000000-AddNetbiosLookupToNetworkDeviceDiscoveryScan.js.map +1 -0
  995. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793100000000-SloProductOverhaul.js +207 -0
  996. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793100000000-SloProductOverhaul.js.map +1 -0
  997. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793200000000-BackfillSloMonitorRulesAndAffectedResources.js +72 -0
  998. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793200000000-BackfillSloMonitorRulesAndAffectedResources.js.map +1 -0
  999. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793300000000-AddDataResidencyToProject.js +20 -0
  1000. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793300000000-AddDataResidencyToProject.js.map +1 -0
  1001. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793400000000-AddSubscriberUpdateNotificationStatus.js +46 -0
  1002. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793400000000-AddSubscriberUpdateNotificationStatus.js.map +1 -0
  1003. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793500000000-MakeOwnerRowsUnique.js +602 -0
  1004. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793500000000-MakeOwnerRowsUnique.js.map +1 -0
  1005. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793700000000-AddAIInvestigationDecision.js +14 -0
  1006. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793700000000-AddAIInvestigationDecision.js.map +1 -0
  1007. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793800000000-RemoveMonitorDescriptionLengthLimit.js +20 -0
  1008. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793800000000-RemoveMonitorDescriptionLengthLimit.js.map +1 -0
  1009. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +20 -0
  1010. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  1011. package/build/dist/Server/Middleware/IdentityRateLimit.js +22 -1
  1012. package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
  1013. package/build/dist/Server/Middleware/PublicDashboardRateLimit.js +117 -36
  1014. package/build/dist/Server/Middleware/PublicDashboardRateLimit.js.map +1 -1
  1015. package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js +112 -56
  1016. package/build/dist/Server/Services/AlertEpisodeLabelRuleEngineService.js.map +1 -1
  1017. package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js +167 -68
  1018. package/build/dist/Server/Services/AlertEpisodeOwnerRuleEngineService.js.map +1 -1
  1019. package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js +87 -26
  1020. package/build/dist/Server/Services/AlertEpisodePrivacyRuleEngineService.js.map +1 -1
  1021. package/build/dist/Server/Services/AlertEpisodeService.js +13 -31
  1022. package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
  1023. package/build/dist/Server/Services/AlertGroupingEngineService.js +7 -4
  1024. package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
  1025. package/build/dist/Server/Services/AlertLabelRuleEngineService.js +270 -203
  1026. package/build/dist/Server/Services/AlertLabelRuleEngineService.js.map +1 -1
  1027. package/build/dist/Server/Services/AlertOwnerRuleEngineService.js +498 -354
  1028. package/build/dist/Server/Services/AlertOwnerRuleEngineService.js.map +1 -1
  1029. package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js +97 -34
  1030. package/build/dist/Server/Services/AlertPrivacyRuleEngineService.js.map +1 -1
  1031. package/build/dist/Server/Services/AlertService.js +104 -39
  1032. package/build/dist/Server/Services/AlertService.js.map +1 -1
  1033. package/build/dist/Server/Services/AuditLogService.js +408 -44
  1034. package/build/dist/Server/Services/AuditLogService.js.map +1 -1
  1035. package/build/dist/Server/Services/BillingInvoiceService.js +94 -85
  1036. package/build/dist/Server/Services/BillingInvoiceService.js.map +1 -1
  1037. package/build/dist/Server/Services/BillingService.js +406 -14
  1038. package/build/dist/Server/Services/BillingService.js.map +1 -1
  1039. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +141 -92
  1040. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -1
  1041. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +191 -99
  1042. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -1
  1043. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js +135 -86
  1044. package/build/dist/Server/Services/CloudResourceLabelRuleEngineService.js.map +1 -1
  1045. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js +192 -99
  1046. package/build/dist/Server/Services/CloudResourceOwnerRuleEngineService.js.map +1 -1
  1047. package/build/dist/Server/Services/DashboardLabelRuleEngineService.js +117 -69
  1048. package/build/dist/Server/Services/DashboardLabelRuleEngineService.js.map +1 -1
  1049. package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js +173 -81
  1050. package/build/dist/Server/Services/DashboardOwnerRuleEngineService.js.map +1 -1
  1051. package/build/dist/Server/Services/DatabaseService.js +196 -19
  1052. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  1053. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js +141 -92
  1054. package/build/dist/Server/Services/DockerHostLabelRuleEngineService.js.map +1 -1
  1055. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js +191 -99
  1056. package/build/dist/Server/Services/DockerHostOwnerRuleEngineService.js.map +1 -1
  1057. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js +145 -91
  1058. package/build/dist/Server/Services/DockerSwarmClusterLabelRuleEngineService.js.map +1 -1
  1059. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js +193 -99
  1060. package/build/dist/Server/Services/DockerSwarmClusterOwnerRuleEngineService.js.map +1 -1
  1061. package/build/dist/Server/Services/HostLabelRuleEngineService.js +141 -92
  1062. package/build/dist/Server/Services/HostLabelRuleEngineService.js.map +1 -1
  1063. package/build/dist/Server/Services/HostOwnerRuleEngineService.js +193 -101
  1064. package/build/dist/Server/Services/HostOwnerRuleEngineService.js.map +1 -1
  1065. package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js +112 -56
  1066. package/build/dist/Server/Services/IncidentEpisodeLabelRuleEngineService.js.map +1 -1
  1067. package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js +222 -63
  1068. package/build/dist/Server/Services/IncidentEpisodeOwnerRuleEngineService.js.map +1 -1
  1069. package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js +87 -26
  1070. package/build/dist/Server/Services/IncidentEpisodePrivacyRuleEngineService.js.map +1 -1
  1071. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +24 -0
  1072. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
  1073. package/build/dist/Server/Services/IncidentEpisodeService.js +15 -68
  1074. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  1075. package/build/dist/Server/Services/IncidentGroupingEngineService.js +7 -4
  1076. package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
  1077. package/build/dist/Server/Services/IncidentLabelRuleEngineService.js +258 -192
  1078. package/build/dist/Server/Services/IncidentLabelRuleEngineService.js.map +1 -1
  1079. package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js +519 -376
  1080. package/build/dist/Server/Services/IncidentOwnerRuleEngineService.js.map +1 -1
  1081. package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js +95 -32
  1082. package/build/dist/Server/Services/IncidentPrivacyRuleEngineService.js.map +1 -1
  1083. package/build/dist/Server/Services/IncidentPublicNoteService.js +24 -0
  1084. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  1085. package/build/dist/Server/Services/IncidentService.js +103 -36
  1086. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  1087. package/build/dist/Server/Services/IncidentTemplateService.js +13 -31
  1088. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  1089. package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js +113 -65
  1090. package/build/dist/Server/Services/IncomingCallPolicyLabelRuleEngineService.js.map +1 -1
  1091. package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js +173 -81
  1092. package/build/dist/Server/Services/IncomingCallPolicyOwnerRuleEngineService.js.map +1 -1
  1093. package/build/dist/Server/Services/Index.js +6 -4
  1094. package/build/dist/Server/Services/Index.js.map +1 -1
  1095. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js +117 -69
  1096. package/build/dist/Server/Services/IoTFleetLabelRuleEngineService.js.map +1 -1
  1097. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js +173 -81
  1098. package/build/dist/Server/Services/IoTFleetOwnerRuleEngineService.js.map +1 -1
  1099. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js +145 -91
  1100. package/build/dist/Server/Services/KubernetesClusterLabelRuleEngineService.js.map +1 -1
  1101. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js +193 -99
  1102. package/build/dist/Server/Services/KubernetesClusterOwnerRuleEngineService.js.map +1 -1
  1103. package/build/dist/Server/Services/LabelService.js +20 -25
  1104. package/build/dist/Server/Services/LabelService.js.map +1 -1
  1105. package/build/dist/Server/Services/MonitorLabelRuleEngineService.js +123 -77
  1106. package/build/dist/Server/Services/MonitorLabelRuleEngineService.js.map +1 -1
  1107. package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js +167 -82
  1108. package/build/dist/Server/Services/MonitorOwnerRuleEngineService.js.map +1 -1
  1109. package/build/dist/Server/Services/MonitorProbeService.js +18 -2
  1110. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  1111. package/build/dist/Server/Services/MonitorService.js +24 -40
  1112. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  1113. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +287 -5
  1114. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -1
  1115. package/build/dist/Server/Services/NetworkDeviceDiagnosticService.js +333 -0
  1116. package/build/dist/Server/Services/NetworkDeviceDiagnosticService.js.map +1 -0
  1117. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +117 -69
  1118. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
  1119. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js +173 -81
  1120. package/build/dist/Server/Services/NetworkDeviceOwnerRuleEngineService.js.map +1 -1
  1121. package/build/dist/Server/Services/NetworkDeviceService.js +36 -2
  1122. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  1123. package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js +117 -64
  1124. package/build/dist/Server/Services/OnCallDutyPolicyLabelRuleEngineService.js.map +1 -1
  1125. package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js +175 -81
  1126. package/build/dist/Server/Services/OnCallDutyPolicyOwnerRuleEngineService.js.map +1 -1
  1127. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js +116 -65
  1128. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLabelRuleEngineService.js.map +1 -1
  1129. package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js +173 -81
  1130. package/build/dist/Server/Services/OnCallDutyPolicyScheduleOwnerRuleEngineService.js.map +1 -1
  1131. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js +141 -92
  1132. package/build/dist/Server/Services/PodmanHostLabelRuleEngineService.js.map +1 -1
  1133. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js +191 -99
  1134. package/build/dist/Server/Services/PodmanHostOwnerRuleEngineService.js.map +1 -1
  1135. package/build/dist/Server/Services/ProjectService.js +82 -10
  1136. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  1137. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +141 -92
  1138. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -1
  1139. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +191 -99
  1140. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -1
  1141. package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js +111 -63
  1142. package/build/dist/Server/Services/RumApplicationLabelRuleEngineService.js.map +1 -1
  1143. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js +164 -76
  1144. package/build/dist/Server/Services/RumApplicationOwnerRuleEngineService.js.map +1 -1
  1145. package/build/dist/Server/Services/RunbookLabelRuleEngineService.js +117 -69
  1146. package/build/dist/Server/Services/RunbookLabelRuleEngineService.js.map +1 -1
  1147. package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js +173 -81
  1148. package/build/dist/Server/Services/RunbookOwnerRuleEngineService.js.map +1 -1
  1149. package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js +280 -209
  1150. package/build/dist/Server/Services/ScheduledMaintenanceLabelRuleEngineService.js.map +1 -1
  1151. package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js +521 -376
  1152. package/build/dist/Server/Services/ScheduledMaintenanceOwnerRuleEngineService.js.map +1 -1
  1153. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +24 -0
  1154. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  1155. package/build/dist/Server/Services/ScheduledMaintenanceService.js +37 -39
  1156. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  1157. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js +12 -29
  1158. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js.map +1 -1
  1159. package/build/dist/Server/Services/SecurityEventConnectionService.js +43 -3
  1160. package/build/dist/Server/Services/SecurityEventConnectionService.js.map +1 -1
  1161. package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js +115 -62
  1162. package/build/dist/Server/Services/ServerlessFunctionLabelRuleEngineService.js.map +1 -1
  1163. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js +166 -76
  1164. package/build/dist/Server/Services/ServerlessFunctionOwnerRuleEngineService.js.map +1 -1
  1165. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js +141 -92
  1166. package/build/dist/Server/Services/ServiceLabelRuleEngineService.js.map +1 -1
  1167. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js +769 -18
  1168. package/build/dist/Server/Services/ServiceLevelObjectiveBurnRateRuleService.js.map +1 -1
  1169. package/build/dist/Server/Services/ServiceLevelObjectiveFeedService.js +96 -0
  1170. package/build/dist/Server/Services/ServiceLevelObjectiveFeedService.js.map +1 -0
  1171. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +614 -87
  1172. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -1
  1173. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js +844 -0
  1174. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js.map +1 -0
  1175. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js +207 -1
  1176. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerTeamService.js.map +1 -1
  1177. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js +221 -1
  1178. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerUserService.js.map +1 -1
  1179. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +997 -50
  1180. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
  1181. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js +193 -100
  1182. package/build/dist/Server/Services/ServiceOwnerRuleEngineService.js.map +1 -1
  1183. package/build/dist/Server/Services/StatusPageAnnouncementService.js +12 -0
  1184. package/build/dist/Server/Services/StatusPageAnnouncementService.js.map +1 -1
  1185. package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js +118 -70
  1186. package/build/dist/Server/Services/StatusPageLabelRuleEngineService.js.map +1 -1
  1187. package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js +158 -76
  1188. package/build/dist/Server/Services/StatusPageOwnerRuleEngineService.js.map +1 -1
  1189. package/build/dist/Server/Services/StatusPagePrivateUserService.js +33 -25
  1190. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  1191. package/build/dist/Server/Services/StatusPagePrivateUserSessionService.js +36 -1
  1192. package/build/dist/Server/Services/StatusPagePrivateUserSessionService.js.map +1 -1
  1193. package/build/dist/Server/Services/StatusPageService.js +50 -35
  1194. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  1195. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +19 -215
  1196. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
  1197. package/build/dist/Server/Services/StatusPageSubscriberService.js +6 -0
  1198. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  1199. package/build/dist/Server/Services/TelemetryUsageBillingService.js +27 -5
  1200. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  1201. package/build/dist/Server/Services/ThreatIntelFeedService.js +1 -1
  1202. package/build/dist/Server/Services/UserSessionService.js +5 -0
  1203. package/build/dist/Server/Services/UserSessionService.js.map +1 -1
  1204. package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js +141 -92
  1205. package/build/dist/Server/Services/VMwareVCenterLabelRuleEngineService.js.map +1 -1
  1206. package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js +191 -99
  1207. package/build/dist/Server/Services/VMwareVCenterOwnerRuleEngineService.js.map +1 -1
  1208. package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js +117 -69
  1209. package/build/dist/Server/Services/WorkflowLabelRuleEngineService.js.map +1 -1
  1210. package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js +173 -81
  1211. package/build/dist/Server/Services/WorkflowOwnerRuleEngineService.js.map +1 -1
  1212. package/build/dist/Server/Types/Database/Permissions/OwnedScopePermission.js +15 -10
  1213. package/build/dist/Server/Types/Database/Permissions/OwnedScopePermission.js.map +1 -1
  1214. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +82 -0
  1215. package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
  1216. package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js +17 -0
  1217. package/build/dist/Server/Utils/AI/AlertAIContextBuilder.js.map +1 -1
  1218. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +12 -3
  1219. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
  1220. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +32 -4
  1221. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
  1222. package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +1 -1
  1223. package/build/dist/Server/Utils/AI/CodeFix/CodeFixAgentCompletion.js +1 -1
  1224. package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js +31 -0
  1225. package/build/dist/Server/Utils/AI/IncidentAIContextBuilder.js.map +1 -1
  1226. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +8 -5
  1227. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  1228. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +33 -13
  1229. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  1230. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +31 -10
  1231. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  1232. package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js +205 -0
  1233. package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js.map +1 -0
  1234. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +13 -0
  1235. package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
  1236. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +24 -1
  1237. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
  1238. package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +21 -1
  1239. package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -1
  1240. package/build/dist/Server/Utils/AI/Toolbox/Index.js +30 -6
  1241. package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
  1242. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js +721 -0
  1243. package/build/dist/Server/Utils/AI/Toolbox/ResourceTools.js.map +1 -0
  1244. package/build/dist/Server/Utils/AI/Toolbox/RumTools.js +330 -0
  1245. package/build/dist/Server/Utils/AI/Toolbox/RumTools.js.map +1 -0
  1246. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +337 -53
  1247. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
  1248. package/build/dist/Server/Utils/AI/Toolbox/ToolTypes.js.map +1 -1
  1249. package/build/dist/Server/Utils/AI/Toolbox/TraceTools.js +1 -1
  1250. package/build/dist/Server/Utils/AI/Toolbox/TraceTools.js.map +1 -1
  1251. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +108 -15
  1252. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
  1253. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js +2 -2
  1254. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js.map +1 -1
  1255. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js +115 -6
  1256. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js.map +1 -1
  1257. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js +11 -0
  1258. package/build/dist/Server/Utils/Database/PostgresErrorTranslator.js.map +1 -1
  1259. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +13 -0
  1260. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
  1261. package/build/dist/Server/Utils/Database/RelationValueUtil.js +82 -0
  1262. package/build/dist/Server/Utils/Database/RelationValueUtil.js.map +1 -0
  1263. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +115 -106
  1264. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js.map +1 -1
  1265. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +17 -21
  1266. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  1267. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +4 -2
  1268. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js.map +1 -1
  1269. package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js +5 -4
  1270. package/build/dist/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.js.map +1 -1
  1271. package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js +50 -10
  1272. package/build/dist/Server/Utils/Monitor/MonitorStepsProjectValidator.js.map +1 -1
  1273. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js +13 -1
  1274. package/build/dist/Server/Utils/Monitor/NetworkDeviceHydrationUtil.js.map +1 -1
  1275. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js +6 -10
  1276. package/build/dist/Server/Utils/Monitor/NetworkDeviceMetricUtil.js.map +1 -1
  1277. package/build/dist/Server/Utils/Rules/MonitorRulePatternValidator.js +34 -0
  1278. package/build/dist/Server/Utils/Rules/MonitorRulePatternValidator.js.map +1 -0
  1279. package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js +163 -0
  1280. package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js.map +1 -0
  1281. package/build/dist/Server/Utils/Rules/RuleRun/RuleApplication.js +25 -0
  1282. package/build/dist/Server/Utils/Rules/RuleRun/RuleApplication.js.map +1 -0
  1283. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunPermission.js +128 -0
  1284. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunPermission.js.map +1 -0
  1285. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +746 -0
  1286. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -0
  1287. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunner.js +221 -0
  1288. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunner.js.map +1 -0
  1289. package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js +3 -2
  1290. package/build/dist/Server/Utils/SecurityEvent/ConnectorErrorMessage.js.map +1 -1
  1291. package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js +6 -4
  1292. package/build/dist/Server/Utils/SecurityEvent/Connectors/ConnectorPlatformHealth.js.map +1 -1
  1293. package/build/dist/Server/Utils/SecurityEvent/{GoogleSecOps → Connectors/GoogleSecOps}/GoogleSecOpsClient.js +174 -14
  1294. package/build/dist/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsClient.js.map +1 -0
  1295. package/build/dist/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.js +1417 -0
  1296. package/build/dist/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnector.js.map +1 -0
  1297. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js +138 -18
  1298. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionPoller.js.map +1 -1
  1299. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js +1 -2
  1300. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionRunExecutor.js.map +1 -1
  1301. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js +23 -18
  1302. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectionTester.js.map +1 -1
  1303. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js +2 -0
  1304. package/build/dist/Server/Utils/SecurityEvent/Connectors/SecurityEventConnectorRegistry.js.map +1 -1
  1305. package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js +95 -0
  1306. package/build/dist/Server/Utils/SecurityEvent/Connectors/Types.js.map +1 -1
  1307. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +1 -1
  1308. package/build/dist/Server/Utils/SecurityEvent/SecurityEventDedupe.js +3 -3
  1309. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +2 -2
  1310. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js +118 -40
  1311. package/build/dist/Server/Utils/SessionReplay/SessionReplayReadService.js.map +1 -1
  1312. package/build/dist/Server/Utils/Slo/SloFeedUtil.js +150 -0
  1313. package/build/dist/Server/Utils/Slo/SloFeedUtil.js.map +1 -0
  1314. package/build/dist/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.js +136 -0
  1315. package/build/dist/Server/Utils/Slo/SloLegacyMonitorLabelAdoption.js.map +1 -0
  1316. package/build/dist/Server/Utils/Slo/SloMetricUtil.js +269 -0
  1317. package/build/dist/Server/Utils/Slo/SloMetricUtil.js.map +1 -0
  1318. package/build/dist/Server/Utils/Slo/SloOwnerReferenceValidator.js +134 -0
  1319. package/build/dist/Server/Utils/Slo/SloOwnerReferenceValidator.js.map +1 -0
  1320. package/build/dist/Server/Utils/Slo/SloRecordReferenceValidator.js +137 -0
  1321. package/build/dist/Server/Utils/Slo/SloRecordReferenceValidator.js.map +1 -0
  1322. package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js +6 -26
  1323. package/build/dist/Server/Utils/StatusPage/MonitorRulePatternValidator.js.map +1 -1
  1324. package/build/dist/Server/Utils/StatusPageResource.js +31 -5
  1325. package/build/dist/Server/Utils/StatusPageResource.js.map +1 -1
  1326. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +171 -6
  1327. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  1328. package/build/dist/Types/AI/AIChatPageContext.js +68 -2
  1329. package/build/dist/Types/AI/AIChatPageContext.js.map +1 -1
  1330. package/build/dist/Types/AI/AIChatTypes.js +4 -0
  1331. package/build/dist/Types/AI/AIChatTypes.js.map +1 -1
  1332. package/build/dist/Types/AI/AIResourceContext.js +162 -0
  1333. package/build/dist/Types/AI/AIResourceContext.js.map +1 -0
  1334. package/build/dist/Types/AI/InvestigationNotStartedReason.js +2 -0
  1335. package/build/dist/Types/AI/InvestigationNotStartedReason.js.map +1 -0
  1336. package/build/dist/Types/Billing/SubscriptionStatus.js +37 -3
  1337. package/build/dist/Types/Billing/SubscriptionStatus.js.map +1 -1
  1338. package/build/dist/Types/Dashboard/DashboardComponentType.js +1 -0
  1339. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  1340. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +5 -0
  1341. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  1342. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloListComponent.js +2 -0
  1343. package/build/dist/Types/Dashboard/DashboardComponents/DashboardSloListComponent.js.map +1 -0
  1344. package/build/dist/Types/Dashboard/DashboardTemplates.js +275 -286
  1345. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  1346. package/build/dist/Types/Database/EnableAuditLog.js +19 -1
  1347. package/build/dist/Types/Database/EnableAuditLog.js.map +1 -1
  1348. package/build/dist/Types/Database/UniqueColumnsTogether.js +19 -0
  1349. package/build/dist/Types/Database/UniqueColumnsTogether.js.map +1 -0
  1350. package/build/dist/Types/Email/EmailTemplateType.js +4 -0
  1351. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  1352. package/build/dist/Types/Metrics/MetricQueryConfigData.js.map +1 -1
  1353. package/build/dist/Types/Monitor/CriteriaFilter.js +45 -6
  1354. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  1355. package/build/dist/Types/Monitor/MonitorStep.js +2 -0
  1356. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  1357. package/build/dist/Types/Monitor/MonitorStepDnsMonitor.js +3 -1
  1358. package/build/dist/Types/Monitor/MonitorStepDnsMonitor.js.map +1 -1
  1359. package/build/dist/Types/Monitor/MonitorStepDnssecMonitor.js +3 -1
  1360. package/build/dist/Types/Monitor/MonitorStepDnssecMonitor.js.map +1 -1
  1361. package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js +3 -1
  1362. package/build/dist/Types/Monitor/MonitorStepDomainMonitor.js.map +1 -1
  1363. package/build/dist/Types/Monitor/MonitorStepExternalStatusPageMonitor.js +3 -1
  1364. package/build/dist/Types/Monitor/MonitorStepExternalStatusPageMonitor.js.map +1 -1
  1365. package/build/dist/Types/Monitor/MonitorStepRetries.js +47 -0
  1366. package/build/dist/Types/Monitor/MonitorStepRetries.js.map +1 -0
  1367. package/build/dist/Types/Monitor/MonitorStepSnmpMonitor.js +3 -1
  1368. package/build/dist/Types/Monitor/MonitorStepSnmpMonitor.js.map +1 -1
  1369. package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticResult.js +29 -0
  1370. package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticResult.js.map +1 -0
  1371. package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticStatus.js +37 -0
  1372. package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticStatus.js.map +1 -0
  1373. package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticType.js +42 -0
  1374. package/build/dist/Types/NetworkDevice/NetworkDeviceDiagnosticType.js.map +1 -0
  1375. package/build/dist/Types/NetworkDevice/NetworkDevicePingMetricNames.js +20 -0
  1376. package/build/dist/Types/NetworkDevice/NetworkDevicePingMetricNames.js.map +1 -0
  1377. package/build/dist/Types/Permission.js +114 -0
  1378. package/build/dist/Types/Permission.js.map +1 -1
  1379. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +5 -0
  1380. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
  1381. package/build/dist/Types/Rules/RuleRun.js +267 -0
  1382. package/build/dist/Types/Rules/RuleRun.js.map +1 -0
  1383. package/build/dist/Types/Rum/SessionReplayApi.js.map +1 -1
  1384. package/build/dist/Types/Rum/WebVitals.js +64 -0
  1385. package/build/dist/Types/Rum/WebVitals.js.map +1 -0
  1386. package/build/dist/Types/SecurityEvent/Connectors/ConnectorDiagnostics.js.map +1 -1
  1387. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js +16 -1
  1388. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectionDiagnostics.js.map +1 -1
  1389. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js +65 -0
  1390. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorCatalog.js.map +1 -1
  1391. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js +6 -2
  1392. package/build/dist/Types/SecurityEvent/Connectors/SecurityEventConnectorProvider.js.map +1 -1
  1393. package/build/dist/Types/ServiceLevelObjective/SloHistoryMetricName.js +26 -0
  1394. package/build/dist/Types/ServiceLevelObjective/SloHistoryMetricName.js.map +1 -0
  1395. package/build/dist/Types/ServiceLevelObjective/SloMetricType.js +45 -0
  1396. package/build/dist/Types/ServiceLevelObjective/SloMetricType.js.map +1 -0
  1397. package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js +4 -0
  1398. package/build/dist/Types/StatusPage/StatusPageSubscriberNotificationEventType.js.map +1 -1
  1399. package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js +295 -0
  1400. package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js.map +1 -0
  1401. package/build/dist/Types/StatusPage/SubscriberNotificationTrigger.js +13 -0
  1402. package/build/dist/Types/StatusPage/SubscriberNotificationTrigger.js.map +1 -0
  1403. package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js +67 -0
  1404. package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js.map +1 -0
  1405. package/build/dist/Types/Telemetry/LockedFilterDetail.js +7 -7
  1406. package/build/dist/Types/Telemetry/ServiceType.js +7 -0
  1407. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  1408. package/build/dist/Types/WebsiteRequest.js +2 -0
  1409. package/build/dist/Types/WebsiteRequest.js.map +1 -1
  1410. package/build/dist/UI/Components/AlertBanner/AlertBanner.js +48 -19
  1411. package/build/dist/UI/Components/AlertBanner/AlertBanner.js.map +1 -1
  1412. package/build/dist/UI/Components/BulkUpdate/BulkArchiveActions.js +10 -2
  1413. package/build/dist/UI/Components/BulkUpdate/BulkArchiveActions.js.map +1 -1
  1414. package/build/dist/UI/Components/Detail/Detail.js +12 -3
  1415. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  1416. package/build/dist/UI/Components/Dropdown/Dropdown.js +33 -5
  1417. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  1418. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +7 -5
  1419. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  1420. package/build/dist/UI/Components/EmptyState/EmptyState.js +3 -3
  1421. package/build/dist/UI/Components/EmptyState/EmptyState.js.map +1 -1
  1422. package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js +47 -0
  1423. package/build/dist/UI/Components/EmptyState/EmptyStateGuideLinks.js.map +1 -0
  1424. package/build/dist/UI/Components/Forms/ModelForm.js +6 -5
  1425. package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
  1426. package/build/dist/UI/Components/LabelRule/LabelRuleTable.js +6 -2
  1427. package/build/dist/UI/Components/LabelRule/LabelRuleTable.js.map +1 -1
  1428. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +1 -1
  1429. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  1430. package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +0 -2
  1431. package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
  1432. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +7 -0
  1433. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  1434. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +3 -1
  1435. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  1436. package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
  1437. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +4 -2
  1438. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  1439. package/build/dist/UI/Components/RuleRun/RuleDetailFields.js +226 -0
  1440. package/build/dist/UI/Components/RuleRun/RuleDetailFields.js.map +1 -0
  1441. package/build/dist/UI/Components/RuleRun/RuleTable.js +97 -0
  1442. package/build/dist/UI/Components/RuleRun/RuleTable.js.map +1 -0
  1443. package/build/dist/UI/Components/RuleRun/RuleView.js +83 -0
  1444. package/build/dist/UI/Components/RuleRun/RuleView.js.map +1 -0
  1445. package/build/dist/UI/Components/RuleRun/RunRuleNowModal.js +74 -0
  1446. package/build/dist/UI/Components/RuleRun/RunRuleNowModal.js.map +1 -0
  1447. package/build/dist/UI/Components/RuleRun/RunRulesBulkAction.js +78 -0
  1448. package/build/dist/UI/Components/RuleRun/RunRulesBulkAction.js.map +1 -0
  1449. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +1 -1
  1450. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  1451. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +24 -50
  1452. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -1
  1453. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js +0 -4
  1454. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryActiveFilterChips.js.map +1 -1
  1455. package/build/dist/UI/Utils/Rules/RuleRunClient.js +98 -0
  1456. package/build/dist/UI/Utils/Rules/RuleRunClient.js.map +1 -0
  1457. package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js +8 -0
  1458. package/build/dist/UI/Utils/Telemetry/TelemetryEntityNames.js.map +1 -1
  1459. package/build/dist/Utils/API.js +8 -4
  1460. package/build/dist/Utils/API.js.map +1 -1
  1461. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js +16 -2
  1462. package/build/dist/Utils/Dashboard/Components/DashboardSloComponent.js.map +1 -1
  1463. package/build/dist/Utils/Dashboard/Components/DashboardSloListComponent.js +94 -0
  1464. package/build/dist/Utils/Dashboard/Components/DashboardSloListComponent.js.map +1 -0
  1465. package/build/dist/Utils/Dashboard/Components/Index.js +4 -0
  1466. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  1467. package/build/dist/Utils/Dashboard/SloWidgetSource.js +125 -0
  1468. package/build/dist/Utils/Dashboard/SloWidgetSource.js.map +1 -0
  1469. package/build/dist/Utils/HTTPResponseBodyReader.js +50 -6
  1470. package/build/dist/Utils/HTTPResponseBodyReader.js.map +1 -1
  1471. package/build/dist/Utils/Markdown/MarkdownEscape.js +49 -0
  1472. package/build/dist/Utils/Markdown/MarkdownEscape.js.map +1 -0
  1473. package/build/dist/Utils/Metrics/MetricExplorerUrl.js +14 -3
  1474. package/build/dist/Utils/Metrics/MetricExplorerUrl.js.map +1 -1
  1475. package/build/dist/Utils/Monitor/MonitorTestAvailabilityUtil.js +68 -0
  1476. package/build/dist/Utils/Monitor/MonitorTestAvailabilityUtil.js.map +1 -0
  1477. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +112 -34
  1478. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -1
  1479. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +22 -0
  1480. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -1
  1481. package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js +129 -0
  1482. package/build/dist/Utils/NetworkDiscovery/NetbiosNameUtil.js.map +1 -0
  1483. package/build/dist/Utils/NetworkDiscovery/RunImportedDeviceNaming.js +255 -0
  1484. package/build/dist/Utils/NetworkDiscovery/RunImportedDeviceNaming.js.map +1 -0
  1485. package/build/dist/Utils/NetworkDiscovery/ShortDeviceNamePlanner.js +184 -0
  1486. package/build/dist/Utils/NetworkDiscovery/ShortDeviceNamePlanner.js.map +1 -0
  1487. package/build/dist/Utils/NetworkDiscovery/ShortHostnameUtil.js +79 -0
  1488. package/build/dist/Utils/NetworkDiscovery/ShortHostnameUtil.js.map +1 -0
  1489. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js +21 -12
  1490. package/build/dist/Utils/NetworkSite/CidrMatchUtil.js.map +1 -1
  1491. package/build/dist/Utils/Project/DataResidency.js +51 -0
  1492. package/build/dist/Utils/Project/DataResidency.js.map +1 -0
  1493. package/build/dist/Utils/Rules/RuleRunSummary.js +197 -0
  1494. package/build/dist/Utils/Rules/RuleRunSummary.js.map +1 -0
  1495. package/build/dist/Utils/Slo/SloAffectedResourceMarkdown.js +51 -0
  1496. package/build/dist/Utils/Slo/SloAffectedResourceMarkdown.js.map +1 -0
  1497. package/build/dist/Utils/Slo/SloBurnRateTemplate.js +228 -0
  1498. package/build/dist/Utils/Slo/SloBurnRateTemplate.js.map +1 -0
  1499. package/build/dist/Utils/Slo/SloFeedMarkdown.js +934 -0
  1500. package/build/dist/Utils/Slo/SloFeedMarkdown.js.map +1 -0
  1501. package/build/dist/Utils/Slo/SloHealth.js +75 -9
  1502. package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
  1503. package/build/dist/Utils/Slo/SloListWidgetFormat.js +217 -0
  1504. package/build/dist/Utils/Slo/SloListWidgetFormat.js.map +1 -0
  1505. package/build/dist/Utils/Slo/SloMetricType.js +212 -0
  1506. package/build/dist/Utils/Slo/SloMetricType.js.map +1 -0
  1507. package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js +216 -0
  1508. package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js.map +1 -0
  1509. package/build/dist/Utils/Slo/SloMonitorStatusSummary.js +129 -0
  1510. package/build/dist/Utils/Slo/SloMonitorStatusSummary.js.map +1 -0
  1511. package/build/dist/Utils/Slo/SloOverviewText.js +110 -0
  1512. package/build/dist/Utils/Slo/SloOverviewText.js.map +1 -0
  1513. package/build/dist/Utils/Slo/SloProjection.js +448 -0
  1514. package/build/dist/Utils/Slo/SloProjection.js.map +1 -0
  1515. package/build/dist/Utils/Slo/SloWidgetFormat.js +4 -2
  1516. package/build/dist/Utils/Slo/SloWidgetFormat.js.map +1 -1
  1517. package/build/dist/Utils/Telemetry/HostIpAddresses.js +42 -3
  1518. package/build/dist/Utils/Telemetry/HostIpAddresses.js.map +1 -1
  1519. package/build/dist/Utils/Telemetry/LockedFilterSearch.js +1 -26
  1520. package/build/dist/Utils/Telemetry/LockedFilterSearch.js.map +1 -1
  1521. package/package.json +5 -5
  1522. package/test-setup.sh +2 -2
  1523. package/Models/DatabaseModels/GoogleSecOpsConnection.ts +0 -447
  1524. package/Models/DatabaseModels/GoogleSecOpsConnectionRun.ts +0 -263
  1525. package/Server/API/GoogleSecOpsConnectionAPI.ts +0 -320
  1526. package/Server/Services/GoogleSecOpsConnectionRunService.ts +0 -10
  1527. package/Server/Services/GoogleSecOpsConnectionService.ts +0 -116
  1528. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.ts +0 -777
  1529. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +0 -1373
  1530. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.ts +0 -512
  1531. package/Tests/App/Dashboard/GoogleSecOpsConnectionForm.test.tsx +0 -838
  1532. package/Tests/App/Dashboard/GoogleSecOpsConnectionsErrors.test.tsx +0 -441
  1533. package/Tests/App/Dashboard/GoogleSecOpsDiagnostics.test.tsx +0 -1001
  1534. package/Tests/Server/API/GoogleSecOpsConnectionAPI.test.ts +0 -657
  1535. package/Tests/Server/Services/GoogleSecOpsDiagnosticsModel.test.ts +0 -153
  1536. package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.test.ts +0 -784
  1537. package/Tests/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.test.ts +0 -823
  1538. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsDiagnostics.test.ts +0 -918
  1539. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +0 -738
  1540. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +0 -874
  1541. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +0 -1297
  1542. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsThreePassPoller.test.ts +0 -1577
  1543. package/Tests/UI/Components/LockedFilterActions.test.tsx +0 -396
  1544. package/Types/SecurityEvent/GoogleSecOpsDiagnostics.ts +0 -111
  1545. package/UI/Components/TelemetryViewer/components/LockedFilterActions.tsx +0 -205
  1546. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js +0 -478
  1547. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnection.js.map +0 -1
  1548. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js +0 -287
  1549. package/build/dist/Models/DatabaseModels/GoogleSecOpsConnectionRun.js.map +0 -1
  1550. package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js +0 -231
  1551. package/build/dist/Server/API/GoogleSecOpsConnectionAPI.js.map +0 -1
  1552. package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js +0 -9
  1553. package/build/dist/Server/Services/GoogleSecOpsConnectionRunService.js.map +0 -1
  1554. package/build/dist/Server/Services/GoogleSecOpsConnectionService.js +0 -70
  1555. package/build/dist/Server/Services/GoogleSecOpsConnectionService.js.map +0 -1
  1556. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +0 -1
  1557. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js +0 -537
  1558. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsConnectionTester.js.map +0 -1
  1559. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +0 -1034
  1560. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +0 -1
  1561. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js +0 -410
  1562. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsRunExecutor.js.map +0 -1
  1563. package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js +0 -2
  1564. package/build/dist/Types/SecurityEvent/GoogleSecOpsDiagnostics.js.map +0 -1
  1565. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js +0 -88
  1566. package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterActions.js.map +0 -1
@@ -17,71 +17,64 @@ import {
17
17
  DashboardTemplateType,
18
18
  getDashboardTemplatesByCategory,
19
19
  getTemplateConfig,
20
+ SLO_TEMPLATE_CHART_GROUP_BY_KEYS,
20
21
  } from "../../../Types/Dashboard/DashboardTemplates";
21
22
  import IconProp from "../../../Types/Icon/IconProp";
22
23
  import AlertMetricType from "../../../Types/Alerts/AlertMetricType";
23
24
  import IncidentMetricType from "../../../Types/Incident/IncidentMetricType";
25
+ import MonitorMetricType from "../../../Types/Monitor/MonitorMetricType";
26
+ import SloMetricType from "../../../Types/ServiceLevelObjective/SloMetricType";
27
+ import DashboardSloComponentUtil from "../../../Utils/Dashboard/Components/DashboardSloComponent";
28
+ import DashboardSloListComponentUtil from "../../../Utils/Dashboard/Components/DashboardSloListComponent";
29
+ import {
30
+ resolveSloWidgetSource,
31
+ SloWidgetSourceState,
32
+ } from "../../../Utils/Dashboard/SloWidgetSource";
33
+ import {
34
+ SLO_LIST_ATTRIBUTE_TO_COLUMN,
35
+ SLO_LIST_DEFAULT_MAX_ROWS,
36
+ } from "../../../Utils/Slo/SloListWidgetFormat";
37
+ import SloMetricTypeUtil, {
38
+ SLO_METRIC_SLO_NAME_ATTRIBUTE,
39
+ } from "../../../Utils/Slo/SloMetricType";
24
40
  import { describe, expect, it } from "@jest/globals";
25
41
 
26
42
  /*
27
- * Editorial invariants for the SLO template specifically. The structural
28
- * rules every template must satisfy (grid bounds, overlap, unique ids,
29
- * aggregation spelling) live in DashboardTemplateInvariants this file
30
- * pins the things that make THIS template the SLO one: that it carries the
31
- * Slo widget at all, which of the SLO's three numbers it shows and how,
32
- * that it ships those widgets unconfigured, and that the metric widgets
33
- * beside them cannot disagree with the Monitor variable.
43
+ * Editorial invariants for the SLO template specifically. The structural rules
44
+ * every template must satisfy (grid bounds, overlap, unique ids, aggregation
45
+ * spelling) live in DashboardTemplateInvariants and the reading rules in
46
+ * DashboardTemplateEditorialInvariants this file pins what makes THIS the SLO
47
+ * dashboard:
48
+ *
49
+ * - it opens on the fleet and is useful with zero configuration,
50
+ * - one toolbar variable scopes every section,
51
+ * - the per-SLO widgets follow that variable instead of waiting for edit
52
+ * mode, so the template carries no instruction row and no inert widget,
53
+ * - and nothing on it is project-wide data presented beside an objective.
34
54
  */
35
55
 
36
56
  /*
37
- * The persisted strings. Both enums are written verbatim into the saved
38
- * dashboard's JSON config, so renaming a member's VALUE silently breaks
39
- * every dashboard already created from this template. Pinned as literals
40
- * rather than as enum members so that rename fails here instead of
41
- * shipping.
57
+ * Persisted strings, pinned as literals rather than enum members: they are
58
+ * written verbatim into every saved dashboard and every metric row, so a
59
+ * renamed VALUE must fail here instead of silently blanking saved widgets.
42
60
  */
43
61
  const SLI_METRIC: string = "Sli";
44
62
  const ERROR_BUDGET_REMAINING_METRIC: string = "ErrorBudgetRemaining";
45
63
  const BURN_RATE_METRIC: string = "BurnRate";
46
-
47
64
  const TILE_DISPLAY: string = "Tile";
48
65
  const CHART_DISPLAY: string = "Chart";
49
66
 
50
- /*
51
- * The two metric series this template is allowed to query. Both are emitted
52
- * by MonitorMetricUtil for every probeable monitor, and both carry the bare
53
- * `monitorName` attribute the Monitor variable binds to.
54
- */
55
- const IS_ONLINE_METRIC: string = "oneuptime.monitor.online";
56
- const RESPONSE_TIME_METRIC: string = "oneuptime.monitor.response.time";
57
-
58
- /*
59
- * Every incident and alert metric, taken from the enums so a member added
60
- * later is covered without editing this list.
61
- *
62
- * Neither family survives this template's Monitor variable.
63
- * IncidentService stamps its metrics with `monitorNames` (plural,
64
- * comma-joined) rather than `monitorName`, so a pick would empty every
65
- * incident tile while the uptime tiles beside them stayed populated.
66
- * AlertService does write the singular key — but a burn-rate alert is
67
- * declared with no monitor attached at all, so it carries no `monitorName`
68
- * and a scoped alert tile would hide precisely the alerts an SLO dashboard
69
- * exists for.
70
- */
71
- const MONITOR_VARIABLE_HOSTILE_METRICS: Array<string> = [
72
- ...Object.values(IncidentMetricType),
73
- ...Object.values(AlertMetricType),
74
- ];
67
+ const BUDGET_PERCENT_SERIES: string =
68
+ "oneuptime.slo.error.budget.remaining.percent";
69
+ const BUDGET_SECONDS_SERIES: string =
70
+ "oneuptime.slo.error.budget.remaining.seconds";
71
+ const BURN_RATE_SERIES: string = "oneuptime.slo.burn.rate";
75
72
 
76
73
  /*
77
- * The bare attribute key MonitorMetricUtil.buildAttributes writes. It
78
- * carries no `resource.` prefix, so a variable that guessed
79
- * "resource.monitorName" would compile and offer an empty picker.
74
+ * The bare attribute key SloMetricUtil stamps on every `oneuptime.slo.*` row.
75
+ * A `resource.`-prefixed key would compile and offer an empty picker.
80
76
  */
81
- const MONITOR_ATTRIBUTE: string = "monitorName";
82
-
83
- const AVG_AGGREGATION: string = "Avg";
84
- const MAX_AGGREGATION: string = "Max";
77
+ const SLO_NAME_ATTRIBUTE: string = "sloName";
85
78
 
86
79
  const GRID_WIDTH_IN_UNITS: number = 12;
87
80
 
@@ -103,9 +96,8 @@ function argumentsOf(component: DashboardBaseComponent): WidgetArguments {
103
96
 
104
97
  /*
105
98
  * Every widget family stores its title under a different argument key, and
106
- * titles are the only stable handle: ids are freshly generated on every
107
- * call and array positions move whenever a row is inserted. The Slo widget
108
- * uses `widgetTitle`, which no other family does.
99
+ * titles are the only stable handle: ids regenerate on every call and array
100
+ * positions move whenever a row is inserted.
109
101
  */
110
102
  const TITLE_ARGUMENT_KEYS: Array<string> = [
111
103
  "title",
@@ -141,7 +133,7 @@ function findWidget(
141
133
  },
142
134
  );
143
135
 
144
- expect(matches).toHaveLength(1);
136
+ expect(`${title}: ${matches.length} widget(s)`).toBe(`${title}: 1 widget(s)`);
145
137
  return matches[0] as DashboardBaseComponent;
146
138
  }
147
139
 
@@ -156,21 +148,28 @@ function componentsOfType(
156
148
  );
157
149
  }
158
150
 
159
- function sloWidgets(
160
- config: DashboardViewConfig,
161
- ): Array<DashboardBaseComponent> {
162
- return componentsOfType(config, DashboardComponentType.Slo);
151
+ function queryDataOf(component: DashboardBaseComponent): WidgetArguments {
152
+ const queryConfig: WidgetArguments =
153
+ (argumentsOf(component)["metricQueryConfig"] as
154
+ | WidgetArguments
155
+ | undefined) || {};
156
+
157
+ return (queryConfig["metricQueryData"] as WidgetArguments | undefined) || {};
163
158
  }
164
159
 
165
160
  function filterDataOf(component: DashboardBaseComponent): WidgetArguments {
161
+ return (
162
+ (queryDataOf(component)["filterData"] as WidgetArguments | undefined) || {}
163
+ );
164
+ }
165
+
166
+ function aliasDataOf(component: DashboardBaseComponent): WidgetArguments {
166
167
  const queryConfig: WidgetArguments =
167
168
  (argumentsOf(component)["metricQueryConfig"] as
168
169
  | WidgetArguments
169
170
  | undefined) || {};
170
- const queryData: WidgetArguments =
171
- (queryConfig["metricQueryData"] as WidgetArguments | undefined) || {};
172
171
 
173
- return (queryData["filterData"] as WidgetArguments | undefined) || {};
172
+ return (queryConfig["metricAliasData"] as WidgetArguments | undefined) || {};
174
173
  }
175
174
 
176
175
  function metricNameOf(component: DashboardBaseComponent): string | undefined {
@@ -178,14 +177,21 @@ function metricNameOf(component: DashboardBaseComponent): string | undefined {
178
177
  return typeof value === "string" ? value : undefined;
179
178
  }
180
179
 
181
- /*
182
- * The aggregation is stored under the MISSPELLED key `aggegationType`.
183
- * That misspelling is what the fetch layer reads, so it is the contract.
184
- */
180
+ // The MISSPELLED key is what the fetch layer reads, so it is the contract.
185
181
  function aggregationOf(component: DashboardBaseComponent): unknown {
186
182
  return filterDataOf(component)["aggegationType"];
187
183
  }
188
184
 
185
+ function metricWidgets(
186
+ config: DashboardViewConfig,
187
+ ): Array<DashboardBaseComponent> {
188
+ return config.components.filter(
189
+ (component: DashboardBaseComponent): boolean => {
190
+ return metricNameOf(component) !== undefined;
191
+ },
192
+ );
193
+ }
194
+
189
195
  function lowestOccupiedEdge(config: DashboardViewConfig): number {
190
196
  return Math.max(
191
197
  ...config.components.map((component: DashboardBaseComponent): number => {
@@ -194,18 +200,28 @@ function lowestOccupiedEdge(config: DashboardViewConfig): number {
194
200
  );
195
201
  }
196
202
 
203
+ function onlyVariable(config: DashboardViewConfig): DashboardVariable {
204
+ const variables: Array<DashboardVariable> = config.variables || [];
205
+
206
+ expect(variables).toHaveLength(1);
207
+ return variables[0] as DashboardVariable;
208
+ }
209
+
210
+ // A one-line layout record, so a moved widget reads as a plain diff.
211
+ function placementOf(component: DashboardBaseComponent): string {
212
+ return `${component.componentType} "${titleOf(component)}" @ row ${component.topInDashboardUnits}, col ${component.leftInDashboardUnits}, ${component.widthInDashboardUnits}x${component.heightInDashboardUnits}`;
213
+ }
214
+
197
215
  // -- Tests -----------------------------------------------------------------
198
216
 
199
217
  describe("SLO dashboard template", () => {
200
218
  describe("catalog entry", () => {
201
219
  it("is registered exactly once", () => {
202
- const entries: Array<DashboardTemplate> = DashboardTemplates.filter(
203
- (template: DashboardTemplate): boolean => {
220
+ expect(
221
+ DashboardTemplates.filter((template: DashboardTemplate): boolean => {
204
222
  return template.type === DashboardTemplateType.Slo;
205
- },
206
- );
207
-
208
- expect(entries).toHaveLength(1);
223
+ }),
224
+ ).toHaveLength(1);
209
225
  });
210
226
 
211
227
  it("is filed under Monitoring with the percent icon the SLO pages use", () => {
@@ -218,962 +234,970 @@ describe("SLO dashboard template", () => {
218
234
  expect(entry.name).toBe("SLO Dashboard");
219
235
  expect(entry.category).toBe(DashboardTemplateCategory.Monitoring);
220
236
  expect(entry.icon).toBe(IconProp.Percent);
221
- expect(entry.description.trim().length).toBeGreaterThan(0);
237
+ expect(
238
+ getDashboardTemplatesByCategory(DashboardTemplateCategory.Monitoring),
239
+ ).toContain(entry);
222
240
  });
223
241
 
224
- it("is listed by getDashboardTemplatesByCategory for Monitoring", () => {
225
- const types: Array<DashboardTemplateType> =
226
- getDashboardTemplatesByCategory(
227
- DashboardTemplateCategory.Monitoring,
228
- ).map((template: DashboardTemplate): DashboardTemplateType => {
229
- return template.type;
230
- });
242
+ /*
243
+ * The card is the whole of what the modal tells a reader. It used to end
244
+ * "Pick the SLO on each widget after creating it" — a chore. It must now
245
+ * describe a dashboard that works on creation and is scoped from the
246
+ * toolbar, and must not promise the monitor, incident or alert widgets the
247
+ * template no longer carries.
248
+ */
249
+ it("describes the fleet view and the toolbar, and promises nothing the template does not ship", () => {
250
+ const description: string = (
251
+ DashboardTemplates.find((template: DashboardTemplate): boolean => {
252
+ return template.type === DashboardTemplateType.Slo;
253
+ }) as DashboardTemplate
254
+ ).description;
231
255
 
232
- expect(types).toContain(DashboardTemplateType.Slo);
233
- });
256
+ expect(description).toContain("Every SLO");
257
+ expect(description).toContain("toolbar");
234
258
 
235
- it("resolves to a config rather than to null the way Blank does", () => {
236
- expect(getTemplateConfig(DashboardTemplateType.Slo)).not.toBeNull();
259
+ for (const stale of [
260
+ "monitor",
261
+ "incident",
262
+ "alert",
263
+ "Pick the SLO on each widget",
264
+ ]) {
265
+ expect(
266
+ `description mentions "${stale}": ${description.toLowerCase().includes(stale.toLowerCase())}`,
267
+ ).toBe(`description mentions "${stale}": false`);
268
+ }
237
269
  });
238
270
 
239
- /*
240
- * The enum value is persisted on the Dashboard row that records which
241
- * template it was created from, so it is a wire string, not a label.
242
- */
243
271
  it("uses the persisted enum value 'Slo'", () => {
244
272
  expect(DashboardTemplateType.Slo).toBe("Slo");
245
273
  });
246
274
  });
247
275
 
248
- describe("the SLO widgets", () => {
276
+ describe("layout", () => {
249
277
  /*
250
- * This is the whole reason the template exists. The three SLO numbers
251
- * live in Postgres and in SloHistory, not in the metric store, so no
252
- * Chart / Value / Gauge widget can ever render them only the
253
- * dedicated Slo widget can.
278
+ * The whole board as one table. Each row of the table is a placement; a
279
+ * widget that moves, resizes, changes type or is renamed fails here with
280
+ * a readable diff, and the per-section tests below say WHY each placement
281
+ * is what it is.
254
282
  */
255
- it("carries the Slo widget, which nothing else on a dashboard can stand in for", () => {
256
- expect(sloWidgets(getConfig()).length).toBeGreaterThan(0);
283
+ it("lays the dashboard out exactly as designed", () => {
284
+ expect(getConfig().components.map(placementOf)).toEqual([
285
+ 'Text "SLO Dashboard" @ row 0, col 0, 12x1',
286
+ 'SloList "Service Level Objectives" @ row 1, col 0, 12x5',
287
+ 'Text "Error Budget & Burn Rate" @ row 6, col 0, 12x1',
288
+ 'Value "Lowest Error Budget Remaining" @ row 7, col 0, 4x1',
289
+ 'Value "Least Error Budget Time Left" @ row 7, col 4, 4x1',
290
+ 'Value "Peak Burn Rate" @ row 7, col 8, 4x1',
291
+ 'Chart "Error Budget Remaining by SLO" @ row 8, col 0, 6x4',
292
+ 'Chart "Burn Rate by SLO" @ row 8, col 6, 6x4',
293
+ 'Text "Selected SLO" @ row 12, col 0, 12x1',
294
+ 'Slo "SLI" @ row 13, col 0, 4x3',
295
+ 'Slo "Error Budget Remaining" @ row 13, col 4, 4x3',
296
+ 'Slo "Burn Rate" @ row 13, col 8, 4x3',
297
+ 'Slo "SLI History" @ row 16, col 0, 4x4',
298
+ 'Slo "Error Budget History" @ row 16, col 4, 4x4',
299
+ 'Slo "Burn Rate History" @ row 16, col 8, 4x4',
300
+ ]);
257
301
  });
258
302
 
259
- /*
260
- * Title, metric and display asserted TOGETHER, per widget. Checking
261
- * only the SET of (metric, display) pairs would pass unchanged if the
262
- * three titles were permuted across the three metrics — a dashboard
263
- * whose "Burn Rate" tile reports the SLI, which is the single worst
264
- * way this template can be wrong and the one a reader cannot see.
265
- */
266
- it("labels each SLO widget with the number it actually reports", () => {
267
- const config: DashboardViewConfig = getConfig();
268
-
269
- const expected: Array<[string, string, string]> = [
270
- ["SLI", SLI_METRIC, TILE_DISPLAY],
271
- ["Error Budget Remaining", ERROR_BUDGET_REMAINING_METRIC, TILE_DISPLAY],
272
- ["Burn Rate", BURN_RATE_METRIC, TILE_DISPLAY],
273
- ["SLI Over Time", SLI_METRIC, CHART_DISPLAY],
274
- [
275
- "Error Budget Remaining Over Time",
276
- ERROR_BUDGET_REMAINING_METRIC,
277
- CHART_DISPLAY,
278
- ],
279
- ["Burn Rate Over Time", BURN_RATE_METRIC, CHART_DISPLAY],
280
- ];
281
-
282
- for (const [title, metric, display] of expected) {
283
- const args: WidgetArguments = argumentsOf(findWidget(config, title));
284
-
285
- expect(`${title} -> ${String(args["sloMetric"])}`).toBe(
286
- `${title} -> ${metric}`,
287
- );
288
- expect(`${title} -> ${String(args["displayType"])}`).toBe(
289
- `${title} -> ${display}`,
290
- );
303
+ it("keeps every widget inside the 12-unit grid", () => {
304
+ for (const component of getConfig().components) {
305
+ expect(component.leftInDashboardUnits).toBeGreaterThanOrEqual(0);
306
+ expect(component.topInDashboardUnits).toBeGreaterThanOrEqual(0);
307
+ expect(component.widthInDashboardUnits).toBeGreaterThan(0);
308
+ expect(component.heightInDashboardUnits).toBeGreaterThan(0);
309
+ expect(
310
+ component.leftInDashboardUnits + component.widthInDashboardUnits,
311
+ ).toBeLessThanOrEqual(GRID_WIDTH_IN_UNITS);
291
312
  }
292
-
293
- // Nothing beyond that table is on the dashboard.
294
- expect(sloWidgets(config)).toHaveLength(expected.length);
295
- });
296
-
297
- /*
298
- * The titles themselves are the contract the table above is written
299
- * against, so assert the set independently: a renamed widget must fail
300
- * here rather than silently making the table above vacuous.
301
- */
302
- it("ships exactly the six SLO widget titles the template documents", () => {
303
- expect(sloWidgets(getConfig()).map(titleOf).sort()).toEqual(
304
- [
305
- "SLI",
306
- "Error Budget Remaining",
307
- "Burn Rate",
308
- "SLI Over Time",
309
- "Error Budget Remaining Over Time",
310
- "Burn Rate Over Time",
311
- ].sort(),
312
- );
313
313
  });
314
314
 
315
- /*
316
- * Every member of SloWidgetMetric, not just the three we happen to
317
- * have written above: a fourth number added to the widget should show
318
- * up on the template that exists to report SLO numbers, and this fails
319
- * when it does not.
320
- */
321
- it("leaves none of the widget's supported metrics off the dashboard", () => {
322
- const metrics: Set<string> = new Set<string>(
323
- sloWidgets(getConfig()).map(
324
- (component: DashboardBaseComponent): string => {
325
- return String(argumentsOf(component)["sloMetric"]);
326
- },
327
- ),
328
- );
315
+ it("places no two widgets on the same grid cell", () => {
316
+ const occupied: Map<string, string> = new Map<string, string>();
317
+ const collisions: Array<string> = [];
329
318
 
330
- for (const metric of Object.values(SloWidgetMetric)) {
331
- expect(`${metric} on the dashboard: ${metrics.has(metric)}`).toBe(
332
- `${metric} on the dashboard: true`,
333
- );
334
- }
335
- });
319
+ for (const component of getConfig().components) {
320
+ for (
321
+ let row: number = component.topInDashboardUnits;
322
+ row <
323
+ component.topInDashboardUnits + component.heightInDashboardUnits;
324
+ row++
325
+ ) {
326
+ for (
327
+ let column: number = component.leftInDashboardUnits;
328
+ column <
329
+ component.leftInDashboardUnits + component.widthInDashboardUnits;
330
+ column++
331
+ ) {
332
+ const cell: string = `${row}:${column}`;
333
+ const existing: string | undefined = occupied.get(cell);
336
334
 
337
- /*
338
- * A template cannot know which of a project's SLOs a reader means, and
339
- * an id baked into a shipped template would point at nothing in every
340
- * project but the one it was copied from. The widget's own setup state
341
- * ("Click to select an SLO") is the intended first render.
342
- */
343
- it("ships every SLO widget unconfigured, with no SLO id baked in", () => {
344
- const configured: Array<string> = [];
335
+ if (existing) {
336
+ collisions.push(
337
+ `cell ${cell} shared by "${existing}" and "${titleOf(component)}"`,
338
+ );
339
+ }
345
340
 
346
- for (const component of sloWidgets(getConfig())) {
347
- if (argumentsOf(component)["serviceLevelObjectiveId"] !== undefined) {
348
- configured.push(titleOf(component));
341
+ occupied.set(cell, titleOf(component));
342
+ }
349
343
  }
350
344
  }
351
345
 
352
- expect(configured).toEqual([]);
346
+ expect(collisions).toEqual([]);
353
347
  });
354
348
 
355
349
  /*
356
- * Left untitled, the renderer names a widget "<SLO name> · <metric>",
357
- * which is nicer once an SLO is picked but leaves all six widgets
358
- * reading "SLO Widget" in a template the reader has just created and
359
- * cannot yet tell apart.
350
+ * Stronger than "no empty row": every row of the board is covered edge to
351
+ * edge. A ragged row two tiles and a gap reads as a widget that failed
352
+ * to render, which is exactly what a half-edited template leaves behind.
360
353
  */
361
- it("titles every SLO widget so an unconfigured dashboard still reads", () => {
362
- const widgets: Array<DashboardBaseComponent> = sloWidgets(getConfig());
354
+ it("fills every row of the grid edge to edge, with no holes", () => {
355
+ const config: DashboardViewConfig = getConfig();
356
+ const covered: Set<string> = new Set<string>();
363
357
 
364
- expect(widgets.length).toBeGreaterThan(0);
358
+ for (const component of config.components) {
359
+ for (
360
+ let row: number = component.topInDashboardUnits;
361
+ row <
362
+ component.topInDashboardUnits + component.heightInDashboardUnits;
363
+ row++
364
+ ) {
365
+ for (
366
+ let column: number = component.leftInDashboardUnits;
367
+ column <
368
+ component.leftInDashboardUnits + component.widthInDashboardUnits;
369
+ column++
370
+ ) {
371
+ covered.add(`${row}:${column}`);
372
+ }
373
+ }
374
+ }
365
375
 
366
- for (const component of widgets) {
367
- const title: unknown = argumentsOf(component)["widgetTitle"];
376
+ const holes: Array<string> = [];
368
377
 
369
- expect(typeof title).toBe("string");
370
- expect(String(title).trim().length).toBeGreaterThan(0);
378
+ for (let row: number = 0; row < lowestOccupiedEdge(config); row++) {
379
+ for (let column: number = 0; column < GRID_WIDTH_IN_UNITS; column++) {
380
+ if (!covered.has(`${row}:${column}`)) {
381
+ holes.push(`${row}:${column}`);
382
+ }
383
+ }
371
384
  }
385
+
386
+ expect(holes).toEqual([]);
372
387
  });
373
388
 
374
- it("stores only real SloWidgetMetric and SloWidgetDisplayType values", () => {
375
- const validMetrics: Array<string> = Object.values(SloWidgetMetric);
376
- const validDisplays: Array<string> = Object.values(SloWidgetDisplayType);
389
+ it("is exactly as tall as its content", () => {
390
+ const config: DashboardViewConfig = getConfig();
377
391
 
378
- for (const component of sloWidgets(getConfig())) {
379
- const args: WidgetArguments = argumentsOf(component);
380
- const label: string = titleOf(component);
381
- const metric: string = String(args["sloMetric"]);
382
- const display: string = String(args["displayType"]);
392
+ expect(config.heightInDashboardUnits).toBeGreaterThanOrEqual(
393
+ lowestOccupiedEdge(config),
394
+ );
395
+ expect(lowestOccupiedEdge(config)).toBe(20);
396
+ });
383
397
 
384
- expect(`${label} metric=${metric}`).toBe(
385
- `${label} metric=${
386
- validMetrics.includes(metric) ? metric : "<not a SloWidgetMetric>"
387
- }`,
398
+ it("renders no widget smaller than the minimum it declares", () => {
399
+ for (const component of getConfig().components) {
400
+ expect(component.widthInDashboardUnits).toBeGreaterThanOrEqual(
401
+ component.minWidthInDashboardUnits,
388
402
  );
389
- expect(`${label} display=${display}`).toBe(
390
- `${label} display=${
391
- validDisplays.includes(display)
392
- ? display
393
- : "<not a SloWidgetDisplayType>"
394
- }`,
403
+ expect(component.heightInDashboardUnits).toBeGreaterThanOrEqual(
404
+ component.minHeightInDashboardUnits,
395
405
  );
396
406
  }
397
407
  });
398
408
 
399
- /*
400
- * The enum values are persisted verbatim into the dashboard's JSON
401
- * config. Renaming one compiles everywhere and silently blanks every
402
- * saved widget, so both directions are pinned.
403
- */
404
- it("pins the persisted metric and display strings", () => {
405
- expect(SloWidgetMetric.Sli).toBe(SLI_METRIC);
406
- expect(SloWidgetMetric.ErrorBudgetRemaining).toBe(
407
- ERROR_BUDGET_REMAINING_METRIC,
409
+ it("opens with a bold, full-width title row", () => {
410
+ const title: DashboardBaseComponent = findWidget(
411
+ getConfig(),
412
+ "SLO Dashboard",
408
413
  );
409
- expect(SloWidgetMetric.BurnRate).toBe(BURN_RATE_METRIC);
410
- expect(SloWidgetDisplayType.Tile).toBe(TILE_DISPLAY);
411
- expect(SloWidgetDisplayType.Chart).toBe(CHART_DISPLAY);
412
- expect(DashboardComponentType.Slo).toBe("Slo");
413
- });
414
414
 
415
- it("declares the same minimum footprint the widget's own default does", () => {
416
- for (const component of sloWidgets(getConfig())) {
417
- expect(component.minWidthInDashboardUnits).toBe(2);
418
- expect(component.minHeightInDashboardUnits).toBe(2);
419
- }
415
+ expect(title.componentType).toBe(DashboardComponentType.Text);
416
+ expect(title.topInDashboardUnits).toBe(0);
417
+ expect(title.widthInDashboardUnits).toBe(GRID_WIDTH_IN_UNITS);
418
+ expect(argumentsOf(title)["isBold"]).toBe(true);
420
419
  });
421
420
 
422
421
  /*
423
- * A tile renders a big number, a status pill and a subline; a chart
424
- * renders a time series under a title row. Both need more than the
425
- * 2x2 floor to be legible, and the charts need the extra width a
426
- * series needs to be readable at all.
422
+ * Like the Monitor and Kubernetes templates, the board opens on its
423
+ * headline band directly under the title. The SLO List card carries its
424
+ * own title, so a section heading above it would stack three titles on
425
+ * one card.
427
426
  */
428
- it("gives the charts a wider tile than the single-number tiles", () => {
427
+ it("opens on the fleet list directly under the title, with no heading between them", () => {
429
428
  const config: DashboardViewConfig = getConfig();
430
- const tiles: Array<DashboardBaseComponent> = sloWidgets(config).filter(
431
- (component: DashboardBaseComponent): boolean => {
432
- return argumentsOf(component)["displayType"] === TILE_DISPLAY;
433
- },
434
- );
435
- const charts: Array<DashboardBaseComponent> = sloWidgets(config).filter(
436
- (component: DashboardBaseComponent): boolean => {
437
- return argumentsOf(component)["displayType"] === CHART_DISPLAY;
438
- },
429
+ const title: DashboardBaseComponent = findWidget(config, "SLO Dashboard");
430
+ const list: DashboardBaseComponent = findWidget(
431
+ config,
432
+ "Service Level Objectives",
439
433
  );
440
434
 
441
- expect(tiles.length).toBeGreaterThan(0);
442
- expect(charts.length).toBeGreaterThan(0);
435
+ expect(list.topInDashboardUnits).toBe(
436
+ title.topInDashboardUnits + title.heightInDashboardUnits,
437
+ );
443
438
 
444
- for (const tile of tiles) {
445
- expect(tile.widthInDashboardUnits).toBeGreaterThanOrEqual(3);
446
- expect(tile.heightInDashboardUnits).toBeGreaterThanOrEqual(3);
447
- }
439
+ const headingsAboveTheList: Array<string> = componentsOfType(
440
+ config,
441
+ DashboardComponentType.Text,
442
+ )
443
+ .filter((component: DashboardBaseComponent): boolean => {
444
+ return (
445
+ component !== title &&
446
+ component.topInDashboardUnits < list.topInDashboardUnits
447
+ );
448
+ })
449
+ .map(titleOf);
448
450
 
449
- for (const chart of charts) {
450
- expect(chart.widthInDashboardUnits).toBeGreaterThanOrEqual(6);
451
- expect(chart.heightInDashboardUnits).toBeGreaterThanOrEqual(4);
452
- }
451
+ expect(headingsAboveTheList).toEqual([]);
453
452
  });
454
453
 
455
454
  /*
456
- * Dashboard variables never reach the Slo widget it resolves one SLO
457
- * from its stored id and has nothing to interpolate. A widget that
458
- * carried a metric query would be read by the metric fetch layer and
459
- * scoped by the Monitor variable, which is not what it reports on.
455
+ * The reading order of the whole product: the fleet, how its budget is
456
+ * being spent, then the one objective the reader picks. The budget band's
457
+ * heading names burn rate too, because two of its widgets are burn rate.
460
458
  */
461
- it("carries no metric query on any SLO widget", () => {
462
- for (const component of sloWidgets(getConfig())) {
463
- expect(argumentsOf(component)["metricQueryConfig"]).toBeUndefined();
464
- expect(metricNameOf(component)).toBeUndefined();
465
- }
466
- });
467
-
468
- it("reads the objective before the trend: tiles sit above the charts", () => {
469
- const config: DashboardViewConfig = getConfig();
470
- const lowestTileEdge: number = Math.max(
471
- ...sloWidgets(config)
472
- .filter((component: DashboardBaseComponent): boolean => {
473
- return argumentsOf(component)["displayType"] === TILE_DISPLAY;
474
- })
475
- .map((component: DashboardBaseComponent): number => {
476
- return (
477
- component.topInDashboardUnits + component.heightInDashboardUnits
478
- );
479
- }),
480
- );
481
- const highestChartTop: number = Math.min(
482
- ...sloWidgets(config)
483
- .filter((component: DashboardBaseComponent): boolean => {
484
- return argumentsOf(component)["displayType"] === CHART_DISPLAY;
485
- })
486
- .map((component: DashboardBaseComponent): number => {
487
- return component.topInDashboardUnits;
488
- }),
489
- );
490
-
491
- expect(highestChartTop).toBeGreaterThanOrEqual(lowestTileEdge);
492
- });
493
- });
494
-
495
- describe("metric queries", () => {
496
- it("queries only the two monitor series that carry monitorName", () => {
459
+ it("labels its two sections in reading order, each directly above its band", () => {
497
460
  const config: DashboardViewConfig = getConfig();
461
+ const headers: Array<[string, number]> = [
462
+ ["Error Budget & Burn Rate", 6],
463
+ ["Selected SLO", 12],
464
+ ];
498
465
 
499
- expect(metricNameOf(findWidget(config, "Monitor Uptime (avg)"))).toBe(
500
- IS_ONLINE_METRIC,
501
- );
502
- expect(metricNameOf(findWidget(config, "Avg Response Time"))).toBe(
503
- RESPONSE_TIME_METRIC,
504
- );
505
- expect(metricNameOf(findWidget(config, "Worst Response Time"))).toBe(
506
- RESPONSE_TIME_METRIC,
507
- );
508
- expect(metricNameOf(findWidget(config, "Monitor Uptime Over Time"))).toBe(
509
- IS_ONLINE_METRIC,
510
- );
511
- expect(metricNameOf(findWidget(config, "Response Time Over Time"))).toBe(
512
- RESPONSE_TIME_METRIC,
513
- );
514
-
515
- const metrics: Array<string> = [];
466
+ expect(
467
+ componentsOfType(config, DashboardComponentType.Text).map(titleOf),
468
+ ).toEqual([
469
+ "SLO Dashboard",
470
+ ...headers.map((header: [string, number]): string => {
471
+ return header[0];
472
+ }),
473
+ ]);
516
474
 
517
- for (const component of config.components) {
518
- const metric: string | undefined = metricNameOf(component);
475
+ for (const [heading, expectedTop] of headers) {
476
+ const header: DashboardBaseComponent = findWidget(config, heading);
519
477
 
520
- if (metric) {
521
- metrics.push(metric);
522
- }
478
+ expect(header.componentType).toBe(DashboardComponentType.Text);
479
+ expect(header.widthInDashboardUnits).toBe(GRID_WIDTH_IN_UNITS);
480
+ expect(header.heightInDashboardUnits).toBe(1);
481
+ expect(argumentsOf(header)["isBold"]).toBe(true);
482
+ expect(`${heading} top=${header.topInDashboardUnits}`).toBe(
483
+ `${heading} top=${expectedTop}`,
484
+ );
485
+ expect(
486
+ config.components.some(
487
+ (component: DashboardBaseComponent): boolean => {
488
+ return component.topInDashboardUnits === expectedTop + 1;
489
+ },
490
+ ),
491
+ ).toBe(true);
523
492
  }
524
-
525
- expect(metrics.length).toBeGreaterThan(0);
526
- expect(Array.from(new Set(metrics)).sort()).toEqual(
527
- [IS_ONLINE_METRIC, RESPONSE_TIME_METRIC].sort(),
528
- );
529
493
  });
530
494
 
531
495
  /*
532
- * THE invariant of this template's second half, and it holds for the
533
- * two families for DIFFERENT reasons.
534
- *
535
- * IncidentService stamps its metrics with `monitorNames` (plural,
536
- * comma-joined) and never the singular key, so picking a monitor in
537
- * this template's variable empties every incident tile while the
538
- * uptime tile beside it stays populated — two widgets side by side
539
- * disagreeing about what is selected.
540
- *
541
- * AlertService DOES write the singular `monitorName`, so alert metrics
542
- * scope correctly for any monitor-attached alert. They are excluded
543
- * anyway: createBurnRateAlert never sets a monitor, so the burn-rate
544
- * alerts this dashboard exists for carry no `monitorName` and would be
545
- * the rows a scoped tile dropped.
546
- *
547
- * The incident and alert LISTS read Postgres and are immune to
548
- * telemetry variables, which is why they are the form those signals
549
- * take here.
496
+ * The old template needed a non-bold "Edit this dashboard to pick an
497
+ * objective on each SLO widget" row, because six widgets were inert until
498
+ * edit mode. Every Text widget now is a heading: nothing on a freshly
499
+ * created board needs explaining.
550
500
  */
551
- it("carries no incident or alert metric, which the Monitor variable would empty", () => {
552
- const offenders: Array<string> = [];
553
-
554
- for (const component of getConfig().components) {
555
- const metric: string | undefined = metricNameOf(component);
556
-
557
- if (metric && MONITOR_VARIABLE_HOSTILE_METRICS.includes(metric)) {
558
- offenders.push(`${titleOf(component)} -> ${metric}`);
559
- }
560
- }
501
+ it("carries no instruction row every Text widget is a bold heading", () => {
502
+ const nonHeadings: Array<string> = componentsOfType(
503
+ getConfig(),
504
+ DashboardComponentType.Text,
505
+ )
506
+ .filter((component: DashboardBaseComponent): boolean => {
507
+ return argumentsOf(component)["isBold"] !== true;
508
+ })
509
+ .map(titleOf);
561
510
 
562
- expect(offenders).toEqual([]);
511
+ expect(nonHeadings).toEqual([]);
563
512
  });
564
513
 
565
- it("picks the aggregation that makes each number mean what its title says", () => {
514
+ it("puts the fleet above the selected objective", () => {
566
515
  const config: DashboardViewConfig = getConfig();
516
+ const selectedHeaderTop: number = findWidget(
517
+ config,
518
+ "Selected SLO",
519
+ ).topInDashboardUnits;
567
520
 
568
- for (const title of [
569
- "Monitor Uptime (avg)",
570
- "Avg Response Time",
571
- "Monitor Uptime Over Time",
572
- "Response Time Over Time",
521
+ for (const component of [
522
+ ...componentsOfType(config, DashboardComponentType.SloList),
523
+ ...metricWidgets(config),
573
524
  ]) {
574
- expect(aggregationOf(findWidget(config, title))).toBe(AVG_AGGREGATION);
525
+ expect(
526
+ component.topInDashboardUnits + component.heightInDashboardUnits,
527
+ ).toBeLessThanOrEqual(selectedHeaderTop);
575
528
  }
576
529
 
577
- expect(aggregationOf(findWidget(config, "Worst Response Time"))).toBe(
578
- MAX_AGGREGATION,
579
- );
530
+ for (const component of componentsOfType(
531
+ config,
532
+ DashboardComponentType.Slo,
533
+ )) {
534
+ expect(component.topInDashboardUnits).toBeGreaterThan(
535
+ selectedHeaderTop,
536
+ );
537
+ }
580
538
  });
581
539
 
582
540
  /*
583
- * IsOnline is emitted as 0/1 with unit "", so Avg is a RATIO in [0, 1]
584
- * and not a percent. A widget labelled with a "%" would print "0.99%"
585
- * for a service that was up all window.
541
+ * Each Selected SLO column reads "now, and how it got here": the tile's
542
+ * history sits directly beneath it, at the same width.
586
543
  */
587
- it("labels the uptime widgets as an average rather than as a percentage", () => {
544
+ it("stacks each tile's history directly beneath it", () => {
588
545
  const config: DashboardViewConfig = getConfig();
546
+ const tiles: Array<DashboardBaseComponent> = componentsOfType(
547
+ config,
548
+ DashboardComponentType.Slo,
549
+ ).filter((component: DashboardBaseComponent): boolean => {
550
+ return argumentsOf(component)["displayType"] === TILE_DISPLAY;
551
+ });
589
552
 
590
- /*
591
- * Read the titles out of the CONFIG. Looping over a local array of
592
- * string literals and asserting those literals lack a "%" is a
593
- * tautology: it tests the test.
594
- */
595
- const uptimeWidgetTitles: Array<string> = config.components
596
- .filter((component: DashboardBaseComponent): boolean => {
597
- return metricNameOf(component) === IS_ONLINE_METRIC;
598
- })
599
- .map(titleOf);
553
+ expect(tiles).toHaveLength(3);
554
+
555
+ for (const tile of tiles) {
556
+ const metric: unknown = argumentsOf(tile)["sloMetric"];
557
+ const history: Array<DashboardBaseComponent> = componentsOfType(
558
+ config,
559
+ DashboardComponentType.Slo,
560
+ ).filter((component: DashboardBaseComponent): boolean => {
561
+ return (
562
+ argumentsOf(component)["displayType"] === CHART_DISPLAY &&
563
+ argumentsOf(component)["sloMetric"] === metric
564
+ );
565
+ });
600
566
 
601
- expect(uptimeWidgetTitles.length).toBeGreaterThan(0);
567
+ expect(history).toHaveLength(1);
602
568
 
603
- for (const title of uptimeWidgetTitles) {
604
- expect(`${title} contains %: ${title.includes("%")}`).toBe(
605
- `${title} contains %: false`,
569
+ const chart: DashboardBaseComponent =
570
+ history[0] as DashboardBaseComponent;
571
+
572
+ expect(
573
+ `${titleOf(tile)} -> ${titleOf(chart)}: left ${chart.leftInDashboardUnits}, width ${chart.widthInDashboardUnits}, top ${chart.topInDashboardUnits}`,
574
+ ).toBe(
575
+ `${titleOf(tile)} -> ${titleOf(chart)}: left ${tile.leftInDashboardUnits}, width ${tile.widthInDashboardUnits}, top ${tile.topInDashboardUnits + tile.heightInDashboardUnits}`,
606
576
  );
607
- // "(avg)" or "Over Time" — either way it must not read as a percent.
608
- expect(title.trim().length).toBeGreaterThan(0);
609
577
  }
610
-
611
- // The single-number tile has to say it is an average outright.
612
- expect(titleOf(findWidget(config, "Monitor Uptime (avg)"))).toContain(
613
- "(avg)",
614
- );
615
578
  });
616
579
 
617
- /*
618
- * Nothing anywhere on the dashboard may promise a percentage, because
619
- * the only percentage-valued numbers here (SLI, error budget) are
620
- * rendered by the Slo widget, which formats its own units. A metric
621
- * widget titled with a "%" would be claiming a unit its series does
622
- * not carry.
623
- */
624
- it("puts no percent sign in any metric widget's title", () => {
625
- const offenders: Array<string> = [];
580
+ it("gives every widget a distinct, non-empty title", () => {
581
+ const titles: Array<string> = getConfig().components.map(titleOf);
626
582
 
627
- for (const component of getConfig().components) {
628
- if (metricNameOf(component) && titleOf(component).includes("%")) {
629
- offenders.push(titleOf(component));
630
- }
583
+ for (const title of titles) {
584
+ expect(title.trim().length).toBeGreaterThan(0);
631
585
  }
632
586
 
633
- expect(offenders).toEqual([]);
587
+ expect(new Set(titles).size).toBe(titles.length);
634
588
  });
589
+ });
635
590
 
636
- it("marks each tile so its trend arrow is colored the right way", () => {
637
- const config: DashboardViewConfig = getConfig();
638
-
639
- expect(
640
- argumentsOf(findWidget(config, "Monitor Uptime (avg)"))[
641
- "trendDirection"
642
- ],
643
- ).toBe(DashboardValueTrendDirection.HigherIsBetter);
591
+ describe("what is not on the template", () => {
592
+ it("uses only the widget kinds that can be scoped to an objective", () => {
593
+ const types: Set<string> = new Set<string>(
594
+ getConfig().components.map(
595
+ (component: DashboardBaseComponent): string => {
596
+ return component.componentType;
597
+ },
598
+ ),
599
+ );
644
600
 
645
- for (const title of ["Avg Response Time", "Worst Response Time"]) {
646
- expect(argumentsOf(findWidget(config, title))["trendDirection"]).toBe(
647
- DashboardValueTrendDirection.HigherIsWorse,
648
- );
649
- }
601
+ expect(Array.from(types).sort()).toEqual(
602
+ [
603
+ DashboardComponentType.Chart,
604
+ DashboardComponentType.Slo,
605
+ DashboardComponentType.SloList,
606
+ DashboardComponentType.Text,
607
+ DashboardComponentType.Value,
608
+ ].sort(),
609
+ );
650
610
  });
651
611
 
652
- it("stores its aggregation under the misspelled key the fetch layer reads", () => {
612
+ /*
613
+ * Project-wide lists beside an objective read as that objective's
614
+ * incidents, alerts and monitors. None of them can be narrowed to an SLO,
615
+ * so none of them belongs here.
616
+ */
617
+ it("ships no project-wide incident, alert or monitor list", () => {
653
618
  const config: DashboardViewConfig = getConfig();
654
- let metricWidgets: number = 0;
655
-
656
- for (const component of config.components) {
657
- if (!metricNameOf(component)) {
658
- continue;
659
- }
660
-
661
- metricWidgets++;
662
619
 
663
- expect(typeof aggregationOf(component)).toBe("string");
664
- expect(
665
- Object.prototype.hasOwnProperty.call(
666
- filterDataOf(component),
667
- "aggregationType",
668
- ),
669
- ).toBe(false);
620
+ for (const listType of [
621
+ DashboardComponentType.IncidentList,
622
+ DashboardComponentType.AlertList,
623
+ DashboardComponentType.MonitorList,
624
+ ]) {
625
+ expect(componentsOfType(config, listType)).toHaveLength(0);
670
626
  }
671
-
672
- expect(metricWidgets).toBeGreaterThan(0);
673
627
  });
674
628
 
675
629
  /*
676
- * A dashboard that prints the same figure under two names is a smaller
677
- * dashboard pretending to be a bigger one. A number paired with its
678
- * own trend chart is fine that is a different widget family, not a
679
- * repeat — so the check is on (family, metric, aggregation).
630
+ * Monitor series carry `monitorName` and incident / alert metrics their
631
+ * own monitor keys none carries `sloName`, so the SLO variable would
632
+ * leave them showing the whole project under a toolbar naming one SLO.
680
633
  */
681
- it("never prints the same metric and aggregation twice in the same widget family", () => {
682
- const seen: Map<string, string> = new Map<string, string>();
683
- const duplicates: Array<string> = [];
684
-
685
- for (const component of getConfig().components) {
686
- const metric: string | undefined = metricNameOf(component);
634
+ it("queries no monitor, incident or alert series", () => {
635
+ const foreignSeries: Array<string> = [
636
+ ...Object.values(MonitorMetricType),
637
+ ...Object.values(IncidentMetricType),
638
+ ...Object.values(AlertMetricType),
639
+ ];
687
640
 
688
- if (!metric) {
689
- continue;
690
- }
641
+ const offenders: Array<string> = [];
691
642
 
692
- const key: string = `${component.componentType}|${metric}|${String(
693
- aggregationOf(component),
694
- )}`;
695
- const existing: string | undefined = seen.get(key);
643
+ for (const component of metricWidgets(getConfig())) {
644
+ const metric: string = metricNameOf(component) as string;
696
645
 
697
- if (existing) {
698
- duplicates.push(
699
- `${key} on "${existing}" and "${titleOf(component)}"`,
700
- );
646
+ if (foreignSeries.includes(metric)) {
647
+ offenders.push(`${titleOf(component)} -> ${metric}`);
701
648
  }
702
-
703
- seen.set(key, titleOf(component));
704
649
  }
705
650
 
706
- expect(duplicates).toEqual([]);
651
+ expect(offenders).toEqual([]);
707
652
  });
653
+ });
708
654
 
709
- it("gives every widget on the dashboard a distinct, non-empty title", () => {
710
- const titles: Array<string> = getConfig().components.map(titleOf);
655
+ describe("the Objectives list", () => {
656
+ it("is one full-width SLO List of every active objective", () => {
657
+ const lists: Array<DashboardBaseComponent> = componentsOfType(
658
+ getConfig(),
659
+ DashboardComponentType.SloList,
660
+ );
711
661
 
712
- expect(
713
- titles.every((title: string): boolean => {
714
- return title.trim().length > 0;
715
- }),
716
- ).toBe(true);
717
- expect(new Set(titles).size).toBe(titles.length);
662
+ expect(lists).toHaveLength(1);
663
+
664
+ const list: DashboardBaseComponent = lists[0] as DashboardBaseComponent;
665
+
666
+ expect(titleOf(list)).toBe("Service Level Objectives");
667
+ expect(list.widthInDashboardUnits).toBe(GRID_WIDTH_IN_UNITS);
718
668
  });
719
- });
720
669
 
721
- describe("the entity lists", () => {
722
670
  /*
723
- * An error budget is spent by downtime, and downtime is what incidents
724
- * and alerts record. These three read Postgres rather than the metric
725
- * store, so unlike a metric tile they stay correct whatever the
726
- * Monitor variable is set to.
671
+ * The fleet view has to show the fleet: a stored status or label filter
672
+ * would hide objectives on a board the reader has not configured yet.
727
673
  */
728
- it("puts exactly one monitor, incident and alert list on the dashboard", () => {
729
- const config: DashboardViewConfig = getConfig();
674
+ it("pre-filters nothing and caps its rows at the widget's own default", () => {
675
+ const args: WidgetArguments = argumentsOf(
676
+ findWidget(getConfig(), "Service Level Objectives"),
677
+ );
730
678
 
731
- expect(
732
- componentsOfType(config, DashboardComponentType.MonitorList),
733
- ).toHaveLength(1);
734
- expect(
735
- componentsOfType(config, DashboardComponentType.IncidentList),
736
- ).toHaveLength(1);
737
- expect(
738
- componentsOfType(config, DashboardComponentType.AlertList),
739
- ).toHaveLength(1);
679
+ expect(args).toEqual({
680
+ title: "Service Level Objectives",
681
+ maxRows: SLO_LIST_DEFAULT_MAX_ROWS,
682
+ viewMode: "list",
683
+ });
740
684
  });
741
685
 
742
- it("renders each list as a list and caps its rows at a positive whole number", () => {
743
- const config: DashboardViewConfig = getConfig();
686
+ it("declares the same floors the widget's own default does", () => {
687
+ const list: DashboardBaseComponent = findWidget(
688
+ getConfig(),
689
+ "Service Level Objectives",
690
+ );
744
691
 
745
- for (const title of [
746
- "All Monitors",
747
- "Latest Incidents",
748
- "Latest Alerts",
749
- ]) {
750
- const args: WidgetArguments = argumentsOf(findWidget(config, title));
692
+ expect(list.minWidthInDashboardUnits).toBe(
693
+ DashboardSloListComponentUtil.getDefaultComponent()
694
+ .minWidthInDashboardUnits,
695
+ );
696
+ expect(list.minHeightInDashboardUnits).toBe(
697
+ DashboardSloListComponentUtil.getDefaultComponent()
698
+ .minHeightInDashboardUnits,
699
+ );
700
+ });
701
+ });
702
+
703
+ describe("the Error Budget row", () => {
704
+ it("charts and totals exactly the designed series, with the designed aggregations", () => {
705
+ expect(
706
+ metricWidgets(getConfig()).map(
707
+ (component: DashboardBaseComponent): string => {
708
+ return `${component.componentType} "${titleOf(component)}": ${metricNameOf(
709
+ component,
710
+ )} ${String(aggregationOf(component))}`;
711
+ },
712
+ ),
713
+ ).toEqual([
714
+ `Value "Lowest Error Budget Remaining": ${BUDGET_PERCENT_SERIES} Min`,
715
+ `Value "Least Error Budget Time Left": ${BUDGET_SECONDS_SERIES} Min`,
716
+ `Value "Peak Burn Rate": ${BURN_RATE_SERIES} Max`,
717
+ `Chart "Error Budget Remaining by SLO": ${BUDGET_PERCENT_SERIES} Avg`,
718
+ `Chart "Burn Rate by SLO": ${BURN_RATE_SERIES} Max`,
719
+ ]);
720
+ });
721
+
722
+ it("names every series through SloMetricType", () => {
723
+ const known: Array<string> = Object.values(SloMetricType);
751
724
 
752
- expect(args["viewMode"]).toBe("list");
753
- expect(typeof args["maxRows"]).toBe("number");
754
- expect(Number.isInteger(args["maxRows"] as number)).toBe(true);
755
- expect(args["maxRows"] as number).toBeGreaterThan(0);
725
+ for (const component of metricWidgets(getConfig())) {
726
+ expect(known).toContain(metricNameOf(component) as string);
756
727
  }
757
728
  });
758
729
 
759
730
  /*
760
- * Both lists sort newest first, so an unfiltered list is the record of
761
- * what the budget was spent on open and recently resolved alike.
762
- * Pre-filtering to "unresolved" would hide every incident that has
763
- * already been closed, which is most of the budget.
731
+ * The fleet charts must aggregate each series the way the series is meant
732
+ * to be read — the same table the SLO Metrics page and the MetricType
733
+ * catalog use — so a burn-rate spike is a Max, never averaged away.
764
734
  */
765
- it("does not pre-filter the incident or alert list to a lifecycle state", () => {
766
- const config: DashboardViewConfig = getConfig();
735
+ it("aggregates, labels and units each chart from SloMetricTypeUtil", () => {
736
+ const charts: Array<DashboardBaseComponent> = componentsOfType(
737
+ getConfig(),
738
+ DashboardComponentType.Chart,
739
+ );
740
+
741
+ expect(charts.length).toBeGreaterThan(0);
742
+
743
+ for (const chart of charts) {
744
+ const metric: SloMetricType = metricNameOf(chart) as SloMetricType;
745
+ const label: string = titleOf(chart);
767
746
 
768
- for (const title of ["Latest Incidents", "Latest Alerts"]) {
747
+ expect(`${label} aggregation=${String(aggregationOf(chart))}`).toBe(
748
+ `${label} aggregation=${SloMetricTypeUtil.getAggregationType(metric)}`,
749
+ );
750
+ expect(`${label} legend=${String(aliasDataOf(chart)["legend"])}`).toBe(
751
+ `${label} legend=${SloMetricTypeUtil.getLegend(metric)}`,
752
+ );
769
753
  expect(
770
- argumentsOf(findWidget(config, title))["stateFilter"],
771
- ).toBeUndefined();
754
+ `${label} legendUnit=${String(aliasDataOf(chart)["legendUnit"])}`,
755
+ ).toBe(
756
+ `${label} legendUnit=${SloMetricTypeUtil.getLegendUnit(metric)}`,
757
+ );
772
758
  }
773
759
  });
774
760
 
775
- /*
776
- * Which monitors back an objective is a per-project question, so the
777
- * list opens on all of them; the reader narrows it with the widget's
778
- * own Labels filter.
779
- */
780
- it("does not pin the monitor list to a monitor type or status", () => {
781
- const args: WidgetArguments = argumentsOf(
782
- findWidget(getConfig(), "All Monitors"),
783
- );
761
+ it("prints percent and multiplier units on the charts", () => {
762
+ const config: DashboardViewConfig = getConfig();
784
763
 
785
- expect(args["monitorTypes"]).toBeUndefined();
786
- expect(args["statusFilter"]).toBeUndefined();
764
+ expect(
765
+ aliasDataOf(findWidget(config, "Error Budget Remaining by SLO"))[
766
+ "legendUnit"
767
+ ],
768
+ ).toBe("%");
769
+ expect(
770
+ aliasDataOf(findWidget(config, "Burn Rate by SLO"))["legendUnit"],
771
+ ).toBe("x");
787
772
  });
788
- });
789
773
 
790
- describe("variables", () => {
791
774
  /*
792
- * The uptime and response-time widgets query series every probeable
793
- * monitor in the project emits. Unscoped they describe the project,
794
- * not the objective this variable is what scopes them.
775
+ * The tiles read Min / Max, not the series' own Avg, because they must be
776
+ * true in BOTH states of the toolbar: across the fleet an average of
777
+ * several objectives' budgets is nobody's budget, while the lowest budget
778
+ * and the peak burn are the numbers someone acts on.
795
779
  */
796
- it("ships one multi-select Monitor picker", () => {
797
- const variables: Array<DashboardVariable> = getConfig().variables || [];
780
+ it("totals the worst case, and says so in each title", () => {
781
+ const config: DashboardViewConfig = getConfig();
798
782
 
799
783
  expect(
800
- variables.map((variable: DashboardVariable): string => {
801
- return variable.name;
802
- }),
803
- ).toEqual(["monitor"]);
784
+ aggregationOf(findWidget(config, "Lowest Error Budget Remaining")),
785
+ ).toBe("Min");
786
+ expect(
787
+ aggregationOf(findWidget(config, "Least Error Budget Time Left")),
788
+ ).toBe("Min");
789
+ expect(aggregationOf(findWidget(config, "Peak Burn Rate"))).toBe("Max");
790
+ });
804
791
 
805
- const variable: DashboardVariable = variables[0] as DashboardVariable;
792
+ it("colours each tile's trend the right way round", () => {
793
+ const config: DashboardViewConfig = getConfig();
806
794
 
807
- expect(variable.type).toBe(DashboardVariableType.TelemetryAttribute);
808
- // An objective is normally backed by several monitors, not one.
809
- expect(variable.isMultiSelect).toBe(true);
810
- expect((variable.label || "").trim().length).toBeGreaterThan(0);
795
+ expect(
796
+ argumentsOf(findWidget(config, "Lowest Error Budget Remaining"))[
797
+ "trendDirection"
798
+ ],
799
+ ).toBe(DashboardValueTrendDirection.HigherIsBetter);
800
+ expect(
801
+ argumentsOf(findWidget(config, "Least Error Budget Time Left"))[
802
+ "trendDirection"
803
+ ],
804
+ ).toBe(DashboardValueTrendDirection.HigherIsBetter);
805
+ expect(
806
+ argumentsOf(findWidget(config, "Peak Burn Rate"))["trendDirection"],
807
+ ).toBe(DashboardValueTrendDirection.HigherIsWorse);
811
808
  });
812
809
 
813
810
  /*
814
- * Monitor metrics carry a BARE attribute key see
815
- * MonitorMetricUtil.buildAttributes. A variable bound to
816
- * `resource.monitorName` would compile and offer an empty picker, and
817
- * one bound to the incident metrics' `monitorNames` would filter the
818
- * uptime widgets against a key they do not carry.
811
+ * One line per OBJECTIVE. By the attribute the toolbar variable binds to,
812
+ * leading so the legend reads by name — and by sloId, because SLO names
813
+ * are not unique: grouped by name alone, two same-named SLOs were drawn as
814
+ * one averaged line under one legend entry (regression). A whole-map
815
+ * `groupBy: { attributes: true }` would split every line by every label.
819
816
  */
820
- it("binds to the bare monitorName key, not a prefixed or plural one", () => {
821
- const variable: DashboardVariable = (getConfig().variables ||
822
- [])[0] as DashboardVariable;
817
+ it("fans each chart out by sloName then sloId, and nothing else", () => {
818
+ expect([...SLO_TEMPLATE_CHART_GROUP_BY_KEYS]).toEqual([
819
+ SLO_NAME_ATTRIBUTE,
820
+ "sloId",
821
+ ]);
822
+
823
+ for (const chart of componentsOfType(
824
+ getConfig(),
825
+ DashboardComponentType.Chart,
826
+ )) {
827
+ expect(queryDataOf(chart)["groupByAttributeKeys"]).toEqual([
828
+ SLO_NAME_ATTRIBUTE,
829
+ "sloId",
830
+ ]);
831
+ expect(queryDataOf(chart)["groupBy"]).toBeUndefined();
832
+ expect(argumentsOf(chart)["chartType"]).toBe(DashboardChartType.Line);
833
+ }
834
+ });
823
835
 
824
- expect(variable.attributeKey).toBe(MONITOR_ATTRIBUTE);
825
- expect(variable.attributeKey).not.toBe("monitorNames");
826
- expect(variable.attributeKey).not.toBe("resource.monitorName");
836
+ it("leaves the tiles ungrouped, so each prints ONE number", () => {
837
+ for (const tile of componentsOfType(
838
+ getConfig(),
839
+ DashboardComponentType.Value,
840
+ )) {
841
+ expect(queryDataOf(tile)["groupByAttributeKeys"]).toBeUndefined();
842
+ }
827
843
  });
828
844
 
829
845
  /*
830
- * A multi-select resolves from its picks alone and starts with none,
831
- * so it opens on "All" and a default would never apply the widgets
832
- * would look scoped behind a control reading "unfiltered".
846
+ * With the toolbar on All the row must describe the fleet; a filter baked
847
+ * into a widget would describe a subset behind a toolbar reading "All".
833
848
  */
834
- it("leaves the multi-select variable without a default", () => {
835
- const variable: DashboardVariable = (getConfig().variables ||
836
- [])[0] as DashboardVariable;
837
-
838
- expect(variable.defaultValue ?? "").toBe("");
849
+ it("stores no attribute filter on any metric widget", () => {
850
+ for (const component of metricWidgets(getConfig())) {
851
+ expect(filterDataOf(component)["attributes"]).toBeUndefined();
852
+ }
839
853
  });
840
- });
841
854
 
842
- describe("layout", () => {
843
- it("lays every widget out inside the 12-unit grid", () => {
844
- for (const component of getConfig().components) {
845
- expect(component.leftInDashboardUnits).toBeGreaterThanOrEqual(0);
846
- expect(component.topInDashboardUnits).toBeGreaterThanOrEqual(0);
847
- expect(component.widthInDashboardUnits).toBeGreaterThan(0);
848
- expect(component.heightInDashboardUnits).toBeGreaterThan(0);
849
- expect(
850
- component.leftInDashboardUnits + component.widthInDashboardUnits,
851
- ).toBeLessThanOrEqual(GRID_WIDTH_IN_UNITS);
855
+ /*
856
+ * Objectives run at different targets, so one axis of SLIs reads as a
857
+ * flat line and a dot. The SLI is shown per objective, against its own
858
+ * target, in the Selected SLO section — never fleet-wide.
859
+ */
860
+ it("does not chart the SLI, the target or the status series fleet-wide", () => {
861
+ const queried: Array<string> = metricWidgets(getConfig()).map(
862
+ (component: DashboardBaseComponent): string => {
863
+ return metricNameOf(component) as string;
864
+ },
865
+ );
866
+
867
+ for (const series of [
868
+ SloMetricType.SliPercent,
869
+ SloMetricType.TargetPercent,
870
+ SloMetricType.Status,
871
+ ]) {
872
+ expect(queried).not.toContain(series);
852
873
  }
853
874
  });
854
875
 
855
- it("places no two widgets on the same grid cell", () => {
856
- const occupied: Map<string, string> = new Map<string, string>();
857
- const collisions: Array<string> = [];
858
-
859
- for (const component of getConfig().components) {
860
- for (
861
- let row: number = component.topInDashboardUnits;
862
- row <
863
- component.topInDashboardUnits + component.heightInDashboardUnits;
864
- row++
865
- ) {
866
- for (
867
- let column: number = component.leftInDashboardUnits;
868
- column <
869
- component.leftInDashboardUnits + component.widthInDashboardUnits;
870
- column++
871
- ) {
872
- const cell: string = `${row}:${column}`;
873
- const existing: string | undefined = occupied.get(cell);
876
+ it("puts no percent sign in a metric widget's title — the unit comes from the catalog", () => {
877
+ const offenders: Array<string> = metricWidgets(getConfig())
878
+ .map(titleOf)
879
+ .filter((title: string): boolean => {
880
+ return title.includes("%");
881
+ });
874
882
 
875
- if (existing) {
876
- collisions.push(
877
- `cell ${cell} shared by "${existing}" and "${titleOf(component)}"`,
878
- );
879
- }
883
+ expect(offenders).toEqual([]);
884
+ });
880
885
 
881
- occupied.set(cell, titleOf(component));
882
- }
883
- }
886
+ it("stores every aggregation under the misspelled key the fetch layer reads", () => {
887
+ for (const component of metricWidgets(getConfig())) {
888
+ expect(typeof aggregationOf(component)).toBe("string");
889
+ expect(
890
+ Object.prototype.hasOwnProperty.call(
891
+ filterDataOf(component),
892
+ "aggregationType",
893
+ ),
894
+ ).toBe(false);
884
895
  }
885
-
886
- expect(collisions).toEqual([]);
887
896
  });
897
+ });
888
898
 
899
+ describe("the Selected SLO widgets", () => {
889
900
  /*
890
- * A band of empty rows in the middle of a template reads as a widget
891
- * that failed to render rather than as whitespace.
901
+ * Title, metric and display asserted TOGETHER per widget: a permutation of
902
+ * titles across metrics a "Burn Rate" tile reporting the SLI — is the
903
+ * worst way this template can be wrong and the one a reader cannot see.
892
904
  */
893
- it("leaves no empty row between the title and the last widget", () => {
905
+ it("labels each SLO widget with the number it actually reports", () => {
894
906
  const config: DashboardViewConfig = getConfig();
895
- const occupiedRows: Set<number> = new Set<number>();
896
-
897
- for (const component of config.components) {
898
- for (
899
- let row: number = component.topInDashboardUnits;
900
- row <
901
- component.topInDashboardUnits + component.heightInDashboardUnits;
902
- row++
903
- ) {
904
- occupiedRows.add(row);
905
- }
906
- }
907
+ const expected: Array<[string, string, string]> = [
908
+ ["SLI", SLI_METRIC, TILE_DISPLAY],
909
+ ["Error Budget Remaining", ERROR_BUDGET_REMAINING_METRIC, TILE_DISPLAY],
910
+ ["Burn Rate", BURN_RATE_METRIC, TILE_DISPLAY],
911
+ ["SLI History", SLI_METRIC, CHART_DISPLAY],
912
+ ["Error Budget History", ERROR_BUDGET_REMAINING_METRIC, CHART_DISPLAY],
913
+ ["Burn Rate History", BURN_RATE_METRIC, CHART_DISPLAY],
914
+ ];
907
915
 
908
- const emptyRows: Array<number> = [];
916
+ for (const [title, metric, display] of expected) {
917
+ const args: WidgetArguments = argumentsOf(findWidget(config, title));
909
918
 
910
- for (let row: number = 0; row < lowestOccupiedEdge(config); row++) {
911
- if (!occupiedRows.has(row)) {
912
- emptyRows.push(row);
913
- }
919
+ expect(
920
+ `${title} -> ${String(args["sloMetric"])}/${String(args["displayType"])}`,
921
+ ).toBe(`${title} -> ${metric}/${display}`);
914
922
  }
915
923
 
916
- expect(emptyRows).toEqual([]);
924
+ expect(componentsOfType(config, DashboardComponentType.Slo)).toHaveLength(
925
+ expected.length,
926
+ );
917
927
  });
918
928
 
919
- it("is tall enough to contain everything on it", () => {
920
- const config: DashboardViewConfig = getConfig();
921
-
922
- expect(config.heightInDashboardUnits).toBeGreaterThanOrEqual(
923
- lowestOccupiedEdge(config),
929
+ it("shows every metric the widget supports, as both a tile and a history", () => {
930
+ const pairs: Set<string> = new Set<string>(
931
+ componentsOfType(getConfig(), DashboardComponentType.Slo).map(
932
+ (component: DashboardBaseComponent): string => {
933
+ const args: WidgetArguments = argumentsOf(component);
934
+ return `${String(args["sloMetric"])}/${String(args["displayType"])}`;
935
+ },
936
+ ),
924
937
  );
925
- });
926
938
 
927
- it("renders no widget smaller than the minimum it declares", () => {
928
- for (const component of getConfig().components) {
929
- expect(component.widthInDashboardUnits).toBeGreaterThanOrEqual(
930
- component.minWidthInDashboardUnits,
931
- );
932
- expect(component.heightInDashboardUnits).toBeGreaterThanOrEqual(
933
- component.minHeightInDashboardUnits,
934
- );
939
+ for (const metric of Object.values(SloWidgetMetric)) {
940
+ for (const display of Object.values(SloWidgetDisplayType)) {
941
+ expect(
942
+ `${metric}/${display} on the board: ${pairs.has(`${metric}/${display}`)}`,
943
+ ).toBe(`${metric}/${display} on the board: true`);
944
+ }
935
945
  }
936
946
  });
937
947
 
938
- it("opens with a bold title row across the full width", () => {
939
- const title: DashboardBaseComponent = findWidget(
948
+ /*
949
+ * A template cannot know a project's SLO ids: a baked-in id would point at
950
+ * nothing elsewhere, and on a public dashboard a stored id is the
951
+ * authorization decision.
952
+ */
953
+ it("pins no SLO id on any widget", () => {
954
+ for (const component of componentsOfType(
940
955
  getConfig(),
941
- "SLO Dashboard",
942
- );
956
+ DashboardComponentType.Slo,
957
+ )) {
958
+ expect(
959
+ argumentsOf(component)["serviceLevelObjectiveId"],
960
+ ).toBeUndefined();
961
+ }
962
+ });
943
963
 
944
- expect(title.componentType).toBe(DashboardComponentType.Text);
945
- expect(title.topInDashboardUnits).toBe(0);
946
- expect(title.leftInDashboardUnits).toBe(0);
947
- expect(title.widthInDashboardUnits).toBe(GRID_WIDTH_IN_UNITS);
948
- expect(argumentsOf(title)["isBold"]).toBe(true);
964
+ it("binds every SLO widget to the template's own SLO variable", () => {
965
+ const config: DashboardViewConfig = getConfig();
966
+ const variableId: string = onlyVariable(config).id;
967
+
968
+ for (const component of componentsOfType(
969
+ config,
970
+ DashboardComponentType.Slo,
971
+ )) {
972
+ expect(
973
+ `${titleOf(component)} follows ${String(
974
+ argumentsOf(component)["serviceLevelObjectiveVariableId"],
975
+ )}`,
976
+ ).toBe(`${titleOf(component)} follows ${variableId}`);
977
+ }
949
978
  });
950
979
 
951
980
  /*
952
- * Rows are asserted, not just boldness: a header that does not sit
953
- * immediately above the band it names labels the wrong widgets, and
954
- * checking only componentType/width/isBold cannot see that.
981
+ * THE property the rewrite exists for, established through the resolver
982
+ * the renderer and the public policy both use: as created, every SLO
983
+ * widget asks for a TOOLBAR pick (never "Click to select an SLO", which
984
+ * does nothing outside edit mode), and one pick resolves all six at once.
955
985
  */
956
- it("labels each band with its own bold section header, on the right row", () => {
986
+ it("waits for one toolbar pick and one pick resolves every SLO widget", () => {
957
987
  const config: DashboardViewConfig = getConfig();
988
+ const variable: DashboardVariable = onlyVariable(config);
989
+ const sloWidgets: Array<DashboardBaseComponent> = componentsOfType(
990
+ config,
991
+ DashboardComponentType.Slo,
992
+ );
958
993
 
959
- const headers: Array<[string, number]> = [
960
- ["Objective Health", 2],
961
- ["Error Budget Trends", 6],
962
- ["Monitor Health", 15],
963
- ];
994
+ expect(sloWidgets.length).toBeGreaterThan(0);
964
995
 
965
- for (const [heading, expectedTop] of headers) {
966
- const header: DashboardBaseComponent = findWidget(config, heading);
996
+ for (const component of sloWidgets) {
997
+ const args: WidgetArguments = argumentsOf(component);
967
998
 
968
- expect(header.componentType).toBe(DashboardComponentType.Text);
969
- expect(header.widthInDashboardUnits).toBe(GRID_WIDTH_IN_UNITS);
970
- expect(header.leftInDashboardUnits).toBe(0);
971
- expect(header.heightInDashboardUnits).toBe(1);
972
- expect(argumentsOf(header)["isBold"]).toBe(true);
973
- expect(`${heading} top=${header.topInDashboardUnits}`).toBe(
974
- `${heading} top=${expectedTop}`,
999
+ expect(
1000
+ `${titleOf(component)} as created: ${
1001
+ resolveSloWidgetSource({
1002
+ serviceLevelObjectiveId: args["serviceLevelObjectiveId"] as
1003
+ | string
1004
+ | undefined,
1005
+ serviceLevelObjectiveVariableId: args[
1006
+ "serviceLevelObjectiveVariableId"
1007
+ ] as string | undefined,
1008
+ variables: config.variables,
1009
+ }).state
1010
+ }`,
1011
+ ).toBe(
1012
+ `${titleOf(component)} as created: ${SloWidgetSourceState.NoSelection}`,
975
1013
  );
976
1014
 
977
- /*
978
- * Something must actually start on the row directly below the
979
- * header, or it heads an empty band.
980
- */
981
- const bandStarts: Array<DashboardBaseComponent> =
982
- config.components.filter(
983
- (component: DashboardBaseComponent): boolean => {
984
- return component.topInDashboardUnits === expectedTop + 1;
985
- },
986
- );
1015
+ expect(
1016
+ resolveSloWidgetSource({
1017
+ serviceLevelObjectiveVariableId: args[
1018
+ "serviceLevelObjectiveVariableId"
1019
+ ] as string | undefined,
1020
+ variables: [{ ...variable, selectedValue: "Checkout API" }],
1021
+ }),
1022
+ ).toEqual({
1023
+ state: SloWidgetSourceState.FollowsSelection,
1024
+ sloName: "Checkout API",
1025
+ });
1026
+ }
1027
+ });
987
1028
 
988
- expect(`${heading} band widgets=${bandStarts.length > 0}`).toBe(
989
- `${heading} band widgets=true`,
990
- );
1029
+ it("titles every SLO widget so the placeholders can be told apart", () => {
1030
+ for (const component of componentsOfType(
1031
+ getConfig(),
1032
+ DashboardComponentType.Slo,
1033
+ )) {
1034
+ expect(
1035
+ String(argumentsOf(component)["widgetTitle"] || "").trim().length,
1036
+ ).toBeGreaterThan(0);
991
1037
  }
1038
+ });
992
1039
 
993
- // Headers are in reading order, top to bottom.
994
- const tops: Array<number> = headers.map(
995
- ([heading]: [string, number]): number => {
996
- return findWidget(config, heading).topInDashboardUnits;
997
- },
1040
+ it("stores only real SloWidgetMetric and SloWidgetDisplayType values", () => {
1041
+ expect(SloWidgetMetric.Sli).toBe(SLI_METRIC);
1042
+ expect(SloWidgetMetric.ErrorBudgetRemaining).toBe(
1043
+ ERROR_BUDGET_REMAINING_METRIC,
998
1044
  );
1045
+ expect(SloWidgetMetric.BurnRate).toBe(BURN_RATE_METRIC);
1046
+ expect(SloWidgetDisplayType.Tile).toBe(TILE_DISPLAY);
1047
+ expect(SloWidgetDisplayType.Chart).toBe(CHART_DISPLAY);
999
1048
 
1000
- expect(tops).toEqual(
1001
- tops.slice().sort((a: number, b: number): number => {
1002
- return a - b;
1003
- }),
1004
- );
1049
+ for (const component of componentsOfType(
1050
+ getConfig(),
1051
+ DashboardComponentType.Slo,
1052
+ )) {
1053
+ const args: WidgetArguments = argumentsOf(component);
1054
+
1055
+ expect(Object.values(SloWidgetMetric)).toContain(args["sloMetric"]);
1056
+ expect(Object.values(SloWidgetDisplayType)).toContain(
1057
+ args["displayType"],
1058
+ );
1059
+ }
1005
1060
  });
1006
1061
 
1007
- /*
1008
- * Every Slo widget on this template is inert until somebody picks an
1009
- * objective, which no other template has to explain. One guidance row
1010
- * says it once, directly under the title, instead of leaving six
1011
- * identical setup placeholders to explain themselves.
1012
- */
1013
- it("carries exactly one non-bold guidance row, directly under the title", () => {
1014
- const config: DashboardViewConfig = getConfig();
1015
- const guidance: Array<DashboardBaseComponent> = componentsOfType(
1016
- config,
1017
- DashboardComponentType.Text,
1018
- ).filter((component: DashboardBaseComponent): boolean => {
1019
- return argumentsOf(component)["isBold"] !== true;
1020
- });
1062
+ it("declares the same floors the widget's own default does, and gives charts room to be read", () => {
1063
+ const floor: DashboardBaseComponent =
1064
+ DashboardSloComponentUtil.getDefaultComponent();
1021
1065
 
1022
- expect(guidance).toHaveLength(1);
1066
+ for (const component of componentsOfType(
1067
+ getConfig(),
1068
+ DashboardComponentType.Slo,
1069
+ )) {
1070
+ expect(component.minWidthInDashboardUnits).toBe(
1071
+ floor.minWidthInDashboardUnits,
1072
+ );
1073
+ expect(component.minHeightInDashboardUnits).toBe(
1074
+ floor.minHeightInDashboardUnits,
1075
+ );
1023
1076
 
1024
- const row: DashboardBaseComponent = guidance[0] as DashboardBaseComponent;
1077
+ const isChart: boolean =
1078
+ argumentsOf(component)["displayType"] === CHART_DISPLAY;
1025
1079
 
1026
- expect(row.topInDashboardUnits).toBe(1);
1027
- expect(row.leftInDashboardUnits).toBe(0);
1028
- expect(row.widthInDashboardUnits).toBe(GRID_WIDTH_IN_UNITS);
1029
- const text: string = titleOf(row);
1080
+ expect(component.widthInDashboardUnits).toBeGreaterThanOrEqual(4);
1081
+ expect(component.heightInDashboardUnits).toBeGreaterThanOrEqual(
1082
+ isChart ? 4 : 3,
1083
+ );
1084
+ }
1085
+ });
1030
1086
 
1031
- expect(text.trim().length).toBeGreaterThan(0);
1087
+ // A metric query on an Slo widget would be read by the metric fetch layer.
1088
+ it("carries no metric query on any SLO widget", () => {
1089
+ for (const component of componentsOfType(
1090
+ getConfig(),
1091
+ DashboardComponentType.Slo,
1092
+ )) {
1093
+ expect(argumentsOf(component)["metricQueryConfig"]).toBeUndefined();
1094
+ }
1095
+ });
1096
+ });
1032
1097
 
1033
- /*
1034
- * It must name the SLO widgets it is about, and the EDIT step. The
1035
- * widgets' own placeholder says "Click to select an SLO", but that
1036
- * click only opens the settings panel in edit mode — and a dashboard
1037
- * created from a template opens in view mode, where following the
1038
- * instruction does nothing. A guidance row that repeats "click"
1039
- * without naming edit sends the reader down a dead end.
1040
- */
1041
- expect(`guidance names SLO: ${text.includes("SLO")}`).toBe(
1042
- "guidance names SLO: true",
1043
- );
1044
- expect(
1045
- `guidance names edit: ${text.toLowerCase().includes("edit")}`,
1046
- ).toBe("guidance names edit: true");
1098
+ describe("the SLO variable", () => {
1099
+ it("is one single-select Telemetry Attribute variable labelled SLO", () => {
1100
+ const variable: DashboardVariable = onlyVariable(getConfig());
1047
1101
 
1102
+ expect(variable.name).toBe("slo");
1103
+ expect(variable.label).toBe("SLO");
1104
+ expect(variable.type).toBe(DashboardVariableType.TelemetryAttribute);
1048
1105
  /*
1049
- * The Text widget scales its font to the widget's height, so a long
1050
- * sentence wraps out of a height-1 row and is clipped. Keep it short
1051
- * enough to render on one line at full width.
1106
+ * Single-select because the Selected SLO widgets can show ONE objective;
1107
+ * a multi-pick would leave six widgets asking for a single pick while
1108
+ * the charts above compared.
1052
1109
  */
1053
- expect(`guidance length ${text.length} <= 80`).toBe(
1054
- `guidance length ${Math.min(text.length, 80)} <= 80`,
1055
- );
1110
+ expect(variable.isMultiSelect).toBe(false);
1056
1111
  });
1057
1112
 
1058
1113
  /*
1059
- * The objective is the subject of this dashboard; the monitors,
1060
- * incidents and alerts are the explanation. Putting a monitor tile
1061
- * above the SLI would make it a monitor dashboard with an SLO on it.
1114
+ * SloMetricUtil stamps a BARE key. `resource.sloName` would compile and
1115
+ * offer an empty picker; `sloId` would offer UUIDs and match no name.
1062
1116
  */
1063
- it("puts the objective above everything that explains it", () => {
1064
- const config: DashboardViewConfig = getConfig();
1065
- const lowestSloEdge: number = Math.max(
1066
- ...sloWidgets(config).map(
1067
- (component: DashboardBaseComponent): number => {
1068
- return (
1069
- component.topInDashboardUnits + component.heightInDashboardUnits
1070
- );
1071
- },
1072
- ),
1073
- );
1117
+ it("binds to the bare sloName key the SLO metrics carry", () => {
1118
+ const variable: DashboardVariable = onlyVariable(getConfig());
1074
1119
 
1075
- for (const title of [
1076
- "Monitor Uptime (avg)",
1077
- "Avg Response Time",
1078
- "Worst Response Time",
1079
- "Monitor Uptime Over Time",
1080
- "Response Time Over Time",
1081
- "All Monitors",
1082
- "Latest Alerts",
1083
- ]) {
1084
- expect(
1085
- `${title} top=${findWidget(config, title).topInDashboardUnits} >= ${lowestSloEdge}`,
1086
- ).toBe(
1087
- `${title} top=${Math.max(
1088
- findWidget(config, title).topInDashboardUnits,
1089
- lowestSloEdge,
1090
- )} >= ${lowestSloEdge}`,
1091
- );
1092
- }
1120
+ expect(variable.attributeKey).toBe(SLO_NAME_ATTRIBUTE);
1121
+ expect(variable.attributeKey).toBe(SLO_METRIC_SLO_NAME_ATTRIBUTE);
1122
+ expect(variable.attributeKey).not.toBe("resource.sloName");
1123
+ expect(variable.attributeKey).not.toBe("sloId");
1093
1124
  });
1094
1125
 
1095
1126
  /*
1096
- * A burn-rate rule declares an incident when the budget starts going
1097
- * fast, so the spike and the record of what was done about it belong
1098
- * on the same row.
1127
+ * One key, three consumers: the charts group by it, the SLO List maps it
1128
+ * to the name column, and the variable binds to it. If any of the three
1129
+ * spells it differently, a pick narrows some sections and not others.
1099
1130
  */
1100
- it("sets the incident list beside the burn rate chart", () => {
1131
+ it("is the same key the charts group by and the SLO List maps to its name column", () => {
1101
1132
  const config: DashboardViewConfig = getConfig();
1102
- const burnRateChart: DashboardBaseComponent = findWidget(
1103
- config,
1104
- "Burn Rate Over Time",
1105
- );
1106
- const incidents: DashboardBaseComponent = findWidget(
1107
- config,
1108
- "Latest Incidents",
1109
- );
1133
+ const key: string = onlyVariable(config).attributeKey as string;
1110
1134
 
1111
- expect(incidents.topInDashboardUnits).toBe(
1112
- burnRateChart.topInDashboardUnits,
1113
- );
1114
- expect(incidents.leftInDashboardUnits).toBe(
1115
- burnRateChart.leftInDashboardUnits +
1116
- burnRateChart.widthInDashboardUnits,
1117
- );
1135
+ expect(SLO_LIST_ATTRIBUTE_TO_COLUMN[key]).toBe("name");
1136
+
1137
+ for (const chart of componentsOfType(
1138
+ config,
1139
+ DashboardComponentType.Chart,
1140
+ )) {
1141
+ // The variable's key leads; sloId after it keeps same-named SLOs apart.
1142
+ expect(
1143
+ (queryDataOf(chart)["groupByAttributeKeys"] as Array<string>)[0],
1144
+ ).toBe(key);
1145
+ }
1118
1146
  });
1119
1147
 
1120
- it("picks a chart shape that suits each monitor series", () => {
1121
- const config: DashboardViewConfig = getConfig();
1148
+ // A template cannot know a project's SLO names.
1149
+ it("ships no default and no selection", () => {
1150
+ const variable: DashboardVariable = onlyVariable(getConfig());
1122
1151
 
1123
- // A filled area for a ratio that should read as coverage...
1124
- expect(
1125
- argumentsOf(findWidget(config, "Monitor Uptime Over Time"))[
1126
- "chartType"
1127
- ],
1128
- ).toBe(DashboardChartType.Area);
1129
- // ...and a line for a latency series read against its own history.
1130
- expect(
1131
- argumentsOf(findWidget(config, "Response Time Over Time"))["chartType"],
1132
- ).toBe(DashboardChartType.Line);
1152
+ expect(variable.defaultValue ?? "").toBe("");
1153
+ expect(variable.selectedValue ?? "").toBe("");
1154
+ expect(variable.selectedValues ?? []).toEqual([]);
1133
1155
  });
1134
1156
  });
1135
1157
 
1136
1158
  describe("freshness", () => {
1137
- /*
1138
- * Two dashboards created from this template must not share component
1139
- * or variable ids — they are independent saved rows from the moment
1140
- * they are created.
1141
- */
1142
1159
  it("generates fresh component and variable ids on every call", () => {
1143
1160
  const first: DashboardViewConfig = getConfig();
1144
1161
  const second: DashboardViewConfig = getConfig();
1145
1162
 
1146
- expect(second.components.length).toBe(first.components.length);
1147
-
1148
- const firstComponentIds: Set<string> = new Set<string>(
1163
+ const firstIds: Set<string> = new Set<string>(
1149
1164
  first.components.map((component: DashboardBaseComponent): string => {
1150
1165
  return component.componentId.toString();
1151
1166
  }),
1152
1167
  );
1168
+
1153
1169
  for (const component of second.components) {
1154
- expect(firstComponentIds.has(component.componentId.toString())).toBe(
1155
- false,
1156
- );
1170
+ expect(firstIds.has(component.componentId.toString())).toBe(false);
1157
1171
  }
1158
1172
 
1159
- const firstVariableIds: Set<string> = new Set<string>(
1160
- (first.variables || []).map((variable: DashboardVariable): string => {
1161
- return variable.id;
1162
- }),
1163
- );
1164
- for (const variable of second.variables || []) {
1165
- expect(firstVariableIds.has(variable.id)).toBe(false);
1166
- }
1173
+ expect(onlyVariable(second).id).not.toBe(onlyVariable(first).id);
1167
1174
  });
1168
1175
 
1169
- it("returns the same widget set on every call", () => {
1170
- const first: DashboardViewConfig = getConfig();
1171
- const second: DashboardViewConfig = getConfig();
1176
+ /*
1177
+ * The binding must point at THIS config's variable. A variable id captured
1178
+ * once at module load would bind every dashboard created afterwards to a
1179
+ * variable it does not have.
1180
+ */
1181
+ it("binds each call's SLO widgets to that same call's variable", () => {
1182
+ for (let call: number = 0; call < 3; call++) {
1183
+ const config: DashboardViewConfig = getConfig();
1184
+ const variableId: string = onlyVariable(config).id;
1185
+
1186
+ for (const component of componentsOfType(
1187
+ config,
1188
+ DashboardComponentType.Slo,
1189
+ )) {
1190
+ expect(
1191
+ argumentsOf(component)["serviceLevelObjectiveVariableId"],
1192
+ ).toBe(variableId);
1193
+ }
1194
+ }
1195
+ });
1172
1196
 
1173
- expect(second.components.map(titleOf)).toEqual(
1174
- first.components.map(titleOf),
1197
+ it("returns the same layout on every call", () => {
1198
+ expect(getConfig().components.map(placementOf)).toEqual(
1199
+ getConfig().components.map(placementOf),
1175
1200
  );
1176
- expect(second.heightInDashboardUnits).toBe(first.heightInDashboardUnits);
1177
1201
  });
1178
1202
  });
1179
1203
  });