@oneuptime/common 12.0.8 → 12.0.9

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 (769) hide show
  1. package/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +1 -1
  2. package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +1 -1
  3. package/Models/DatabaseModels/AIConversation.ts +32 -0
  4. package/Models/DatabaseModels/AIConversationMessage.ts +41 -0
  5. package/Models/DatabaseModels/AlertEpisodeMember.ts +27 -0
  6. package/Models/DatabaseModels/IncidentEpisodeMember.ts +28 -0
  7. package/Models/DatabaseModels/Index.ts +12 -4
  8. package/Models/DatabaseModels/{TelemetryEntity.ts → InventoryItem.ts} +139 -9
  9. package/Models/DatabaseModels/InventoryItemCustomField.ts +434 -0
  10. package/Models/DatabaseModels/{TelemetryEntityRelationship.ts → InventoryItemRelationship.ts} +8 -8
  11. package/Models/DatabaseModels/NetworkDevice.ts +141 -0
  12. package/Models/DatabaseModels/NetworkDeviceLink.ts +699 -0
  13. package/Models/DatabaseModels/NetworkDeviceLinkRule.ts +467 -0
  14. package/Models/DatabaseModels/NetworkTopologySuppression.ts +429 -0
  15. package/Models/DatabaseModels/OnCallDutyPolicyFeed.ts +9 -0
  16. package/Models/DatabaseModels/Project.ts +78 -0
  17. package/Models/DatabaseModels/UserCall.ts +42 -0
  18. package/Models/DatabaseModels/UserEmail.ts +44 -0
  19. package/Models/DatabaseModels/UserNotificationRule.ts +425 -55
  20. package/Models/DatabaseModels/UserOnCallLogTimeline.ts +24 -2
  21. package/Models/DatabaseModels/UserPush.ts +49 -0
  22. package/Models/DatabaseModels/UserSMS.ts +43 -0
  23. package/Models/DatabaseModels/UserTelegram.ts +59 -0
  24. package/Models/DatabaseModels/UserWebhook.ts +52 -0
  25. package/Models/DatabaseModels/UserWhatsApp.ts +41 -0
  26. package/Models/DatabaseModels/WorkflowVariable.ts +12 -0
  27. package/Server/API/AIChatAPI.ts +315 -1
  28. package/Server/API/DashboardAPI.ts +217 -1
  29. package/Server/API/OnCallReadinessAPI.ts +841 -0
  30. package/Server/API/TeamComplianceAPI.ts +69 -17
  31. package/Server/API/TelemetryAPI.ts +220 -12
  32. package/Server/EnvironmentConfig.ts +52 -0
  33. package/Server/Infrastructure/Postgres/DataSourceOptions.ts +22 -0
  34. package/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.ts +4 -4
  35. package/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.ts +5 -5
  36. package/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.ts +35 -0
  37. package/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.ts +82 -0
  38. package/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.ts +91 -0
  39. package/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.ts +47 -0
  40. package/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.ts +255 -0
  41. package/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.ts +107 -0
  42. package/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.ts +90 -0
  43. package/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.ts +39 -0
  44. package/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.ts +33 -0
  45. package/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.ts +59 -0
  46. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +20 -0
  47. package/Server/Infrastructure/Queue.ts +78 -13
  48. package/Server/Middleware/PublicDashboardRateLimit.ts +593 -0
  49. package/Server/Services/AIService.ts +7 -0
  50. package/Server/Services/AlertEpisodeStateTimelineService.ts +29 -0
  51. package/Server/Services/AlertSeverityService.ts +63 -0
  52. package/Server/Services/DashboardService.ts +9 -10
  53. package/Server/Services/DatabaseService.ts +32 -2
  54. package/Server/Services/IncidentEpisodeStateTimelineService.ts +29 -0
  55. package/Server/Services/IncidentSeverityService.ts +76 -0
  56. package/Server/Services/Index.ts +12 -4
  57. package/Server/Services/InventoryItemCustomFieldService.ts +9 -0
  58. package/Server/Services/{TelemetryEntityRelationshipService.ts → InventoryItemRelationshipService.ts} +4 -4
  59. package/Server/Services/{TelemetryEntityService.ts → InventoryItemService.ts} +89 -20
  60. package/Server/Services/LogAggregationService.ts +45 -8
  61. package/Server/Services/MetricAggregationService.ts +121 -0
  62. package/Server/Services/MetricService.ts +7 -7
  63. package/Server/Services/NetworkDeviceLinkRuleService.ts +10 -0
  64. package/Server/Services/NetworkDeviceLinkService.ts +84 -0
  65. package/Server/Services/NetworkDeviceService.ts +140 -0
  66. package/Server/Services/NetworkSiteService.ts +77 -25
  67. package/Server/Services/NetworkTopologySuppressionService.ts +84 -0
  68. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +41 -29
  69. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +8 -0
  70. package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +62 -13
  71. package/Server/Services/OnCallDutyPolicyScheduleService.ts +61 -1
  72. package/Server/Services/OnCallNotificationAlertingService.ts +742 -0
  73. package/Server/Services/OnCallReadinessService.ts +2803 -0
  74. package/Server/Services/OnCallSetupReminderService.ts +955 -0
  75. package/Server/Services/ProfileAggregationService.ts +123 -0
  76. package/Server/Services/StatusPageService.ts +9 -10
  77. package/Server/Services/TeamComplianceService.ts +429 -252
  78. package/Server/Services/UserCallService.ts +26 -1
  79. package/Server/Services/UserEmailService.ts +26 -1
  80. package/Server/Services/UserNotificationRuleAdminService.ts +1183 -0
  81. package/Server/Services/UserNotificationRuleService.ts +3812 -333
  82. package/Server/Services/UserOnCallLogService.ts +561 -48
  83. package/Server/Services/UserPushService.ts +29 -0
  84. package/Server/Services/UserService.ts +11 -0
  85. package/Server/Services/UserSmsService.ts +26 -1
  86. package/Server/Services/UserTelegramService.ts +24 -1
  87. package/Server/Services/UserWebhookService.ts +28 -1
  88. package/Server/Services/UserWhatsAppService.ts +24 -1
  89. package/Server/Types/Database/Permissions/BasePermission.ts +19 -0
  90. package/Server/Types/Database/Permissions/CreatePermission.ts +164 -0
  91. package/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.ts +340 -0
  92. package/Server/Types/Database/Permissions/QueryPermission.ts +48 -0
  93. package/Server/Types/Database/Permissions/TenantPermission.ts +8 -1
  94. package/Server/Types/Workflow/Components/API/Delete.ts +1 -1
  95. package/Server/Types/Workflow/Components/API/Get.ts +1 -1
  96. package/Server/Types/Workflow/Components/API/Patch.ts +1 -1
  97. package/Server/Types/Workflow/Components/API/Post.ts +1 -1
  98. package/Server/Types/Workflow/Components/API/Put.ts +1 -1
  99. package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +29 -5
  100. package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +18 -10
  101. package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +55 -0
  102. package/Server/Types/Workflow/Components/Conditions/IfElse.ts +3 -17
  103. package/Server/Types/Workflow/Components/Email.ts +25 -7
  104. package/Server/Types/Workflow/Components/JavaScript.ts +10 -3
  105. package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +1 -1
  106. package/Server/Utils/AI/Chat/ChatAgentRunner.ts +643 -48
  107. package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +32 -3
  108. package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +20 -6
  109. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +7 -0
  110. package/Server/Utils/AI/Toolbox/AIActionTools.ts +2 -2
  111. package/Server/Utils/AI/Toolbox/AIMetaTools.ts +863 -0
  112. package/Server/Utils/AI/Toolbox/AlertTools.ts +177 -15
  113. package/Server/Utils/AI/Toolbox/IncidentTools.ts +191 -10
  114. package/Server/Utils/AI/Toolbox/Index.ts +48 -0
  115. package/Server/Utils/AI/Toolbox/MonitorTools.ts +298 -11
  116. package/Server/Utils/AI/Toolbox/NoteWriteTools.ts +295 -0
  117. package/Server/Utils/AI/Toolbox/OnCallTools.ts +1246 -0
  118. package/Server/Utils/AI/Toolbox/RunbookTools.ts +424 -0
  119. package/Server/Utils/AI/Toolbox/SloTools.ts +456 -0
  120. package/Server/Utils/AI/Toolbox/StatusPageTools.ts +559 -0
  121. package/Server/Utils/AI/Toolbox/TeamTools.ts +327 -0
  122. package/Server/Utils/AI/Toolbox/TimelineTools.ts +615 -0
  123. package/Server/Utils/AI/Toolbox/WorkflowProbeTools.ts +664 -0
  124. package/Server/Utils/ClientIp.ts +221 -0
  125. package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +47 -0
  126. package/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.ts +163 -0
  127. package/Server/Utils/Dashboard/PublicDashboardSloWidget.ts +147 -0
  128. package/Server/Utils/Express.ts +12 -17
  129. package/Server/Utils/LLM/LLMService.ts +85 -8
  130. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +204 -10
  131. package/Server/Utils/SSRFProtection.ts +98 -23
  132. package/Server/Utils/StartServer.ts +12 -3
  133. package/Server/Utils/Telemetry/EntityRegistry.ts +205 -18
  134. package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +25 -25
  135. package/Server/Utils/Telemetry/TelemetryEntity.ts +160 -52
  136. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +7 -3
  137. package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +2146 -0
  138. package/Tests/App/Dashboard/CreateWorkflowModal.test.tsx +561 -0
  139. package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +2470 -0
  140. package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +1897 -0
  141. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +3606 -0
  142. package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +784 -0
  143. package/Tests/App/Dashboard/OnCallRulesTable.test.tsx +1119 -0
  144. package/Tests/App/Dashboard/SloWidgetFetching.test.tsx +531 -0
  145. package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +1312 -0
  146. package/Tests/App/Dashboard/UserSettingsSetupChecklistPage.test.tsx +1390 -0
  147. package/Tests/Models/InventoryItemModel.test.ts +174 -0
  148. package/Tests/Models/InventoryItemNaming.test.ts +302 -0
  149. package/Tests/Server/API/AIChatCancelAndFeedback.test.ts +437 -0
  150. package/Tests/Server/API/DashboardPublicRateLimit.test.ts +659 -0
  151. package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +18 -0
  152. package/Tests/Server/API/DashboardPublicSloAPI.test.ts +880 -0
  153. package/Tests/Server/API/Helpers.ts +24 -15
  154. package/Tests/Server/API/OnCallReadinessAPI.test.ts +2680 -0
  155. package/Tests/Server/API/OnCallSetupReminderAPI.test.ts +915 -0
  156. package/Tests/Server/Infrastructure/Postgres/EpisodeMemberNotifyIndexesMigration.test.ts +533 -0
  157. package/Tests/Server/Infrastructure/Postgres/InventoryItemArchiveMigration.test.ts +213 -0
  158. package/Tests/Server/Infrastructure/Postgres/RenameInventoryItemMigration.test.ts +432 -0
  159. package/Tests/Server/Infrastructure/Queue.test.ts +293 -0
  160. package/Tests/Server/Middleware/PublicDashboardRateLimit.test.ts +1645 -0
  161. package/Tests/Server/Services/AdminRuleEditGuards.test.ts +2848 -0
  162. package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1393 -0
  163. package/Tests/Server/Services/EpisodeRuleSeverityRepair.test.ts +1802 -0
  164. package/Tests/Server/Services/EpisodeStateTimelineNote.test.ts +304 -0
  165. package/Tests/Server/Services/InventoryItemDisplayName.test.ts +339 -0
  166. package/Tests/Server/Services/{TelemetryEntityManualCreate.test.ts → InventoryItemManualCreate.test.ts} +27 -27
  167. package/Tests/Server/Services/IpAllowlistSpoofing.test.ts +450 -0
  168. package/Tests/Server/Services/LogAggregationService.test.ts +235 -1
  169. package/Tests/Server/Services/MetricAggregationService.test.ts +231 -0
  170. package/Tests/Server/Services/MetricEntityMVKeyParity.test.ts +80 -29
  171. package/Tests/Server/Services/MetricServiceAggregate.test.ts +30 -30
  172. package/Tests/Server/Services/NetworkSiteService.test.ts +18 -3
  173. package/Tests/Server/Services/NotificationChannelEventCoverage.test.ts +1728 -0
  174. package/Tests/Server/Services/NotificationDeletionImpact.test.ts +2402 -0
  175. package/Tests/Server/Services/OnCallDutyPolicyExecutionLogTimelineGapFeed.test.ts +394 -0
  176. package/Tests/Server/Services/OnCallNotificationFallback.test.ts +1744 -0
  177. package/Tests/Server/Services/OnCallReadinessService.test.ts +4295 -0
  178. package/Tests/Server/Services/OnCallSetupReminder.test.ts +1272 -0
  179. package/Tests/Server/Services/OnCallWeeklyReadinessDigest.test.ts +1021 -0
  180. package/Tests/Server/Services/ProfileAggregationService.test.ts +296 -0
  181. package/Tests/Server/Services/SeverityCreationRuleBackfill.test.ts +1536 -0
  182. package/Tests/Server/Services/SeverityRuleBackfill.test.ts +1818 -0
  183. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +1845 -0
  184. package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +1394 -0
  185. package/Tests/Server/Services/UserNotificationRuleDefaultCreation.test.ts +1166 -0
  186. package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1468 -0
  187. package/Tests/Server/Services/UserOnCallLogNoNotificationRules.test.ts +1457 -0
  188. package/Tests/Server/Types/Database/Permissions/AdminNotificationRuleAccess.test.ts +1546 -0
  189. package/Tests/Server/Types/Database/Permissions/CreateOwnershipScoping.test.ts +529 -0
  190. package/Tests/Server/Types/Database/Permissions/OwnerOnlyColumns.test.ts +1219 -0
  191. package/Tests/Server/Types/Database/Permissions/UserNotificationRuleScoping.test.ts +1089 -0
  192. package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +2 -1
  193. package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +190 -0
  194. package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +44 -14
  195. package/Tests/Server/Types/Workflow/Components/Email.test.ts +151 -0
  196. package/Tests/Server/Types/Workflow/Components/IfElse.test.ts +98 -0
  197. package/Tests/Server/Types/Workflow/Components/JavaScript.test.ts +51 -0
  198. package/Tests/Server/Utils/AI/AIMetaTools.test.ts +586 -0
  199. package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +582 -0
  200. package/Tests/Server/Utils/AI/ChatAgentRunner.test.ts +726 -0
  201. package/Tests/Server/Utils/AI/IncidentToolsFilters.test.ts +315 -0
  202. package/Tests/Server/Utils/AI/LLMServiceStopReason.test.ts +314 -0
  203. package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +26 -3
  204. package/Tests/Server/Utils/AI/NoteWriteTools.test.ts +268 -0
  205. package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +169 -0
  206. package/Tests/Server/Utils/AI/OnCallTools.test.ts +664 -0
  207. package/Tests/Server/Utils/AI/RunbookTools.test.ts +325 -0
  208. package/Tests/Server/Utils/AI/SloTools.test.ts +306 -0
  209. package/Tests/Server/Utils/AI/StatusPageTools.test.ts +391 -0
  210. package/Tests/Server/Utils/AI/TeamTools.test.ts +257 -0
  211. package/Tests/Server/Utils/AI/TimelineTools.test.ts +472 -0
  212. package/Tests/Server/Utils/AI/WorkflowProbeTools.test.ts +428 -0
  213. package/Tests/Server/Utils/ClientIp.test.ts +438 -0
  214. package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +171 -0
  215. package/Tests/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.test.ts +383 -0
  216. package/Tests/Server/Utils/EntityRegistryRowFence.test.ts +23 -25
  217. package/Tests/Server/Utils/MicrosoftTeamsWebhookUrlValidation.test.ts +6 -0
  218. package/Tests/Server/Utils/Monitor/Criteria/DnssecMonitorCriteria.test.ts +307 -0
  219. package/Tests/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.test.ts +468 -0
  220. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorTelemetryDeepLinks.test.ts +460 -0
  221. package/Tests/Server/Utils/ResponseRateLimitStatusCodes.test.ts +137 -0
  222. package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +40 -8
  223. package/Tests/Server/Utils/SSRFProtectionUserInfo.test.ts +351 -0
  224. package/Tests/Server/Utils/Telemetry/EntityRegistryRetirement.test.ts +531 -0
  225. package/Tests/Server/Utils/Telemetry/InventoryEntityRegistry.test.ts +15 -15
  226. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +356 -39
  227. package/Tests/Types/IP/IP.test.ts +263 -0
  228. package/Tests/Types/IP/IPWhitelist.test.ts +197 -0
  229. package/Tests/Types/IP/IPv6.test.ts +12 -1
  230. package/Tests/Types/Monitor/SnmpOid.test.ts +64 -0
  231. package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +110 -0
  232. package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeAudit.test.ts +106 -0
  233. package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeDifferential.test.ts +511 -0
  234. package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageEndToEnd.test.ts +489 -0
  235. package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageGapTolerance.test.ts +479 -0
  236. package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageState.test.ts +822 -0
  237. package/Tests/Types/Telemetry/EntityTypeGroups.test.ts +6 -6
  238. package/Tests/Types/Workflow/BaseModelComponents.test.ts +429 -0
  239. package/Tests/Types/Workflow/Components/BaseModel.test.ts +225 -0
  240. package/Tests/Types/Workflow/IntegrationCredentialMetadata.test.ts +100 -0
  241. package/Tests/Types/Workflow/TemplateSyntax.test.ts +112 -0
  242. package/Tests/Types/Workflow/Templates.test.ts +916 -101
  243. package/Tests/UI/Components/ActiveFilterChipsOpenRoute.test.tsx +82 -0
  244. package/Tests/UI/Components/ComponentsModal.test.tsx +564 -7
  245. package/Tests/UI/Components/KeyboardShortcut.test.tsx +95 -0
  246. package/Tests/UI/Components/LogDetailsPanelCrossSignal.test.tsx +448 -0
  247. package/Tests/UI/Components/LogsTableCrossLinks.test.tsx +263 -0
  248. package/Tests/UI/Components/PendingProjectInvitations.test.tsx +913 -0
  249. package/Tests/UI/Components/SimpleLogViewer.test.tsx +228 -0
  250. package/Tests/UI/Components/TableRowSelectability.test.tsx +312 -0
  251. package/Tests/UI/Components/Workflow/GraphLint.test.ts +72 -0
  252. package/Tests/UI/Components/Workflow/GraphLintSummary.test.ts +755 -0
  253. package/Tests/UI/Components/Workflow/ModelColumnEditor.test.ts +242 -7
  254. package/Tests/UI/Components/Workflow/ModelColumnEditorServerContract.test.ts +15 -7
  255. package/Tests/UI/Components/Workflow/ModelSchema.test.ts +242 -28
  256. package/Tests/UI/Components/Workflow/RunStatusWatcher.test.ts +59 -1
  257. package/Tests/UI/Components/Workflow/StepTraceViewer.test.tsx +256 -0
  258. package/Tests/UI/Components/Workflow/UseRunWatch.test.tsx +665 -0
  259. package/Tests/UI/Components/Workflow/WorkflowIssuesModal.test.tsx +485 -0
  260. package/Tests/UI/Components/Workflow/WorkflowLogModal.test.tsx +478 -0
  261. package/Tests/UI/Components/Workflow/WorkflowStatusBar.test.tsx +379 -0
  262. package/Tests/UI/EsbuildConfig.test.ts +607 -0
  263. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +5 -0
  264. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +11 -4
  265. package/Tests/UI/Utils/ModelAPICreateMiscData.test.ts +94 -0
  266. package/Tests/UI/Utils/Platform.test.ts +147 -0
  267. package/Tests/UI/Utils/ProjectInvitationDisplay.test.ts +357 -0
  268. package/Tests/Utils/Monitor/NetworkDeviceLinkRuleUtil.test.ts +198 -0
  269. package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +487 -0
  270. package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +698 -0
  271. package/Tests/__mocks__/bullmq.js +55 -0
  272. package/Types/AI/AIChatMessageStatus.ts +8 -1
  273. package/Types/AI/AIChatTypes.ts +12 -0
  274. package/Types/Database/AccessControl/OwnerOnlyColumn.ts +88 -0
  275. package/Types/Exception/ExceptionCode.ts +2 -0
  276. package/Types/Exception/ServiceUnavailableException.ts +8 -0
  277. package/Types/Exception/TooManyRequestsException.ts +8 -0
  278. package/Types/IP/IP.ts +93 -47
  279. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +49 -3
  280. package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +55 -0
  281. package/Types/OnCallDutyPolicy/Layer.ts +203 -149
  282. package/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.ts +13 -0
  283. package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +155 -10
  284. package/Types/Permission.ts +193 -0
  285. package/Types/Telemetry/EntityRelationshipType.ts +1 -1
  286. package/Types/Telemetry/EntitySource.ts +1 -1
  287. package/Types/Telemetry/EntityType.ts +1 -1
  288. package/Types/Telemetry/EntityTypeGroups.ts +1 -1
  289. package/Types/Workflow/Components/BaseModel.ts +75 -29
  290. package/Types/Workflow/Components/Discord.ts +1 -0
  291. package/Types/Workflow/Components/Email.ts +12 -3
  292. package/Types/Workflow/Components/JavaScript.ts +7 -0
  293. package/Types/Workflow/Components/MicrosoftTeams.ts +3 -2
  294. package/Types/Workflow/Components/Slack.ts +1 -0
  295. package/Types/Workflow/Components/Telegram.ts +1 -0
  296. package/Types/Workflow/TemplateSyntax.ts +44 -0
  297. package/Types/Workflow/Templates.ts +2097 -45
  298. package/UI/Components/Calendar/Calendar.css +43 -0
  299. package/UI/Components/Calendar/Calendar.tsx +8 -0
  300. package/UI/Components/Card/Card.tsx +2 -2
  301. package/UI/Components/Checkbox/Checkbox.tsx +16 -0
  302. package/UI/Components/Dictionary/Dictionary.tsx +48 -9
  303. package/UI/Components/FormModal/BasicFormModal.tsx +2 -1
  304. package/UI/Components/Header/HeaderIconDropdownButton.tsx +53 -3
  305. package/UI/Components/Input/Input.tsx +1 -0
  306. package/UI/Components/KeyboardShortcut/KeyboardKey.ts +185 -0
  307. package/UI/Components/KeyboardShortcut/KeyboardShortcut.tsx +87 -0
  308. package/UI/Components/LogsViewer/LogsViewer.tsx +28 -0
  309. package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +31 -0
  310. package/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.tsx +18 -18
  311. package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +363 -14
  312. package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +11 -0
  313. package/UI/Components/LogsViewer/components/LogsTable.tsx +155 -12
  314. package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +29 -0
  315. package/UI/Components/LogsViewer/types.ts +23 -0
  316. package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +9 -2
  317. package/UI/Components/Navbar/NavBarMenuModal.tsx +15 -30
  318. package/UI/Components/ProjectInvitations/PendingProjectInvitations.tsx +442 -0
  319. package/UI/Components/SimpleLogViewer/SimpleLogViewer.tsx +23 -1
  320. package/UI/Components/Table/Table.tsx +49 -16
  321. package/UI/Components/Table/TableBody.tsx +53 -28
  322. package/UI/Components/Table/TableHeader.tsx +13 -0
  323. package/UI/Components/Table/TableRow.tsx +58 -26
  324. package/UI/Components/Workflow/ArgumentsForm.tsx +155 -9
  325. package/UI/Components/Workflow/ComponentReturnValueViewer.tsx +26 -0
  326. package/UI/Components/Workflow/ComponentSettingsModal.tsx +10 -1
  327. package/UI/Components/Workflow/ComponentValuePickerModal.tsx +135 -7
  328. package/UI/Components/Workflow/ComponentsModal.tsx +116 -22
  329. package/UI/Components/Workflow/DocumentationViewer.tsx +59 -9
  330. package/UI/Components/Workflow/GraphLint.ts +42 -5
  331. package/UI/Components/Workflow/GraphLintSummary.ts +390 -0
  332. package/UI/Components/Workflow/ModelColumnEditor.tsx +154 -22
  333. package/UI/Components/Workflow/ModelSchema.ts +115 -33
  334. package/UI/Components/Workflow/RunStatusWatcher.ts +1 -1
  335. package/UI/Components/Workflow/StepTraceViewer.tsx +1 -1
  336. package/UI/Components/Workflow/UseRunWatch.ts +212 -0
  337. package/UI/Components/Workflow/VariableModal.tsx +6 -2
  338. package/UI/Components/Workflow/Workflow.tsx +49 -3
  339. package/UI/Components/Workflow/WorkflowIssuesModal.tsx +255 -0
  340. package/UI/Components/Workflow/WorkflowLogModal.tsx +128 -0
  341. package/UI/Components/Workflow/WorkflowStatusBar.tsx +224 -0
  342. package/UI/Utils/AIChatExport/ConversationMarkdown.ts +10 -0
  343. package/UI/Utils/ModelAPI/ModelAPI.ts +7 -1
  344. package/UI/Utils/Platform.ts +149 -0
  345. package/UI/Utils/ProjectInvitationDisplay.ts +118 -0
  346. package/UI/esbuild-config.js +22 -1
  347. package/Utils/Monitor/NetworkDeviceLinkRuleUtil.ts +187 -0
  348. package/Utils/Monitor/NetworkTopologyUtil.ts +888 -164
  349. package/Utils/Telemetry/CrossSignalScope.ts +502 -0
  350. package/Utils/Telemetry/EntityKey.ts +5 -5
  351. package/Utils/Telemetry/EntityRelationship.ts +1 -1
  352. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +1 -1
  353. package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +1 -1
  354. package/build/dist/Models/DatabaseModels/AIConversation.js +32 -0
  355. package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
  356. package/build/dist/Models/DatabaseModels/AIConversationMessage.js +42 -0
  357. package/build/dist/Models/DatabaseModels/AIConversationMessage.js.map +1 -1
  358. package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js +28 -0
  359. package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js.map +1 -1
  360. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js +29 -0
  361. package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js.map +1 -1
  362. package/build/dist/Models/DatabaseModels/Index.js +12 -4
  363. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  364. package/build/dist/Models/DatabaseModels/{TelemetryEntity.js → InventoryItem.js} +167 -31
  365. package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -0
  366. package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js +454 -0
  367. package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js.map +1 -0
  368. package/build/dist/Models/DatabaseModels/{TelemetryEntityRelationship.js → InventoryItemRelationship.js} +27 -27
  369. package/build/dist/Models/DatabaseModels/InventoryItemRelationship.js.map +1 -0
  370. package/build/dist/Models/DatabaseModels/NetworkDevice.js +141 -0
  371. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  372. package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js +719 -0
  373. package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js.map +1 -0
  374. package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js +475 -0
  375. package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js.map +1 -0
  376. package/build/dist/Models/DatabaseModels/NetworkTopologySuppression.js +446 -0
  377. package/build/dist/Models/DatabaseModels/NetworkTopologySuppression.js.map +1 -0
  378. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js +9 -0
  379. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js.map +1 -1
  380. package/build/dist/Models/DatabaseModels/Project.js +80 -0
  381. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  382. package/build/dist/Models/DatabaseModels/UserCall.js +46 -2
  383. package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
  384. package/build/dist/Models/DatabaseModels/UserEmail.js +48 -2
  385. package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
  386. package/build/dist/Models/DatabaseModels/UserNotificationRule.js +424 -55
  387. package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
  388. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +24 -2
  389. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
  390. package/build/dist/Models/DatabaseModels/UserPush.js +51 -1
  391. package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
  392. package/build/dist/Models/DatabaseModels/UserSMS.js +47 -2
  393. package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
  394. package/build/dist/Models/DatabaseModels/UserTelegram.js +65 -3
  395. package/build/dist/Models/DatabaseModels/UserTelegram.js.map +1 -1
  396. package/build/dist/Models/DatabaseModels/UserWebhook.js +56 -2
  397. package/build/dist/Models/DatabaseModels/UserWebhook.js.map +1 -1
  398. package/build/dist/Models/DatabaseModels/UserWhatsApp.js +45 -2
  399. package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
  400. package/build/dist/Models/DatabaseModels/WorkflowVariable.js +12 -0
  401. package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
  402. package/build/dist/Server/API/AIChatAPI.js +237 -1
  403. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  404. package/build/dist/Server/API/DashboardAPI.js +165 -13
  405. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  406. package/build/dist/Server/API/OnCallReadinessAPI.js +599 -0
  407. package/build/dist/Server/API/OnCallReadinessAPI.js.map +1 -0
  408. package/build/dist/Server/API/TeamComplianceAPI.js +68 -9
  409. package/build/dist/Server/API/TeamComplianceAPI.js.map +1 -1
  410. package/build/dist/Server/API/TelemetryAPI.js +129 -18
  411. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  412. package/build/dist/Server/EnvironmentConfig.js +45 -0
  413. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  414. package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +22 -0
  415. package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
  416. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.js +4 -4
  417. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.js +18 -0
  418. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.js.map +1 -0
  419. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.js +39 -0
  420. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.js.map +1 -0
  421. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.js +38 -0
  422. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.js.map +1 -0
  423. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.js +22 -0
  424. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.js.map +1 -0
  425. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.js +150 -0
  426. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.js.map +1 -0
  427. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.js +57 -0
  428. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.js.map +1 -0
  429. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.js +69 -0
  430. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.js.map +1 -0
  431. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.js +32 -0
  432. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.js.map +1 -0
  433. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.js +26 -0
  434. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.js.map +1 -0
  435. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.js +48 -0
  436. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.js.map +1 -0
  437. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +20 -0
  438. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  439. package/build/dist/Server/Infrastructure/Queue.js +72 -13
  440. package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
  441. package/build/dist/Server/Middleware/PublicDashboardRateLimit.js +399 -0
  442. package/build/dist/Server/Middleware/PublicDashboardRateLimit.js.map +1 -0
  443. package/build/dist/Server/Services/AIService.js +1 -0
  444. package/build/dist/Server/Services/AIService.js.map +1 -1
  445. package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js +24 -3
  446. package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js.map +1 -1
  447. package/build/dist/Server/Services/AlertSeverityService.js +54 -0
  448. package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
  449. package/build/dist/Server/Services/DashboardService.js +10 -9
  450. package/build/dist/Server/Services/DashboardService.js.map +1 -1
  451. package/build/dist/Server/Services/DatabaseService.js +24 -2
  452. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  453. package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +24 -3
  454. package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
  455. package/build/dist/Server/Services/IncidentSeverityService.js +67 -0
  456. package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
  457. package/build/dist/Server/Services/Index.js +12 -4
  458. package/build/dist/Server/Services/Index.js.map +1 -1
  459. package/build/dist/Server/Services/InventoryItemCustomFieldService.js +9 -0
  460. package/build/dist/Server/Services/InventoryItemCustomFieldService.js.map +1 -0
  461. package/build/dist/Server/Services/{TelemetryEntityRelationshipService.js → InventoryItemRelationshipService.js} +6 -6
  462. package/build/dist/Server/Services/InventoryItemRelationshipService.js.map +1 -0
  463. package/build/dist/Server/Services/{TelemetryEntityService.js → InventoryItemService.js} +68 -23
  464. package/build/dist/Server/Services/InventoryItemService.js.map +1 -0
  465. package/build/dist/Server/Services/LogAggregationService.js +27 -8
  466. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  467. package/build/dist/Server/Services/MetricAggregationService.js +80 -0
  468. package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
  469. package/build/dist/Server/Services/MetricService.js +6 -6
  470. package/build/dist/Server/Services/MetricService.js.map +1 -1
  471. package/build/dist/Server/Services/NetworkDeviceLinkRuleService.js +9 -0
  472. package/build/dist/Server/Services/NetworkDeviceLinkRuleService.js.map +1 -0
  473. package/build/dist/Server/Services/NetworkDeviceLinkService.js +71 -0
  474. package/build/dist/Server/Services/NetworkDeviceLinkService.js.map +1 -0
  475. package/build/dist/Server/Services/NetworkDeviceService.js +113 -0
  476. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  477. package/build/dist/Server/Services/NetworkSiteService.js +53 -13
  478. package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
  479. package/build/dist/Server/Services/NetworkTopologySuppressionService.js +85 -0
  480. package/build/dist/Server/Services/NetworkTopologySuppressionService.js.map +1 -0
  481. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +48 -32
  482. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  483. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +8 -0
  484. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  485. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +51 -12
  486. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
  487. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +57 -13
  488. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  489. package/build/dist/Server/Services/OnCallNotificationAlertingService.js +548 -0
  490. package/build/dist/Server/Services/OnCallNotificationAlertingService.js.map +1 -0
  491. package/build/dist/Server/Services/OnCallReadinessService.js +1961 -0
  492. package/build/dist/Server/Services/OnCallReadinessService.js.map +1 -0
  493. package/build/dist/Server/Services/OnCallSetupReminderService.js +738 -0
  494. package/build/dist/Server/Services/OnCallSetupReminderService.js.map +1 -0
  495. package/build/dist/Server/Services/ProfileAggregationService.js +68 -4
  496. package/build/dist/Server/Services/ProfileAggregationService.js.map +1 -1
  497. package/build/dist/Server/Services/StatusPageService.js +11 -10
  498. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  499. package/build/dist/Server/Services/TeamComplianceService.js +312 -160
  500. package/build/dist/Server/Services/TeamComplianceService.js.map +1 -1
  501. package/build/dist/Server/Services/UserCallService.js +24 -1
  502. package/build/dist/Server/Services/UserCallService.js.map +1 -1
  503. package/build/dist/Server/Services/UserEmailService.js +24 -1
  504. package/build/dist/Server/Services/UserEmailService.js.map +1 -1
  505. package/build/dist/Server/Services/UserNotificationRuleAdminService.js +858 -0
  506. package/build/dist/Server/Services/UserNotificationRuleAdminService.js.map +1 -0
  507. package/build/dist/Server/Services/UserNotificationRuleService.js +2830 -175
  508. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  509. package/build/dist/Server/Services/UserOnCallLogService.js +488 -43
  510. package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
  511. package/build/dist/Server/Services/UserPushService.js +26 -0
  512. package/build/dist/Server/Services/UserPushService.js.map +1 -1
  513. package/build/dist/Server/Services/UserService.js +10 -0
  514. package/build/dist/Server/Services/UserService.js.map +1 -1
  515. package/build/dist/Server/Services/UserSmsService.js +24 -1
  516. package/build/dist/Server/Services/UserSmsService.js.map +1 -1
  517. package/build/dist/Server/Services/UserTelegramService.js +22 -1
  518. package/build/dist/Server/Services/UserTelegramService.js.map +1 -1
  519. package/build/dist/Server/Services/UserWebhookService.js +25 -1
  520. package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
  521. package/build/dist/Server/Services/UserWhatsAppService.js +22 -1
  522. package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
  523. package/build/dist/Server/Types/Database/Permissions/BasePermission.js +12 -1
  524. package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
  525. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +126 -0
  526. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  527. package/build/dist/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.js +254 -0
  528. package/build/dist/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.js.map +1 -0
  529. package/build/dist/Server/Types/Database/Permissions/QueryPermission.js +47 -2
  530. package/build/dist/Server/Types/Database/Permissions/QueryPermission.js.map +1 -1
  531. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +7 -0
  532. package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
  533. package/build/dist/Server/Types/Workflow/Components/API/Delete.js +1 -1
  534. package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
  535. package/build/dist/Server/Types/Workflow/Components/API/Get.js +1 -1
  536. package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
  537. package/build/dist/Server/Types/Workflow/Components/API/Patch.js +1 -1
  538. package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
  539. package/build/dist/Server/Types/Workflow/Components/API/Post.js +1 -1
  540. package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
  541. package/build/dist/Server/Types/Workflow/Components/API/Put.js +1 -1
  542. package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
  543. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +21 -5
  544. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
  545. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +14 -10
  546. package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
  547. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +31 -0
  548. package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -1
  549. package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js +3 -9
  550. package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js.map +1 -1
  551. package/build/dist/Server/Types/Workflow/Components/Email.js +15 -4
  552. package/build/dist/Server/Types/Workflow/Components/Email.js.map +1 -1
  553. package/build/dist/Server/Types/Workflow/Components/JavaScript.js +7 -2
  554. package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
  555. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +1 -1
  556. package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
  557. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +514 -56
  558. package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
  559. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +20 -3
  560. package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
  561. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +19 -6
  562. package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
  563. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +7 -0
  564. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  565. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js +2 -2
  566. package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js.map +1 -1
  567. package/build/dist/Server/Utils/AI/Toolbox/AIMetaTools.js +692 -0
  568. package/build/dist/Server/Utils/AI/Toolbox/AIMetaTools.js.map +1 -0
  569. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +148 -12
  570. package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
  571. package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +157 -10
  572. package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -1
  573. package/build/dist/Server/Utils/AI/Toolbox/Index.js +37 -0
  574. package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
  575. package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js +259 -14
  576. package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js.map +1 -1
  577. package/build/dist/Server/Utils/AI/Toolbox/NoteWriteTools.js +235 -0
  578. package/build/dist/Server/Utils/AI/Toolbox/NoteWriteTools.js.map +1 -0
  579. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +1000 -0
  580. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -0
  581. package/build/dist/Server/Utils/AI/Toolbox/RunbookTools.js +356 -0
  582. package/build/dist/Server/Utils/AI/Toolbox/RunbookTools.js.map +1 -0
  583. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +394 -0
  584. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -0
  585. package/build/dist/Server/Utils/AI/Toolbox/StatusPageTools.js +465 -0
  586. package/build/dist/Server/Utils/AI/Toolbox/StatusPageTools.js.map +1 -0
  587. package/build/dist/Server/Utils/AI/Toolbox/TeamTools.js +280 -0
  588. package/build/dist/Server/Utils/AI/Toolbox/TeamTools.js.map +1 -0
  589. package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js +527 -0
  590. package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js.map +1 -0
  591. package/build/dist/Server/Utils/AI/Toolbox/WorkflowProbeTools.js +548 -0
  592. package/build/dist/Server/Utils/AI/Toolbox/WorkflowProbeTools.js.map +1 -0
  593. package/build/dist/Server/Utils/ClientIp.js +137 -0
  594. package/build/dist/Server/Utils/ClientIp.js.map +1 -0
  595. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +38 -0
  596. package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
  597. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js +89 -0
  598. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js.map +1 -0
  599. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js +77 -0
  600. package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js.map +1 -0
  601. package/build/dist/Server/Utils/Express.js +12 -12
  602. package/build/dist/Server/Utils/Express.js.map +1 -1
  603. package/build/dist/Server/Utils/LLM/LLMService.js +70 -7
  604. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  605. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +121 -11
  606. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  607. package/build/dist/Server/Utils/SSRFProtection.js +82 -21
  608. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  609. package/build/dist/Server/Utils/StartServer.js +12 -4
  610. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  611. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +165 -18
  612. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  613. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +11 -11
  614. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -1
  615. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +122 -47
  616. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  617. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +7 -3
  618. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  619. package/build/dist/Types/AI/AIChatMessageStatus.js +8 -1
  620. package/build/dist/Types/AI/AIChatMessageStatus.js.map +1 -1
  621. package/build/dist/Types/AI/AIChatTypes.js +12 -0
  622. package/build/dist/Types/AI/AIChatTypes.js.map +1 -1
  623. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +60 -0
  624. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -0
  625. package/build/dist/Types/Exception/ExceptionCode.js +2 -0
  626. package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
  627. package/build/dist/Types/Exception/ServiceUnavailableException.js +8 -0
  628. package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -0
  629. package/build/dist/Types/Exception/TooManyRequestsException.js +8 -0
  630. package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -0
  631. package/build/dist/Types/IP/IP.js +87 -43
  632. package/build/dist/Types/IP/IP.js.map +1 -1
  633. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +50 -0
  634. package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -0
  635. package/build/dist/Types/OnCallDutyPolicy/Layer.js +186 -123
  636. package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
  637. package/build/dist/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.js +13 -0
  638. package/build/dist/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.js.map +1 -1
  639. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +105 -11
  640. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
  641. package/build/dist/Types/Permission.js +174 -0
  642. package/build/dist/Types/Permission.js.map +1 -1
  643. package/build/dist/Types/Telemetry/EntityRelationshipType.js +1 -1
  644. package/build/dist/Types/Telemetry/EntitySource.js +1 -1
  645. package/build/dist/Types/Telemetry/EntityType.js +1 -1
  646. package/build/dist/Types/Telemetry/EntityTypeGroups.js +1 -1
  647. package/build/dist/Types/Telemetry/EntityTypeGroups.js.map +1 -1
  648. package/build/dist/Types/Workflow/Components/BaseModel.js +66 -28
  649. package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
  650. package/build/dist/Types/Workflow/Components/Discord.js +1 -0
  651. package/build/dist/Types/Workflow/Components/Discord.js.map +1 -1
  652. package/build/dist/Types/Workflow/Components/Email.js +12 -3
  653. package/build/dist/Types/Workflow/Components/Email.js.map +1 -1
  654. package/build/dist/Types/Workflow/Components/JavaScript.js +7 -0
  655. package/build/dist/Types/Workflow/Components/JavaScript.js.map +1 -1
  656. package/build/dist/Types/Workflow/Components/MicrosoftTeams.js +3 -2
  657. package/build/dist/Types/Workflow/Components/MicrosoftTeams.js.map +1 -1
  658. package/build/dist/Types/Workflow/Components/Slack.js +1 -0
  659. package/build/dist/Types/Workflow/Components/Slack.js.map +1 -1
  660. package/build/dist/Types/Workflow/Components/Telegram.js +1 -0
  661. package/build/dist/Types/Workflow/Components/Telegram.js.map +1 -1
  662. package/build/dist/Types/Workflow/TemplateSyntax.js +12 -0
  663. package/build/dist/Types/Workflow/TemplateSyntax.js.map +1 -1
  664. package/build/dist/Types/Workflow/Templates.js +1931 -38
  665. package/build/dist/Types/Workflow/Templates.js.map +1 -1
  666. package/build/dist/UI/Components/Calendar/Calendar.js +1 -1
  667. package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
  668. package/build/dist/UI/Components/Checkbox/Checkbox.js +1 -1
  669. package/build/dist/UI/Components/Checkbox/Checkbox.js.map +1 -1
  670. package/build/dist/UI/Components/Dictionary/Dictionary.js +25 -11
  671. package/build/dist/UI/Components/Dictionary/Dictionary.js.map +1 -1
  672. package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
  673. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +27 -4
  674. package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
  675. package/build/dist/UI/Components/Input/Input.js +1 -0
  676. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  677. package/build/dist/UI/Components/KeyboardShortcut/KeyboardKey.js +163 -0
  678. package/build/dist/UI/Components/KeyboardShortcut/KeyboardKey.js.map +1 -0
  679. package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcut.js +47 -0
  680. package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcut.js.map +1 -0
  681. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +4 -4
  682. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  683. package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +11 -1
  684. package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
  685. package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js +10 -8
  686. package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js.map +1 -1
  687. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +227 -14
  688. package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
  689. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +5 -0
  690. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
  691. package/build/dist/UI/Components/LogsViewer/components/LogsTable.js +69 -5
  692. package/build/dist/UI/Components/LogsViewer/components/LogsTable.js.map +1 -1
  693. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +8 -0
  694. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
  695. package/build/dist/UI/Components/LogsViewer/types.js.map +1 -1
  696. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +9 -2
  697. package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
  698. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +8 -21
  699. package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
  700. package/build/dist/UI/Components/ProjectInvitations/PendingProjectInvitations.js +251 -0
  701. package/build/dist/UI/Components/ProjectInvitations/PendingProjectInvitations.js.map +1 -0
  702. package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js +9 -2
  703. package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js.map +1 -1
  704. package/build/dist/UI/Components/Table/Table.js +27 -15
  705. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  706. package/build/dist/UI/Components/Table/TableBody.js +24 -18
  707. package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
  708. package/build/dist/UI/Components/Table/TableHeader.js +9 -1
  709. package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
  710. package/build/dist/UI/Components/Table/TableRow.js +29 -21
  711. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  712. package/build/dist/UI/Components/Workflow/ArgumentsForm.js +130 -12
  713. package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
  714. package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js +10 -1
  715. package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js.map +1 -1
  716. package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js +4 -4
  717. package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js.map +1 -1
  718. package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js +57 -7
  719. package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js.map +1 -1
  720. package/build/dist/UI/Components/Workflow/ComponentsModal.js +53 -18
  721. package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
  722. package/build/dist/UI/Components/Workflow/DocumentationViewer.js +19 -6
  723. package/build/dist/UI/Components/Workflow/DocumentationViewer.js.map +1 -1
  724. package/build/dist/UI/Components/Workflow/GraphLint.js +33 -4
  725. package/build/dist/UI/Components/Workflow/GraphLint.js.map +1 -1
  726. package/build/dist/UI/Components/Workflow/GraphLintSummary.js +231 -0
  727. package/build/dist/UI/Components/Workflow/GraphLintSummary.js.map +1 -0
  728. package/build/dist/UI/Components/Workflow/ModelColumnEditor.js +116 -21
  729. package/build/dist/UI/Components/Workflow/ModelColumnEditor.js.map +1 -1
  730. package/build/dist/UI/Components/Workflow/ModelSchema.js +72 -34
  731. package/build/dist/UI/Components/Workflow/ModelSchema.js.map +1 -1
  732. package/build/dist/UI/Components/Workflow/RunStatusWatcher.js +1 -1
  733. package/build/dist/UI/Components/Workflow/RunStatusWatcher.js.map +1 -1
  734. package/build/dist/UI/Components/Workflow/StepTraceViewer.js +1 -1
  735. package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -1
  736. package/build/dist/UI/Components/Workflow/UseRunWatch.js +123 -0
  737. package/build/dist/UI/Components/Workflow/UseRunWatch.js.map +1 -0
  738. package/build/dist/UI/Components/Workflow/VariableModal.js +3 -2
  739. package/build/dist/UI/Components/Workflow/VariableModal.js.map +1 -1
  740. package/build/dist/UI/Components/Workflow/Workflow.js +41 -1
  741. package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
  742. package/build/dist/UI/Components/Workflow/WorkflowIssuesModal.js +99 -0
  743. package/build/dist/UI/Components/Workflow/WorkflowIssuesModal.js.map +1 -0
  744. package/build/dist/UI/Components/Workflow/WorkflowLogModal.js +56 -0
  745. package/build/dist/UI/Components/Workflow/WorkflowLogModal.js.map +1 -0
  746. package/build/dist/UI/Components/Workflow/WorkflowStatusBar.js +92 -0
  747. package/build/dist/UI/Components/Workflow/WorkflowStatusBar.js.map +1 -0
  748. package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js +9 -0
  749. package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js.map +1 -1
  750. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +1 -1
  751. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  752. package/build/dist/UI/Utils/Platform.js +118 -0
  753. package/build/dist/UI/Utils/Platform.js.map +1 -0
  754. package/build/dist/UI/Utils/ProjectInvitationDisplay.js +106 -0
  755. package/build/dist/UI/Utils/ProjectInvitationDisplay.js.map +1 -0
  756. package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js +108 -0
  757. package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js.map +1 -0
  758. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +642 -136
  759. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  760. package/build/dist/Utils/Telemetry/CrossSignalScope.js +328 -0
  761. package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -0
  762. package/build/dist/Utils/Telemetry/EntityKey.js +5 -5
  763. package/build/dist/Utils/Telemetry/EntityRelationship.js +1 -1
  764. package/jest.config.json +1 -0
  765. package/package.json +1 -1
  766. package/build/dist/Models/DatabaseModels/TelemetryEntity.js.map +0 -1
  767. package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js.map +0 -1
  768. package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +0 -1
  769. package/build/dist/Server/Services/TelemetryEntityService.js.map +0 -1
