@oneuptime/common 11.0.0 → 11.0.2

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 (357) hide show
  1. package/Models/DatabaseModels/Alert.ts +110 -0
  2. package/Models/DatabaseModels/CephCluster.ts +964 -0
  3. package/Models/DatabaseModels/CephClusterLabelRule.ts +514 -0
  4. package/Models/DatabaseModels/CephClusterOwnerRule.ts +596 -0
  5. package/Models/DatabaseModels/CephClusterOwnerTeam.ts +487 -0
  6. package/Models/DatabaseModels/CephClusterOwnerUser.ts +486 -0
  7. package/Models/DatabaseModels/CephResource.ts +809 -0
  8. package/Models/DatabaseModels/Host.ts +64 -0
  9. package/Models/DatabaseModels/Incident.ts +110 -0
  10. package/Models/DatabaseModels/Index.ts +24 -0
  11. package/Models/DatabaseModels/ProxmoxCluster.ts +943 -0
  12. package/Models/DatabaseModels/ProxmoxClusterLabelRule.ts +514 -0
  13. package/Models/DatabaseModels/ProxmoxClusterOwnerRule.ts +596 -0
  14. package/Models/DatabaseModels/ProxmoxClusterOwnerTeam.ts +487 -0
  15. package/Models/DatabaseModels/ProxmoxClusterOwnerUser.ts +486 -0
  16. package/Models/DatabaseModels/ProxmoxResource.ts +726 -0
  17. package/Models/DatabaseModels/ScheduledMaintenance.ts +110 -0
  18. package/Server/API/BillingInvoiceAPI.ts +47 -7
  19. package/Server/API/CephResourceAPI.ts +134 -0
  20. package/Server/API/DashboardAPI.ts +46 -0
  21. package/Server/API/ProjectAPI.ts +15 -0
  22. package/Server/API/ProxmoxResourceAPI.ts +132 -0
  23. package/Server/API/ResellerPlanAPI.ts +17 -0
  24. package/Server/Infrastructure/GlobalCache.ts +8 -2
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/1781500000000-AddProxmoxAndCephClusterTables.ts +163 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1781600000000-AddProxmoxCephV2Columns.ts +211 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1781600000001-AddProxmoxCephActivityAndRules.ts +590 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1781700000000-AddProxmoxCephV3Columns.ts +64 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  30. package/Server/Infrastructure/Redis.ts +40 -12
  31. package/Server/Services/AnalyticsDatabaseService.ts +1 -1
  32. package/Server/Services/BillingService.ts +109 -21
  33. package/Server/Services/CephClusterLabelRuleEngineService.ts +200 -0
  34. package/Server/Services/CephClusterLabelRuleService.ts +14 -0
  35. package/Server/Services/CephClusterOwnerRuleEngineService.ts +218 -0
  36. package/Server/Services/CephClusterOwnerRuleService.ts +14 -0
  37. package/Server/Services/CephClusterOwnerTeamService.ts +10 -0
  38. package/Server/Services/CephClusterOwnerUserService.ts +10 -0
  39. package/Server/Services/CephClusterService.ts +401 -0
  40. package/Server/Services/CephResourceService.ts +383 -0
  41. package/Server/Services/CloudResourceService.ts +11 -3
  42. package/Server/Services/DockerHostService.ts +11 -3
  43. package/Server/Services/ExceptionAggregationService.ts +2 -0
  44. package/Server/Services/HostService.ts +11 -3
  45. package/Server/Services/Index.ts +24 -0
  46. package/Server/Services/KubernetesClusterService.ts +11 -3
  47. package/Server/Services/LogAggregationService.ts +2 -0
  48. package/Server/Services/MetricAggregationService.ts +2 -0
  49. package/Server/Services/OpenTelemetryIngestService.ts +36 -0
  50. package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +204 -0
  51. package/Server/Services/ProxmoxClusterLabelRuleService.ts +14 -0
  52. package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +222 -0
  53. package/Server/Services/ProxmoxClusterOwnerRuleService.ts +14 -0
  54. package/Server/Services/ProxmoxClusterOwnerTeamService.ts +10 -0
  55. package/Server/Services/ProxmoxClusterOwnerUserService.ts +10 -0
  56. package/Server/Services/ProxmoxClusterService.ts +382 -0
  57. package/Server/Services/ProxmoxResourceService.ts +404 -0
  58. package/Server/Services/RumApplicationService.ts +11 -3
  59. package/Server/Services/ServerlessFunctionService.ts +11 -3
  60. package/Server/Services/TelemetryUsageBillingService.ts +41 -3
  61. package/Server/Services/TraceAggregationService.ts +2 -0
  62. package/Server/Types/AnalyticsDatabase/AggregateBy.ts +8 -23
  63. package/Server/Utils/Monitor/MonitorAlert.ts +45 -0
  64. package/Server/Utils/Monitor/MonitorClusterContext.ts +129 -0
  65. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +344 -4
  66. package/Server/Utils/Monitor/MonitorIncident.ts +130 -7
  67. package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +39 -6
  68. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +3 -1
  69. package/Server/Utils/Monitor/SeriesResourceLabels.ts +33 -0
  70. package/Server/Utils/Profiling.ts +37 -2
  71. package/Server/Utils/Telemetry/EntityRegistry.ts +4 -0
  72. package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +1096 -0
  73. package/Server/Utils/Telemetry/TelemetryEntity.ts +85 -0
  74. package/Server/Utils/Telemetry.ts +8 -19
  75. package/Tests/Server/API/BillingInvoiceAPI.test.ts +194 -0
  76. package/Tests/Server/API/ProjectAPI.test.ts +91 -0
  77. package/Tests/Server/API/ResellerPlanAPI.test.ts +207 -0
  78. package/Tests/Server/Infrastructure/GlobalCache.test.ts +100 -0
  79. package/Tests/Server/Services/BillingService.test.ts +323 -0
  80. package/Tests/Server/Services/CephResourceService.test.ts +264 -0
  81. package/Tests/Server/Services/ProxmoxResourceService.test.ts +326 -0
  82. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +322 -0
  83. package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +13 -0
  84. package/Tests/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.test.ts +879 -0
  85. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +196 -0
  86. package/Tests/Types/Monitor/CephAlertTemplates.test.ts +1231 -0
  87. package/Tests/Types/Monitor/ProxmoxAlertTemplates.test.ts +732 -0
  88. package/Tests/Utils/ModelImportExport.test.ts +366 -0
  89. package/Tests/Utils/Telemetry/EntityRelationship.test.ts +49 -0
  90. package/Tests/Utils/Telemetry/HeartbeatAvailability.test.ts +423 -0
  91. package/Types/BaseDatabase/AggregationIntervalUtil.ts +74 -0
  92. package/Types/Dashboard/DashboardComponentType.ts +4 -0
  93. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +2 -0
  94. package/Types/Dashboard/DashboardComponents/DashboardCephOsdListComponent.ts +15 -0
  95. package/Types/Dashboard/DashboardComponents/DashboardCephPoolListComponent.ts +14 -0
  96. package/Types/Dashboard/DashboardComponents/DashboardProxmoxGuestListComponent.ts +17 -0
  97. package/Types/Dashboard/DashboardComponents/DashboardProxmoxNodeListComponent.ts +16 -0
  98. package/Types/Dashboard/DashboardTemplates.ts +446 -0
  99. package/Types/Icon/IconProp.ts +2 -0
  100. package/Types/Monitor/CephAlertTemplates.ts +1647 -0
  101. package/Types/Monitor/CephMetricCatalog.ts +409 -0
  102. package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +44 -0
  103. package/Types/Monitor/MonitorStep.ts +64 -0
  104. package/Types/Monitor/MonitorStepCephMonitor.ts +57 -0
  105. package/Types/Monitor/MonitorStepProxmoxMonitor.ts +81 -0
  106. package/Types/Monitor/MonitorType.ts +29 -1
  107. package/Types/Monitor/ProxmoxAlertTemplates.ts +899 -0
  108. package/Types/Monitor/ProxmoxMetricCatalog.ts +382 -0
  109. package/Types/Permission.ts +464 -0
  110. package/Types/Telemetry/EntityType.ts +11 -0
  111. package/Types/Telemetry/ServiceType.ts +2 -0
  112. package/UI/Components/Icon/Icon.tsx +84 -0
  113. package/UI/Components/ImportExport/ExportModelCard.tsx +90 -0
  114. package/UI/Components/ImportExport/ImportModelsModal.tsx +239 -0
  115. package/UI/Components/ModelTable/ModelTable.tsx +294 -143
  116. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +9 -5
  117. package/UI/Utils/ModelImportExport.ts +207 -0
  118. package/UI/Utils/Telemetry/Telemetry.ts +16 -21
  119. package/UI/Utils/TelemetryService.ts +7 -3
  120. package/Utils/Dashboard/Components/DashboardCephOsdListComponent.ts +63 -0
  121. package/Utils/Dashboard/Components/DashboardCephPoolListComponent.ts +32 -0
  122. package/Utils/Dashboard/Components/DashboardCephResourceListShared.ts +61 -0
  123. package/Utils/Dashboard/Components/DashboardProxmoxGuestListComponent.ts +69 -0
  124. package/Utils/Dashboard/Components/DashboardProxmoxNodeListComponent.ts +55 -0
  125. package/Utils/Dashboard/Components/DashboardProxmoxResourceListShared.ts +61 -0
  126. package/Utils/Dashboard/Components/Index.ts +28 -0
  127. package/Utils/ModelImportExport.ts +369 -0
  128. package/Utils/Telemetry/EntityKey.ts +35 -0
  129. package/Utils/Telemetry/EntityRelationship.ts +6 -0
  130. package/Utils/Telemetry/HeartbeatAvailability.ts +262 -0
  131. package/build/dist/Models/DatabaseModels/Alert.js +108 -0
  132. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  133. package/build/dist/Models/DatabaseModels/CephCluster.js +992 -0
  134. package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -0
  135. package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js +522 -0
  136. package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js.map +1 -0
  137. package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js +603 -0
  138. package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js.map +1 -0
  139. package/build/dist/Models/DatabaseModels/CephClusterOwnerTeam.js +503 -0
  140. package/build/dist/Models/DatabaseModels/CephClusterOwnerTeam.js.map +1 -0
  141. package/build/dist/Models/DatabaseModels/CephClusterOwnerUser.js +502 -0
  142. package/build/dist/Models/DatabaseModels/CephClusterOwnerUser.js.map +1 -0
  143. package/build/dist/Models/DatabaseModels/CephResource.js +846 -0
  144. package/build/dist/Models/DatabaseModels/CephResource.js.map +1 -0
  145. package/build/dist/Models/DatabaseModels/Host.js +63 -0
  146. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  147. package/build/dist/Models/DatabaseModels/Incident.js +108 -0
  148. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  149. package/build/dist/Models/DatabaseModels/Index.js +24 -0
  150. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  151. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +967 -0
  152. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -0
  153. package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js +522 -0
  154. package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js.map +1 -0
  155. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js +603 -0
  156. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js.map +1 -0
  157. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerTeam.js +503 -0
  158. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerTeam.js.map +1 -0
  159. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerUser.js +502 -0
  160. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerUser.js.map +1 -0
  161. package/build/dist/Models/DatabaseModels/ProxmoxResource.js +761 -0
  162. package/build/dist/Models/DatabaseModels/ProxmoxResource.js.map +1 -0
  163. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +108 -0
  164. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  165. package/build/dist/Server/API/BillingInvoiceAPI.js +35 -5
  166. package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
  167. package/build/dist/Server/API/CephResourceAPI.js +98 -0
  168. package/build/dist/Server/API/CephResourceAPI.js.map +1 -0
  169. package/build/dist/Server/API/DashboardAPI.js +46 -0
  170. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  171. package/build/dist/Server/API/ProjectAPI.js +11 -0
  172. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  173. package/build/dist/Server/API/ProxmoxResourceAPI.js +95 -0
  174. package/build/dist/Server/API/ProxmoxResourceAPI.js.map +1 -0
  175. package/build/dist/Server/API/ResellerPlanAPI.js +17 -3
  176. package/build/dist/Server/API/ResellerPlanAPI.js.map +1 -1
  177. package/build/dist/Server/Infrastructure/GlobalCache.js +7 -2
  178. package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
  179. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781500000000-AddProxmoxAndCephClusterTables.js +76 -0
  180. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781500000000-AddProxmoxAndCephClusterTables.js.map +1 -0
  181. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000000-AddProxmoxCephV2Columns.js +108 -0
  182. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000000-AddProxmoxCephV2Columns.js.map +1 -0
  183. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000001-AddProxmoxCephActivityAndRules.js +253 -0
  184. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000001-AddProxmoxCephActivityAndRules.js.map +1 -0
  185. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781700000000-AddProxmoxCephV3Columns.js +43 -0
  186. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781700000000-AddProxmoxCephV3Columns.js.map +1 -0
  187. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  188. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  189. package/build/dist/Server/Infrastructure/Redis.js +31 -8
  190. package/build/dist/Server/Infrastructure/Redis.js.map +1 -1
  191. package/build/dist/Server/Services/AnalyticsDatabaseService.js +1 -1
  192. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  193. package/build/dist/Server/Services/BillingService.js +85 -23
  194. package/build/dist/Server/Services/BillingService.js.map +1 -1
  195. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +166 -0
  196. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -0
  197. package/build/dist/Server/Services/CephClusterLabelRuleService.js +13 -0
  198. package/build/dist/Server/Services/CephClusterLabelRuleService.js.map +1 -0
  199. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +186 -0
  200. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -0
  201. package/build/dist/Server/Services/CephClusterOwnerRuleService.js +13 -0
  202. package/build/dist/Server/Services/CephClusterOwnerRuleService.js.map +1 -0
  203. package/build/dist/Server/Services/CephClusterOwnerTeamService.js +9 -0
  204. package/build/dist/Server/Services/CephClusterOwnerTeamService.js.map +1 -0
  205. package/build/dist/Server/Services/CephClusterOwnerUserService.js +9 -0
  206. package/build/dist/Server/Services/CephClusterOwnerUserService.js.map +1 -0
  207. package/build/dist/Server/Services/CephClusterService.js +353 -0
  208. package/build/dist/Server/Services/CephClusterService.js.map +1 -0
  209. package/build/dist/Server/Services/CephResourceService.js +257 -0
  210. package/build/dist/Server/Services/CephResourceService.js.map +1 -0
  211. package/build/dist/Server/Services/CloudResourceService.js +10 -2
  212. package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
  213. package/build/dist/Server/Services/DockerHostService.js +10 -2
  214. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  215. package/build/dist/Server/Services/ExceptionAggregationService.js +2 -0
  216. package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
  217. package/build/dist/Server/Services/HostService.js +10 -2
  218. package/build/dist/Server/Services/HostService.js.map +1 -1
  219. package/build/dist/Server/Services/Index.js +24 -0
  220. package/build/dist/Server/Services/Index.js.map +1 -1
  221. package/build/dist/Server/Services/KubernetesClusterService.js +10 -2
  222. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  223. package/build/dist/Server/Services/LogAggregationService.js +2 -0
  224. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  225. package/build/dist/Server/Services/MetricAggregationService.js +2 -0
  226. package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
  227. package/build/dist/Server/Services/OpenTelemetryIngestService.js +37 -7
  228. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  229. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +166 -0
  230. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -0
  231. package/build/dist/Server/Services/ProxmoxClusterLabelRuleService.js +13 -0
  232. package/build/dist/Server/Services/ProxmoxClusterLabelRuleService.js.map +1 -0
  233. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +186 -0
  234. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -0
  235. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleService.js +13 -0
  236. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleService.js.map +1 -0
  237. package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js +9 -0
  238. package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js.map +1 -0
  239. package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js +9 -0
  240. package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js.map +1 -0
  241. package/build/dist/Server/Services/ProxmoxClusterService.js +337 -0
  242. package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -0
  243. package/build/dist/Server/Services/ProxmoxResourceService.js +285 -0
  244. package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -0
  245. package/build/dist/Server/Services/RumApplicationService.js +10 -2
  246. package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
  247. package/build/dist/Server/Services/ServerlessFunctionService.js +10 -2
  248. package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
  249. package/build/dist/Server/Services/TelemetryUsageBillingService.js +30 -3
  250. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  251. package/build/dist/Server/Services/TraceAggregationService.js +2 -0
  252. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  253. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +8 -25
  254. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
  255. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +36 -0
  256. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  257. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +90 -0
  258. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +1 -0
  259. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +228 -4
  260. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  261. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +103 -8
  262. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  263. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +23 -6
  264. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
  265. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +3 -1
  266. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  267. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +23 -0
  268. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  269. package/build/dist/Server/Utils/Profiling.js +24 -3
  270. package/build/dist/Server/Utils/Profiling.js.map +1 -1
  271. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +4 -0
  272. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  273. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +854 -0
  274. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -0
  275. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +62 -0
  276. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  277. package/build/dist/Server/Utils/Telemetry.js +8 -10
  278. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  279. package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js +69 -0
  280. package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js.map +1 -0
  281. package/build/dist/Types/Dashboard/DashboardComponentType.js +4 -0
  282. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  283. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +2 -0
  284. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  285. package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephOsdListComponent.js +2 -0
  286. package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephOsdListComponent.js.map +1 -0
  287. package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephPoolListComponent.js +2 -0
  288. package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephPoolListComponent.js.map +1 -0
  289. package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxGuestListComponent.js +2 -0
  290. package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxGuestListComponent.js.map +1 -0
  291. package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxNodeListComponent.js +2 -0
  292. package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxNodeListComponent.js.map +1 -0
  293. package/build/dist/Types/Dashboard/DashboardTemplates.js +394 -0
  294. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  295. package/build/dist/Types/Icon/IconProp.js +2 -0
  296. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  297. package/build/dist/Types/Monitor/CephAlertTemplates.js +1379 -0
  298. package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -0
  299. package/build/dist/Types/Monitor/CephMetricCatalog.js +353 -0
  300. package/build/dist/Types/Monitor/CephMetricCatalog.js.map +1 -0
  301. package/build/dist/Types/Monitor/MonitorStep.js +46 -0
  302. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  303. package/build/dist/Types/Monitor/MonitorStepCephMonitor.js +34 -0
  304. package/build/dist/Types/Monitor/MonitorStepCephMonitor.js.map +1 -0
  305. package/build/dist/Types/Monitor/MonitorStepProxmoxMonitor.js +36 -0
  306. package/build/dist/Types/Monitor/MonitorStepProxmoxMonitor.js.map +1 -0
  307. package/build/dist/Types/Monitor/MonitorType.js +27 -1
  308. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  309. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +743 -0
  310. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -0
  311. package/build/dist/Types/Monitor/ProxmoxMetricCatalog.js +320 -0
  312. package/build/dist/Types/Monitor/ProxmoxMetricCatalog.js.map +1 -0
  313. package/build/dist/Types/Permission.js +408 -0
  314. package/build/dist/Types/Permission.js.map +1 -1
  315. package/build/dist/Types/Telemetry/EntityType.js +11 -0
  316. package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
  317. package/build/dist/Types/Telemetry/ServiceType.js +2 -0
  318. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  319. package/build/dist/UI/Components/Icon/Icon.js +33 -0
  320. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  321. package/build/dist/UI/Components/ImportExport/ExportModelCard.js +50 -0
  322. package/build/dist/UI/Components/ImportExport/ExportModelCard.js.map +1 -0
  323. package/build/dist/UI/Components/ImportExport/ImportModelsModal.js +115 -0
  324. package/build/dist/UI/Components/ImportExport/ImportModelsModal.js.map +1 -0
  325. package/build/dist/UI/Components/ModelTable/ModelTable.js +166 -74
  326. package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
  327. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +5 -1
  328. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  329. package/build/dist/UI/Utils/ModelImportExport.js +142 -0
  330. package/build/dist/UI/Utils/ModelImportExport.js.map +1 -0
  331. package/build/dist/UI/Utils/Telemetry/Telemetry.js +11 -10
  332. package/build/dist/UI/Utils/Telemetry/Telemetry.js.map +1 -1
  333. package/build/dist/UI/Utils/TelemetryService.js +5 -2
  334. package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
  335. package/build/dist/Utils/Dashboard/Components/DashboardCephOsdListComponent.js +50 -0
  336. package/build/dist/Utils/Dashboard/Components/DashboardCephOsdListComponent.js.map +1 -0
  337. package/build/dist/Utils/Dashboard/Components/DashboardCephPoolListComponent.js +27 -0
  338. package/build/dist/Utils/Dashboard/Components/DashboardCephPoolListComponent.js.map +1 -0
  339. package/build/dist/Utils/Dashboard/Components/DashboardCephResourceListShared.js +46 -0
  340. package/build/dist/Utils/Dashboard/Components/DashboardCephResourceListShared.js.map +1 -0
  341. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxGuestListComponent.js +55 -0
  342. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxGuestListComponent.js.map +1 -0
  343. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxNodeListComponent.js +42 -0
  344. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxNodeListComponent.js.map +1 -0
  345. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxResourceListShared.js +46 -0
  346. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxResourceListShared.js.map +1 -0
  347. package/build/dist/Utils/Dashboard/Components/Index.js +16 -0
  348. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  349. package/build/dist/Utils/ModelImportExport.js +257 -0
  350. package/build/dist/Utils/ModelImportExport.js.map +1 -0
  351. package/build/dist/Utils/Telemetry/EntityKey.js +27 -0
  352. package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
  353. package/build/dist/Utils/Telemetry/EntityRelationship.js +3 -0
  354. package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
  355. package/build/dist/Utils/Telemetry/HeartbeatAvailability.js +174 -0
  356. package/build/dist/Utils/Telemetry/HeartbeatAvailability.js.map +1 -0
  357. package/package.json +29 -21
