@oneuptime/common 12.0.7 → 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.
- package/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +1 -1
- package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +1 -1
- package/Models/DatabaseModels/AIConversation.ts +32 -0
- package/Models/DatabaseModels/AIConversationMessage.ts +41 -0
- package/Models/DatabaseModels/AlertEpisodeMember.ts +27 -0
- package/Models/DatabaseModels/IncidentEpisodeMember.ts +28 -0
- package/Models/DatabaseModels/Index.ts +12 -4
- package/Models/DatabaseModels/{TelemetryEntity.ts → InventoryItem.ts} +184 -9
- package/Models/DatabaseModels/InventoryItemCustomField.ts +434 -0
- package/Models/DatabaseModels/{TelemetryEntityRelationship.ts → InventoryItemRelationship.ts} +33 -7
- package/Models/DatabaseModels/NetworkDevice.ts +141 -0
- package/Models/DatabaseModels/NetworkDeviceLink.ts +699 -0
- package/Models/DatabaseModels/NetworkDeviceLinkRule.ts +467 -0
- package/Models/DatabaseModels/NetworkTopologySuppression.ts +429 -0
- package/Models/DatabaseModels/OnCallDutyPolicyFeed.ts +9 -0
- package/Models/DatabaseModels/Project.ts +78 -0
- package/Models/DatabaseModels/UserCall.ts +42 -0
- package/Models/DatabaseModels/UserEmail.ts +44 -0
- package/Models/DatabaseModels/UserNotificationRule.ts +425 -55
- package/Models/DatabaseModels/UserOnCallLogTimeline.ts +24 -2
- package/Models/DatabaseModels/UserPush.ts +49 -0
- package/Models/DatabaseModels/UserSMS.ts +43 -0
- package/Models/DatabaseModels/UserTelegram.ts +59 -0
- package/Models/DatabaseModels/UserWebhook.ts +52 -0
- package/Models/DatabaseModels/UserWhatsApp.ts +41 -0
- package/Models/DatabaseModels/WorkflowLog.ts +38 -0
- package/Models/DatabaseModels/WorkflowVariable.ts +12 -0
- package/Server/API/AIChatAPI.ts +315 -1
- package/Server/API/DashboardAPI.ts +217 -1
- package/Server/API/OnCallReadinessAPI.ts +841 -0
- package/Server/API/TeamComplianceAPI.ts +69 -17
- package/Server/API/TelemetryAPI.ts +220 -12
- package/Server/API/UserAPI.ts +16 -1
- package/Server/EnvironmentConfig.ts +52 -0
- package/Server/Infrastructure/Postgres/DataSourceOptions.ts +22 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.ts +4 -4
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.ts +5 -5
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786551733814-MigrationName.ts +41 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.ts +35 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.ts +82 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.ts +91 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.ts +255 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.ts +107 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.ts +90 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.ts +39 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.ts +59 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +24 -0
- package/Server/Infrastructure/Queue.ts +78 -13
- package/Server/Middleware/MasterAdminAuthorization.ts +11 -6
- package/Server/Middleware/PublicDashboardRateLimit.ts +593 -0
- package/Server/Services/AIService.ts +7 -0
- package/Server/Services/AlertEpisodeStateTimelineService.ts +29 -0
- package/Server/Services/AlertSeverityService.ts +63 -0
- package/Server/Services/DashboardService.ts +9 -10
- package/Server/Services/DatabaseService.ts +32 -2
- package/Server/Services/IncidentEpisodeStateTimelineService.ts +29 -0
- package/Server/Services/IncidentSeverityService.ts +76 -0
- package/Server/Services/Index.ts +12 -4
- package/Server/Services/InventoryItemCustomFieldService.ts +9 -0
- package/Server/Services/{TelemetryEntityRelationshipService.ts → InventoryItemRelationshipService.ts} +7 -4
- package/Server/Services/{TelemetryEntityService.ts → InventoryItemService.ts} +203 -21
- package/Server/Services/LogAggregationService.ts +45 -8
- package/Server/Services/MetricAggregationService.ts +121 -0
- package/Server/Services/MetricService.ts +7 -7
- package/Server/Services/NetworkDeviceLinkRuleService.ts +10 -0
- package/Server/Services/NetworkDeviceLinkService.ts +84 -0
- package/Server/Services/NetworkDeviceService.ts +140 -0
- package/Server/Services/NetworkSiteService.ts +77 -25
- package/Server/Services/NetworkTopologySuppressionService.ts +84 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +41 -29
- package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +8 -0
- package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +62 -13
- package/Server/Services/OnCallDutyPolicyScheduleService.ts +61 -1
- package/Server/Services/OnCallNotificationAlertingService.ts +742 -0
- package/Server/Services/OnCallReadinessService.ts +2803 -0
- package/Server/Services/OnCallSetupReminderService.ts +955 -0
- package/Server/Services/ProfileAggregationService.ts +123 -0
- package/Server/Services/StatusPageService.ts +9 -10
- package/Server/Services/TeamComplianceService.ts +429 -252
- package/Server/Services/UserCallService.ts +26 -1
- package/Server/Services/UserEmailService.ts +26 -1
- package/Server/Services/UserNotificationRuleAdminService.ts +1183 -0
- package/Server/Services/UserNotificationRuleService.ts +3812 -333
- package/Server/Services/UserOnCallLogService.ts +561 -48
- package/Server/Services/UserPushService.ts +29 -0
- package/Server/Services/UserService.ts +11 -0
- package/Server/Services/UserSmsService.ts +26 -1
- package/Server/Services/UserTelegramService.ts +24 -1
- package/Server/Services/UserWebhookService.ts +28 -1
- package/Server/Services/UserWhatsAppService.ts +24 -1
- package/Server/Types/Database/Permissions/BasePermission.ts +19 -0
- package/Server/Types/Database/Permissions/CreatePermission.ts +164 -0
- package/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.ts +340 -0
- package/Server/Types/Database/Permissions/QueryPermission.ts +48 -0
- package/Server/Types/Database/Permissions/TenantPermission.ts +8 -1
- package/Server/Types/Workflow/Components/API/Delete.ts +1 -1
- package/Server/Types/Workflow/Components/API/Get.ts +1 -1
- package/Server/Types/Workflow/Components/API/Patch.ts +1 -1
- package/Server/Types/Workflow/Components/API/Post.ts +1 -1
- package/Server/Types/Workflow/Components/API/Put.ts +1 -1
- package/Server/Types/Workflow/Components/API/Utils.ts +44 -1
- package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +29 -5
- package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +18 -10
- package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +55 -0
- package/Server/Types/Workflow/Components/Conditions/IfElse.ts +3 -17
- package/Server/Types/Workflow/Components/Email.ts +25 -7
- package/Server/Types/Workflow/Components/JavaScript.ts +10 -3
- package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +1 -1
- package/Server/Types/Workflow/TriggerCode.ts +12 -0
- package/Server/Types/Workflow/Workflow.ts +5 -0
- package/Server/Utils/AI/Chat/ChatAgentRunner.ts +643 -48
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +32 -3
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +20 -6
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +7 -0
- package/Server/Utils/AI/Toolbox/AIActionTools.ts +2 -2
- package/Server/Utils/AI/Toolbox/AIMetaTools.ts +863 -0
- package/Server/Utils/AI/Toolbox/AlertTools.ts +177 -15
- package/Server/Utils/AI/Toolbox/IncidentTools.ts +191 -10
- package/Server/Utils/AI/Toolbox/Index.ts +48 -0
- package/Server/Utils/AI/Toolbox/MonitorTools.ts +298 -11
- package/Server/Utils/AI/Toolbox/NoteWriteTools.ts +295 -0
- package/Server/Utils/AI/Toolbox/OnCallTools.ts +1246 -0
- package/Server/Utils/AI/Toolbox/RunbookTools.ts +424 -0
- package/Server/Utils/AI/Toolbox/SloTools.ts +456 -0
- package/Server/Utils/AI/Toolbox/StatusPageTools.ts +559 -0
- package/Server/Utils/AI/Toolbox/TeamTools.ts +327 -0
- package/Server/Utils/AI/Toolbox/TimelineTools.ts +615 -0
- package/Server/Utils/AI/Toolbox/WorkflowProbeTools.ts +664 -0
- package/Server/Utils/ClientIp.ts +221 -0
- package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +47 -0
- package/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.ts +163 -0
- package/Server/Utils/Dashboard/PublicDashboardSloWidget.ts +147 -0
- package/Server/Utils/Express.ts +12 -17
- package/Server/Utils/LLM/LLMService.ts +85 -8
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +204 -10
- package/Server/Utils/SSRFProtection.ts +98 -23
- package/Server/Utils/StartServer.ts +12 -3
- package/Server/Utils/Telemetry/EntityRegistry.ts +205 -18
- package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +689 -0
- package/Server/Utils/Telemetry/TelemetryEntity.ts +160 -52
- package/Server/Utils/VM/VMAPI.ts +56 -8
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +7 -3
- package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +2146 -0
- package/Tests/App/Dashboard/CreateWorkflowModal.test.tsx +561 -0
- package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +2470 -0
- package/Tests/App/Dashboard/MonitorCriteriaAttributeFilter.test.tsx +574 -0
- package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +1897 -0
- package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +3606 -0
- package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +784 -0
- package/Tests/App/Dashboard/OnCallRulesTable.test.tsx +1119 -0
- package/Tests/App/Dashboard/SloWidgetFetching.test.tsx +531 -0
- package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +1312 -0
- package/Tests/App/Dashboard/UserSettingsSetupChecklistPage.test.tsx +1390 -0
- package/Tests/Models/InventoryItemModel.test.ts +174 -0
- package/Tests/Models/InventoryItemNaming.test.ts +302 -0
- package/Tests/Server/API/AIChatCancelAndFeedback.test.ts +437 -0
- package/Tests/Server/API/DashboardPublicRateLimit.test.ts +659 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +18 -0
- package/Tests/Server/API/DashboardPublicSloAPI.test.ts +880 -0
- package/Tests/Server/API/Helpers.ts +24 -15
- package/Tests/Server/API/OnCallReadinessAPI.test.ts +2680 -0
- package/Tests/Server/API/OnCallSetupReminderAPI.test.ts +915 -0
- package/Tests/Server/API/UserProjectsAPI.test.ts +478 -4
- package/Tests/Server/Infrastructure/Postgres/EpisodeMemberNotifyIndexesMigration.test.ts +533 -0
- package/Tests/Server/Infrastructure/Postgres/InventoryItemArchiveMigration.test.ts +213 -0
- package/Tests/Server/Infrastructure/Postgres/RenameInventoryItemMigration.test.ts +432 -0
- package/Tests/Server/Infrastructure/Queue.test.ts +293 -0
- package/Tests/Server/Middleware/PublicDashboardRateLimit.test.ts +1645 -0
- package/Tests/Server/Services/AdminRuleEditGuards.test.ts +2848 -0
- package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1393 -0
- package/Tests/Server/Services/EpisodeRuleSeverityRepair.test.ts +1802 -0
- package/Tests/Server/Services/EpisodeStateTimelineNote.test.ts +304 -0
- package/Tests/Server/Services/InventoryItemDisplayName.test.ts +339 -0
- package/Tests/Server/Services/InventoryItemManualCreate.test.ts +248 -0
- package/Tests/Server/Services/IpAllowlistSpoofing.test.ts +450 -0
- package/Tests/Server/Services/LogAggregationService.test.ts +235 -1
- package/Tests/Server/Services/MetricAggregationService.test.ts +231 -0
- package/Tests/Server/Services/MetricEntityMVKeyParity.test.ts +80 -29
- package/Tests/Server/Services/MetricServiceAggregate.test.ts +30 -30
- package/Tests/Server/Services/NetworkSiteService.test.ts +18 -3
- package/Tests/Server/Services/NotificationChannelEventCoverage.test.ts +1728 -0
- package/Tests/Server/Services/NotificationDeletionImpact.test.ts +2402 -0
- package/Tests/Server/Services/OnCallDutyPolicyExecutionLogTimelineGapFeed.test.ts +394 -0
- package/Tests/Server/Services/OnCallNotificationFallback.test.ts +1744 -0
- package/Tests/Server/Services/OnCallReadinessService.test.ts +4295 -0
- package/Tests/Server/Services/OnCallSetupReminder.test.ts +1272 -0
- package/Tests/Server/Services/OnCallWeeklyReadinessDigest.test.ts +1021 -0
- package/Tests/Server/Services/ProfileAggregationService.test.ts +296 -0
- package/Tests/Server/Services/SeverityCreationRuleBackfill.test.ts +1536 -0
- package/Tests/Server/Services/SeverityRuleBackfill.test.ts +1818 -0
- package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +1845 -0
- package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +1394 -0
- package/Tests/Server/Services/UserNotificationRuleDefaultCreation.test.ts +1166 -0
- package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1468 -0
- package/Tests/Server/Services/UserOnCallLogNoNotificationRules.test.ts +1457 -0
- package/Tests/Server/Types/Database/Permissions/AdminNotificationRuleAccess.test.ts +1546 -0
- package/Tests/Server/Types/Database/Permissions/CreateOwnershipScoping.test.ts +529 -0
- package/Tests/Server/Types/Database/Permissions/OwnerOnlyColumns.test.ts +1219 -0
- package/Tests/Server/Types/Database/Permissions/UserNotificationRuleScoping.test.ts +1089 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +2 -1
- package/Tests/Server/Types/Workflow/Components/ApiComponentHeaders.test.ts +192 -0
- package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +190 -0
- package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +44 -14
- package/Tests/Server/Types/Workflow/Components/Email.test.ts +151 -0
- package/Tests/Server/Types/Workflow/Components/IfElse.test.ts +98 -0
- package/Tests/Server/Types/Workflow/Components/JavaScript.test.ts +51 -0
- package/Tests/Server/Utils/AI/AIMetaTools.test.ts +586 -0
- package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +582 -0
- package/Tests/Server/Utils/AI/ChatAgentRunner.test.ts +726 -0
- package/Tests/Server/Utils/AI/IncidentToolsFilters.test.ts +315 -0
- package/Tests/Server/Utils/AI/LLMServiceStopReason.test.ts +314 -0
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +26 -3
- package/Tests/Server/Utils/AI/NoteWriteTools.test.ts +268 -0
- package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +169 -0
- package/Tests/Server/Utils/AI/OnCallTools.test.ts +664 -0
- package/Tests/Server/Utils/AI/RunbookTools.test.ts +325 -0
- package/Tests/Server/Utils/AI/SloTools.test.ts +306 -0
- package/Tests/Server/Utils/AI/StatusPageTools.test.ts +391 -0
- package/Tests/Server/Utils/AI/TeamTools.test.ts +257 -0
- package/Tests/Server/Utils/AI/TimelineTools.test.ts +472 -0
- package/Tests/Server/Utils/AI/WorkflowProbeTools.test.ts +428 -0
- package/Tests/Server/Utils/AnalyticsDatabase/QuerySettingsHelper.test.ts +152 -0
- package/Tests/Server/Utils/ClientIp.test.ts +438 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +171 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.test.ts +383 -0
- package/Tests/Server/Utils/EntityRegistryRowFence.test.ts +23 -25
- package/Tests/Server/Utils/MicrosoftTeamsWebhookUrlValidation.test.ts +6 -0
- package/Tests/Server/Utils/Monitor/Criteria/DnssecMonitorCriteria.test.ts +307 -0
- package/Tests/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.test.ts +468 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorTelemetryDeepLinks.test.ts +460 -0
- package/Tests/Server/Utils/ResponseRateLimitStatusCodes.test.ts +137 -0
- package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +40 -8
- package/Tests/Server/Utils/SSRFProtectionUserInfo.test.ts +351 -0
- package/Tests/Server/Utils/Telemetry/EntityRegistryRetirement.test.ts +531 -0
- package/Tests/Server/Utils/Telemetry/InventoryEntityRegistry.test.ts +322 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +356 -39
- package/Tests/Server/Utils/VM/VMAPISubstitution.test.ts +243 -0
- package/Tests/Types/IP/IP.test.ts +263 -0
- package/Tests/Types/IP/IPWhitelist.test.ts +197 -0
- package/Tests/Types/IP/IPv6.test.ts +12 -1
- package/Tests/Types/Monitor/SnmpOid.test.ts +64 -0
- package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +110 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeAudit.test.ts +106 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeDifferential.test.ts +511 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageEndToEnd.test.ts +489 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageGapTolerance.test.ts +479 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageState.test.ts +822 -0
- package/Tests/Types/SerializableObjectDictionaryImportCycle.test.ts +197 -0
- package/Tests/Types/Telemetry/EntityTypeGroups.test.ts +140 -0
- package/Tests/Types/Workflow/BaseModelComponents.test.ts +429 -0
- package/Tests/Types/Workflow/Components/BaseModel.test.ts +225 -0
- package/Tests/Types/Workflow/IntegrationCredentialMetadata.test.ts +100 -0
- package/Tests/Types/Workflow/StepTrace.test.ts +235 -0
- package/Tests/Types/Workflow/TemplateSyntax.test.ts +491 -0
- package/Tests/Types/Workflow/Templates.test.ts +1218 -0
- package/Tests/UI/Components/ActiveFilterChipsOpenRoute.test.tsx +82 -0
- package/Tests/UI/Components/ComponentsModal.test.tsx +564 -7
- package/Tests/UI/Components/CustomTimeRangeModal.test.tsx +459 -0
- package/Tests/UI/Components/DictionaryAttributeFilterRow.test.tsx +477 -0
- package/Tests/UI/Components/Forms/AnchoredFieldPopupKeyboard.test.tsx +382 -0
- package/Tests/UI/Components/Forms/ColorPickerPicking.test.tsx +569 -0
- package/Tests/UI/Components/Forms/ValidationJSON.test.ts +241 -0
- package/Tests/UI/Components/KeyboardShortcut.test.tsx +95 -0
- package/Tests/UI/Components/LogDetailsPanelCrossSignal.test.tsx +448 -0
- package/Tests/UI/Components/LogTimeRangePicker.test.tsx +42 -0
- package/Tests/UI/Components/LogsTableCrossLinks.test.tsx +263 -0
- package/Tests/UI/Components/ModalPortalDismissal.test.tsx +90 -0
- package/Tests/UI/Components/PendingProjectInvitations.test.tsx +913 -0
- package/Tests/UI/Components/SimpleLogViewer.test.tsx +228 -0
- package/Tests/UI/Components/TableRowSelectability.test.tsx +312 -0
- package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +49 -7
- package/Tests/UI/Components/TimeRangePickerDropdown.test.tsx +325 -0
- package/Tests/UI/Components/Workflow/GraphLint.test.ts +893 -0
- package/Tests/UI/Components/Workflow/GraphLintSummary.test.ts +755 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditor.test.ts +522 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditorServerContract.test.ts +193 -0
- package/Tests/UI/Components/Workflow/ModelSchema.test.ts +388 -0
- package/Tests/UI/Components/Workflow/RunStatusWatcher.test.ts +210 -0
- package/Tests/UI/Components/Workflow/StepTraceViewer.test.tsx +256 -0
- package/Tests/UI/Components/Workflow/UseRunWatch.test.tsx +665 -0
- package/Tests/UI/Components/Workflow/Utils.test.ts +192 -0
- package/Tests/UI/Components/Workflow/WorkflowIssuesModal.test.tsx +485 -0
- package/Tests/UI/Components/Workflow/WorkflowLogModal.test.tsx +478 -0
- package/Tests/UI/Components/Workflow/WorkflowStatusBar.test.tsx +379 -0
- package/Tests/UI/EsbuildConfig.test.ts +607 -0
- package/Tests/UI/Monitor/MonitorStepCriteriaView.test.tsx +432 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +5 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +11 -4
- package/Tests/UI/Utils/ModelAPICreateMiscData.test.ts +94 -0
- package/Tests/UI/Utils/Platform.test.ts +147 -0
- package/Tests/UI/Utils/ProjectInvitationDisplay.test.ts +357 -0
- package/Tests/Utils/Monitor/NetworkDeviceLinkRuleUtil.test.ts +198 -0
- package/Tests/Utils/Monitor/NetworkDeviceRoleUtil.test.ts +514 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +727 -0
- package/Tests/Utils/Schema/AnalyticsModelSchema.test.ts +469 -0
- package/Tests/Utils/Schema/ModelSchema.test.ts +268 -0
- package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +698 -0
- package/Tests/Utils/Telemetry/EntityKeyNonTelemetry.test.ts +193 -0
- package/Tests/__mocks__/bullmq.js +55 -0
- package/Types/AI/AIChatMessageStatus.ts +8 -1
- package/Types/AI/AIChatTypes.ts +12 -0
- package/Types/Database/AccessControl/OwnerOnlyColumn.ts +88 -0
- package/Types/Exception/ExceptionCode.ts +2 -0
- package/Types/Exception/ServiceUnavailableException.ts +8 -0
- package/Types/Exception/TooManyRequestsException.ts +8 -0
- package/Types/IP/IP.ts +93 -47
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +80 -3
- package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +55 -0
- package/Types/OnCallDutyPolicy/Layer.ts +203 -149
- package/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.ts +13 -0
- package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +155 -10
- package/Types/Permission.ts +193 -0
- package/Types/SerializableObjectDictionary.ts +133 -39
- package/Types/Telemetry/EntityRelationshipType.ts +1 -1
- package/Types/Telemetry/EntitySource.ts +40 -0
- package/Types/Telemetry/EntityType.ts +28 -1
- package/Types/Telemetry/EntityTypeGroups.ts +65 -0
- package/Types/Workflow/Component.ts +29 -0
- package/Types/Workflow/Components/API.ts +35 -0
- package/Types/Workflow/Components/BaseModel.ts +77 -27
- package/Types/Workflow/Components/Discord.ts +1 -0
- package/Types/Workflow/Components/Email.ts +12 -3
- package/Types/Workflow/Components/JavaScript.ts +7 -0
- package/Types/Workflow/Components/MicrosoftTeams.ts +3 -2
- package/Types/Workflow/Components/Slack.ts +1 -0
- package/Types/Workflow/Components/Telegram.ts +1 -0
- package/Types/Workflow/StepTrace.ts +181 -0
- package/Types/Workflow/TemplateSyntax.ts +543 -0
- package/Types/Workflow/Templates.ts +2368 -0
- package/UI/Components/Calendar/Calendar.css +43 -0
- package/UI/Components/Calendar/Calendar.tsx +8 -0
- package/UI/Components/Card/Card.tsx +2 -2
- package/UI/Components/Checkbox/Checkbox.tsx +16 -0
- package/UI/Components/Date/CustomTimeRangeModal.tsx +278 -0
- package/UI/Components/Date/TimeRangePickerDropdown.tsx +250 -0
- package/UI/Components/Dictionary/Dictionary.tsx +71 -15
- package/UI/Components/FormModal/BasicFormModal.tsx +2 -1
- package/UI/Components/Forms/Fields/ColorPicker.tsx +66 -10
- package/UI/Components/Forms/Fields/IconPicker.tsx +48 -10
- package/UI/Components/Forms/Types/Field.ts +7 -0
- package/UI/Components/Forms/Validation.ts +63 -1
- package/UI/Components/Header/HeaderIconDropdownButton.tsx +53 -3
- package/UI/Components/Input/Input.tsx +32 -3
- package/UI/Components/KeyboardShortcut/KeyboardKey.ts +185 -0
- package/UI/Components/KeyboardShortcut/KeyboardShortcut.tsx +87 -0
- package/UI/Components/LogsViewer/LogsViewer.tsx +28 -0
- package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +31 -0
- package/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.tsx +18 -18
- package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +363 -14
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +11 -216
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +11 -0
- package/UI/Components/LogsViewer/components/LogsTable.tsx +155 -12
- package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +29 -0
- package/UI/Components/LogsViewer/types.ts +23 -0
- package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +9 -2
- package/UI/Components/Modal/Modal.tsx +37 -4
- package/UI/Components/Navbar/NavBarMenuModal.tsx +15 -30
- package/UI/Components/ProjectInvitations/PendingProjectInvitations.tsx +442 -0
- package/UI/Components/SimpleLogViewer/SimpleLogViewer.tsx +23 -1
- package/UI/Components/Table/Table.tsx +49 -16
- package/UI/Components/Table/TableBody.tsx +53 -28
- package/UI/Components/Table/TableHeader.tsx +13 -0
- package/UI/Components/Table/TableRow.tsx +58 -26
- package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +11 -210
- package/UI/Components/Workflow/ArgumentsForm.tsx +341 -8
- package/UI/Components/Workflow/Component.tsx +28 -26
- package/UI/Components/Workflow/ComponentReturnValueViewer.tsx +26 -0
- package/UI/Components/Workflow/ComponentSettingsModal.tsx +79 -9
- package/UI/Components/Workflow/ComponentValuePickerModal.tsx +135 -7
- package/UI/Components/Workflow/ComponentsModal.tsx +116 -22
- package/UI/Components/Workflow/DocumentationViewer.tsx +59 -9
- package/UI/Components/Workflow/GraphLint.ts +628 -0
- package/UI/Components/Workflow/GraphLintSummary.ts +390 -0
- package/UI/Components/Workflow/ModelColumnEditor.tsx +528 -0
- package/UI/Components/Workflow/ModelSchema.ts +278 -0
- package/UI/Components/Workflow/RunForm.tsx +41 -7
- package/UI/Components/Workflow/RunStatusWatcher.ts +122 -0
- package/UI/Components/Workflow/StepTraceViewer.tsx +186 -0
- package/UI/Components/Workflow/UseRunWatch.ts +212 -0
- package/UI/Components/Workflow/Utils.ts +93 -1
- package/UI/Components/Workflow/VariableModal.tsx +6 -2
- package/UI/Components/Workflow/Workflow.tsx +126 -7
- package/UI/Components/Workflow/WorkflowIssuesModal.tsx +255 -0
- package/UI/Components/Workflow/WorkflowLogModal.tsx +128 -0
- package/UI/Components/Workflow/WorkflowStatusBar.tsx +224 -0
- package/UI/Types/LayeredDismissal.ts +31 -0
- package/UI/Types/UseAnchoredFieldPopup.ts +99 -0
- package/UI/Utils/AIChatExport/ConversationMarkdown.ts +10 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +7 -1
- package/UI/Utils/Platform.ts +149 -0
- package/UI/Utils/ProjectInvitationDisplay.ts +118 -0
- package/UI/esbuild-config.js +22 -1
- package/Utils/Monitor/NetworkDeviceLinkRuleUtil.ts +187 -0
- package/Utils/Monitor/NetworkDeviceRoleUtil.ts +533 -0
- package/Utils/Monitor/NetworkTopologyUtil.ts +917 -155
- package/Utils/Telemetry/CrossSignalScope.ts +502 -0
- package/Utils/Telemetry/EntityKey.ts +71 -5
- package/Utils/Telemetry/EntityRelationship.ts +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +1 -1
- package/build/dist/Models/DatabaseModels/AIConversation.js +32 -0
- package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AIConversationMessage.js +42 -0
- package/build/dist/Models/DatabaseModels/AIConversationMessage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js +28 -0
- package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js +29 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +12 -4
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/{TelemetryEntity.js → InventoryItem.js} +212 -29
- package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -0
- package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js +454 -0
- package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js.map +1 -0
- package/build/dist/Models/DatabaseModels/{TelemetryEntityRelationship.js → InventoryItemRelationship.js} +52 -25
- package/build/dist/Models/DatabaseModels/InventoryItemRelationship.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +141 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js +719 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js +475 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkTopologySuppression.js +446 -0
- package/build/dist/Models/DatabaseModels/NetworkTopologySuppression.js.map +1 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js +9 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +80 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserCall.js +46 -2
- package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserEmail.js +48 -2
- package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationRule.js +424 -55
- package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +24 -2
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserPush.js +51 -1
- package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserSMS.js +47 -2
- package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserTelegram.js +65 -3
- package/build/dist/Models/DatabaseModels/UserTelegram.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWebhook.js +56 -2
- package/build/dist/Models/DatabaseModels/UserWebhook.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js +45 -2
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowLog.js +39 -0
- package/build/dist/Models/DatabaseModels/WorkflowLog.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js +12 -0
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +237 -1
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +165 -13
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/OnCallReadinessAPI.js +599 -0
- package/build/dist/Server/API/OnCallReadinessAPI.js.map +1 -0
- package/build/dist/Server/API/TeamComplianceAPI.js +68 -9
- package/build/dist/Server/API/TeamComplianceAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +129 -18
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/API/UserAPI.js +16 -1
- package/build/dist/Server/API/UserAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +45 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.js +4 -4
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786551733814-MigrationName.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786551733814-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.js +39 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.js +38 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.js +150 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.js +57 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.js +69 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.js +32 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.js +48 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +24 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Queue.js +72 -13
- package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js +11 -6
- package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
- package/build/dist/Server/Middleware/PublicDashboardRateLimit.js +399 -0
- package/build/dist/Server/Middleware/PublicDashboardRateLimit.js.map +1 -0
- package/build/dist/Server/Services/AIService.js +1 -0
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js +24 -3
- package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/AlertSeverityService.js +54 -0
- package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
- package/build/dist/Server/Services/DashboardService.js +10 -9
- package/build/dist/Server/Services/DashboardService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +24 -2
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +24 -3
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentSeverityService.js +67 -0
- package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +12 -4
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemCustomFieldService.js +9 -0
- package/build/dist/Server/Services/InventoryItemCustomFieldService.js.map +1 -0
- package/build/dist/Server/Services/{TelemetryEntityRelationshipService.js → InventoryItemRelationshipService.js} +9 -6
- package/build/dist/Server/Services/InventoryItemRelationshipService.js.map +1 -0
- package/build/dist/Server/Services/{TelemetryEntityService.js → InventoryItemService.js} +158 -23
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -0
- package/build/dist/Server/Services/LogAggregationService.js +27 -8
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +80 -0
- package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricService.js +6 -6
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceLinkRuleService.js +9 -0
- package/build/dist/Server/Services/NetworkDeviceLinkRuleService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceLinkService.js +71 -0
- package/build/dist/Server/Services/NetworkDeviceLinkService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceService.js +113 -0
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +53 -13
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/NetworkTopologySuppressionService.js +85 -0
- package/build/dist/Server/Services/NetworkTopologySuppressionService.js.map +1 -0
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +48 -32
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +8 -0
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +51 -12
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +57 -13
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallNotificationAlertingService.js +548 -0
- package/build/dist/Server/Services/OnCallNotificationAlertingService.js.map +1 -0
- package/build/dist/Server/Services/OnCallReadinessService.js +1961 -0
- package/build/dist/Server/Services/OnCallReadinessService.js.map +1 -0
- package/build/dist/Server/Services/OnCallSetupReminderService.js +738 -0
- package/build/dist/Server/Services/OnCallSetupReminderService.js.map +1 -0
- package/build/dist/Server/Services/ProfileAggregationService.js +68 -4
- package/build/dist/Server/Services/ProfileAggregationService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +11 -10
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TeamComplianceService.js +312 -160
- package/build/dist/Server/Services/TeamComplianceService.js.map +1 -1
- package/build/dist/Server/Services/UserCallService.js +24 -1
- package/build/dist/Server/Services/UserCallService.js.map +1 -1
- package/build/dist/Server/Services/UserEmailService.js +24 -1
- package/build/dist/Server/Services/UserEmailService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleAdminService.js +858 -0
- package/build/dist/Server/Services/UserNotificationRuleAdminService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js +2830 -175
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserOnCallLogService.js +488 -43
- package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
- package/build/dist/Server/Services/UserPushService.js +26 -0
- package/build/dist/Server/Services/UserPushService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +10 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Services/UserSmsService.js +24 -1
- package/build/dist/Server/Services/UserSmsService.js.map +1 -1
- package/build/dist/Server/Services/UserTelegramService.js +22 -1
- package/build/dist/Server/Services/UserTelegramService.js.map +1 -1
- package/build/dist/Server/Services/UserWebhookService.js +25 -1
- package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
- package/build/dist/Server/Services/UserWhatsAppService.js +22 -1
- package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js +12 -1
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +126 -0
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.js +254 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.js.map +1 -0
- package/build/dist/Server/Types/Database/Permissions/QueryPermission.js +47 -2
- package/build/dist/Server/Types/Database/Permissions/QueryPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +7 -0
- package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js +28 -0
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +21 -5
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +14 -10
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +31 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js +3 -9
- package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Email.js +15 -4
- package/build/dist/Server/Types/Workflow/Components/Email.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js +7 -2
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/TriggerCode.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +514 -56
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +20 -3
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +19 -6
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +7 -0
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js +2 -2
- package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AIMetaTools.js +692 -0
- package/build/dist/Server/Utils/AI/Toolbox/AIMetaTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +148 -12
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +157 -10
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/Index.js +37 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js +259 -14
- package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/NoteWriteTools.js +235 -0
- package/build/dist/Server/Utils/AI/Toolbox/NoteWriteTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +1000 -0
- package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/RunbookTools.js +356 -0
- package/build/dist/Server/Utils/AI/Toolbox/RunbookTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +394 -0
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/StatusPageTools.js +465 -0
- package/build/dist/Server/Utils/AI/Toolbox/StatusPageTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/TeamTools.js +280 -0
- package/build/dist/Server/Utils/AI/Toolbox/TeamTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js +527 -0
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/WorkflowProbeTools.js +548 -0
- package/build/dist/Server/Utils/AI/Toolbox/WorkflowProbeTools.js.map +1 -0
- package/build/dist/Server/Utils/ClientIp.js +137 -0
- package/build/dist/Server/Utils/ClientIp.js.map +1 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +38 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js +89 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js.map +1 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js +77 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js.map +1 -0
- package/build/dist/Server/Utils/Express.js +12 -12
- package/build/dist/Server/Utils/Express.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +70 -7
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +121 -11
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +82 -21
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +12 -4
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +165 -18
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +507 -0
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +122 -47
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMAPI.js +51 -4
- package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +7 -3
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/AI/AIChatMessageStatus.js +8 -1
- package/build/dist/Types/AI/AIChatMessageStatus.js.map +1 -1
- package/build/dist/Types/AI/AIChatTypes.js +12 -0
- package/build/dist/Types/AI/AIChatTypes.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +60 -0
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -0
- package/build/dist/Types/Exception/ExceptionCode.js +2 -0
- package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
- package/build/dist/Types/Exception/ServiceUnavailableException.js +8 -0
- package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -0
- package/build/dist/Types/Exception/TooManyRequestsException.js +8 -0
- package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -0
- package/build/dist/Types/IP/IP.js +87 -43
- package/build/dist/Types/IP/IP.js.map +1 -1
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +50 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/Layer.js +186 -123
- package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.js +13 -0
- package/build/dist/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +105 -11
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
- package/build/dist/Types/Permission.js +174 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/SerializableObjectDictionary.js +133 -39
- package/build/dist/Types/SerializableObjectDictionary.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityRelationshipType.js +1 -1
- package/build/dist/Types/Telemetry/EntitySource.js +39 -0
- package/build/dist/Types/Telemetry/EntitySource.js.map +1 -0
- package/build/dist/Types/Telemetry/EntityType.js +28 -1
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityTypeGroups.js +57 -0
- package/build/dist/Types/Telemetry/EntityTypeGroups.js.map +1 -0
- package/build/dist/Types/Workflow/Component.js +21 -0
- package/build/dist/Types/Workflow/Component.js.map +1 -1
- package/build/dist/Types/Workflow/Components/API.js +35 -0
- package/build/dist/Types/Workflow/Components/API.js.map +1 -1
- package/build/dist/Types/Workflow/Components/BaseModel.js +68 -26
- package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Discord.js +1 -0
- package/build/dist/Types/Workflow/Components/Discord.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Email.js +12 -3
- package/build/dist/Types/Workflow/Components/Email.js.map +1 -1
- package/build/dist/Types/Workflow/Components/JavaScript.js +7 -0
- package/build/dist/Types/Workflow/Components/JavaScript.js.map +1 -1
- package/build/dist/Types/Workflow/Components/MicrosoftTeams.js +3 -2
- package/build/dist/Types/Workflow/Components/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Slack.js +1 -0
- package/build/dist/Types/Workflow/Components/Slack.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Telegram.js +1 -0
- package/build/dist/Types/Workflow/Components/Telegram.js.map +1 -1
- package/build/dist/Types/Workflow/StepTrace.js +104 -0
- package/build/dist/Types/Workflow/StepTrace.js.map +1 -0
- package/build/dist/Types/Workflow/TemplateSyntax.js +338 -0
- package/build/dist/Types/Workflow/TemplateSyntax.js.map +1 -0
- package/build/dist/Types/Workflow/Templates.js +2111 -0
- package/build/dist/Types/Workflow/Templates.js.map +1 -0
- package/build/dist/UI/Components/Calendar/Calendar.js +1 -1
- package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
- package/build/dist/UI/Components/Checkbox/Checkbox.js +1 -1
- package/build/dist/UI/Components/Checkbox/Checkbox.js.map +1 -1
- package/build/dist/UI/Components/Date/CustomTimeRangeModal.js +126 -0
- package/build/dist/UI/Components/Date/CustomTimeRangeModal.js.map +1 -0
- package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js +123 -0
- package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js.map +1 -0
- package/build/dist/UI/Components/Dictionary/Dictionary.js +47 -17
- package/build/dist/UI/Components/Dictionary/Dictionary.js.map +1 -1
- package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/ColorPicker.js +52 -13
- package/build/dist/UI/Components/Forms/Fields/ColorPicker.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/IconPicker.js +28 -12
- package/build/dist/UI/Components/Forms/Fields/IconPicker.js.map +1 -1
- package/build/dist/UI/Components/Forms/Validation.js +44 -0
- package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +27 -4
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +13 -4
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardKey.js +163 -0
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardKey.js.map +1 -0
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcut.js +47 -0
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcut.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +4 -4
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +11 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js +10 -8
- package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +227 -14
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +5 -108
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +5 -0
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js +69 -5
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +8 -0
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/types.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +9 -2
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +31 -5
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +8 -21
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Components/ProjectInvitations/PendingProjectInvitations.js +251 -0
- package/build/dist/UI/Components/ProjectInvitations/PendingProjectInvitations.js.map +1 -0
- package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js +9 -2
- package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js.map +1 -1
- package/build/dist/UI/Components/Table/Table.js +27 -15
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableBody.js +24 -18
- package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
- package/build/dist/UI/Components/Table/TableHeader.js +9 -1
- package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +29 -21
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +5 -105
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js +261 -14
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Component.js +20 -19
- package/build/dist/UI/Components/Workflow/Component.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js +10 -1
- package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js +35 -7
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js +57 -7
- package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentsModal.js +53 -18
- package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/DocumentationViewer.js +19 -6
- package/build/dist/UI/Components/Workflow/DocumentationViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/GraphLint.js +425 -0
- package/build/dist/UI/Components/Workflow/GraphLint.js.map +1 -0
- package/build/dist/UI/Components/Workflow/GraphLintSummary.js +231 -0
- package/build/dist/UI/Components/Workflow/GraphLintSummary.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ModelColumnEditor.js +320 -0
- package/build/dist/UI/Components/Workflow/ModelColumnEditor.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ModelSchema.js +156 -0
- package/build/dist/UI/Components/Workflow/ModelSchema.js.map +1 -0
- package/build/dist/UI/Components/Workflow/RunForm.js +22 -6
- package/build/dist/UI/Components/Workflow/RunForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/RunStatusWatcher.js +76 -0
- package/build/dist/UI/Components/Workflow/RunStatusWatcher.js.map +1 -0
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js +76 -0
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -0
- package/build/dist/UI/Components/Workflow/UseRunWatch.js +123 -0
- package/build/dist/UI/Components/Workflow/UseRunWatch.js.map +1 -0
- package/build/dist/UI/Components/Workflow/Utils.js +73 -1
- package/build/dist/UI/Components/Workflow/Utils.js.map +1 -1
- package/build/dist/UI/Components/Workflow/VariableModal.js +3 -2
- package/build/dist/UI/Components/Workflow/VariableModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Workflow.js +92 -7
- package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
- package/build/dist/UI/Components/Workflow/WorkflowIssuesModal.js +99 -0
- package/build/dist/UI/Components/Workflow/WorkflowIssuesModal.js.map +1 -0
- package/build/dist/UI/Components/Workflow/WorkflowLogModal.js +56 -0
- package/build/dist/UI/Components/Workflow/WorkflowLogModal.js.map +1 -0
- package/build/dist/UI/Components/Workflow/WorkflowStatusBar.js +92 -0
- package/build/dist/UI/Components/Workflow/WorkflowStatusBar.js.map +1 -0
- package/build/dist/UI/Types/LayeredDismissal.js +21 -0
- package/build/dist/UI/Types/LayeredDismissal.js.map +1 -0
- package/build/dist/UI/Types/UseAnchoredFieldPopup.js +74 -1
- package/build/dist/UI/Types/UseAnchoredFieldPopup.js.map +1 -1
- package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js +9 -0
- package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/Platform.js +118 -0
- package/build/dist/UI/Utils/Platform.js.map +1 -0
- package/build/dist/UI/Utils/ProjectInvitationDisplay.js +106 -0
- package/build/dist/UI/Utils/ProjectInvitationDisplay.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js +108 -0
- package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js +386 -0
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +661 -126
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/Telemetry/CrossSignalScope.js +328 -0
- package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +57 -5
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityRelationship.js +1 -1
- package/jest.config.json +1 -0
- package/package.json +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryEntity.js.map +0 -1
- package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js.map +0 -1
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +0 -1
- package/build/dist/Server/Services/TelemetryEntityService.js.map +0 -1
|
@@ -0,0 +1,1166 @@
|
|
|
1
|
+
import AlertSeverityService from "../../../Server/Services/AlertSeverityService";
|
|
2
|
+
import IncidentSeverityService from "../../../Server/Services/IncidentSeverityService";
|
|
3
|
+
import UserEmailService from "../../../Server/Services/UserEmailService";
|
|
4
|
+
import UserNotificationRuleService, {
|
|
5
|
+
NotificationMethodDescriptor,
|
|
6
|
+
} from "../../../Server/Services/UserNotificationRuleService";
|
|
7
|
+
import CreateBy from "../../../Server/Types/Database/CreateBy";
|
|
8
|
+
import AlertSeverity from "../../../Models/DatabaseModels/AlertSeverity";
|
|
9
|
+
import IncidentSeverity from "../../../Models/DatabaseModels/IncidentSeverity";
|
|
10
|
+
import UserEmail from "../../../Models/DatabaseModels/UserEmail";
|
|
11
|
+
import Model from "../../../Models/DatabaseModels/UserNotificationRule";
|
|
12
|
+
import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
|
|
13
|
+
import Email from "../../../Types/Email";
|
|
14
|
+
import NotificationRuleType from "../../../Types/NotificationRule/NotificationRuleType";
|
|
15
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
16
|
+
import { afterEach, beforeEach, describe, expect, test } from "@jest/globals";
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
* The defaults a brand-new responder is given.
|
|
20
|
+
*
|
|
21
|
+
* Everything about "will this person actually be paged?" starts here. When a
|
|
22
|
+
* user joins a project (TeamMemberService), or verifies a phone / push / e-mail
|
|
23
|
+
* / Telegram / WhatsApp / webhook identity (the UserXxxAPI verify endpoints),
|
|
24
|
+
* UserNotificationRuleService seeds a set of notification rules for them. If the
|
|
25
|
+
* seeding is wrong — a severity skipped, a rule type missed, a delay that is not
|
|
26
|
+
* zero, or the method id written onto the wrong foreign key — the user is on an
|
|
27
|
+
* on-call policy that pages nobody, and nothing tells them so.
|
|
28
|
+
*
|
|
29
|
+
* This file pins the shape of that seeding:
|
|
30
|
+
*
|
|
31
|
+
* (A) addDefaultNotificationRulesForVerifiedMethod
|
|
32
|
+
* - one ON_CALL_EXECUTED_INCIDENT rule per incident severity,
|
|
33
|
+
* - one ON_CALL_EXECUTED_ALERT rule per alert severity,
|
|
34
|
+
* - one ON_CALL_EXECUTED_INCIDENT_EPISODE rule per incident severity and
|
|
35
|
+
* one ON_CALL_EXECUTED_ALERT_EPISODE rule per alert severity (Phase 1
|
|
36
|
+
* closed GAP G here: these two used to be seeded once each with a NULL
|
|
37
|
+
* severity, which matched no severity-filtered page and showed up in no
|
|
38
|
+
* severity-scoped UI table - "defaults" that were unreachable and
|
|
39
|
+
* invisible at the same time),
|
|
40
|
+
* - exactly two "single" rules (goes on call, goes off call), which
|
|
41
|
+
* legitimately have no severity because they are about the user's shift
|
|
42
|
+
* rather than about anything that fired,
|
|
43
|
+
* - every rule at notifyAfterMinutes = 0 (page immediately),
|
|
44
|
+
* - the verified method's id written to exactly one FK column, chosen per
|
|
45
|
+
* channel, and the same column used in the duplicate lookup,
|
|
46
|
+
* - idempotence: an existing rule for a (method, severity, ruleType)
|
|
47
|
+
* triple suppresses only that one create, never its neighbours,
|
|
48
|
+
* - a project with zero severities gets the two shift rules and nothing
|
|
49
|
+
* else, because a rule for a severity that does not exist could never
|
|
50
|
+
* have matched a page anyway.
|
|
51
|
+
*
|
|
52
|
+
* (B) addDefaultNotificationRuleForUser, which is the joining-a-project entry
|
|
53
|
+
* point: it materialises a *verified* UserEmail when one does not exist,
|
|
54
|
+
* reuses one when it does, and then delegates to (A).
|
|
55
|
+
*
|
|
56
|
+
* Nothing here touches Postgres: the two severity services, UserEmailService and
|
|
57
|
+
* the service's own findOneBy/create are all stubbed, so what is asserted is the
|
|
58
|
+
* decision-making, not the persistence.
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
const PROJECT_ID: ObjectID = new ObjectID(
|
|
62
|
+
"11111111-1111-4111-8111-111111111111",
|
|
63
|
+
);
|
|
64
|
+
const USER_ID: ObjectID = new ObjectID("22222222-2222-4222-8222-222222222222");
|
|
65
|
+
|
|
66
|
+
const INCIDENT_SEV_1: ObjectID = new ObjectID(
|
|
67
|
+
"aaaaaaa1-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
|
|
68
|
+
);
|
|
69
|
+
const INCIDENT_SEV_2: ObjectID = new ObjectID(
|
|
70
|
+
"aaaaaaa2-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
|
|
71
|
+
);
|
|
72
|
+
const INCIDENT_SEV_3: ObjectID = new ObjectID(
|
|
73
|
+
"aaaaaaa3-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const ALERT_SEV_1: ObjectID = new ObjectID(
|
|
77
|
+
"bbbbbbb1-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
|
|
78
|
+
);
|
|
79
|
+
const ALERT_SEV_2: ObjectID = new ObjectID(
|
|
80
|
+
"bbbbbbb2-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const METHOD_ID: ObjectID = new ObjectID(
|
|
84
|
+
"ccccccc1-cccc-4ccc-8ccc-cccccccccccc",
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const EXISTING_EMAIL_ID: ObjectID = new ObjectID(
|
|
88
|
+
"ddddddd1-dddd-4ddd-8ddd-dddddddddddd",
|
|
89
|
+
);
|
|
90
|
+
const CREATED_EMAIL_ID: ObjectID = new ObjectID(
|
|
91
|
+
"ddddddd2-dddd-4ddd-8ddd-dddddddddddd",
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
const USER_EMAIL: Email = new Email("responder@company.com");
|
|
95
|
+
|
|
96
|
+
/* The seven FK columns a NotificationMethodDescriptor can drive. */
|
|
97
|
+
type ChannelColumn =
|
|
98
|
+
| "userEmailId"
|
|
99
|
+
| "userSmsId"
|
|
100
|
+
| "userCallId"
|
|
101
|
+
| "userWhatsAppId"
|
|
102
|
+
| "userTelegramId"
|
|
103
|
+
| "userWebhookId"
|
|
104
|
+
| "userPushId";
|
|
105
|
+
|
|
106
|
+
const ALL_CHANNELS: Array<ChannelColumn> = [
|
|
107
|
+
"userEmailId",
|
|
108
|
+
"userSmsId",
|
|
109
|
+
"userCallId",
|
|
110
|
+
"userWhatsAppId",
|
|
111
|
+
"userTelegramId",
|
|
112
|
+
"userWebhookId",
|
|
113
|
+
"userPushId",
|
|
114
|
+
];
|
|
115
|
+
|
|
116
|
+
/* The rule types that are seeded once, regardless of severities. */
|
|
117
|
+
const SINGLE_RULE_TYPES: Array<NotificationRuleType> = [
|
|
118
|
+
NotificationRuleType.WHEN_USER_GOES_ON_CALL,
|
|
119
|
+
NotificationRuleType.WHEN_USER_GOES_OFF_CALL,
|
|
120
|
+
];
|
|
121
|
+
|
|
122
|
+
/*
|
|
123
|
+
* The episode rule types. Since Phase 1 closed GAP G these are seeded once per
|
|
124
|
+
* severity - alert episodes against alert severities, incident episodes against
|
|
125
|
+
* incident severities - exactly like their non-episode counterparts.
|
|
126
|
+
*/
|
|
127
|
+
const EPISODE_RULE_TYPES: Array<NotificationRuleType> = [
|
|
128
|
+
NotificationRuleType.ON_CALL_EXECUTED_ALERT_EPISODE,
|
|
129
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE,
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
/*
|
|
133
|
+
* With the fixture below (3 incident severities, 2 alert severities):
|
|
134
|
+
* 3 incident + 2 alert + 2 alert episode + 3 incident episode + 2 single.
|
|
135
|
+
*/
|
|
136
|
+
const TOTAL_SEEDED_RULES: number = 12;
|
|
137
|
+
|
|
138
|
+
/* The order the rules are seeded in, which is also the duplicate-check order. */
|
|
139
|
+
const SEEDED_RULE_ORDER: Array<NotificationRuleType> = [
|
|
140
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
141
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
142
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
143
|
+
NotificationRuleType.ON_CALL_EXECUTED_ALERT,
|
|
144
|
+
NotificationRuleType.ON_CALL_EXECUTED_ALERT,
|
|
145
|
+
NotificationRuleType.ON_CALL_EXECUTED_ALERT_EPISODE,
|
|
146
|
+
NotificationRuleType.ON_CALL_EXECUTED_ALERT_EPISODE,
|
|
147
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE,
|
|
148
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE,
|
|
149
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE,
|
|
150
|
+
NotificationRuleType.WHEN_USER_GOES_ON_CALL,
|
|
151
|
+
NotificationRuleType.WHEN_USER_GOES_OFF_CALL,
|
|
152
|
+
];
|
|
153
|
+
|
|
154
|
+
function incidentSeverity(id: ObjectID): IncidentSeverity {
|
|
155
|
+
const severity: IncidentSeverity = new IncidentSeverity(id);
|
|
156
|
+
severity._id = id.toString();
|
|
157
|
+
|
|
158
|
+
return severity;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function alertSeverity(id: ObjectID): AlertSeverity {
|
|
162
|
+
const severity: AlertSeverity = new AlertSeverity(id);
|
|
163
|
+
severity._id = id.toString();
|
|
164
|
+
|
|
165
|
+
return severity;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function existingUserEmail(id: ObjectID, isVerified: boolean): UserEmail {
|
|
169
|
+
const userEmail: UserEmail = new UserEmail(id);
|
|
170
|
+
userEmail._id = id.toString();
|
|
171
|
+
userEmail.projectId = PROJECT_ID;
|
|
172
|
+
userEmail.userId = USER_ID;
|
|
173
|
+
userEmail.email = USER_EMAIL;
|
|
174
|
+
userEmail.isVerified = isVerified;
|
|
175
|
+
|
|
176
|
+
return userEmail;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* A rule row standing in for "this default already exists". */
|
|
180
|
+
function existingRule(): Model {
|
|
181
|
+
const rule: Model = new Model(
|
|
182
|
+
new ObjectID("eeeeeee1-eeee-4eee-8eee-eeeeeeeeeeee"),
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
return rule;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function descriptorFor(channel: ChannelColumn): NotificationMethodDescriptor {
|
|
189
|
+
return { [channel]: METHOD_ID } as NotificationMethodDescriptor;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
let findOneBySpy: jest.SpyInstance;
|
|
193
|
+
let createSpy: jest.SpyInstance;
|
|
194
|
+
let incidentSeveritiesSpy: jest.SpyInstance;
|
|
195
|
+
let alertSeveritiesSpy: jest.SpyInstance;
|
|
196
|
+
let userEmailFindOneBySpy: jest.SpyInstance;
|
|
197
|
+
let userEmailCreateSpy: jest.SpyInstance;
|
|
198
|
+
|
|
199
|
+
/* Every UserNotificationRule handed to create(), in the order it was created. */
|
|
200
|
+
function createdRules(): Array<Model> {
|
|
201
|
+
return createSpy.mock.calls.map((call: Array<unknown>): Model => {
|
|
202
|
+
return (call[0] as CreateBy<Model>).data;
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function createdRulesOfType(ruleType: NotificationRuleType): Array<Model> {
|
|
207
|
+
return createdRules().filter((rule: Model): boolean => {
|
|
208
|
+
return rule.ruleType === ruleType;
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* Every query object handed to the service's own findOneBy duplicate check. */
|
|
213
|
+
function duplicateCheckQueries(): Array<Record<string, unknown>> {
|
|
214
|
+
return findOneBySpy.mock.calls.map(
|
|
215
|
+
(call: Array<unknown>): Record<string, unknown> => {
|
|
216
|
+
return (call[0] as { query: Record<string, unknown> }).query;
|
|
217
|
+
},
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function runForDescriptor(
|
|
222
|
+
notificationMethod: NotificationMethodDescriptor,
|
|
223
|
+
): Promise<void> {
|
|
224
|
+
return UserNotificationRuleService.addDefaultNotificationRulesForVerifiedMethod(
|
|
225
|
+
{
|
|
226
|
+
projectId: PROJECT_ID,
|
|
227
|
+
userId: USER_ID,
|
|
228
|
+
notificationMethod: notificationMethod,
|
|
229
|
+
},
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function runForEmailMethod(): Promise<void> {
|
|
234
|
+
return runForDescriptor({ userEmailId: METHOD_ID });
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
beforeEach(() => {
|
|
238
|
+
incidentSeveritiesSpy = jest
|
|
239
|
+
.spyOn(IncidentSeverityService, "findBy")
|
|
240
|
+
.mockResolvedValue([
|
|
241
|
+
incidentSeverity(INCIDENT_SEV_1),
|
|
242
|
+
incidentSeverity(INCIDENT_SEV_2),
|
|
243
|
+
incidentSeverity(INCIDENT_SEV_3),
|
|
244
|
+
] as never);
|
|
245
|
+
|
|
246
|
+
alertSeveritiesSpy = jest
|
|
247
|
+
.spyOn(AlertSeverityService, "findBy")
|
|
248
|
+
.mockResolvedValue([
|
|
249
|
+
alertSeverity(ALERT_SEV_1),
|
|
250
|
+
alertSeverity(ALERT_SEV_2),
|
|
251
|
+
] as never);
|
|
252
|
+
|
|
253
|
+
// Nothing exists yet, so every candidate rule is created.
|
|
254
|
+
findOneBySpy = jest.spyOn(UserNotificationRuleService, "findOneBy");
|
|
255
|
+
findOneBySpy.mockResolvedValue(null as never);
|
|
256
|
+
|
|
257
|
+
createSpy = jest.spyOn(UserNotificationRuleService, "create");
|
|
258
|
+
createSpy.mockImplementation((createBy: CreateBy<Model>): Promise<Model> => {
|
|
259
|
+
return Promise.resolve(createBy.data);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
userEmailFindOneBySpy = jest
|
|
263
|
+
.spyOn(UserEmailService, "findOneBy")
|
|
264
|
+
.mockResolvedValue(null as never);
|
|
265
|
+
|
|
266
|
+
userEmailCreateSpy = jest
|
|
267
|
+
.spyOn(UserEmailService, "create")
|
|
268
|
+
.mockResolvedValue(existingUserEmail(CREATED_EMAIL_ID, true) as never);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
afterEach(() => {
|
|
272
|
+
jest.restoreAllMocks();
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
describe("addDefaultNotificationRulesForVerifiedMethod - what gets seeded", () => {
|
|
276
|
+
test("one incident on-call rule per incident severity in the project", async () => {
|
|
277
|
+
await runForEmailMethod();
|
|
278
|
+
|
|
279
|
+
const incidentRules: Array<Model> = createdRulesOfType(
|
|
280
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
expect(incidentRules).toHaveLength(3);
|
|
284
|
+
expect(
|
|
285
|
+
incidentRules.map((rule: Model): string => {
|
|
286
|
+
return rule.incidentSeverityId!.toString();
|
|
287
|
+
}),
|
|
288
|
+
).toEqual([
|
|
289
|
+
INCIDENT_SEV_1.toString(),
|
|
290
|
+
INCIDENT_SEV_2.toString(),
|
|
291
|
+
INCIDENT_SEV_3.toString(),
|
|
292
|
+
]);
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
test("an incident rule is scoped to its severity only - no alert severity leaks in", async () => {
|
|
296
|
+
await runForEmailMethod();
|
|
297
|
+
|
|
298
|
+
for (const rule of createdRulesOfType(
|
|
299
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
300
|
+
)) {
|
|
301
|
+
expect(rule.alertSeverityId).toBeUndefined();
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
|
|
305
|
+
test("one alert on-call rule per alert severity in the project", async () => {
|
|
306
|
+
await runForEmailMethod();
|
|
307
|
+
|
|
308
|
+
const alertRules: Array<Model> = createdRulesOfType(
|
|
309
|
+
NotificationRuleType.ON_CALL_EXECUTED_ALERT,
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
expect(alertRules).toHaveLength(2);
|
|
313
|
+
expect(
|
|
314
|
+
alertRules.map((rule: Model): string => {
|
|
315
|
+
return rule.alertSeverityId!.toString();
|
|
316
|
+
}),
|
|
317
|
+
).toEqual([ALERT_SEV_1.toString(), ALERT_SEV_2.toString()]);
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
test("an alert rule is scoped to its severity only - no incident severity leaks in", async () => {
|
|
321
|
+
await runForEmailMethod();
|
|
322
|
+
|
|
323
|
+
for (const rule of createdRulesOfType(
|
|
324
|
+
NotificationRuleType.ON_CALL_EXECUTED_ALERT,
|
|
325
|
+
)) {
|
|
326
|
+
expect(rule.incidentSeverityId).toBeUndefined();
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
test("exactly two single rules are seeded, one of each non-severity rule type", async () => {
|
|
331
|
+
await runForEmailMethod();
|
|
332
|
+
|
|
333
|
+
for (const ruleType of SINGLE_RULE_TYPES) {
|
|
334
|
+
expect(createdRulesOfType(ruleType)).toHaveLength(1);
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
test("the two single rules carry no severity at all - they are not severity scoped", async () => {
|
|
339
|
+
await runForEmailMethod();
|
|
340
|
+
|
|
341
|
+
const singles: Array<Model> = createdRules().filter(
|
|
342
|
+
(rule: Model): boolean => {
|
|
343
|
+
return SINGLE_RULE_TYPES.includes(rule.ruleType!);
|
|
344
|
+
},
|
|
345
|
+
);
|
|
346
|
+
|
|
347
|
+
expect(singles).toHaveLength(2);
|
|
348
|
+
for (const rule of singles) {
|
|
349
|
+
expect(rule.incidentSeverityId).toBeUndefined();
|
|
350
|
+
expect(rule.alertSeverityId).toBeUndefined();
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
test("one alert episode rule per ALERT severity, each carrying that severity", async () => {
|
|
355
|
+
/*
|
|
356
|
+
* GAP G, closed by Phase 1. These rows used to be created once with a NULL
|
|
357
|
+
* alertSeverityId, which the severity-filtered count query in
|
|
358
|
+
* UserOnCallLogService could never match - so every alert episode page for a
|
|
359
|
+
* user on defaults was dropped.
|
|
360
|
+
*/
|
|
361
|
+
await runForEmailMethod();
|
|
362
|
+
|
|
363
|
+
const episodeRules: Array<Model> = createdRulesOfType(
|
|
364
|
+
NotificationRuleType.ON_CALL_EXECUTED_ALERT_EPISODE,
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
expect(episodeRules).toHaveLength(2);
|
|
368
|
+
expect(
|
|
369
|
+
episodeRules.map((rule: Model): string => {
|
|
370
|
+
return rule.alertSeverityId!.toString();
|
|
371
|
+
}),
|
|
372
|
+
).toEqual([ALERT_SEV_1.toString(), ALERT_SEV_2.toString()]);
|
|
373
|
+
|
|
374
|
+
for (const rule of episodeRules) {
|
|
375
|
+
expect(rule.incidentSeverityId).toBeUndefined();
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
test("one incident episode rule per INCIDENT severity, each carrying that severity", async () => {
|
|
380
|
+
// GAP G, closed by Phase 1 - see the alert episode case above.
|
|
381
|
+
await runForEmailMethod();
|
|
382
|
+
|
|
383
|
+
const episodeRules: Array<Model> = createdRulesOfType(
|
|
384
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE,
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
expect(episodeRules).toHaveLength(3);
|
|
388
|
+
expect(
|
|
389
|
+
episodeRules.map((rule: Model): string => {
|
|
390
|
+
return rule.incidentSeverityId!.toString();
|
|
391
|
+
}),
|
|
392
|
+
).toEqual([
|
|
393
|
+
INCIDENT_SEV_1.toString(),
|
|
394
|
+
INCIDENT_SEV_2.toString(),
|
|
395
|
+
INCIDENT_SEV_3.toString(),
|
|
396
|
+
]);
|
|
397
|
+
|
|
398
|
+
for (const rule of episodeRules) {
|
|
399
|
+
expect(rule.alertSeverityId).toBeUndefined();
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
test("no seeded episode rule is left without a severity", async () => {
|
|
404
|
+
/*
|
|
405
|
+
* The precise statement of GAP G: a NULL-severity episode rule matches no
|
|
406
|
+
* page and appears in no UI table, so it is worse than no rule at all - the
|
|
407
|
+
* user is told they are covered when they are not.
|
|
408
|
+
*/
|
|
409
|
+
await runForEmailMethod();
|
|
410
|
+
|
|
411
|
+
const episodeRules: Array<Model> = createdRules().filter(
|
|
412
|
+
(rule: Model): boolean => {
|
|
413
|
+
return EPISODE_RULE_TYPES.includes(rule.ruleType!);
|
|
414
|
+
},
|
|
415
|
+
);
|
|
416
|
+
|
|
417
|
+
expect(episodeRules).toHaveLength(5);
|
|
418
|
+
for (const rule of episodeRules) {
|
|
419
|
+
expect(
|
|
420
|
+
rule.alertSeverityId !== undefined ||
|
|
421
|
+
rule.incidentSeverityId !== undefined,
|
|
422
|
+
).toBe(true);
|
|
423
|
+
}
|
|
424
|
+
});
|
|
425
|
+
|
|
426
|
+
test("the total is incident + alert severities twice over, plus two, and nothing else", async () => {
|
|
427
|
+
await runForEmailMethod();
|
|
428
|
+
|
|
429
|
+
/*
|
|
430
|
+
* 3 incident + 2 alert on-call rules, then 2 alert episode + 3 incident
|
|
431
|
+
* episode rules, then the 2 shift rules.
|
|
432
|
+
*/
|
|
433
|
+
expect(createSpy).toHaveBeenCalledTimes(TOTAL_SEEDED_RULES);
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
test("every seeded rule pages immediately - notifyAfterMinutes is 0", async () => {
|
|
437
|
+
await runForEmailMethod();
|
|
438
|
+
|
|
439
|
+
const rules: Array<Model> = createdRules();
|
|
440
|
+
expect(rules).toHaveLength(TOTAL_SEEDED_RULES);
|
|
441
|
+
for (const rule of rules) {
|
|
442
|
+
expect(rule.notifyAfterMinutes).toBe(0);
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
test("every seeded rule is stamped with the project and the user it belongs to", async () => {
|
|
447
|
+
await runForEmailMethod();
|
|
448
|
+
|
|
449
|
+
for (const rule of createdRules()) {
|
|
450
|
+
expect(rule.projectId!.toString()).toBe(PROJECT_ID.toString());
|
|
451
|
+
expect(rule.userId!.toString()).toBe(USER_ID.toString());
|
|
452
|
+
}
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
test("every create is an internal, root-scoped write", async () => {
|
|
456
|
+
await runForEmailMethod();
|
|
457
|
+
|
|
458
|
+
for (const call of createSpy.mock.calls) {
|
|
459
|
+
expect((call[0] as CreateBy<Model>).props.isRoot).toBe(true);
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
test("rules are seeded on-call-first, then the episodes, then the singles in a fixed order", async () => {
|
|
464
|
+
/*
|
|
465
|
+
* The order is not load-bearing for correctness, but it is the order the
|
|
466
|
+
* duplicate checks run in too, so pinning it makes a reordering visible.
|
|
467
|
+
*/
|
|
468
|
+
await runForEmailMethod();
|
|
469
|
+
|
|
470
|
+
expect(
|
|
471
|
+
createdRules().map((rule: Model): NotificationRuleType => {
|
|
472
|
+
return rule.ruleType!;
|
|
473
|
+
}),
|
|
474
|
+
).toEqual(SEEDED_RULE_ORDER);
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
test("severities are read for this project only, root-scoped, and up to the per-project limit", async () => {
|
|
478
|
+
/*
|
|
479
|
+
* GAP A (OnCallNotificationReadiness.md 2.2): this read is a point-in-time
|
|
480
|
+
* snapshot. Severities created after this call are never backfilled onto
|
|
481
|
+
* existing users - pinned here so the backfill work has a baseline.
|
|
482
|
+
*
|
|
483
|
+
* Each list is read exactly ONCE even though it now drives two rule types
|
|
484
|
+
* apiece (on-call and episode), which is why the counts below stay at one.
|
|
485
|
+
*/
|
|
486
|
+
await runForEmailMethod();
|
|
487
|
+
|
|
488
|
+
expect(incidentSeveritiesSpy).toHaveBeenCalledTimes(1);
|
|
489
|
+
expect(alertSeveritiesSpy).toHaveBeenCalledTimes(1);
|
|
490
|
+
|
|
491
|
+
for (const spy of [incidentSeveritiesSpy, alertSeveritiesSpy]) {
|
|
492
|
+
const arg: {
|
|
493
|
+
query: { projectId: ObjectID };
|
|
494
|
+
props: { isRoot: boolean };
|
|
495
|
+
limit: number;
|
|
496
|
+
skip: number;
|
|
497
|
+
select: Record<string, boolean>;
|
|
498
|
+
} = spy.mock.calls[0][0] as {
|
|
499
|
+
query: { projectId: ObjectID };
|
|
500
|
+
props: { isRoot: boolean };
|
|
501
|
+
limit: number;
|
|
502
|
+
skip: number;
|
|
503
|
+
select: Record<string, boolean>;
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
expect(arg.query.projectId.toString()).toBe(PROJECT_ID.toString());
|
|
507
|
+
expect(arg.props.isRoot).toBe(true);
|
|
508
|
+
expect(arg.limit).toBe(LIMIT_PER_PROJECT);
|
|
509
|
+
expect(arg.skip).toBe(0);
|
|
510
|
+
expect(arg.select["_id"]).toBe(true);
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
describe("addDefaultNotificationRulesForVerifiedMethod - the method lands on the right column", () => {
|
|
516
|
+
test.each(ALL_CHANNELS)(
|
|
517
|
+
"a %s descriptor sets that column on every seeded rule and no other channel column",
|
|
518
|
+
async (channel: ChannelColumn) => {
|
|
519
|
+
await runForDescriptor(descriptorFor(channel));
|
|
520
|
+
|
|
521
|
+
const rules: Array<Model> = createdRules();
|
|
522
|
+
expect(rules).toHaveLength(TOTAL_SEEDED_RULES);
|
|
523
|
+
|
|
524
|
+
for (const rule of rules) {
|
|
525
|
+
expect(rule[channel]?.toString()).toBe(METHOD_ID.toString());
|
|
526
|
+
|
|
527
|
+
for (const otherChannel of ALL_CHANNELS) {
|
|
528
|
+
if (otherChannel === channel) {
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
expect(rule[otherChannel]).toBeUndefined();
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
},
|
|
535
|
+
);
|
|
536
|
+
|
|
537
|
+
test.each(ALL_CHANNELS)(
|
|
538
|
+
"the duplicate check for a %s descriptor is keyed on that same column",
|
|
539
|
+
async (channel: ChannelColumn) => {
|
|
540
|
+
/*
|
|
541
|
+
* If the lookup column and the write column ever diverge, the service
|
|
542
|
+
* re-creates the same defaults on every verification - so they are
|
|
543
|
+
* asserted together.
|
|
544
|
+
*/
|
|
545
|
+
await runForDescriptor(descriptorFor(channel));
|
|
546
|
+
|
|
547
|
+
const queries: Array<Record<string, unknown>> = duplicateCheckQueries();
|
|
548
|
+
expect(queries).toHaveLength(TOTAL_SEEDED_RULES);
|
|
549
|
+
|
|
550
|
+
for (const query of queries) {
|
|
551
|
+
expect((query[channel] as ObjectID).toString()).toBe(
|
|
552
|
+
METHOD_ID.toString(),
|
|
553
|
+
);
|
|
554
|
+
|
|
555
|
+
for (const otherChannel of ALL_CHANNELS) {
|
|
556
|
+
if (otherChannel === channel) {
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
expect(query[otherChannel]).toBeUndefined();
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
},
|
|
563
|
+
);
|
|
564
|
+
|
|
565
|
+
test("a descriptor carrying several verified methods writes all of them onto one rule", async () => {
|
|
566
|
+
/*
|
|
567
|
+
* No caller does this today (each verify endpoint passes exactly one id),
|
|
568
|
+
* but the descriptor permits it and applyNotificationMethod copies each
|
|
569
|
+
* present key independently.
|
|
570
|
+
*/
|
|
571
|
+
await runForDescriptor({
|
|
572
|
+
userEmailId: METHOD_ID,
|
|
573
|
+
userSmsId: EXISTING_EMAIL_ID,
|
|
574
|
+
userPushId: CREATED_EMAIL_ID,
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
for (const rule of createdRules()) {
|
|
578
|
+
expect(rule.userEmailId!.toString()).toBe(METHOD_ID.toString());
|
|
579
|
+
expect(rule.userSmsId!.toString()).toBe(EXISTING_EMAIL_ID.toString());
|
|
580
|
+
expect(rule.userPushId!.toString()).toBe(CREATED_EMAIL_ID.toString());
|
|
581
|
+
expect(rule.userCallId).toBeUndefined();
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
test("an EMPTY descriptor still seeds a full set of method-less rules", async () => {
|
|
586
|
+
/*
|
|
587
|
+
* KNOWN DEFECT, pinned as-is. With no id on the descriptor the duplicate
|
|
588
|
+
* check degenerates to (projectId, userId, ruleType) and the created rows
|
|
589
|
+
* carry no notification method at all - onBeforeCreate would reject them
|
|
590
|
+
* with "Call, SMS, WhatsApp, Telegram, Webhook, Email, or Push notification
|
|
591
|
+
* is required" against a real database. Nothing in this method guards
|
|
592
|
+
* against being handed an empty descriptor.
|
|
593
|
+
*/
|
|
594
|
+
await runForDescriptor({});
|
|
595
|
+
|
|
596
|
+
const rules: Array<Model> = createdRules();
|
|
597
|
+
expect(rules).toHaveLength(TOTAL_SEEDED_RULES);
|
|
598
|
+
|
|
599
|
+
for (const rule of rules) {
|
|
600
|
+
for (const channel of ALL_CHANNELS) {
|
|
601
|
+
expect(rule[channel]).toBeUndefined();
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
for (const query of duplicateCheckQueries()) {
|
|
606
|
+
for (const channel of ALL_CHANNELS) {
|
|
607
|
+
expect(query[channel]).toBeUndefined();
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
test("the duplicate check is root-scoped and keyed on project, user and rule type", async () => {
|
|
613
|
+
await runForEmailMethod();
|
|
614
|
+
|
|
615
|
+
expect(findOneBySpy).toHaveBeenCalledTimes(TOTAL_SEEDED_RULES);
|
|
616
|
+
|
|
617
|
+
for (const call of findOneBySpy.mock.calls) {
|
|
618
|
+
const arg: {
|
|
619
|
+
query: Record<string, unknown>;
|
|
620
|
+
props: { isRoot: boolean };
|
|
621
|
+
} = call[0] as {
|
|
622
|
+
query: Record<string, unknown>;
|
|
623
|
+
props: { isRoot: boolean };
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
expect((arg.query["projectId"] as ObjectID).toString()).toBe(
|
|
627
|
+
PROJECT_ID.toString(),
|
|
628
|
+
);
|
|
629
|
+
expect((arg.query["userId"] as ObjectID).toString()).toBe(
|
|
630
|
+
USER_ID.toString(),
|
|
631
|
+
);
|
|
632
|
+
expect(arg.query["ruleType"]).toBeDefined();
|
|
633
|
+
expect(arg.props.isRoot).toBe(true);
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
test("the severity duplicate checks carry the severity id they are checking", async () => {
|
|
638
|
+
await runForEmailMethod();
|
|
639
|
+
|
|
640
|
+
const queries: Array<Record<string, unknown>> = duplicateCheckQueries();
|
|
641
|
+
|
|
642
|
+
expect(
|
|
643
|
+
queries.slice(0, 3).map((query: Record<string, unknown>): string => {
|
|
644
|
+
return (query["incidentSeverityId"] as ObjectID).toString();
|
|
645
|
+
}),
|
|
646
|
+
).toEqual([
|
|
647
|
+
INCIDENT_SEV_1.toString(),
|
|
648
|
+
INCIDENT_SEV_2.toString(),
|
|
649
|
+
INCIDENT_SEV_3.toString(),
|
|
650
|
+
]);
|
|
651
|
+
|
|
652
|
+
expect(
|
|
653
|
+
queries.slice(3, 5).map((query: Record<string, unknown>): string => {
|
|
654
|
+
return (query["alertSeverityId"] as ObjectID).toString();
|
|
655
|
+
}),
|
|
656
|
+
).toEqual([ALERT_SEV_1.toString(), ALERT_SEV_2.toString()]);
|
|
657
|
+
|
|
658
|
+
// The episode checks are severity-keyed too, since Phase 1 closed GAP G.
|
|
659
|
+
expect(
|
|
660
|
+
queries.slice(5, 7).map((query: Record<string, unknown>): string => {
|
|
661
|
+
return (query["alertSeverityId"] as ObjectID).toString();
|
|
662
|
+
}),
|
|
663
|
+
).toEqual([ALERT_SEV_1.toString(), ALERT_SEV_2.toString()]);
|
|
664
|
+
|
|
665
|
+
expect(
|
|
666
|
+
queries.slice(7, 10).map((query: Record<string, unknown>): string => {
|
|
667
|
+
return (query["incidentSeverityId"] as ObjectID).toString();
|
|
668
|
+
}),
|
|
669
|
+
).toEqual([
|
|
670
|
+
INCIDENT_SEV_1.toString(),
|
|
671
|
+
INCIDENT_SEV_2.toString(),
|
|
672
|
+
INCIDENT_SEV_3.toString(),
|
|
673
|
+
]);
|
|
674
|
+
|
|
675
|
+
// Only the two shift rules are looked up without a severity.
|
|
676
|
+
for (const query of queries.slice(10)) {
|
|
677
|
+
expect(query["incidentSeverityId"]).toBeUndefined();
|
|
678
|
+
expect(query["alertSeverityId"]).toBeUndefined();
|
|
679
|
+
}
|
|
680
|
+
});
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
describe("addDefaultNotificationRulesForVerifiedMethod - idempotence", () => {
|
|
684
|
+
test("re-verifying a method that already has all its defaults creates nothing", async () => {
|
|
685
|
+
/*
|
|
686
|
+
* The verify endpoints call this every time a method is re-verified. A
|
|
687
|
+
* second run must not double the user's rules (which would double every
|
|
688
|
+
* page they receive).
|
|
689
|
+
*/
|
|
690
|
+
findOneBySpy.mockResolvedValue(existingRule() as never);
|
|
691
|
+
|
|
692
|
+
await runForEmailMethod();
|
|
693
|
+
|
|
694
|
+
expect(findOneBySpy).toHaveBeenCalledTimes(TOTAL_SEEDED_RULES);
|
|
695
|
+
expect(createSpy).not.toHaveBeenCalled();
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
test("an existing rule for ONE incident severity suppresses only that severity", async () => {
|
|
699
|
+
findOneBySpy.mockImplementation(
|
|
700
|
+
(findBy: { query: Record<string, unknown> }): Promise<Model | null> => {
|
|
701
|
+
const severityId: ObjectID | undefined = findBy.query[
|
|
702
|
+
"incidentSeverityId"
|
|
703
|
+
] as ObjectID | undefined;
|
|
704
|
+
|
|
705
|
+
if (severityId && severityId.toString() === INCIDENT_SEV_2.toString()) {
|
|
706
|
+
return Promise.resolve(existingRule());
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
return Promise.resolve(null);
|
|
710
|
+
},
|
|
711
|
+
);
|
|
712
|
+
|
|
713
|
+
await runForEmailMethod();
|
|
714
|
+
|
|
715
|
+
/*
|
|
716
|
+
* Two rows are suppressed, not one: the incident on-call rule for SEV_2 and
|
|
717
|
+
* the incident EPISODE rule for SEV_2, both of which are now keyed on the
|
|
718
|
+
* same severity.
|
|
719
|
+
*/
|
|
720
|
+
expect(createSpy).toHaveBeenCalledTimes(TOTAL_SEEDED_RULES - 2);
|
|
721
|
+
|
|
722
|
+
const incidentRules: Array<Model> = createdRulesOfType(
|
|
723
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT,
|
|
724
|
+
);
|
|
725
|
+
expect(
|
|
726
|
+
incidentRules.map((rule: Model): string => {
|
|
727
|
+
return rule.incidentSeverityId!.toString();
|
|
728
|
+
}),
|
|
729
|
+
).toEqual([INCIDENT_SEV_1.toString(), INCIDENT_SEV_3.toString()]);
|
|
730
|
+
|
|
731
|
+
expect(
|
|
732
|
+
createdRulesOfType(
|
|
733
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE,
|
|
734
|
+
).map((rule: Model): string => {
|
|
735
|
+
return rule.incidentSeverityId!.toString();
|
|
736
|
+
}),
|
|
737
|
+
).toEqual([INCIDENT_SEV_1.toString(), INCIDENT_SEV_3.toString()]);
|
|
738
|
+
});
|
|
739
|
+
|
|
740
|
+
test("an existing rule for ONE alert severity suppresses only that severity", async () => {
|
|
741
|
+
findOneBySpy.mockImplementation(
|
|
742
|
+
(findBy: { query: Record<string, unknown> }): Promise<Model | null> => {
|
|
743
|
+
const severityId: ObjectID | undefined = findBy.query[
|
|
744
|
+
"alertSeverityId"
|
|
745
|
+
] as ObjectID | undefined;
|
|
746
|
+
|
|
747
|
+
if (severityId && severityId.toString() === ALERT_SEV_1.toString()) {
|
|
748
|
+
return Promise.resolve(existingRule());
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
return Promise.resolve(null);
|
|
752
|
+
},
|
|
753
|
+
);
|
|
754
|
+
|
|
755
|
+
await runForEmailMethod();
|
|
756
|
+
|
|
757
|
+
// Again two rows: the alert on-call rule and the alert episode rule.
|
|
758
|
+
expect(createSpy).toHaveBeenCalledTimes(TOTAL_SEEDED_RULES - 2);
|
|
759
|
+
|
|
760
|
+
const alertRules: Array<Model> = createdRulesOfType(
|
|
761
|
+
NotificationRuleType.ON_CALL_EXECUTED_ALERT,
|
|
762
|
+
);
|
|
763
|
+
expect(alertRules).toHaveLength(1);
|
|
764
|
+
expect(alertRules[0]!.alertSeverityId!.toString()).toBe(
|
|
765
|
+
ALERT_SEV_2.toString(),
|
|
766
|
+
);
|
|
767
|
+
|
|
768
|
+
const alertEpisodeRules: Array<Model> = createdRulesOfType(
|
|
769
|
+
NotificationRuleType.ON_CALL_EXECUTED_ALERT_EPISODE,
|
|
770
|
+
);
|
|
771
|
+
expect(alertEpisodeRules).toHaveLength(1);
|
|
772
|
+
expect(alertEpisodeRules[0]!.alertSeverityId!.toString()).toBe(
|
|
773
|
+
ALERT_SEV_2.toString(),
|
|
774
|
+
);
|
|
775
|
+
});
|
|
776
|
+
|
|
777
|
+
test("all incident severities covered still leaves the alert and single rules to seed", async () => {
|
|
778
|
+
findOneBySpy.mockImplementation(
|
|
779
|
+
(findBy: { query: Record<string, unknown> }): Promise<Model | null> => {
|
|
780
|
+
return Promise.resolve(
|
|
781
|
+
findBy.query["incidentSeverityId"] ? existingRule() : null,
|
|
782
|
+
);
|
|
783
|
+
},
|
|
784
|
+
);
|
|
785
|
+
|
|
786
|
+
await runForEmailMethod();
|
|
787
|
+
|
|
788
|
+
/*
|
|
789
|
+
* Every incident-severity-keyed row is suppressed - the 3 on-call rules and
|
|
790
|
+
* the 3 episode rules - leaving 2 alert, 2 alert episode and 2 shift rules.
|
|
791
|
+
*/
|
|
792
|
+
expect(createSpy).toHaveBeenCalledTimes(6);
|
|
793
|
+
expect(
|
|
794
|
+
createdRulesOfType(NotificationRuleType.ON_CALL_EXECUTED_INCIDENT),
|
|
795
|
+
).toHaveLength(0);
|
|
796
|
+
expect(
|
|
797
|
+
createdRulesOfType(
|
|
798
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE,
|
|
799
|
+
),
|
|
800
|
+
).toHaveLength(0);
|
|
801
|
+
expect(
|
|
802
|
+
createdRulesOfType(NotificationRuleType.ON_CALL_EXECUTED_ALERT),
|
|
803
|
+
).toHaveLength(2);
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
test.each(SINGLE_RULE_TYPES)(
|
|
807
|
+
"an existing %s rule suppresses only that single rule",
|
|
808
|
+
async (existingRuleType: NotificationRuleType) => {
|
|
809
|
+
findOneBySpy.mockImplementation(
|
|
810
|
+
(findBy: { query: Record<string, unknown> }): Promise<Model | null> => {
|
|
811
|
+
return Promise.resolve(
|
|
812
|
+
findBy.query["ruleType"] === existingRuleType
|
|
813
|
+
? existingRule()
|
|
814
|
+
: null,
|
|
815
|
+
);
|
|
816
|
+
},
|
|
817
|
+
);
|
|
818
|
+
|
|
819
|
+
await runForEmailMethod();
|
|
820
|
+
|
|
821
|
+
expect(createSpy).toHaveBeenCalledTimes(TOTAL_SEEDED_RULES - 1);
|
|
822
|
+
expect(createdRulesOfType(existingRuleType)).toHaveLength(0);
|
|
823
|
+
|
|
824
|
+
for (const otherRuleType of SINGLE_RULE_TYPES) {
|
|
825
|
+
if (otherRuleType === existingRuleType) {
|
|
826
|
+
continue;
|
|
827
|
+
}
|
|
828
|
+
expect(createdRulesOfType(otherRuleType)).toHaveLength(1);
|
|
829
|
+
}
|
|
830
|
+
},
|
|
831
|
+
);
|
|
832
|
+
|
|
833
|
+
test.each<[NotificationRuleType, number]>([
|
|
834
|
+
[NotificationRuleType.ON_CALL_EXECUTED_ALERT_EPISODE, 2],
|
|
835
|
+
[NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE, 3],
|
|
836
|
+
])(
|
|
837
|
+
"existing %s rules for every severity suppress exactly %i rows",
|
|
838
|
+
async (existingRuleType: NotificationRuleType, suppressedCount: number) => {
|
|
839
|
+
/*
|
|
840
|
+
* Episode rules are per-severity now, so "already seeded" is a statement
|
|
841
|
+
* about one severity at a time - stubbing the whole rule type standing in
|
|
842
|
+
* for a user who has all of them.
|
|
843
|
+
*/
|
|
844
|
+
findOneBySpy.mockImplementation(
|
|
845
|
+
(findBy: { query: Record<string, unknown> }): Promise<Model | null> => {
|
|
846
|
+
return Promise.resolve(
|
|
847
|
+
findBy.query["ruleType"] === existingRuleType
|
|
848
|
+
? existingRule()
|
|
849
|
+
: null,
|
|
850
|
+
);
|
|
851
|
+
},
|
|
852
|
+
);
|
|
853
|
+
|
|
854
|
+
await runForEmailMethod();
|
|
855
|
+
|
|
856
|
+
expect(createSpy).toHaveBeenCalledTimes(
|
|
857
|
+
TOTAL_SEEDED_RULES - suppressedCount,
|
|
858
|
+
);
|
|
859
|
+
expect(createdRulesOfType(existingRuleType)).toHaveLength(0);
|
|
860
|
+
},
|
|
861
|
+
);
|
|
862
|
+
|
|
863
|
+
test("a rule that exists for a DIFFERENT method does not suppress this method's defaults", async () => {
|
|
864
|
+
/*
|
|
865
|
+
* The duplicate query is keyed on the method column, so a user who already
|
|
866
|
+
* has e-mail rules still gets a full set of SMS rules when they verify a
|
|
867
|
+
* phone number.
|
|
868
|
+
*/
|
|
869
|
+
findOneBySpy.mockImplementation(
|
|
870
|
+
(findBy: { query: Record<string, unknown> }): Promise<Model | null> => {
|
|
871
|
+
return Promise.resolve(
|
|
872
|
+
findBy.query["userEmailId"] ? existingRule() : null,
|
|
873
|
+
);
|
|
874
|
+
},
|
|
875
|
+
);
|
|
876
|
+
|
|
877
|
+
await runForDescriptor({ userSmsId: METHOD_ID });
|
|
878
|
+
|
|
879
|
+
expect(createSpy).toHaveBeenCalledTimes(TOTAL_SEEDED_RULES);
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
test("the duplicate check runs once per candidate rule - no extra reads", async () => {
|
|
883
|
+
await runForEmailMethod();
|
|
884
|
+
|
|
885
|
+
expect(findOneBySpy).toHaveBeenCalledTimes(createSpy.mock.calls.length);
|
|
886
|
+
});
|
|
887
|
+
});
|
|
888
|
+
|
|
889
|
+
describe("addDefaultNotificationRulesForVerifiedMethod - a project with no severities", () => {
|
|
890
|
+
test("no per-severity rules are seeded, but the two shift rules still are", async () => {
|
|
891
|
+
/*
|
|
892
|
+
* The episode rules follow the severities now, so a project with none gets
|
|
893
|
+
* no episode rules either. That is the correct reading of GAP G: a rule for
|
|
894
|
+
* a severity that does not exist could never have matched a page anyway.
|
|
895
|
+
*/
|
|
896
|
+
incidentSeveritiesSpy.mockResolvedValue([] as never);
|
|
897
|
+
alertSeveritiesSpy.mockResolvedValue([] as never);
|
|
898
|
+
|
|
899
|
+
await runForEmailMethod();
|
|
900
|
+
|
|
901
|
+
expect(createSpy).toHaveBeenCalledTimes(2);
|
|
902
|
+
expect(
|
|
903
|
+
createdRules().map((rule: Model): NotificationRuleType => {
|
|
904
|
+
return rule.ruleType!;
|
|
905
|
+
}),
|
|
906
|
+
).toEqual(SINGLE_RULE_TYPES);
|
|
907
|
+
});
|
|
908
|
+
|
|
909
|
+
test("with no severities the duplicate check runs only for the two shift rules", async () => {
|
|
910
|
+
incidentSeveritiesSpy.mockResolvedValue([] as never);
|
|
911
|
+
alertSeveritiesSpy.mockResolvedValue([] as never);
|
|
912
|
+
|
|
913
|
+
await runForEmailMethod();
|
|
914
|
+
|
|
915
|
+
expect(findOneBySpy).toHaveBeenCalledTimes(2);
|
|
916
|
+
for (const query of duplicateCheckQueries()) {
|
|
917
|
+
expect(query["incidentSeverityId"]).toBeUndefined();
|
|
918
|
+
expect(query["alertSeverityId"]).toBeUndefined();
|
|
919
|
+
}
|
|
920
|
+
});
|
|
921
|
+
|
|
922
|
+
test("the shift rules still get the method and notifyAfterMinutes 0", async () => {
|
|
923
|
+
incidentSeveritiesSpy.mockResolvedValue([] as never);
|
|
924
|
+
alertSeveritiesSpy.mockResolvedValue([] as never);
|
|
925
|
+
|
|
926
|
+
await runForDescriptor({ userCallId: METHOD_ID });
|
|
927
|
+
|
|
928
|
+
for (const rule of createdRules()) {
|
|
929
|
+
expect(rule.userCallId!.toString()).toBe(METHOD_ID.toString());
|
|
930
|
+
expect(rule.notifyAfterMinutes).toBe(0);
|
|
931
|
+
}
|
|
932
|
+
});
|
|
933
|
+
|
|
934
|
+
test("only incident severities missing still seeds the alert rules", async () => {
|
|
935
|
+
incidentSeveritiesSpy.mockResolvedValue([] as never);
|
|
936
|
+
|
|
937
|
+
await runForEmailMethod();
|
|
938
|
+
|
|
939
|
+
// 0 incident + 2 alert + 2 alert episode + 0 incident episode + 2 shift.
|
|
940
|
+
expect(createSpy).toHaveBeenCalledTimes(6);
|
|
941
|
+
expect(
|
|
942
|
+
createdRulesOfType(NotificationRuleType.ON_CALL_EXECUTED_ALERT),
|
|
943
|
+
).toHaveLength(2);
|
|
944
|
+
expect(
|
|
945
|
+
createdRulesOfType(NotificationRuleType.ON_CALL_EXECUTED_ALERT_EPISODE),
|
|
946
|
+
).toHaveLength(2);
|
|
947
|
+
expect(
|
|
948
|
+
createdRulesOfType(
|
|
949
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE,
|
|
950
|
+
),
|
|
951
|
+
).toHaveLength(0);
|
|
952
|
+
});
|
|
953
|
+
|
|
954
|
+
test("only alert severities missing still seeds the incident rules", async () => {
|
|
955
|
+
alertSeveritiesSpy.mockResolvedValue([] as never);
|
|
956
|
+
|
|
957
|
+
await runForEmailMethod();
|
|
958
|
+
|
|
959
|
+
// 3 incident + 0 alert + 0 alert episode + 3 incident episode + 2 shift.
|
|
960
|
+
expect(createSpy).toHaveBeenCalledTimes(8);
|
|
961
|
+
expect(
|
|
962
|
+
createdRulesOfType(NotificationRuleType.ON_CALL_EXECUTED_INCIDENT),
|
|
963
|
+
).toHaveLength(3);
|
|
964
|
+
expect(
|
|
965
|
+
createdRulesOfType(
|
|
966
|
+
NotificationRuleType.ON_CALL_EXECUTED_INCIDENT_EPISODE,
|
|
967
|
+
),
|
|
968
|
+
).toHaveLength(3);
|
|
969
|
+
expect(
|
|
970
|
+
createdRulesOfType(NotificationRuleType.ON_CALL_EXECUTED_ALERT_EPISODE),
|
|
971
|
+
).toHaveLength(0);
|
|
972
|
+
});
|
|
973
|
+
});
|
|
974
|
+
|
|
975
|
+
describe("addDefaultNotificationRuleForUser - materialising the e-mail identity", () => {
|
|
976
|
+
test("a user with no UserEmail row gets one created, already verified", async () => {
|
|
977
|
+
await UserNotificationRuleService.addDefaultNotificationRuleForUser(
|
|
978
|
+
PROJECT_ID,
|
|
979
|
+
USER_ID,
|
|
980
|
+
USER_EMAIL,
|
|
981
|
+
);
|
|
982
|
+
|
|
983
|
+
expect(userEmailCreateSpy).toHaveBeenCalledTimes(1);
|
|
984
|
+
|
|
985
|
+
const created: UserEmail = (
|
|
986
|
+
userEmailCreateSpy.mock.calls[0][0] as CreateBy<UserEmail>
|
|
987
|
+
).data;
|
|
988
|
+
|
|
989
|
+
expect(created.projectId!.toString()).toBe(PROJECT_ID.toString());
|
|
990
|
+
expect(created.userId!.toString()).toBe(USER_ID.toString());
|
|
991
|
+
expect(created.email!.toString()).toBe(USER_EMAIL.toString());
|
|
992
|
+
/*
|
|
993
|
+
* The join path trusts the address the account already verified, so the
|
|
994
|
+
* row is born verified - otherwise the user would have to verify an
|
|
995
|
+
* address they never typed in.
|
|
996
|
+
*/
|
|
997
|
+
expect(created.isVerified).toBe(true);
|
|
998
|
+
});
|
|
999
|
+
|
|
1000
|
+
test("the UserEmail is created as an internal, root-scoped write", async () => {
|
|
1001
|
+
await UserNotificationRuleService.addDefaultNotificationRuleForUser(
|
|
1002
|
+
PROJECT_ID,
|
|
1003
|
+
USER_ID,
|
|
1004
|
+
USER_EMAIL,
|
|
1005
|
+
);
|
|
1006
|
+
|
|
1007
|
+
expect(
|
|
1008
|
+
(userEmailCreateSpy.mock.calls[0][0] as CreateBy<UserEmail>).props.isRoot,
|
|
1009
|
+
).toBe(true);
|
|
1010
|
+
});
|
|
1011
|
+
|
|
1012
|
+
test("the lookup is by project, user AND address, root-scoped", async () => {
|
|
1013
|
+
await UserNotificationRuleService.addDefaultNotificationRuleForUser(
|
|
1014
|
+
PROJECT_ID,
|
|
1015
|
+
USER_ID,
|
|
1016
|
+
USER_EMAIL,
|
|
1017
|
+
);
|
|
1018
|
+
|
|
1019
|
+
expect(userEmailFindOneBySpy).toHaveBeenCalledTimes(1);
|
|
1020
|
+
|
|
1021
|
+
const arg: {
|
|
1022
|
+
query: { projectId: ObjectID; userId: ObjectID; email: Email };
|
|
1023
|
+
props: { isRoot: boolean };
|
|
1024
|
+
} = userEmailFindOneBySpy.mock.calls[0][0] as {
|
|
1025
|
+
query: { projectId: ObjectID; userId: ObjectID; email: Email };
|
|
1026
|
+
props: { isRoot: boolean };
|
|
1027
|
+
};
|
|
1028
|
+
|
|
1029
|
+
expect(arg.query.projectId.toString()).toBe(PROJECT_ID.toString());
|
|
1030
|
+
expect(arg.query.userId.toString()).toBe(USER_ID.toString());
|
|
1031
|
+
expect(arg.query.email.toString()).toBe(USER_EMAIL.toString());
|
|
1032
|
+
expect(arg.props.isRoot).toBe(true);
|
|
1033
|
+
});
|
|
1034
|
+
|
|
1035
|
+
test("the newly created e-mail's id is the one the default rules are hung off", async () => {
|
|
1036
|
+
await UserNotificationRuleService.addDefaultNotificationRuleForUser(
|
|
1037
|
+
PROJECT_ID,
|
|
1038
|
+
USER_ID,
|
|
1039
|
+
USER_EMAIL,
|
|
1040
|
+
);
|
|
1041
|
+
|
|
1042
|
+
const rules: Array<Model> = createdRules();
|
|
1043
|
+
expect(rules).toHaveLength(TOTAL_SEEDED_RULES);
|
|
1044
|
+
for (const rule of rules) {
|
|
1045
|
+
expect(rule.userEmailId!.toString()).toBe(CREATED_EMAIL_ID.toString());
|
|
1046
|
+
expect(rule.userSmsId).toBeUndefined();
|
|
1047
|
+
expect(rule.userCallId).toBeUndefined();
|
|
1048
|
+
}
|
|
1049
|
+
});
|
|
1050
|
+
|
|
1051
|
+
test("it delegates to addDefaultNotificationRulesForVerifiedMethod with exactly that descriptor", async () => {
|
|
1052
|
+
const delegateSpy: jest.SpyInstance = jest
|
|
1053
|
+
.spyOn(
|
|
1054
|
+
UserNotificationRuleService,
|
|
1055
|
+
"addDefaultNotificationRulesForVerifiedMethod",
|
|
1056
|
+
)
|
|
1057
|
+
.mockResolvedValue(undefined as never);
|
|
1058
|
+
|
|
1059
|
+
await UserNotificationRuleService.addDefaultNotificationRuleForUser(
|
|
1060
|
+
PROJECT_ID,
|
|
1061
|
+
USER_ID,
|
|
1062
|
+
USER_EMAIL,
|
|
1063
|
+
);
|
|
1064
|
+
|
|
1065
|
+
expect(delegateSpy).toHaveBeenCalledTimes(1);
|
|
1066
|
+
|
|
1067
|
+
const arg: {
|
|
1068
|
+
projectId: ObjectID;
|
|
1069
|
+
userId: ObjectID;
|
|
1070
|
+
notificationMethod: NotificationMethodDescriptor;
|
|
1071
|
+
} = delegateSpy.mock.calls[0][0] as {
|
|
1072
|
+
projectId: ObjectID;
|
|
1073
|
+
userId: ObjectID;
|
|
1074
|
+
notificationMethod: NotificationMethodDescriptor;
|
|
1075
|
+
};
|
|
1076
|
+
|
|
1077
|
+
expect(arg.projectId.toString()).toBe(PROJECT_ID.toString());
|
|
1078
|
+
expect(arg.userId.toString()).toBe(USER_ID.toString());
|
|
1079
|
+
expect(Object.keys(arg.notificationMethod)).toEqual(["userEmailId"]);
|
|
1080
|
+
expect(arg.notificationMethod.userEmailId!.toString()).toBe(
|
|
1081
|
+
CREATED_EMAIL_ID.toString(),
|
|
1082
|
+
);
|
|
1083
|
+
});
|
|
1084
|
+
});
|
|
1085
|
+
|
|
1086
|
+
describe("addDefaultNotificationRuleForUser - reusing an existing e-mail identity", () => {
|
|
1087
|
+
beforeEach(() => {
|
|
1088
|
+
userEmailFindOneBySpy.mockResolvedValue(
|
|
1089
|
+
existingUserEmail(EXISTING_EMAIL_ID, true) as never,
|
|
1090
|
+
);
|
|
1091
|
+
});
|
|
1092
|
+
|
|
1093
|
+
test("no second UserEmail row is created", async () => {
|
|
1094
|
+
await UserNotificationRuleService.addDefaultNotificationRuleForUser(
|
|
1095
|
+
PROJECT_ID,
|
|
1096
|
+
USER_ID,
|
|
1097
|
+
USER_EMAIL,
|
|
1098
|
+
);
|
|
1099
|
+
|
|
1100
|
+
expect(userEmailCreateSpy).not.toHaveBeenCalled();
|
|
1101
|
+
});
|
|
1102
|
+
|
|
1103
|
+
test("the existing row's id is what the default rules point at", async () => {
|
|
1104
|
+
await UserNotificationRuleService.addDefaultNotificationRuleForUser(
|
|
1105
|
+
PROJECT_ID,
|
|
1106
|
+
USER_ID,
|
|
1107
|
+
USER_EMAIL,
|
|
1108
|
+
);
|
|
1109
|
+
|
|
1110
|
+
const rules: Array<Model> = createdRules();
|
|
1111
|
+
expect(rules).toHaveLength(TOTAL_SEEDED_RULES);
|
|
1112
|
+
for (const rule of rules) {
|
|
1113
|
+
expect(rule.userEmailId!.toString()).toBe(EXISTING_EMAIL_ID.toString());
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
|
|
1117
|
+
test("re-running for a user who already has the defaults creates nothing at all", async () => {
|
|
1118
|
+
findOneBySpy.mockResolvedValue(existingRule() as never);
|
|
1119
|
+
|
|
1120
|
+
await UserNotificationRuleService.addDefaultNotificationRuleForUser(
|
|
1121
|
+
PROJECT_ID,
|
|
1122
|
+
USER_ID,
|
|
1123
|
+
USER_EMAIL,
|
|
1124
|
+
);
|
|
1125
|
+
|
|
1126
|
+
expect(userEmailCreateSpy).not.toHaveBeenCalled();
|
|
1127
|
+
expect(createSpy).not.toHaveBeenCalled();
|
|
1128
|
+
});
|
|
1129
|
+
|
|
1130
|
+
test("an UNVERIFIED existing e-mail is reused as-is and still gets default rules", async () => {
|
|
1131
|
+
/*
|
|
1132
|
+
* KNOWN DEFECT, pinned as-is. The reuse branch never inspects isVerified,
|
|
1133
|
+
* so a project e-mail the user has not confirmed becomes the target of
|
|
1134
|
+
* every default on-call rule - and is neither verified nor rejected here.
|
|
1135
|
+
*/
|
|
1136
|
+
userEmailFindOneBySpy.mockResolvedValue(
|
|
1137
|
+
existingUserEmail(EXISTING_EMAIL_ID, false) as never,
|
|
1138
|
+
);
|
|
1139
|
+
|
|
1140
|
+
await UserNotificationRuleService.addDefaultNotificationRuleForUser(
|
|
1141
|
+
PROJECT_ID,
|
|
1142
|
+
USER_ID,
|
|
1143
|
+
USER_EMAIL,
|
|
1144
|
+
);
|
|
1145
|
+
|
|
1146
|
+
expect(userEmailCreateSpy).not.toHaveBeenCalled();
|
|
1147
|
+
expect(createSpy).toHaveBeenCalledTimes(TOTAL_SEEDED_RULES);
|
|
1148
|
+
expect(createdRules()[0]!.userEmailId!.toString()).toBe(
|
|
1149
|
+
EXISTING_EMAIL_ID.toString(),
|
|
1150
|
+
);
|
|
1151
|
+
});
|
|
1152
|
+
|
|
1153
|
+
test("the seeded set is identical to the verified-method path", async () => {
|
|
1154
|
+
await UserNotificationRuleService.addDefaultNotificationRuleForUser(
|
|
1155
|
+
PROJECT_ID,
|
|
1156
|
+
USER_ID,
|
|
1157
|
+
USER_EMAIL,
|
|
1158
|
+
);
|
|
1159
|
+
|
|
1160
|
+
expect(
|
|
1161
|
+
createdRules().map((rule: Model): NotificationRuleType => {
|
|
1162
|
+
return rule.ruleType!;
|
|
1163
|
+
}),
|
|
1164
|
+
).toEqual(SEEDED_RULE_ORDER);
|
|
1165
|
+
});
|
|
1166
|
+
});
|