@@ -0,0 +1,1219 @@
1
+ import UserCall from "../../../../../Models/DatabaseModels/UserCall";
2
+ import UserEmail from "../../../../../Models/DatabaseModels/UserEmail";
3
+ import UserPush from "../../../../../Models/DatabaseModels/UserPush";
4
+ import UserSMS from "../../../../../Models/DatabaseModels/UserSMS";
5
+ import UserTelegram from "../../../../../Models/DatabaseModels/UserTelegram";
6
+ import UserWebhook from "../../../../../Models/DatabaseModels/UserWebhook";
7
+ import UserWhatsApp from "../../../../../Models/DatabaseModels/UserWhatsApp";
8
+ import BaseModel from "../../../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
9
+ import DatabaseService from "../../../../../Server/Services/DatabaseService";
10
+ import FindBy from "../../../../../Server/Types/Database/FindBy";
11
+ import ModelPermission from "../../../../../Server/Types/Database/Permissions/Index";
12
+ import { CheckReadPermissionType } from "../../../../../Server/Types/Database/Permissions/ReadPermission";
13
+ import Query from "../../../../../Server/Types/Database/Query";
14
+ import Select from "../../../../../Server/Types/Database/Select";
15
+ import NotEqual from "../../../../../Types/BaseDatabase/NotEqual";
16
+ import SortOrder from "../../../../../Types/BaseDatabase/SortOrder";
17
+ import DatabaseCommonInteractionProps from "../../../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
18
+ import ColumnAccessControl from "../../../../../Types/Database/AccessControl/ColumnAccessControl";
19
+ import TableAccessControl from "../../../../../Types/Database/AccessControl/TableAccessControl";
20
+ import CurrentUserCanAccessRecordBy from "../../../../../Types/Database/CurrentUserCanAccessRecordBy";
21
+ import TableColumn from "../../../../../Types/Database/TableColumn";
22
+ import TableColumnType from "../../../../../Types/Database/TableColumnType";
23
+ import TenantColumn from "../../../../../Types/Database/TenantColumn";
24
+ import NotAuthorizedException from "../../../../../Types/Exception/NotAuthorizedException";
25
+ import ObjectID from "../../../../../Types/ObjectID";
26
+ import Permission from "../../../../../Types/Permission";
27
+ import UserType from "../../../../../Types/UserType";
28
+
29
+ /*
30
+ * WHAT THIS FILE PINS
31
+ *
32
+ * @OwnerOnlyColumn() marks a column that may be read only by a query pinned to
33
+ * the row's owner. Phase 3 widens UserNotificationRule's TABLE read to
34
+ * administrators - which is the feature, and is correct - and the moment it
35
+ * does, an admin's read of that table is no longer confined to their own rows.
36
+ * Everything reachable from those rows is then reachable by an admin, and the
37
+ * seven notification-method models hang off them by ManyToOne relation.
38
+ *
39
+ * There are FOUR routes into a marked column, and closing three of them is the
40
+ * same as closing none. Every route below is driven through the real permission
41
+ * entry point - ModelPermission.checkReadQueryPermission for the query and
42
+ * select routes, DatabaseService's own sort-injection for the sort route -
43
+ * never by asserting on decorator metadata. A guard that is only proved by
44
+ * reading back the mark that configures it proves nothing about whether the
45
+ * mark is consulted.
46
+ *
47
+ * Route 1 select: { webhookUrl: true } on UserWebhook
48
+ * Route 2 select: { userWebhook: { webhookUrl: true } } on a rule
49
+ * Route 3 sort: { webhookUrl: "ASC" } injected post-gate
50
+ * Route 4 query: { webhookUrl: "https://..." } as a value oracle
51
+ *
52
+ * HOW THE ADMIN CASE IS SET UP, AND WHY IT IS NOT THEATRE. Today the seven
53
+ * method models list [CurrentUser] and nothing else, so TenantPermission stamps
54
+ * every non-root caller's own userId onto their query and an administrator is
55
+ * indistinguishable from a plain member - the admin case is currently
56
+ * unreachable on those models, and that is precisely what Phase 3 changes. The
57
+ * AdminReadable* classes below are the REAL models with the REAL marked columns
58
+ * and one thing altered: Permission.ProjectAdmin added to the table read list,
59
+ * exactly the change Phase 3 makes. Nothing about the columns, the ownership
60
+ * column or the relation metadata is simulated.
61
+ */
62
+
63
+ const projectId: ObjectID = ObjectID.generate();
64
+ const ownerUserId: ObjectID = ObjectID.generate();
65
+ const adminUserId: ObjectID = ObjectID.generate();
66
+ const otherUserId: ObjectID = ObjectID.generate();
67
+
68
+ type ModelTypeUnderTest = { new (): BaseModel };
69
+
70
+ /*
71
+ * The seven notification-method models with the post-Phase-3 table read. Only
72
+ * the table access control is restated; every column, its @OwnerOnlyColumn
73
+ * mark, the tenant column and @CurrentUserCanAccessRecordBy("userId") are
74
+ * inherited from the production model.
75
+ */
76
+ const ADMIN_READABLE_TABLE_ACCESS: {
77
+ create: Array<Permission>;
78
+ read: Array<Permission>;
79
+ update: Array<Permission>;
80
+ delete: Array<Permission>;
81
+ } = {
82
+ create: [Permission.CurrentUser],
83
+ read: [Permission.CurrentUser, Permission.ProjectAdmin],
84
+ update: [Permission.CurrentUser, Permission.ProjectAdmin],
85
+ delete: [Permission.CurrentUser],
86
+ };
87
+
88
+ @TableAccessControl(ADMIN_READABLE_TABLE_ACCESS)
89
+ class AdminReadableUserEmail extends UserEmail {}
90
+
91
+ @TableAccessControl(ADMIN_READABLE_TABLE_ACCESS)
92
+ class AdminReadableUserSMS extends UserSMS {}
93
+
94
+ @TableAccessControl(ADMIN_READABLE_TABLE_ACCESS)
95
+ class AdminReadableUserCall extends UserCall {}
96
+
97
+ @TableAccessControl(ADMIN_READABLE_TABLE_ACCESS)
98
+ class AdminReadableUserPush extends UserPush {}
99
+
100
+ @TableAccessControl(ADMIN_READABLE_TABLE_ACCESS)
101
+ class AdminReadableUserWhatsApp extends UserWhatsApp {}
102
+
103
+ @TableAccessControl(ADMIN_READABLE_TABLE_ACCESS)
104
+ class AdminReadableUserTelegram extends UserTelegram {}
105
+
106
+ @TableAccessControl(ADMIN_READABLE_TABLE_ACCESS)
107
+ class AdminReadableUserWebhook extends UserWebhook {}
108
+
109
+ /*
110
+ * UserNotificationRule's shape after Phase 3: readable by an administrator,
111
+ * still owned by a user, and pointing at the REAL method models through the
112
+ * same ManyToOne relations the production rule model uses. The relation columns
113
+ * carry read permissions an admin holds, because the point of Phase 3 is that
114
+ * an admin CAN read this table - the question this file answers is what they
115
+ * can reach through it.
116
+ */
117
+ @TenantColumn("projectId")
118
+ @TableAccessControl(ADMIN_READABLE_TABLE_ACCESS)
119
+ @CurrentUserCanAccessRecordBy("userId")
120
+ class AdminReadableRuleModel extends BaseModel {
121
+ @ColumnAccessControl({
122
+ create: [Permission.CurrentUser],
123
+ read: [Permission.CurrentUser, Permission.ProjectAdmin],
124
+ update: [],
125
+ })
126
+ @TableColumn({
127
+ type: TableColumnType.ObjectID,
128
+ title: "Project ID",
129
+ })
130
+ public projectId?: ObjectID = undefined;
131
+
132
+ @ColumnAccessControl({
133
+ create: [Permission.CurrentUser],
134
+ read: [Permission.CurrentUser, Permission.ProjectAdmin],
135
+ update: [],
136
+ })
137
+ @TableColumn({
138
+ type: TableColumnType.ObjectID,
139
+ title: "User ID",
140
+ })
141
+ public userId?: ObjectID = undefined;
142
+
143
+ @ColumnAccessControl({
144
+ create: [Permission.CurrentUser],
145
+ read: [Permission.CurrentUser, Permission.ProjectAdmin],
146
+ update: [],
147
+ })
148
+ @TableColumn({
149
+ type: TableColumnType.Entity,
150
+ modelType: UserEmail,
151
+ manyToOneRelationColumn: "userEmailId",
152
+ title: "User Email",
153
+ })
154
+ public userEmail?: UserEmail = undefined;
155
+
156
+ @ColumnAccessControl({
157
+ create: [Permission.CurrentUser],
158
+ read: [Permission.CurrentUser, Permission.ProjectAdmin],
159
+ update: [],
160
+ })
161
+ @TableColumn({
162
+ type: TableColumnType.Entity,
163
+ modelType: UserSMS,
164
+ manyToOneRelationColumn: "userSmsId",
165
+ title: "User SMS",
166
+ })
167
+ public userSms?: UserSMS = undefined;
168
+
169
+ @ColumnAccessControl({
170
+ create: [Permission.CurrentUser],
171
+ read: [Permission.CurrentUser, Permission.ProjectAdmin],
172
+ update: [],
173
+ })
174
+ @TableColumn({
175
+ type: TableColumnType.Entity,
176
+ modelType: UserCall,
177
+ manyToOneRelationColumn: "userCallId",
178
+ title: "User Call",
179
+ })
180
+ public userCall?: UserCall = undefined;
181
+
182
+ @ColumnAccessControl({
183
+ create: [Permission.CurrentUser],
184
+ read: [Permission.CurrentUser, Permission.ProjectAdmin],
185
+ update: [],
186
+ })
187
+ @TableColumn({
188
+ type: TableColumnType.Entity,
189
+ modelType: UserPush,
190
+ manyToOneRelationColumn: "userPushId",
191
+ title: "User Push",
192
+ })
193
+ public userPush?: UserPush = undefined;
194
+
195
+ @ColumnAccessControl({
196
+ create: [Permission.CurrentUser],
197
+ read: [Permission.CurrentUser, Permission.ProjectAdmin],
198
+ update: [],
199
+ })
200
+ @TableColumn({
201
+ type: TableColumnType.Entity,
202
+ modelType: UserWhatsApp,
203
+ manyToOneRelationColumn: "userWhatsAppId",
204
+ title: "User WhatsApp",
205
+ })
206
+ public userWhatsApp?: UserWhatsApp = undefined;
207
+
208
+ @ColumnAccessControl({
209
+ create: [Permission.CurrentUser],
210
+ read: [Permission.CurrentUser, Permission.ProjectAdmin],
211
+ update: [],
212
+ })
213
+ @TableColumn({
214
+ type: TableColumnType.Entity,
215
+ modelType: UserTelegram,
216
+ manyToOneRelationColumn: "userTelegramId",
217
+ title: "User Telegram",
218
+ })
219
+ public userTelegram?: UserTelegram = undefined;
220
+
221
+ @ColumnAccessControl({
222
+ create: [Permission.CurrentUser],
223
+ read: [Permission.CurrentUser, Permission.ProjectAdmin],
224
+ update: [],
225
+ })
226
+ @TableColumn({
227
+ type: TableColumnType.Entity,
228
+ modelType: UserWebhook,
229
+ manyToOneRelationColumn: "userWebhookId",
230
+ title: "User Webhook",
231
+ })
232
+ public userWebhook?: UserWebhook = undefined;
233
+ }
234
+
235
+ interface MethodModelUnderTest {
236
+ name: string;
237
+ /* The production model, whose table read is [CurrentUser] today. */
238
+ modelType: ModelTypeUnderTest;
239
+ /* The same model with Phase 3's widened table read. */
240
+ adminReadableModelType: ModelTypeUnderTest;
241
+ /* The relation this method hangs off on a notification rule. */
242
+ relationColumnName: string;
243
+ /* Every column marked @OwnerOnlyColumn() on the model. */
244
+ ownerOnlyColumns: Array<string>;
245
+ /*
246
+ * The marked columns this guard actually decides: marked AND selectable by an
247
+ * ordinary authenticated caller.
248
+ *
249
+ * The four SMS/call/email/WhatsApp verification codes are marked but carry
250
+ * `read: []`, so the column-permission layer already refuses them to
251
+ * everybody including their owner - asserting on those would test the older
252
+ * gate, not this one. UserTelegram.verificationCode is the instructive
253
+ * counter-example: it is readable by CurrentUser (the user has to be shown
254
+ * the code to type into the bot), and CurrentUser is auto-granted to every
255
+ * authenticated caller, so the owner-only mark is the ONLY thing standing
256
+ * between it and any admin in the project.
257
+ */
258
+ ownerOnlyColumnsSelectableByOwner: Array<string>;
259
+ /*
260
+ * A marked column that is ALSO canReadOnRelationQuery, i.e. one that a nested
261
+ * select can actually ask for. This is the route-2 attack surface.
262
+ */
263
+ ownerOnlyColumnReachableThroughRelation: string;
264
+ /*
265
+ * An unmarked column that a nested select can ask for. This is what an admin
266
+ * surface labels rows with, and it must keep working.
267
+ */
268
+ labelColumnReachableThroughRelation: string;
269
+ /* Unmarked columns an admin must keep being able to read directly. */
270
+ labelColumns: Array<string>;
271
+ /* An unmarked, non-relation column that can be sorted on. */
272
+ unmarkedSortColumn: string;
273
+ }
274
+
275
+ const METHOD_MODELS: Array<MethodModelUnderTest> = [
276
+ {
277
+ name: "UserEmail",
278
+ modelType: UserEmail,
279
+ adminReadableModelType: AdminReadableUserEmail,
280
+ relationColumnName: "userEmail",
281
+ ownerOnlyColumns: ["email", "verificationCode"],
282
+ ownerOnlyColumnsSelectableByOwner: ["email"],
283
+ ownerOnlyColumnReachableThroughRelation: "email",
284
+ labelColumnReachableThroughRelation: "projectId",
285
+ labelColumns: ["userId", "projectId", "isVerified"],
286
+ unmarkedSortColumn: "isVerified",
287
+ },
288
+ {
289
+ name: "UserSMS",
290
+ modelType: UserSMS,
291
+ adminReadableModelType: AdminReadableUserSMS,
292
+ relationColumnName: "userSms",
293
+ ownerOnlyColumns: ["phone", "verificationCode"],
294
+ ownerOnlyColumnsSelectableByOwner: ["phone"],
295
+ ownerOnlyColumnReachableThroughRelation: "phone",
296
+ labelColumnReachableThroughRelation: "projectId",
297
+ labelColumns: ["userId", "projectId", "isVerified"],
298
+ unmarkedSortColumn: "isVerified",
299
+ },
300
+ {
301
+ name: "UserCall",
302
+ modelType: UserCall,
303
+ adminReadableModelType: AdminReadableUserCall,
304
+ relationColumnName: "userCall",
305
+ ownerOnlyColumns: ["phone", "verificationCode"],
306
+ ownerOnlyColumnsSelectableByOwner: ["phone"],
307
+ ownerOnlyColumnReachableThroughRelation: "phone",
308
+ labelColumnReachableThroughRelation: "projectId",
309
+ labelColumns: ["userId", "projectId", "isVerified"],
310
+ unmarkedSortColumn: "isVerified",
311
+ },
312
+ {
313
+ name: "UserPush",
314
+ modelType: UserPush,
315
+ adminReadableModelType: AdminReadableUserPush,
316
+ relationColumnName: "userPush",
317
+ ownerOnlyColumns: ["deviceToken"],
318
+ ownerOnlyColumnsSelectableByOwner: ["deviceToken"],
319
+ ownerOnlyColumnReachableThroughRelation: "deviceToken",
320
+ labelColumnReachableThroughRelation: "deviceName",
321
+ labelColumns: [
322
+ "userId",
323
+ "projectId",
324
+ "isVerified",
325
+ "deviceName",
326
+ "deviceType",
327
+ ],
328
+ unmarkedSortColumn: "deviceName",
329
+ },
330
+ {
331
+ name: "UserWhatsApp",
332
+ modelType: UserWhatsApp,
333
+ adminReadableModelType: AdminReadableUserWhatsApp,
334
+ relationColumnName: "userWhatsApp",
335
+ ownerOnlyColumns: ["phone", "verificationCode"],
336
+ ownerOnlyColumnsSelectableByOwner: ["phone"],
337
+ ownerOnlyColumnReachableThroughRelation: "phone",
338
+ labelColumnReachableThroughRelation: "projectId",
339
+ labelColumns: ["userId", "projectId", "isVerified"],
340
+ unmarkedSortColumn: "isVerified",
341
+ },
342
+ {
343
+ name: "UserTelegram",
344
+ modelType: UserTelegram,
345
+ adminReadableModelType: AdminReadableUserTelegram,
346
+ relationColumnName: "userTelegram",
347
+ ownerOnlyColumns: [
348
+ "telegramUserHandle",
349
+ "telegramChatId",
350
+ "verificationCode",
351
+ ],
352
+ ownerOnlyColumnsSelectableByOwner: [
353
+ "telegramUserHandle",
354
+ "telegramChatId",
355
+ "verificationCode",
356
+ ],
357
+ ownerOnlyColumnReachableThroughRelation: "telegramChatId",
358
+ labelColumnReachableThroughRelation: "projectId",
359
+ labelColumns: ["userId", "projectId", "isVerified"],
360
+ unmarkedSortColumn: "isVerified",
361
+ },
362
+ {
363
+ name: "UserWebhook",
364
+ modelType: UserWebhook,
365
+ adminReadableModelType: AdminReadableUserWebhook,
366
+ relationColumnName: "userWebhook",
367
+ ownerOnlyColumns: ["webhookUrl", "secret"],
368
+ ownerOnlyColumnsSelectableByOwner: ["webhookUrl", "secret"],
369
+ ownerOnlyColumnReachableThroughRelation: "webhookUrl",
370
+ labelColumnReachableThroughRelation: "name",
371
+ labelColumns: ["userId", "projectId", "name"],
372
+ unmarkedSortColumn: "name",
373
+ },
374
+ ];
375
+
376
+ /*
377
+ * The marked columns that no permission list lets an ordinary caller select at
378
+ * all. Pinned separately so that the guarded list above stays honest about what
379
+ * this guard is responsible for.
380
+ */
381
+ const WRITE_ONLY_VERIFICATION_CODE_MODELS: Array<ModelTypeUnderTest> = [
382
+ UserEmail,
383
+ UserSMS,
384
+ UserCall,
385
+ UserWhatsApp,
386
+ ];
387
+
388
+ /*
389
+ * Props are rebuilt for every call rather than shared. getUserPermissions()
390
+ * MUTATES the props it is given (it pushes the auto-granted Public and
391
+ * CurrentUser onto the global permission list), so a shared object would carry
392
+ * state between assertions.
393
+ */
394
+ function makeOwnerProps(): DatabaseCommonInteractionProps {
395
+ return {
396
+ userId: ownerUserId,
397
+ tenantId: projectId,
398
+ };
399
+ }
400
+
401
+ function makeAdminProps(): DatabaseCommonInteractionProps {
402
+ return {
403
+ userId: adminUserId,
404
+ tenantId: projectId,
405
+ userTenantAccessPermission: {
406
+ [projectId.toString()]: {
407
+ projectId: projectId,
408
+ permissions: [
409
+ {
410
+ permission: Permission.ProjectAdmin,
411
+ labelIds: [],
412
+ isBlockPermission: false,
413
+ _type: "UserPermission",
414
+ },
415
+ ],
416
+ _type: "UserTenantAccessPermission",
417
+ },
418
+ },
419
+ };
420
+ }
421
+
422
+ /*
423
+ * An API key carrying a project role and no user identity at all. There is no
424
+ * id such a caller could be pinned to, so every marked column must refuse.
425
+ */
426
+ function makeApiKeyAdminProps(): DatabaseCommonInteractionProps {
427
+ return {
428
+ userType: UserType.API,
429
+ tenantId: projectId,
430
+ userTenantAccessPermission: {
431
+ [projectId.toString()]: {
432
+ projectId: projectId,
433
+ permissions: [
434
+ {
435
+ permission: Permission.ProjectAdmin,
436
+ labelIds: [],
437
+ isBlockPermission: false,
438
+ _type: "UserPermission",
439
+ },
440
+ ],
441
+ _type: "UserTenantAccessPermission",
442
+ },
443
+ },
444
+ };
445
+ }
446
+
447
+ function makeRootProps(): DatabaseCommonInteractionProps {
448
+ return {
449
+ isRoot: true,
450
+ tenantId: projectId,
451
+ };
452
+ }
453
+
454
+ type ReadCheck = (
455
+ modelType: ModelTypeUnderTest,
456
+ query: Record<string, unknown>,
457
+ select: Record<string, unknown> | null,
458
+ props: DatabaseCommonInteractionProps,
459
+ ) => Promise<CheckReadPermissionType<BaseModel>>;
460
+
461
+ /*
462
+ * The real entry point every read in the product goes through - DatabaseService
463
+ * calls exactly this before handing anything to TypeORM.
464
+ */
465
+ const checkRead: ReadCheck = (
466
+ modelType: ModelTypeUnderTest,
467
+ query: Record<string, unknown>,
468
+ select: Record<string, unknown> | null,
469
+ props: DatabaseCommonInteractionProps,
470
+ ): Promise<CheckReadPermissionType<BaseModel>> => {
471
+ return ModelPermission.checkReadQueryPermission<BaseModel>(
472
+ modelType,
473
+ query as Query<BaseModel>,
474
+ select as Select<BaseModel> | null,
475
+ props,
476
+ );
477
+ };
478
+
479
+ describe("route 1 - a marked column named directly in the select", () => {
480
+ it.each(METHOD_MODELS)(
481
+ "lets the owner read every owner-only column on $name",
482
+ async (model: MethodModelUnderTest): Promise<void> => {
483
+ /*
484
+ * The owner sends no ownership filter at all here. They do not need to:
485
+ * the method models are CurrentUser-only, so TenantPermission stamps
486
+ * `userId = me` onto the query before the select is ever inspected, and
487
+ * that stamp is what pins the read.
488
+ */
489
+ for (const columnName of model.ownerOnlyColumnsSelectableByOwner) {
490
+ const result: CheckReadPermissionType<BaseModel> = await checkRead(
491
+ model.modelType,
492
+ {},
493
+ { [columnName]: true },
494
+ makeOwnerProps(),
495
+ );
496
+
497
+ expect((result.select as Record<string, unknown>)[columnName]).toBe(
498
+ true,
499
+ );
500
+ }
501
+ },
502
+ );
503
+
504
+ it.each(METHOD_MODELS)(
505
+ "lets the owner read every owner-only column on $name when they name their own id",
506
+ async (model: MethodModelUnderTest): Promise<void> => {
507
+ /*
508
+ * Only the subset the owner may actually select: a verificationCode is
509
+ * read: [] for everybody, so demanding it here would assert a leak.
510
+ */
511
+ for (const columnName of model.ownerOnlyColumnsSelectableByOwner) {
512
+ await expect(
513
+ checkRead(
514
+ model.modelType,
515
+ { userId: ownerUserId },
516
+ { [columnName]: true },
517
+ makeOwnerProps(),
518
+ ),
519
+ ).resolves.toBeDefined();
520
+ }
521
+ },
522
+ );
523
+
524
+ it.each(METHOD_MODELS)(
525
+ "refuses an admin reading another member's owner-only columns on $name",
526
+ async (model: MethodModelUnderTest): Promise<void> => {
527
+ for (const columnName of model.ownerOnlyColumns) {
528
+ await expect(
529
+ checkRead(
530
+ model.adminReadableModelType,
531
+ { userId: otherUserId },
532
+ { [columnName]: true },
533
+ makeAdminProps(),
534
+ ),
535
+ ).rejects.toThrow(NotAuthorizedException);
536
+ }
537
+ },
538
+ );
539
+
540
+ it.each(METHOD_MODELS)(
541
+ "refuses an admin sweeping $name for owner-only columns across the whole project",
542
+ async (model: MethodModelUnderTest): Promise<void> => {
543
+ /*
544
+ * The most valuable version of the attack asks for no user at all: one
545
+ * request, every row in the project, every credential on it.
546
+ */
547
+ for (const columnName of model.ownerOnlyColumns) {
548
+ await expect(
549
+ checkRead(
550
+ model.adminReadableModelType,
551
+ {},
552
+ { [columnName]: true },
553
+ makeAdminProps(),
554
+ ),
555
+ ).rejects.toThrow(NotAuthorizedException);
556
+ }
557
+ },
558
+ );
559
+
560
+ it.each(METHOD_MODELS)(
561
+ "lets an admin read their OWN owner-only columns on $name",
562
+ async (model: MethodModelUnderTest): Promise<void> => {
563
+ /*
564
+ * Being an administrator does not cost you your own settings page. The
565
+ * rule is about which ROW is being read, not about who is asking.
566
+ */
567
+ /*
568
+ * Only the subset the owner may actually select: a verificationCode is
569
+ * read: [] for everybody, so demanding it here would assert a leak.
570
+ */
571
+ for (const columnName of model.ownerOnlyColumnsSelectableByOwner) {
572
+ await expect(
573
+ checkRead(
574
+ model.adminReadableModelType,
575
+ { userId: adminUserId },
576
+ { [columnName]: true },
577
+ makeAdminProps(),
578
+ ),
579
+ ).resolves.toBeDefined();
580
+ }
581
+ },
582
+ );
583
+
584
+ it.each(METHOD_MODELS)(
585
+ "refuses an ownership filter on $name that is a query operator rather than an id",
586
+ async (model: MethodModelUnderTest): Promise<void> => {
587
+ /*
588
+ * NotEqual stringifies to the id it wraps, so a guard comparing only
589
+ * string values would read `userId != me` as `userId = me` and hand back
590
+ * every OTHER row in the project - the exact inversion of what was asked
591
+ * for. The type is checked before the value.
592
+ */
593
+ await expect(
594
+ checkRead(
595
+ model.adminReadableModelType,
596
+ { userId: new NotEqual<string>(adminUserId.toString()) },
597
+ { [model.ownerOnlyColumnReachableThroughRelation]: true },
598
+ makeAdminProps(),
599
+ ),
600
+ ).rejects.toThrow(NotAuthorizedException);
601
+ },
602
+ );
603
+
604
+ it.each(METHOD_MODELS)(
605
+ "refuses an API key with a project role reading owner-only columns on $name",
606
+ async (model: MethodModelUnderTest): Promise<void> => {
607
+ /*
608
+ * An API key holds project permissions and no user identity. There is no
609
+ * id to pin to, so there is no pinning, so there is no read. Fail closed.
610
+ */
611
+ await expect(
612
+ checkRead(
613
+ model.adminReadableModelType,
614
+ {},
615
+ { [model.ownerOnlyColumnReachableThroughRelation]: true },
616
+ makeApiKeyAdminProps(),
617
+ ),
618
+ ).rejects.toThrow(NotAuthorizedException);
619
+ },
620
+ );
621
+
622
+ it.each(METHOD_MODELS)(
623
+ "still lets an admin read the unmarked label columns of another member's $name",
624
+ async (model: MethodModelUnderTest): Promise<void> => {
625
+ /*
626
+ * This is the half of Phase 3 that has to keep working. An admin who
627
+ * cannot see that a row exists, what kind of thing it is and whether it
628
+ * is verified cannot audit anybody's on-call setup - the feature would be
629
+ * gone. Only the credential is withheld.
630
+ */
631
+ await expect(
632
+ checkRead(
633
+ model.adminReadableModelType,
634
+ { userId: otherUserId },
635
+ /*
636
+ * The label columns come from the fixture rather than a hardcoded
637
+ * list, because they genuinely differ per model: UserWebhook has no
638
+ * isVerified column at all - a webhook skips verification - so naming
639
+ * it here would fail that model for a reason that has nothing to do
640
+ * with this guard.
641
+ */
642
+ model.labelColumns.reduce(
643
+ (
644
+ selected: Record<string, boolean>,
645
+ columnName: string,
646
+ ): Record<string, boolean> => {
647
+ selected[columnName] = true;
648
+
649
+ return selected;
650
+ },
651
+ { _id: true } as Record<string, boolean>,
652
+ ),
653
+ makeAdminProps(),
654
+ ),
655
+ ).resolves.toBeDefined();
656
+ },
657
+ );
658
+
659
+ it.each(METHOD_MODELS)(
660
+ "lets root read owner-only columns on $name with no ownership filter",
661
+ async (model: MethodModelUnderTest): Promise<void> => {
662
+ /*
663
+ * Delivery reads these exact columns as root in order to actually send
664
+ * the notification. A phone number the pager cannot read is a phone that
665
+ * never rings, so root has to short-circuit before any of this.
666
+ */
667
+ for (const columnName of model.ownerOnlyColumns) {
668
+ await expect(
669
+ checkRead(
670
+ model.modelType,
671
+ {},
672
+ { [columnName]: true },
673
+ makeRootProps(),
674
+ ),
675
+ ).resolves.toBeDefined();
676
+ }
677
+ },
678
+ );
679
+ });
680
+
681
+ describe("route 2 - a marked column reached through a relation", () => {
682
+ it.each(METHOD_MODELS)(
683
+ "lets the owner read $name's identifier through the rule relation",
684
+ async (model: MethodModelUnderTest): Promise<void> => {
685
+ /*
686
+ * "Email: jane@example.com" on a user's own rule table. This is the
687
+ * legitimate use of canReadOnRelationQuery, and it must survive.
688
+ */
689
+ const result: CheckReadPermissionType<BaseModel> = await checkRead(
690
+ AdminReadableRuleModel,
691
+ {},
692
+ {
693
+ [model.relationColumnName]: {
694
+ [model.ownerOnlyColumnReachableThroughRelation]: true,
695
+ },
696
+ },
697
+ makeOwnerProps(),
698
+ );
699
+
700
+ expect(
701
+ (result.relationSelect as Record<string, unknown>)[
702
+ model.relationColumnName
703
+ ],
704
+ ).toBe(true);
705
+ },
706
+ );
707
+
708
+ it.each(METHOD_MODELS)(
709
+ "refuses an admin reading $name's identifier through another member's rule",
710
+ async (model: MethodModelUnderTest): Promise<void> => {
711
+ /*
712
+ * THE BLOCKER, EXACTLY. Nothing about the method table was widened here -
713
+ * only the rule table was - and the credential still walks out through
714
+ * the join, because checkRelationQueryPermission used to `continue` past
715
+ * every permission check the moment canReadOnRelationQuery was set. The
716
+ * outer query is the only thing that knows these related rows are not the
717
+ * caller's, which is why it has to be threaded into the traversal.
718
+ */
719
+ await expect(
720
+ checkRead(
721
+ AdminReadableRuleModel,
722
+ { userId: otherUserId },
723
+ {
724
+ [model.relationColumnName]: {
725
+ [model.ownerOnlyColumnReachableThroughRelation]: true,
726
+ },
727
+ },
728
+ makeAdminProps(),
729
+ ),
730
+ ).rejects.toThrow(NotAuthorizedException);
731
+ },
732
+ );
733
+
734
+ it.each(METHOD_MODELS)(
735
+ "refuses an admin sweeping every rule in the project for $name identifiers",
736
+ async (model: MethodModelUnderTest): Promise<void> => {
737
+ await expect(
738
+ checkRead(
739
+ AdminReadableRuleModel,
740
+ {},
741
+ {
742
+ [model.relationColumnName]: {
743
+ [model.ownerOnlyColumnReachableThroughRelation]: true,
744
+ },
745
+ },
746
+ makeAdminProps(),
747
+ ),
748
+ ).rejects.toThrow(NotAuthorizedException);
749
+ },
750
+ );
751
+
752
+ it.each(METHOD_MODELS)(
753
+ "lets an admin read $name's identifier through their OWN rule",
754
+ async (model: MethodModelUnderTest): Promise<void> => {
755
+ await expect(
756
+ checkRead(
757
+ AdminReadableRuleModel,
758
+ { userId: adminUserId },
759
+ {
760
+ [model.relationColumnName]: {
761
+ [model.ownerOnlyColumnReachableThroughRelation]: true,
762
+ },
763
+ },
764
+ makeAdminProps(),
765
+ ),
766
+ ).resolves.toBeDefined();
767
+ },
768
+ );
769
+
770
+ it.each(METHOD_MODELS)(
771
+ "refuses a relation read of $name when the ownership filter is a query operator",
772
+ async (model: MethodModelUnderTest): Promise<void> => {
773
+ await expect(
774
+ checkRead(
775
+ AdminReadableRuleModel,
776
+ { userId: new NotEqual<string>(adminUserId.toString()) },
777
+ {
778
+ [model.relationColumnName]: {
779
+ [model.ownerOnlyColumnReachableThroughRelation]: true,
780
+ },
781
+ },
782
+ makeAdminProps(),
783
+ ),
784
+ ).rejects.toThrow(NotAuthorizedException);
785
+ },
786
+ );
787
+
788
+ it.each(METHOD_MODELS)(
789
+ "refuses an API key with a project role reading $name through a rule",
790
+ async (model: MethodModelUnderTest): Promise<void> => {
791
+ await expect(
792
+ checkRead(
793
+ AdminReadableRuleModel,
794
+ {},
795
+ {
796
+ [model.relationColumnName]: {
797
+ [model.ownerOnlyColumnReachableThroughRelation]: true,
798
+ },
799
+ },
800
+ makeApiKeyAdminProps(),
801
+ ),
802
+ ).rejects.toThrow(NotAuthorizedException);
803
+ },
804
+ );
805
+
806
+ it.each(METHOD_MODELS)(
807
+ "still lets an admin label another member's rule with $name's unmarked column",
808
+ async (model: MethodModelUnderTest): Promise<void> => {
809
+ /*
810
+ * The admin rule table still renders "Webhook: My Slack" and "Push:
811
+ * Jane's iPhone". Naming the method is not the same as being handed it.
812
+ */
813
+ await expect(
814
+ checkRead(
815
+ AdminReadableRuleModel,
816
+ { userId: otherUserId },
817
+ {
818
+ _id: true,
819
+ [model.relationColumnName]: {
820
+ [model.labelColumnReachableThroughRelation]: true,
821
+ },
822
+ },
823
+ makeAdminProps(),
824
+ ),
825
+ ).resolves.toBeDefined();
826
+ },
827
+ );
828
+
829
+ it.each(METHOD_MODELS)(
830
+ "refuses the whole select when a marked $name column rides along with unmarked ones",
831
+ async (model: MethodModelUnderTest): Promise<void> => {
832
+ /*
833
+ * A refusal that only fires for a select containing nothing BUT the
834
+ * credential is a refusal an attacker routes around by asking for one
835
+ * extra column.
836
+ */
837
+ await expect(
838
+ checkRead(
839
+ AdminReadableRuleModel,
840
+ { userId: otherUserId },
841
+ {
842
+ _id: true,
843
+ [model.relationColumnName]: {
844
+ [model.labelColumnReachableThroughRelation]: true,
845
+ [model.ownerOnlyColumnReachableThroughRelation]: true,
846
+ },
847
+ },
848
+ makeAdminProps(),
849
+ ),
850
+ ).rejects.toThrow(NotAuthorizedException);
851
+ },
852
+ );
853
+
854
+ it("lets root read every method identifier through any rule", async () => {
855
+ for (const model of METHOD_MODELS) {
856
+ await expect(
857
+ checkRead(
858
+ AdminReadableRuleModel,
859
+ {},
860
+ {
861
+ [model.relationColumnName]: {
862
+ [model.ownerOnlyColumnReachableThroughRelation]: true,
863
+ },
864
+ },
865
+ makeRootProps(),
866
+ ),
867
+ ).resolves.toBeDefined();
868
+ }
869
+ });
870
+ });
871
+
872
+ describe("route 3 - a marked column injected into the select as a sort key", () => {
873
+ /*
874
+ * DatabaseService adds sorted columns to the select AFTER ModelPermission has
875
+ * finished, validating them only with hasColumn/isEntityColumn. That is the
876
+ * gap: the permission layer never sees the column at all. The private method
877
+ * is called directly here because the public path (_findBy) needs a live
878
+ * database connection, and the injection is the whole of the behaviour under
879
+ * test - this is the production method, not a restatement of it.
880
+ */
881
+ type SortInjector = {
882
+ addSortColumnsToSelect: (findBy: FindBy<BaseModel>) => Array<string>;
883
+ };
884
+
885
+ function injectSortColumns(
886
+ modelType: ModelTypeUnderTest,
887
+ findBy: FindBy<BaseModel>,
888
+ ): Array<string> {
889
+ const service: DatabaseService<BaseModel> = new DatabaseService<BaseModel>(
890
+ modelType,
891
+ );
892
+
893
+ return (service as unknown as SortInjector).addSortColumnsToSelect(findBy);
894
+ }
895
+
896
+ it.each(METHOD_MODELS)(
897
+ "does not smuggle an owner-only $name column into the select via sort",
898
+ (model: MethodModelUnderTest): void => {
899
+ for (const columnName of model.ownerOnlyColumns) {
900
+ const findBy: FindBy<BaseModel> = {
901
+ query: {},
902
+ select: { _id: true } as Select<BaseModel>,
903
+ sort: { [columnName]: SortOrder.Ascending } as Record<
904
+ string,
905
+ SortOrder
906
+ >,
907
+ limit: 10,
908
+ skip: 0,
909
+ props: makeOwnerProps(),
910
+ };
911
+
912
+ expect(injectSortColumns(model.modelType, findBy)).toEqual([]);
913
+ expect(
914
+ (findBy.select as Record<string, unknown>)[columnName],
915
+ ).toBeUndefined();
916
+ }
917
+ },
918
+ );
919
+
920
+ it.each(METHOD_MODELS)(
921
+ "still adds an unmarked sorted column on $name to the select",
922
+ (model: MethodModelUnderTest): void => {
923
+ /*
924
+ * The mechanism this method exists for has to keep working, or the fix
925
+ * would just be "delete the feature". Sorting on an ordinary column while
926
+ * a relation is selected still needs the column in the select or TypeORM
927
+ * fails the query outright.
928
+ */
929
+ const findBy: FindBy<BaseModel> = {
930
+ query: {},
931
+ select: { _id: true } as Select<BaseModel>,
932
+ // Per-model: UserWebhook has no isVerified column to sort on.
933
+ sort: { [model.unmarkedSortColumn]: SortOrder.Ascending } as Record<
934
+ string,
935
+ SortOrder
936
+ >,
937
+ limit: 10,
938
+ skip: 0,
939
+ props: makeOwnerProps(),
940
+ };
941
+
942
+ expect(injectSortColumns(model.modelType, findBy)).toEqual([
943
+ model.unmarkedSortColumn,
944
+ ]);
945
+ expect(
946
+ (findBy.select as Record<string, unknown>)[model.unmarkedSortColumn],
947
+ ).toBe(true);
948
+ },
949
+ );
950
+
951
+ it("leaves a marked column alone when the caller already selected it legitimately", () => {
952
+ /*
953
+ * An owner who passed route 1 has the column in their select already, so
954
+ * the injector never reaches it - the exclusion costs a legitimate reader
955
+ * nothing at all.
956
+ */
957
+ const findBy: FindBy<BaseModel> = {
958
+ query: {},
959
+ select: { _id: true, webhookUrl: true } as Select<BaseModel>,
960
+ sort: { webhookUrl: SortOrder.Ascending } as Record<string, SortOrder>,
961
+ limit: 10,
962
+ skip: 0,
963
+ props: makeOwnerProps(),
964
+ };
965
+
966
+ expect(injectSortColumns(UserWebhook, findBy)).toEqual([]);
967
+ expect((findBy.select as Record<string, unknown>)["webhookUrl"]).toBe(true);
968
+ });
969
+
970
+ it("still injects marked sort columns for root", () => {
971
+ const findBy: FindBy<BaseModel> = {
972
+ query: {},
973
+ select: { _id: true } as Select<BaseModel>,
974
+ sort: { webhookUrl: SortOrder.Ascending } as Record<string, SortOrder>,
975
+ limit: 10,
976
+ skip: 0,
977
+ props: makeRootProps(),
978
+ };
979
+
980
+ expect(injectSortColumns(UserWebhook, findBy)).toEqual(["webhookUrl"]);
981
+ expect((findBy.select as Record<string, unknown>)["webhookUrl"]).toBe(true);
982
+ });
983
+ });
984
+
985
+ describe("route 4 - a marked column used as a query predicate", () => {
986
+ it.each(METHOD_MODELS)(
987
+ "lets the owner filter their own $name rows on an owner-only column",
988
+ async (model: MethodModelUnderTest): Promise<void> => {
989
+ await expect(
990
+ checkRead(
991
+ model.modelType,
992
+ { [model.ownerOnlyColumnReachableThroughRelation]: "probe-value" },
993
+ { _id: true },
994
+ makeOwnerProps(),
995
+ ),
996
+ ).resolves.toBeDefined();
997
+ },
998
+ );
999
+
1000
+ it.each(METHOD_MODELS)(
1001
+ "refuses an admin probing $name for a value across the project",
1002
+ async (model: MethodModelUnderTest): Promise<void> => {
1003
+ /*
1004
+ * Nothing is selected here. Equality on a secret is a confirm/deny
1005
+ * oracle, and a few thousand of these read the value out without a single
1006
+ * row ever being returned - so a WHERE is held to the same standard as a
1007
+ * SELECT.
1008
+ */
1009
+ await expect(
1010
+ checkRead(
1011
+ model.adminReadableModelType,
1012
+ { [model.ownerOnlyColumnReachableThroughRelation]: "probe-value" },
1013
+ { _id: true },
1014
+ makeAdminProps(),
1015
+ ),
1016
+ ).rejects.toThrow(NotAuthorizedException);
1017
+ },
1018
+ );
1019
+
1020
+ it.each(METHOD_MODELS)(
1021
+ "refuses an admin probing another member's $name rows",
1022
+ async (model: MethodModelUnderTest): Promise<void> => {
1023
+ await expect(
1024
+ checkRead(
1025
+ model.adminReadableModelType,
1026
+ {
1027
+ userId: otherUserId,
1028
+ [model.ownerOnlyColumnReachableThroughRelation]: "probe-value",
1029
+ },
1030
+ { _id: true },
1031
+ makeAdminProps(),
1032
+ ),
1033
+ ).rejects.toThrow(NotAuthorizedException);
1034
+ },
1035
+ );
1036
+
1037
+ it.each(METHOD_MODELS)(
1038
+ "lets an admin filter their OWN $name rows on an owner-only column",
1039
+ async (model: MethodModelUnderTest): Promise<void> => {
1040
+ await expect(
1041
+ checkRead(
1042
+ model.adminReadableModelType,
1043
+ {
1044
+ userId: adminUserId,
1045
+ [model.ownerOnlyColumnReachableThroughRelation]: "probe-value",
1046
+ },
1047
+ { _id: true },
1048
+ makeAdminProps(),
1049
+ ),
1050
+ ).resolves.toBeDefined();
1051
+ },
1052
+ );
1053
+
1054
+ it.each(METHOD_MODELS)(
1055
+ "refuses an admin probing $name through a relation filter on a rule",
1056
+ async (model: MethodModelUnderTest): Promise<void> => {
1057
+ /*
1058
+ * The predicate route has the same nested variant as the select route:
1059
+ * `{ userWebhook: { webhookUrl: x } }` probes the identical value one
1060
+ * level out.
1061
+ */
1062
+ await expect(
1063
+ checkRead(
1064
+ AdminReadableRuleModel,
1065
+ {
1066
+ userId: otherUserId,
1067
+ [model.relationColumnName]: {
1068
+ [model.ownerOnlyColumnReachableThroughRelation]: "probe-value",
1069
+ },
1070
+ },
1071
+ { _id: true },
1072
+ makeAdminProps(),
1073
+ ),
1074
+ ).rejects.toThrow(NotAuthorizedException);
1075
+ },
1076
+ );
1077
+
1078
+ it.each(METHOD_MODELS)(
1079
+ "lets the owner filter their own rules through a $name relation predicate",
1080
+ async (model: MethodModelUnderTest): Promise<void> => {
1081
+ await expect(
1082
+ checkRead(
1083
+ AdminReadableRuleModel,
1084
+ {
1085
+ [model.relationColumnName]: {
1086
+ [model.ownerOnlyColumnReachableThroughRelation]: "probe-value",
1087
+ },
1088
+ },
1089
+ { _id: true },
1090
+ makeOwnerProps(),
1091
+ ),
1092
+ ).resolves.toBeDefined();
1093
+ },
1094
+ );
1095
+
1096
+ it.each(METHOD_MODELS)(
1097
+ "lets root probe $name on an owner-only column",
1098
+ async (model: MethodModelUnderTest): Promise<void> => {
1099
+ await expect(
1100
+ checkRead(
1101
+ model.modelType,
1102
+ { [model.ownerOnlyColumnReachableThroughRelation]: "probe-value" },
1103
+ { _id: true },
1104
+ makeRootProps(),
1105
+ ),
1106
+ ).resolves.toBeDefined();
1107
+ },
1108
+ );
1109
+ });
1110
+
1111
+ describe("the verification codes nobody may read, owner included", () => {
1112
+ /*
1113
+ * These four columns are the one place where @OwnerOnlyColumn is NOT the thing
1114
+ * doing the work, and that is worth pinning explicitly.
1115
+ *
1116
+ * A live verification code is not a privacy question, it is an account-takeover
1117
+ * one: reading somebody's code is claiming their notification channel, and
1118
+ * claiming their channel is claiming their pages. So the column list refuses
1119
+ * EVERYONE - `read: []` - rather than refusing everyone-except-the-owner. The
1120
+ * owner has no need to read it back either; they received it out of band, and
1121
+ * they submit it rather than fetch it.
1122
+ *
1123
+ * The @OwnerOnlyColumn marker sits on top as belt and braces. If somebody later
1124
+ * widens that read list - to build an admin "resend code" screen, say - the
1125
+ * marker is what stops the widening from silently becoming cross-user, and
1126
+ * these assertions are what tell them the empty list was deliberate rather than
1127
+ * an oversight.
1128
+ */
1129
+ it.each(WRITE_ONLY_VERIFICATION_CODE_MODELS)(
1130
+ "refuses even the OWNER selecting verificationCode on %p",
1131
+ async (modelType: ModelTypeUnderTest): Promise<void> => {
1132
+ await expect(
1133
+ checkRead(
1134
+ modelType,
1135
+ { userId: ownerUserId },
1136
+ { verificationCode: true },
1137
+ makeOwnerProps(),
1138
+ ),
1139
+ ).rejects.toThrow();
1140
+ },
1141
+ );
1142
+
1143
+ it.each(WRITE_ONLY_VERIFICATION_CODE_MODELS)(
1144
+ "refuses an administrator selecting verificationCode on another member's %p",
1145
+ async (modelType: ModelTypeUnderTest): Promise<void> => {
1146
+ await expect(
1147
+ checkRead(
1148
+ modelType,
1149
+ { userId: ownerUserId },
1150
+ { verificationCode: true },
1151
+ makeAdminProps(),
1152
+ ),
1153
+ ).rejects.toThrow();
1154
+ },
1155
+ );
1156
+
1157
+ it.each(WRITE_ONLY_VERIFICATION_CODE_MODELS)(
1158
+ "still lets the verification flow itself read it as root on %p",
1159
+ async (modelType: ModelTypeUnderTest): Promise<void> => {
1160
+ /*
1161
+ * The code has to be readable by SOMETHING or verification cannot work.
1162
+ * That something is the server verifying a submitted code, which runs as
1163
+ * root and short-circuits every check above. If this ever starts failing,
1164
+ * nobody can verify a notification method again.
1165
+ */
1166
+ await expect(
1167
+ checkRead(
1168
+ modelType,
1169
+ { userId: ownerUserId },
1170
+ { verificationCode: true },
1171
+ makeRootProps(),
1172
+ ),
1173
+ ).resolves.toBeDefined();
1174
+ },
1175
+ );
1176
+ });
1177
+
1178
+ describe("the production models are still owner-scoped without any of this", () => {
1179
+ it.each(METHOD_MODELS)(
1180
+ "refuses a plain member naming another user on $name outright",
1181
+ async (model: MethodModelUnderTest): Promise<void> => {
1182
+ /*
1183
+ * The owner-only guard is the second lock, not the first. On the
1184
+ * production models the table read is still [CurrentUser], so
1185
+ * TenantPermission rejects a member who names somebody else before the
1186
+ * select is ever considered. Phase 3 removes that first lock for admins
1187
+ * on purpose; this test is here so that a future change which removes it
1188
+ * for everyone is not mistaken for a passing suite.
1189
+ */
1190
+ await expect(
1191
+ checkRead(
1192
+ model.modelType,
1193
+ { userId: otherUserId },
1194
+ { _id: true },
1195
+ makeOwnerProps(),
1196
+ ),
1197
+ ).rejects.toThrow(NotAuthorizedException);
1198
+ },
1199
+ );
1200
+
1201
+ it.each(METHOD_MODELS)(
1202
+ "refuses a plain member naming another user on the admin-readable $name too",
1203
+ async (model: MethodModelUnderTest): Promise<void> => {
1204
+ /*
1205
+ * Widening the table read to ProjectAdmin does not widen it to everybody:
1206
+ * a member holding no role still intersects on CurrentUser alone and is
1207
+ * still force-scoped to their own rows.
1208
+ */
1209
+ await expect(
1210
+ checkRead(
1211
+ model.adminReadableModelType,
1212
+ { userId: otherUserId },
1213
+ { _id: true },
1214
+ makeOwnerProps(),
1215
+ ),
1216
+ ).rejects.toThrow(NotAuthorizedException);
1217
+ },
1218
+ );
1219
+ });