@@ -0,0 +1,366 @@
1
+ import Dashboard from "../../Models/DatabaseModels/Dashboard";
2
+ import Monitor from "../../Models/DatabaseModels/Monitor";
3
+ import ScheduledMaintenanceTemplate from "../../Models/DatabaseModels/ScheduledMaintenanceTemplate";
4
+ import StatusPage from "../../Models/DatabaseModels/StatusPage";
5
+ import EventInterval from "../../Types/Events/EventInterval";
6
+ import Recurring from "../../Types/Events/Recurring";
7
+ import BadDataException from "../../Types/Exception/BadDataException";
8
+ import { JSONObject } from "../../Types/JSON";
9
+ import ObjectID from "../../Types/ObjectID";
10
+ import PositiveNumber from "../../Types/PositiveNumber";
11
+ import ModelImportExport, {
12
+ MODEL_EXPORT_FILE_TYPE,
13
+ MODEL_EXPORT_SCHEMA_VERSION,
14
+ } from "../../Utils/ModelImportExport";
15
+ import { describe, expect, test } from "@jest/globals";
16
+
17
+ describe("ModelImportExport", () => {
18
+ describe("getImportExportableColumnNames", () => {
19
+ test("should include user-editable configuration columns for Dashboard", () => {
20
+ const columns: Array<string> =
21
+ ModelImportExport.getImportExportableColumnNames(Dashboard);
22
+
23
+ expect(columns).toContain("name");
24
+ expect(columns).toContain("description");
25
+ expect(columns).toContain("dashboardViewConfig");
26
+ });
27
+
28
+ test("should exclude server-controlled and system columns", () => {
29
+ const columns: Array<string> =
30
+ ModelImportExport.getImportExportableColumnNames(Dashboard);
31
+
32
+ expect(columns).not.toContain("_id");
33
+ expect(columns).not.toContain("createdAt");
34
+ expect(columns).not.toContain("updatedAt");
35
+ expect(columns).not.toContain("deletedAt");
36
+ expect(columns).not.toContain("version");
37
+ expect(columns).not.toContain("slug");
38
+ });
39
+
40
+ test("should exclude the tenant column", () => {
41
+ const columns: Array<string> =
42
+ ModelImportExport.getImportExportableColumnNames(Dashboard);
43
+
44
+ expect(columns).not.toContain("projectId");
45
+ });
46
+
47
+ test("should exclude entity relations and their foreign key columns", () => {
48
+ const columns: Array<string> =
49
+ ModelImportExport.getImportExportableColumnNames(Dashboard);
50
+
51
+ expect(columns).not.toContain("labels");
52
+ expect(columns).not.toContain("createdByUser");
53
+ expect(columns).not.toContain("createdByUserId");
54
+ expect(columns).not.toContain("deletedByUser");
55
+ expect(columns).not.toContain("deletedByUserId");
56
+ expect(columns).not.toContain("logoFile");
57
+ expect(columns).not.toContain("logoFileId");
58
+ });
59
+
60
+ test("should include monitor configuration columns", () => {
61
+ const columns: Array<string> =
62
+ ModelImportExport.getImportExportableColumnNames(Monitor);
63
+
64
+ expect(columns).toContain("name");
65
+ expect(columns).toContain("monitorType");
66
+ expect(columns).toContain("monitorSteps");
67
+ expect(columns).not.toContain("currentMonitorStatusId");
68
+ expect(columns).not.toContain("projectId");
69
+ expect(columns).not.toContain("slug");
70
+ });
71
+
72
+ test("should exclude status page foreign keys and relations", () => {
73
+ const columns: Array<string> =
74
+ ModelImportExport.getImportExportableColumnNames(StatusPage);
75
+
76
+ expect(columns).toContain("name");
77
+ expect(columns).not.toContain("projectId");
78
+ expect(columns).not.toContain("labels");
79
+ expect(columns).not.toContain("faviconFileId");
80
+ });
81
+
82
+ test("should exclude plain-text credentials via the per-table exclusion list", () => {
83
+ const columns: Array<string> =
84
+ ModelImportExport.getImportExportableColumnNames(StatusPage);
85
+
86
+ expect(columns).not.toContain("embeddedOverallStatusToken");
87
+ });
88
+
89
+ test("should exclude monitor runtime-state columns", () => {
90
+ const columns: Array<string> =
91
+ ModelImportExport.getImportExportableColumnNames(Monitor);
92
+
93
+ expect(columns).not.toContain("incomingMonitorRequest");
94
+ expect(columns).not.toContain("serverMonitorResponse");
95
+ expect(columns).not.toContain("incomingRequestMonitorHeartbeatCheckedAt");
96
+ expect(columns).not.toContain("serverMonitorRequestReceivedAt");
97
+ expect(columns).not.toContain("telemetryMonitorNextMonitorAt");
98
+ expect(columns).not.toContain("telemetryMonitorLastMonitorAt");
99
+ });
100
+ });
101
+
102
+ describe("getImportExportSelect", () => {
103
+ test("should build a select object from exportable columns", () => {
104
+ const select: JSONObject = ModelImportExport.getImportExportSelect(
105
+ Dashboard,
106
+ ) as JSONObject;
107
+
108
+ expect(select["name"]).toBe(true);
109
+ expect(select["dashboardViewConfig"]).toBe(true);
110
+ expect(select["_id"]).toBeUndefined();
111
+ expect(select["projectId"]).toBeUndefined();
112
+ });
113
+ });
114
+
115
+ describe("buildExportEnvelope and toExportJSON", () => {
116
+ test("should build a valid envelope and strip non-exportable columns", () => {
117
+ const dashboard: Dashboard = new Dashboard();
118
+ dashboard.name = "My Dashboard";
119
+ dashboard.description = "My Description";
120
+ dashboard._id = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa";
121
+ dashboard.projectId = new ObjectID(
122
+ "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
123
+ );
124
+
125
+ const envelope: JSONObject = ModelImportExport.buildExportEnvelope({
126
+ modelType: Dashboard,
127
+ items: [dashboard],
128
+ exportedAt: new Date("2026-06-11T00:00:00.000Z"),
129
+ });
130
+
131
+ expect(envelope["fileType"]).toBe(MODEL_EXPORT_FILE_TYPE);
132
+ expect(envelope["schemaVersion"]).toBe(MODEL_EXPORT_SCHEMA_VERSION);
133
+ expect(envelope["resourceType"]).toBe(new Dashboard().tableName);
134
+ expect(envelope["exportedAt"]).toBe("2026-06-11T00:00:00.000Z");
135
+
136
+ const items: Array<JSONObject> = envelope["items"] as Array<JSONObject>;
137
+ expect(items).toHaveLength(1);
138
+ expect(items[0]!["name"]).toBe("My Dashboard");
139
+ expect(items[0]!["description"]).toBe("My Description");
140
+ expect(items[0]!["_id"]).toBeUndefined();
141
+ expect(items[0]!["projectId"]).toBeUndefined();
142
+ });
143
+ });
144
+
145
+ describe("parseImportPayload", () => {
146
+ test("should accept a valid envelope", () => {
147
+ const items: Array<JSONObject> = ModelImportExport.parseImportPayload({
148
+ modelType: Dashboard,
149
+ payload: {
150
+ fileType: MODEL_EXPORT_FILE_TYPE,
151
+ schemaVersion: MODEL_EXPORT_SCHEMA_VERSION,
152
+ resourceType: new Dashboard().tableName!,
153
+ items: [{ name: "Imported Dashboard" }],
154
+ },
155
+ });
156
+
157
+ expect(items).toHaveLength(1);
158
+ expect(items[0]!["name"]).toBe("Imported Dashboard");
159
+ });
160
+
161
+ test("should accept a plain array of items", () => {
162
+ const items: Array<JSONObject> = ModelImportExport.parseImportPayload({
163
+ modelType: Dashboard,
164
+ payload: [{ name: "One" }, { name: "Two" }],
165
+ });
166
+
167
+ expect(items).toHaveLength(2);
168
+ });
169
+
170
+ test("should accept a single bare item object", () => {
171
+ const items: Array<JSONObject> = ModelImportExport.parseImportPayload({
172
+ modelType: Dashboard,
173
+ payload: { name: "Only One" },
174
+ });
175
+
176
+ expect(items).toHaveLength(1);
177
+ });
178
+
179
+ test("should reject an envelope for a different resource type", () => {
180
+ expect(() => {
181
+ ModelImportExport.parseImportPayload({
182
+ modelType: Dashboard,
183
+ payload: {
184
+ fileType: MODEL_EXPORT_FILE_TYPE,
185
+ resourceType: new Monitor().tableName!,
186
+ items: [{ name: "A Monitor" }],
187
+ },
188
+ });
189
+ }).toThrow(BadDataException);
190
+ });
191
+
192
+ test("should reject an envelope with no items", () => {
193
+ expect(() => {
194
+ ModelImportExport.parseImportPayload({
195
+ modelType: Dashboard,
196
+ payload: {
197
+ fileType: MODEL_EXPORT_FILE_TYPE,
198
+ resourceType: new Dashboard().tableName!,
199
+ items: [],
200
+ },
201
+ });
202
+ }).toThrow(BadDataException);
203
+ });
204
+
205
+ test("should reject items that are not objects", () => {
206
+ expect(() => {
207
+ ModelImportExport.parseImportPayload({
208
+ modelType: Dashboard,
209
+ payload: ["not-an-object"] as any,
210
+ });
211
+ }).toThrow(BadDataException);
212
+ });
213
+ });
214
+
215
+ describe("fromImportJSON", () => {
216
+ test("should build a model with only importable columns", () => {
217
+ const item: Dashboard = ModelImportExport.fromImportJSON({
218
+ json: {
219
+ _id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
220
+ id: "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
221
+ slug: "my-dashboard",
222
+ projectId: "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb",
223
+ createdAt: "2026-01-01T00:00:00.000Z",
224
+ name: "My Dashboard",
225
+ description: "My Description",
226
+ dashboardViewConfig: { components: [], heightInDashboardUnits: 60 },
227
+ unknownColumn: "should be dropped",
228
+ },
229
+ modelType: Dashboard,
230
+ });
231
+
232
+ expect(item.name).toBe("My Dashboard");
233
+ expect(item.description).toBe("My Description");
234
+ expect(item.dashboardViewConfig).toBeDefined();
235
+ expect(item._id).toBeUndefined();
236
+ expect(item.projectId).toBeUndefined();
237
+ expect(item.slug).toBeUndefined();
238
+ expect(item.createdAt).toBeUndefined();
239
+ expect((item as any)["unknownColumn"]).toBeUndefined();
240
+ });
241
+
242
+ test("should round-trip an exported dashboard back into a creatable model", () => {
243
+ const original: Dashboard = new Dashboard();
244
+ original.name = "Round Trip";
245
+ original.description = "Round trip description";
246
+
247
+ const envelope: JSONObject = ModelImportExport.buildExportEnvelope({
248
+ modelType: Dashboard,
249
+ items: [original],
250
+ exportedAt: new Date(),
251
+ });
252
+
253
+ const itemJsons: Array<JSONObject> = ModelImportExport.parseImportPayload(
254
+ {
255
+ modelType: Dashboard,
256
+ payload: envelope,
257
+ },
258
+ );
259
+
260
+ const imported: Dashboard = ModelImportExport.fromImportJSON({
261
+ json: itemJsons[0]!,
262
+ modelType: Dashboard,
263
+ });
264
+
265
+ expect(imported.name).toBe("Round Trip");
266
+ expect(imported.description).toBe("Round trip description");
267
+ expect(imported._id).toBeUndefined();
268
+ });
269
+
270
+ test("should advance past recurring dates for scheduled maintenance templates", () => {
271
+ const dayInMs: number = 24 * 60 * 60 * 1000;
272
+
273
+ const template: ScheduledMaintenanceTemplate =
274
+ new ScheduledMaintenanceTemplate();
275
+ template.templateName = "Weekly Maintenance";
276
+ template.isRecurringEvent = true;
277
+
278
+ const recurring: Recurring = new Recurring();
279
+ recurring.intervalType = EventInterval.Week;
280
+ recurring.intervalCount = new PositiveNumber(1);
281
+ template.recurringInterval = recurring;
282
+
283
+ const pastScheduledAt: Date = new Date(Date.now() - 30 * dayInMs);
284
+ const pastStartsAt: Date = new Date(Date.now() - 29 * dayInMs);
285
+ const pastEndsAt: Date = new Date(
286
+ pastStartsAt.getTime() + 2 * 60 * 60 * 1000,
287
+ );
288
+
289
+ template.firstEventScheduledAt = pastScheduledAt;
290
+ template.firstEventStartsAt = pastStartsAt;
291
+ template.firstEventEndsAt = pastEndsAt;
292
+
293
+ const envelope: JSONObject = ModelImportExport.buildExportEnvelope({
294
+ modelType: ScheduledMaintenanceTemplate,
295
+ items: [template],
296
+ exportedAt: new Date(),
297
+ });
298
+
299
+ const itemJsons: Array<JSONObject> = ModelImportExport.parseImportPayload(
300
+ {
301
+ modelType: ScheduledMaintenanceTemplate,
302
+ payload: envelope,
303
+ },
304
+ );
305
+
306
+ const imported: ScheduledMaintenanceTemplate =
307
+ ModelImportExport.fromImportJSON({
308
+ json: itemJsons[0]!,
309
+ modelType: ScheduledMaintenanceTemplate,
310
+ });
311
+
312
+ expect(imported.firstEventScheduledAt!.getTime()).toBeGreaterThan(
313
+ Date.now(),
314
+ );
315
+ expect(imported.firstEventStartsAt!.getTime()).toBeGreaterThan(
316
+ Date.now(),
317
+ );
318
+ expect(imported.firstEventEndsAt!.getTime()).toBeGreaterThan(Date.now());
319
+
320
+ // offsets between the dates are preserved.
321
+ expect(
322
+ imported.firstEventStartsAt!.getTime() -
323
+ imported.firstEventScheduledAt!.getTime(),
324
+ ).toBe(pastStartsAt.getTime() - pastScheduledAt.getTime());
325
+ expect(
326
+ imported.firstEventEndsAt!.getTime() -
327
+ imported.firstEventStartsAt!.getTime(),
328
+ ).toBe(pastEndsAt.getTime() - pastStartsAt.getTime());
329
+ });
330
+
331
+ test("should leave future recurring dates unchanged", () => {
332
+ const dayInMs: number = 24 * 60 * 60 * 1000;
333
+
334
+ const template: ScheduledMaintenanceTemplate =
335
+ new ScheduledMaintenanceTemplate();
336
+ template.templateName = "Future Maintenance";
337
+ template.isRecurringEvent = true;
338
+
339
+ const recurring: Recurring = new Recurring();
340
+ recurring.intervalType = EventInterval.Day;
341
+ recurring.intervalCount = new PositiveNumber(1);
342
+ template.recurringInterval = recurring;
343
+
344
+ const futureScheduledAt: Date = new Date(Date.now() + 10 * dayInMs);
345
+ template.firstEventScheduledAt = futureScheduledAt;
346
+ template.firstEventStartsAt = new Date(Date.now() + 11 * dayInMs);
347
+ template.firstEventEndsAt = new Date(Date.now() + 12 * dayInMs);
348
+
349
+ const envelope: JSONObject = ModelImportExport.buildExportEnvelope({
350
+ modelType: ScheduledMaintenanceTemplate,
351
+ items: [template],
352
+ exportedAt: new Date(),
353
+ });
354
+
355
+ const imported: ScheduledMaintenanceTemplate =
356
+ ModelImportExport.fromImportJSON({
357
+ json: (envelope["items"] as Array<JSONObject>)[0]!,
358
+ modelType: ScheduledMaintenanceTemplate,
359
+ });
360
+
361
+ expect(imported.firstEventScheduledAt!.getTime()).toBe(
362
+ futureScheduledAt.getTime(),
363
+ );
364
+ });
365
+ });
366
+ });
@@ -32,6 +32,18 @@ describe("inferRelationshipType", () => {
32
32
  ).toBe(EntityRelationshipType.InstanceOf);
33
33
  });
34
34
 
35
+ test("infers the proxmox topology (node → cluster, guest → node/cluster)", () => {
36
+ expect(
37
+ inferRelationshipType(EntityType.ProxmoxNode, EntityType.ProxmoxCluster),
38
+ ).toBe(EntityRelationshipType.MemberOf);
39
+ expect(
40
+ inferRelationshipType(EntityType.ProxmoxGuest, EntityType.ProxmoxNode),
41
+ ).toBe(EntityRelationshipType.RunsOn);
42
+ expect(
43
+ inferRelationshipType(EntityType.ProxmoxGuest, EntityType.ProxmoxCluster),
44
+ ).toBe(EntityRelationshipType.MemberOf);
45
+ });
46
+
35
47
  test("is directional (the reverse pair yields nothing)", () => {
36
48
  expect(
37
49
  inferRelationshipType(
@@ -42,6 +54,9 @@ describe("inferRelationshipType", () => {
42
54
  expect(
43
55
  inferRelationshipType(EntityType.Host, EntityType.Service),
44
56
  ).toBeNull();
57
+ expect(
58
+ inferRelationshipType(EntityType.ProxmoxCluster, EntityType.ProxmoxNode),
59
+ ).toBeNull();
45
60
  });
46
61
 
47
62
  test("unrelated or self type pairs yield null", () => {
@@ -51,6 +66,17 @@ describe("inferRelationshipType", () => {
51
66
  expect(
52
67
  inferRelationshipType(EntityType.Service, EntityType.Service),
53
68
  ).toBeNull();
69
+ /*
70
+ * Deliberately absent (mirrors the missing host|k8s.cluster rule): a
71
+ * resource carrying both host.* and proxmox/ceph cluster attributes
72
+ * does not imply the host is a member of that cluster.
73
+ */
74
+ expect(
75
+ inferRelationshipType(EntityType.Host, EntityType.ProxmoxCluster),
76
+ ).toBeNull();
77
+ expect(
78
+ inferRelationshipType(EntityType.Host, EntityType.CephCluster),
79
+ ).toBeNull();
54
80
  });
55
81
 
56
82
  test("depends-on is never inferred from co-occurrence (span-derived only)", () => {
@@ -127,6 +153,29 @@ describe("deriveRelationships", () => {
127
153
  );
128
154
  });
129
155
 
156
+ test("derives the full directed edge set for a proxmox resource", () => {
157
+ const edges: Array<EntityRelationshipEdge> = deriveRelationships([
158
+ { entityType: EntityType.ProxmoxCluster, entityKey: "cluster" },
159
+ { entityType: EntityType.ProxmoxNode, entityKey: "node" },
160
+ { entityType: EntityType.ProxmoxGuest, entityKey: "guest" },
161
+ ]);
162
+
163
+ expect(
164
+ hasEdge(edges, "node", "cluster", EntityRelationshipType.MemberOf),
165
+ ).toBe(true);
166
+ expect(hasEdge(edges, "guest", "node", EntityRelationshipType.RunsOn)).toBe(
167
+ true,
168
+ );
169
+ expect(
170
+ hasEdge(edges, "guest", "cluster", EntityRelationshipType.MemberOf),
171
+ ).toBe(true);
172
+ // No reverse edge.
173
+ expect(
174
+ hasEdge(edges, "cluster", "node", EntityRelationshipType.MemberOf),
175
+ ).toBe(false);
176
+ expect(edges.length).toBe(3);
177
+ });
178
+
130
179
  test("empty / single-entity sets produce no edges", () => {
131
180
  expect(deriveRelationships([])).toEqual([]);
132
181
  expect(