@oneuptime/common 12.0.6 → 12.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/AIInsight.ts +1 -1
- package/Models/DatabaseModels/DatabaseBaseModel/FileModel.ts +2 -3
- package/Models/DatabaseModels/DeletedProject.ts +595 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/Monitor.ts +111 -0
- package/Models/DatabaseModels/Project.ts +3 -3
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +19 -1
- package/Server/API/FileAPI.ts +15 -2
- package/Server/API/MicrosoftTeamsAPI.ts +6 -1
- package/Server/API/ProjectAPI.ts +214 -0
- package/Server/API/StatusPageAPI.ts +39 -6
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.ts +50 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.ts +67 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.ts +39 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Services/AIAgentService.ts +20 -0
- package/Server/Services/DashboardDomainService.ts +73 -28
- package/Server/Services/DatabaseService.ts +1 -0
- package/Server/Services/DeletedProjectService.ts +138 -0
- package/Server/Services/FileService.ts +61 -0
- package/Server/Services/IncidentEpisodePublicNoteService.ts +18 -0
- package/Server/Services/IncidentPublicNoteService.ts +18 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/MonitorService.ts +311 -0
- package/Server/Services/ProbeService.ts +20 -0
- package/Server/Services/ProjectService.ts +297 -1
- package/Server/Services/PushNotificationService.ts +71 -0
- package/Server/Services/ScheduledMaintenancePublicNoteService.ts +18 -0
- package/Server/Services/StatusPageAnnouncementService.ts +53 -0
- package/Server/Services/StatusPageDomainService.ts +73 -28
- package/Server/Services/TeamMemberService.ts +117 -12
- package/Server/Services/TelemetryIngestionKeyService.ts +1 -0
- package/Server/Services/UserWebhookService.ts +34 -109
- package/Server/Services/WorkspaceNotificationRuleService.ts +69 -0
- package/Server/Services/WorkspaceProjectAuthTokenService.ts +37 -1
- package/Server/Types/Database/DeleteById.ts +2 -0
- package/Server/Types/Database/DeleteOneBy.ts +6 -0
- package/Server/Types/Domain.ts +41 -0
- package/Server/Types/Workflow/Components/API/Delete.ts +2 -1
- package/Server/Types/Workflow/Components/API/Get.ts +2 -1
- package/Server/Types/Workflow/Components/API/Patch.ts +2 -1
- package/Server/Types/Workflow/Components/API/Post.ts +2 -1
- package/Server/Types/Workflow/Components/API/Put.ts +2 -1
- package/Server/Types/Workflow/Components/API/Utils.ts +41 -2
- package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +25 -19
- package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +6 -5
- package/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.ts +32 -14
- package/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.ts +31 -13
- package/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.ts +29 -20
- package/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.ts +28 -21
- package/Server/Types/Workflow/Components/BaseModel/LogComponentError.ts +89 -0
- package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +208 -0
- package/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts +11 -0
- package/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.ts +41 -18
- package/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.ts +45 -19
- package/Server/Types/Workflow/Components/Discord/SendMessageToChannel.ts +16 -9
- package/Server/Types/Workflow/Components/IncomingWebhookUtils.ts +66 -0
- package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +15 -9
- package/Server/Types/Workflow/Components/Slack/SendMessageToChannel.ts +17 -0
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
- package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +171 -0
- package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +3 -3
- package/Server/Utils/AI/SRE/Insights/FixRouting.ts +3 -2
- package/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.ts +1 -1
- package/Server/Utils/AI/Toolbox/CodeWriteTools.ts +6 -6
- package/Server/Utils/CodeRepository/GitHub/GitHub.ts +43 -5
- package/Server/Utils/DataSource/EgressGuard.ts +176 -16
- package/Server/Utils/DataSource/HttpFetch.ts +6 -45
- package/Server/Utils/Execute.ts +8 -0
- package/Server/Utils/InlineImageAccessTokenSync.ts +23 -0
- package/Server/Utils/LLM/LLMService.ts +57 -12
- package/Server/Utils/Monitor/MonitorAlert.ts +40 -0
- package/Server/Utils/Monitor/MonitorDependencySuppression.ts +192 -0
- package/Server/Utils/Monitor/MonitorIncident.ts +40 -0
- package/Server/Utils/Monitor/MonitorResource.ts +36 -0
- package/Server/Utils/Response.ts +142 -6
- package/Server/Utils/SSRFProtection.ts +273 -60
- package/Server/Utils/StartServer.ts +8 -0
- package/Server/Utils/VM/VMRunner.ts +88 -1
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +555 -49
- package/Server/Utils/Workspace/Slack/Slack.ts +25 -2
- package/Server/Utils/Workspace/WorkspaceBase.ts +6 -0
- package/Tests/App/Dashboard/DangerZone.test.tsx +334 -0
- package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +539 -0
- package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +678 -0
- package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +706 -0
- package/Tests/App/Dashboard/DashboardVariablesModal.test.tsx +508 -0
- package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +470 -0
- package/Tests/App/StatusPage/StatusPageDetailPagesNotFound.test.tsx +308 -0
- package/Tests/Models/DatabaseModels/DeletedProjectModel.test.ts +251 -0
- package/Tests/Models/DatabaseModels/SavedViewJSONColumnTuples.test.ts +115 -0
- package/Tests/Server/API/FileAPIAccessControl.test.ts +316 -0
- package/Tests/Server/API/ProjectAPI.test.ts +299 -1
- package/Tests/Server/API/ProjectAPIAdjustBalance.test.ts +459 -0
- package/Tests/Server/API/ProjectAPIAdjustBalanceBillingDisabled.test.ts +177 -0
- package/Tests/Server/Services/DatabaseServiceDeletionReason.test.ts +123 -0
- package/Tests/Server/Services/DeletedProjectService.test.ts +415 -0
- package/Tests/Server/Services/DeletedProjectServiceSelfHosted.test.ts +70 -0
- package/Tests/Server/Services/DomainSubdomainHooks.test.ts +94 -0
- package/Tests/Server/Services/FileIsPublicBooleanMigration.test.ts +244 -0
- package/Tests/Server/Services/FileServiceMimeType.test.ts +89 -0
- package/Tests/Server/Services/MonitorServiceDependencyValidation.test.ts +702 -0
- package/Tests/Server/Services/ProjectServiceAdjustBalance.test.ts +615 -0
- package/Tests/Server/Services/ProjectServiceDeleteAudit.test.ts +406 -0
- package/Tests/Server/Services/PublishTimeImageVisibility.test.ts +450 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +669 -0
- package/Tests/Server/Services/UserWebhookSSRF.test.ts +174 -0
- package/Tests/Server/Services/WebPushEndpointAllowlist.test.ts +133 -0
- package/Tests/Server/Services/WorkspaceProjectAuthTokenRepoint.test.ts +618 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +26 -1
- package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +215 -0
- package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +742 -0
- package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +256 -0
- package/Tests/Server/Types/Workflow/Components/ModelArguments.test.ts +371 -0
- package/Tests/Server/Utils/AI/CodeAgentCommandGuard.test.ts +204 -0
- package/Tests/Server/Utils/AI/CodeAgentWriteLimits.test.ts +213 -0
- package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +52 -5
- package/Tests/Server/Utils/AI/LLMServiceBaseUrl.test.ts +3 -0
- package/Tests/Server/Utils/AI/LLMServiceEgressGuard.test.ts +315 -0
- package/Tests/Server/Utils/AI/LLMServiceModelCompatibility.test.ts +3 -0
- package/Tests/Server/Utils/AI/LLMServiceRequestPolicy.test.ts +17 -5
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +14 -1
- package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +35 -0
- package/Tests/Server/Utils/AI/StubLLMEgressGuard.ts +25 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +62 -7
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +69 -0
- package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +330 -0
- package/Tests/Server/Utils/GitHubCreatePullRequestWithToken.test.ts +393 -0
- package/Tests/Server/Utils/InlineImageAccessTokenSync.test.ts +202 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppression.test.ts +811 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +604 -0
- package/Tests/Server/Utils/ResponseSendFileResponse.test.ts +192 -0
- package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +406 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +1169 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelsList.test.ts +2 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +1605 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsTenantResolution.test.ts +1218 -0
- package/Tests/Types/AI/AIChatMessageStatus.test.ts +79 -0
- package/Tests/Types/AI/AIInsightStatus.test.ts +40 -0
- package/Tests/Types/API/HostnameAuthorityParsing.test.ts +157 -0
- package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +27 -0
- package/Tests/Types/DataSource/DataSourceLimits.test.ts +71 -0
- package/Tests/Types/DataSource/DataSourceType.test.ts +181 -0
- package/Tests/Types/DomainSubdomainValidation.test.ts +90 -0
- package/Tests/Types/JSONFunctions.test.ts +252 -1
- package/Tests/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.test.ts +61 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.test.ts +62 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.test.ts +68 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpVersion.test.ts +51 -0
- package/Tests/UI/Components/404.test.tsx +1 -1
- package/Tests/UI/Components/Alert.test.tsx +1 -1
- package/Tests/UI/Components/Badge.test.tsx +1 -1
- package/Tests/UI/Components/BasicForm.test.tsx +39 -10
- package/Tests/UI/Components/Button.test.tsx +1 -1
- package/Tests/UI/Components/Card.test.tsx +1 -1
- package/Tests/UI/Components/Charts/AxisTickColor.test.tsx +1 -1
- package/Tests/UI/Components/ColorViewer.test.tsx +1 -1
- package/Tests/UI/Components/ComponentsModal.test.tsx +7 -1
- package/Tests/UI/Components/DictionaryOfStrings.test.tsx +1 -1
- package/Tests/UI/Components/Dropdown.test.tsx +1 -1
- package/Tests/UI/Components/FilePicker.test.tsx +1 -1
- package/Tests/UI/Components/HiddenText.test.tsx +1 -1
- package/Tests/UI/Components/Input.test.tsx +1 -1
- package/Tests/UI/Components/Loader.test.tsx +1 -1
- package/Tests/UI/Components/LogTimeRangePicker.test.tsx +1 -1
- package/Tests/UI/Components/MasterPage.test.tsx +1 -1
- package/Tests/UI/Components/ModalPortalDismissal.test.tsx +489 -0
- package/Tests/UI/Components/ModelDelete.test.tsx +214 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkSelectAll.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1 -1
- package/Tests/UI/Components/NavBar.test.tsx +1 -1
- package/Tests/UI/Components/OperatorSelectorKeyboard.test.tsx +1 -1
- package/Tests/UI/Components/Pagination.test.tsx +1 -1
- package/Tests/UI/Components/Pill.test.tsx +1 -1
- package/Tests/UI/Components/Probe.test.tsx +1 -1
- package/Tests/UI/Components/ProgressBar.test.tsx +1 -1
- package/Tests/UI/Components/RadioButtons.test.tsx +1 -1
- package/Tests/UI/Components/SideMenuItem.test.tsx +1 -1
- package/Tests/UI/Components/SideOver.test.tsx +500 -6
- package/Tests/UI/Components/Tabs.test.tsx +1 -1
- package/Tests/UI/Components/TelemetrySearchBar.test.tsx +1 -1
- package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +1 -1
- package/Tests/UI/Components/TextArea.test.tsx +1 -1
- package/Tests/UI/Components/Toast.test.tsx +1 -1
- package/Tests/UI/Components/Toggle.test.tsx +1 -1
- package/Tests/UI/Components/TopSection.test.tsx +1 -1
- package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +1 -1
- package/Tests/UI/Rum/ReplayScrubber.test.tsx +1 -1
- package/Tests/UI/Rum/ReplayStage.test.tsx +1 -1
- package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +1 -1
- package/Tests/UI/Utils/LocalStorageArrayRoundTrip.test.ts +72 -0
- package/Tests/Utils/Dashboard/HtmlWidgetDocument.test.ts +19 -2
- package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +44 -0
- package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +288 -5
- package/Tests/Utils/Dashboard/VariableUrlState.test.ts +42 -0
- package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +27 -0
- package/Tests/Utils/LegacySerializedArray.test.ts +139 -0
- package/Tests/Utils/Monitor/MonitorDependencyRule.test.ts +190 -0
- package/Tests/Utils/Realtime.test.ts +78 -0
- package/Tests/Utils/Telemetry/SavedViewFilters.test.ts +246 -0
- package/Tests/__mocks__/i18next-browser-languagedetector.js +21 -0
- package/Types/AI/FixPullRequestCiStatus.ts +1 -1
- package/Types/AI/FixVerificationStatus.ts +2 -2
- package/Types/API/Hostname.ts +92 -4
- package/Types/API/URL.ts +43 -25
- package/Types/Billing/BalanceAdjustmentType.ts +14 -0
- package/Types/Billing/ProjectBalanceType.ts +13 -0
- package/Types/Domain.ts +26 -0
- package/Types/File/MimeType.ts +11 -0
- package/Types/JSONFunctions.ts +15 -0
- package/Types/Telemetry/TelemetrySavedViewState.ts +9 -1
- package/Types/Workflow/Components/BaseModel.ts +92 -28
- package/Typings/Index.d.ts +12 -0
- package/UI/Components/GanttChart/ChartContainer.tsx +4 -3
- package/UI/Components/Modal/ConfirmModal.tsx +10 -5
- package/UI/Components/Modal/Modal.tsx +27 -47
- package/UI/Components/ModelDelete/ModelDelete.tsx +23 -6
- package/UI/Components/SideOver/SideOver.tsx +195 -68
- package/UI/Utils/PageScrollLock.ts +66 -0
- package/Utils/Dashboard/HtmlWidgetDocument.ts +4 -2
- package/Utils/Dashboard/VariableInterpolation.ts +19 -1
- package/Utils/LegacySerializedArray.ts +60 -0
- package/Utils/Monitor/MonitorDependencyRule.ts +88 -0
- package/Utils/Telemetry/SavedViewFilters.ts +88 -0
- package/build/dist/Models/DatabaseModels/AIInsight.js +1 -1
- package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js +2 -3
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DeletedProject.js +640 -0
- package/build/dist/Models/DatabaseModels/DeletedProject.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +106 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +3 -3
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
- package/build/dist/Server/API/FileAPI.js +14 -2
- package/build/dist/Server/API/FileAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +6 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectAPI.js +157 -4
- package/build/dist/Server/API/ProjectAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +27 -3
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AIAgentService.js +17 -0
- package/build/dist/Server/Services/AIAgentService.js.map +1 -1
- package/build/dist/Server/Services/DashboardDomainService.js +55 -18
- package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +1 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DeletedProjectService.js +124 -0
- package/build/dist/Server/Services/DeletedProjectService.js.map +1 -0
- package/build/dist/Server/Services/FileService.js +52 -0
- package/build/dist/Server/Services/FileService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +10 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js +10 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +232 -0
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/ProbeService.js +17 -0
- package/build/dist/Server/Services/ProbeService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +228 -6
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/PushNotificationService.js +56 -0
- package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +10 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageAnnouncementService.js +54 -0
- package/build/dist/Server/Services/StatusPageAnnouncementService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageDomainService.js +55 -18
- package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +97 -6
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js +1 -0
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
- package/build/dist/Server/Services/UserWebhookService.js +31 -87
- package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +65 -0
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +23 -0
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
- package/build/dist/Server/Types/Domain.js +37 -0
- package/build/dist/Server/Types/Domain.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js +35 -2
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +15 -11
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +2 -3
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js +21 -10
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js +21 -10
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js +18 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js +18 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js +43 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +116 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js +7 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js +24 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js +27 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js +14 -6
- package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js +42 -0
- package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +15 -6
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js +10 -2
- package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +141 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.js +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js +6 -6
- package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +39 -5
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +94 -10
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +1 -19
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
- package/build/dist/Server/Utils/Execute.js +2 -2
- package/build/dist/Server/Utils/Execute.js.map +1 -1
- package/build/dist/Server/Utils/InlineImageAccessTokenSync.js +13 -0
- package/build/dist/Server/Utils/InlineImageAccessTokenSync.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +43 -12
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +44 -24
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js +158 -0
- package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +50 -30
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +32 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Response.js +112 -5
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +219 -53
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +7 -0
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +73 -1
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +445 -43
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +18 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
- package/build/dist/Types/AI/FixPullRequestCiStatus.js +1 -1
- package/build/dist/Types/AI/FixVerificationStatus.js +2 -2
- package/build/dist/Types/API/Hostname.js +73 -4
- package/build/dist/Types/API/Hostname.js.map +1 -1
- package/build/dist/Types/API/URL.js +42 -24
- package/build/dist/Types/API/URL.js.map +1 -1
- package/build/dist/Types/Billing/BalanceAdjustmentType.js +15 -0
- package/build/dist/Types/Billing/BalanceAdjustmentType.js.map +1 -0
- package/build/dist/Types/Billing/ProjectBalanceType.js +14 -0
- package/build/dist/Types/Billing/ProjectBalanceType.js.map +1 -0
- package/build/dist/Types/Domain.js +22 -0
- package/build/dist/Types/Domain.js.map +1 -1
- package/build/dist/Types/File/MimeType.js +11 -0
- package/build/dist/Types/File/MimeType.js.map +1 -1
- package/build/dist/Types/JSONFunctions.js +14 -0
- package/build/dist/Types/JSONFunctions.js.map +1 -1
- package/build/dist/Types/Workflow/Components/BaseModel.js +83 -28
- package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
- package/build/dist/UI/Components/GanttChart/ChartContainer.js +4 -3
- package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +1 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js +3 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +24 -34
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/ModelDelete/ModelDelete.js +11 -6
- package/build/dist/UI/Components/ModelDelete/ModelDelete.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +105 -30
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Utils/PageScrollLock.js +52 -0
- package/build/dist/UI/Utils/PageScrollLock.js.map +1 -0
- package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js +4 -2
- package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js.map +1 -1
- package/build/dist/Utils/Dashboard/VariableInterpolation.js +19 -1
- package/build/dist/Utils/Dashboard/VariableInterpolation.js.map +1 -1
- package/build/dist/Utils/LegacySerializedArray.js +51 -0
- package/build/dist/Utils/LegacySerializedArray.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorDependencyRule.js +47 -0
- package/build/dist/Utils/Monitor/MonitorDependencyRule.js.map +1 -0
- package/build/dist/Utils/Telemetry/SavedViewFilters.js +52 -0
- package/build/dist/Utils/Telemetry/SavedViewFilters.js.map +1 -0
- package/jest.config.json +3 -0
- package/package.json +1 -1
- package/tsconfig.json +3 -1
|
@@ -0,0 +1,604 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* PasswordHash fails to COMPILE under ts-jest (TS 5.9 + @types/node Buffer
|
|
3
|
+
* mismatch) and DatabaseService (which every concrete service used below
|
|
4
|
+
* extends) imports it. Nothing password-related is under test here, so the
|
|
5
|
+
* module is replaced WITH A FACTORY — an automock would still require (and
|
|
6
|
+
* type-check) the real file.
|
|
7
|
+
*/
|
|
8
|
+
jest.mock("../../../../Server/Utils/PasswordHash", () => {
|
|
9
|
+
return {
|
|
10
|
+
__esModule: true,
|
|
11
|
+
default: {
|
|
12
|
+
hash: jest.fn(),
|
|
13
|
+
verify: jest.fn(),
|
|
14
|
+
generateSalt: jest.fn(),
|
|
15
|
+
needsUpgrade: jest.fn(),
|
|
16
|
+
applyPepper: jest.fn(),
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
import Alert from "../../../../Models/DatabaseModels/Alert";
|
|
22
|
+
import AlertStateTimeline from "../../../../Models/DatabaseModels/AlertStateTimeline";
|
|
23
|
+
import Incident from "../../../../Models/DatabaseModels/Incident";
|
|
24
|
+
import IncidentStateTimeline from "../../../../Models/DatabaseModels/IncidentStateTimeline";
|
|
25
|
+
import Monitor from "../../../../Models/DatabaseModels/Monitor";
|
|
26
|
+
import AlertService from "../../../../Server/Services/AlertService";
|
|
27
|
+
import AlertStateTimelineService from "../../../../Server/Services/AlertStateTimelineService";
|
|
28
|
+
import IncidentService from "../../../../Server/Services/IncidentService";
|
|
29
|
+
import IncidentStateTimelineService from "../../../../Server/Services/IncidentStateTimelineService";
|
|
30
|
+
import NetworkDeviceOwnerUserService from "../../../../Server/Services/NetworkDeviceOwnerUserService";
|
|
31
|
+
import ProjectScopedReferenceValidator from "../../../../Server/Utils/Database/ProjectScopedReferenceValidator";
|
|
32
|
+
import MonitorAlert from "../../../../Server/Utils/Monitor/MonitorAlert";
|
|
33
|
+
import MonitorClusterContextUtil from "../../../../Server/Utils/Monitor/MonitorClusterContext";
|
|
34
|
+
import { DependencySuppressionResult } from "../../../../Server/Utils/Monitor/MonitorDependencySuppression";
|
|
35
|
+
import MonitorIncident from "../../../../Server/Utils/Monitor/MonitorIncident";
|
|
36
|
+
import Dictionary from "../../../../Types/Dictionary";
|
|
37
|
+
import MonitorCriteriaInstance from "../../../../Types/Monitor/MonitorCriteriaInstance";
|
|
38
|
+
import MonitorEvaluationSummary, {
|
|
39
|
+
MonitorEvaluationEvent,
|
|
40
|
+
MonitorEvaluationEventType,
|
|
41
|
+
} from "../../../../Types/Monitor/MonitorEvaluationSummary";
|
|
42
|
+
import MonitorType from "../../../../Types/Monitor/MonitorType";
|
|
43
|
+
import ObjectID from "../../../../Types/ObjectID";
|
|
44
|
+
import ProbeMonitorResponse from "../../../../Types/Probe/ProbeMonitorResponse";
|
|
45
|
+
import { afterEach, beforeEach, describe, expect, it } from "@jest/globals";
|
|
46
|
+
|
|
47
|
+
/*
|
|
48
|
+
* PR #3122 (alert-dependency suppression) added a skip block to BOTH
|
|
49
|
+
* creators — MonitorAlert.criteriaMetCreateAlertsAndUpdateMonitorStatus and
|
|
50
|
+
* MonitorIncident.criteriaMetCreateIncidentsAndUpdateMonitorStatus. These
|
|
51
|
+
* tests pin the block's contract, which the util-level tests
|
|
52
|
+
* (MonitorDependencySuppression.test.ts) cannot see:
|
|
53
|
+
*
|
|
54
|
+
* - isSuppressed=true → the create service is never called and exactly
|
|
55
|
+
* one "alert-skipped"/"incident-skipped" event naming the suppressing
|
|
56
|
+
* parent (via buildSuppressionReason) is pushed.
|
|
57
|
+
* - The open-alert/open-incident RESOLVE pass still runs first —
|
|
58
|
+
* resolution is never suppressed, only creation.
|
|
59
|
+
* - dependencySuppression undefined or {isSuppressed:false} → the flow
|
|
60
|
+
* proceeds past the skip block exactly as before the feature.
|
|
61
|
+
* - createAlerts/createIncidents=false returns BEFORE the skip block, so
|
|
62
|
+
* a suppressed evaluation of a non-creating criteria pushes no event.
|
|
63
|
+
* - The resolve-only entry points take no suppression input at all, so
|
|
64
|
+
* suppression state cannot block resolution.
|
|
65
|
+
*
|
|
66
|
+
* Mocking follows MonitorSummaryPersistence.test.ts: the real creators run
|
|
67
|
+
* with the surrounding services stubbed, and assertions are made on what
|
|
68
|
+
* was handed to AlertService.create / IncidentService.create.
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
// The house workaround for @jest/globals vs @types/jest spy typing.
|
|
72
|
+
type SpyLike = {
|
|
73
|
+
mock: { calls: Array<Array<unknown>> };
|
|
74
|
+
mockRestore: () => void;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const PROJECT_ID: ObjectID = new ObjectID(
|
|
78
|
+
"11111111-1111-4111-8111-111111111111",
|
|
79
|
+
);
|
|
80
|
+
const MONITOR_ID: ObjectID = new ObjectID(
|
|
81
|
+
"22222222-2222-4222-8222-222222222222",
|
|
82
|
+
);
|
|
83
|
+
const SEVERITY_ID: ObjectID = new ObjectID(
|
|
84
|
+
"55555555-5555-4555-8555-555555555555",
|
|
85
|
+
);
|
|
86
|
+
const RESOLVED_STATE_ID: ObjectID = new ObjectID(
|
|
87
|
+
"88888888-8888-4888-8888-888888888888",
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
const SUPPRESSING_PARENT_NAME: string = "Core Router";
|
|
91
|
+
|
|
92
|
+
function suppressed(): DependencySuppressionResult {
|
|
93
|
+
return {
|
|
94
|
+
isSuppressed: true,
|
|
95
|
+
suppressingParents: [
|
|
96
|
+
{
|
|
97
|
+
monitorId: "99999999-9999-4999-8999-999999999999",
|
|
98
|
+
monitorName: SUPPRESSING_PARENT_NAME,
|
|
99
|
+
statusName: "Offline",
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function notSuppressed(): DependencySuppressionResult {
|
|
106
|
+
return {
|
|
107
|
+
isSuppressed: false,
|
|
108
|
+
suppressingParents: [],
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function monitor(): Monitor {
|
|
113
|
+
const model: Monitor = new Monitor();
|
|
114
|
+
model._id = MONITOR_ID.toString();
|
|
115
|
+
model.projectId = PROJECT_ID;
|
|
116
|
+
model.monitorType = MonitorType.Website;
|
|
117
|
+
model.name = "Child API Monitor";
|
|
118
|
+
return model;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function criteriaInstance(input: {
|
|
122
|
+
createIncidents: boolean;
|
|
123
|
+
createAlerts: boolean;
|
|
124
|
+
}): MonitorCriteriaInstance {
|
|
125
|
+
const instance: MonitorCriteriaInstance = new MonitorCriteriaInstance();
|
|
126
|
+
instance.data!.id = "criteria-1";
|
|
127
|
+
instance.data!.name = "Is Offline";
|
|
128
|
+
instance.data!.createIncidents = input.createIncidents;
|
|
129
|
+
instance.data!.createAlerts = input.createAlerts;
|
|
130
|
+
instance.data!.incidents = [
|
|
131
|
+
{
|
|
132
|
+
id: "incident-template-1",
|
|
133
|
+
title: "API is down",
|
|
134
|
+
description: "The API stopped responding.",
|
|
135
|
+
incidentSeverityId: SEVERITY_ID,
|
|
136
|
+
autoResolveIncident: false,
|
|
137
|
+
},
|
|
138
|
+
];
|
|
139
|
+
instance.data!.alerts = [
|
|
140
|
+
{
|
|
141
|
+
id: "alert-template-1",
|
|
142
|
+
title: "API is down",
|
|
143
|
+
description: "The API stopped responding.",
|
|
144
|
+
alertSeverityId: SEVERITY_ID,
|
|
145
|
+
autoResolveAlert: false,
|
|
146
|
+
},
|
|
147
|
+
];
|
|
148
|
+
return instance;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const dataToProcess: ProbeMonitorResponse = {
|
|
152
|
+
projectId: PROJECT_ID,
|
|
153
|
+
monitorId: MONITOR_ID,
|
|
154
|
+
monitorStepId: new ObjectID("33333333-3333-4333-8333-333333333333"),
|
|
155
|
+
probeId: new ObjectID("44444444-4444-4444-8444-444444444444"),
|
|
156
|
+
failureCause: "Connection refused",
|
|
157
|
+
responseCode: 503,
|
|
158
|
+
monitoredAt: new Date("2026-07-31T10:00:00.000Z"),
|
|
159
|
+
} as unknown as ProbeMonitorResponse;
|
|
160
|
+
|
|
161
|
+
const NO_AUTO_RESOLVE: Dictionary<Array<string>> = {};
|
|
162
|
+
|
|
163
|
+
function emptyEvaluationSummary(): MonitorEvaluationSummary {
|
|
164
|
+
return {
|
|
165
|
+
evaluatedAt: new Date("2026-07-31T10:00:00.000Z"),
|
|
166
|
+
criteriaResults: [],
|
|
167
|
+
events: [],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function eventsOfType(
|
|
172
|
+
summary: MonitorEvaluationSummary,
|
|
173
|
+
type: MonitorEvaluationEventType,
|
|
174
|
+
): Array<MonitorEvaluationEvent> {
|
|
175
|
+
return summary.events.filter((event: MonitorEvaluationEvent) => {
|
|
176
|
+
return event.type === type;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
describe("Dependency-suppression skip block in the alert / incident creators", () => {
|
|
181
|
+
let createdIncidents: Array<Incident> = [];
|
|
182
|
+
let createdAlerts: Array<Alert> = [];
|
|
183
|
+
let createdAlertStateTimelines: Array<AlertStateTimeline> = [];
|
|
184
|
+
let createdIncidentStateTimelines: Array<IncidentStateTimeline> = [];
|
|
185
|
+
|
|
186
|
+
let alertFindBySpy: SpyLike;
|
|
187
|
+
let incidentFindBySpy: SpyLike;
|
|
188
|
+
let clusterContextSpy: SpyLike;
|
|
189
|
+
|
|
190
|
+
beforeEach(() => {
|
|
191
|
+
createdIncidents = [];
|
|
192
|
+
createdAlerts = [];
|
|
193
|
+
createdAlertStateTimelines = [];
|
|
194
|
+
createdIncidentStateTimelines = [];
|
|
195
|
+
|
|
196
|
+
// No incident / alert is already open for this monitor (per-test overrides re-spy).
|
|
197
|
+
incidentFindBySpy = jest
|
|
198
|
+
.spyOn(IncidentService, "findBy")
|
|
199
|
+
.mockResolvedValue([]) as unknown as SpyLike;
|
|
200
|
+
alertFindBySpy = jest
|
|
201
|
+
.spyOn(AlertService, "findBy")
|
|
202
|
+
.mockResolvedValue([]) as unknown as SpyLike;
|
|
203
|
+
|
|
204
|
+
// The criteria's severity belongs to this project, so no fallback lookup.
|
|
205
|
+
jest
|
|
206
|
+
.spyOn(ProjectScopedReferenceValidator, "isUsableInProject")
|
|
207
|
+
.mockResolvedValue(true);
|
|
208
|
+
|
|
209
|
+
/*
|
|
210
|
+
* First statement AFTER the dependency-suppression skip block in both
|
|
211
|
+
* creators — its call count is how these tests observe whether the flow
|
|
212
|
+
* proceeded past the block.
|
|
213
|
+
*/
|
|
214
|
+
clusterContextSpy = jest
|
|
215
|
+
.spyOn(MonitorClusterContextUtil, "resolveClusterContextForMonitor")
|
|
216
|
+
.mockResolvedValue({
|
|
217
|
+
proxmoxClusterIds: [],
|
|
218
|
+
cephClusterIds: [],
|
|
219
|
+
dockerSwarmClusterIds: [],
|
|
220
|
+
iotFleetIds: [],
|
|
221
|
+
}) as unknown as SpyLike;
|
|
222
|
+
|
|
223
|
+
jest
|
|
224
|
+
.spyOn(NetworkDeviceOwnerUserService, "getDeviceOwnersForMonitor")
|
|
225
|
+
.mockResolvedValue({ ownerUserIds: [], ownerTeamIds: [] });
|
|
226
|
+
|
|
227
|
+
jest
|
|
228
|
+
.spyOn(IncidentService, "create")
|
|
229
|
+
.mockImplementation(async (createBy: unknown): Promise<Incident> => {
|
|
230
|
+
const incident: Incident = (createBy as { data: Incident }).data;
|
|
231
|
+
createdIncidents.push(incident);
|
|
232
|
+
incident._id = new ObjectID(
|
|
233
|
+
"66666666-6666-4666-8666-666666666666",
|
|
234
|
+
).toString();
|
|
235
|
+
return incident;
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
jest
|
|
239
|
+
.spyOn(AlertService, "create")
|
|
240
|
+
.mockImplementation(async (createBy: unknown): Promise<Alert> => {
|
|
241
|
+
const alert: Alert = (createBy as { data: Alert }).data;
|
|
242
|
+
createdAlerts.push(alert);
|
|
243
|
+
alert._id = new ObjectID(
|
|
244
|
+
"77777777-7777-4777-8777-777777777777",
|
|
245
|
+
).toString();
|
|
246
|
+
return alert;
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
jest.spyOn(IncidentService, "addOwners").mockResolvedValue(undefined);
|
|
250
|
+
jest.spyOn(AlertService, "addOwners").mockResolvedValue(undefined);
|
|
251
|
+
|
|
252
|
+
// The resolve pass (test 5's entry points) writes a resolved state timeline.
|
|
253
|
+
jest
|
|
254
|
+
.spyOn(AlertStateTimelineService, "getResolvedStateIdForProject")
|
|
255
|
+
.mockResolvedValue(RESOLVED_STATE_ID);
|
|
256
|
+
jest
|
|
257
|
+
.spyOn(AlertStateTimelineService, "create")
|
|
258
|
+
.mockImplementation(
|
|
259
|
+
async (createBy: unknown): Promise<AlertStateTimeline> => {
|
|
260
|
+
const timeline: AlertStateTimeline = (
|
|
261
|
+
createBy as { data: AlertStateTimeline }
|
|
262
|
+
).data;
|
|
263
|
+
createdAlertStateTimelines.push(timeline);
|
|
264
|
+
return timeline;
|
|
265
|
+
},
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
jest
|
|
269
|
+
.spyOn(IncidentStateTimelineService, "getResolvedStateIdForProject")
|
|
270
|
+
.mockResolvedValue(RESOLVED_STATE_ID);
|
|
271
|
+
jest
|
|
272
|
+
.spyOn(IncidentStateTimelineService, "create")
|
|
273
|
+
.mockImplementation(
|
|
274
|
+
async (createBy: unknown): Promise<IncidentStateTimeline> => {
|
|
275
|
+
const timeline: IncidentStateTimeline = (
|
|
276
|
+
createBy as { data: IncidentStateTimeline }
|
|
277
|
+
).data;
|
|
278
|
+
createdIncidentStateTimelines.push(timeline);
|
|
279
|
+
return timeline;
|
|
280
|
+
},
|
|
281
|
+
);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
afterEach(() => {
|
|
285
|
+
jest.restoreAllMocks();
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
async function runAlertCreator(input: {
|
|
289
|
+
createAlerts: boolean;
|
|
290
|
+
dependencySuppression: DependencySuppressionResult | undefined;
|
|
291
|
+
summary: MonitorEvaluationSummary;
|
|
292
|
+
}): Promise<void> {
|
|
293
|
+
await MonitorAlert.criteriaMetCreateAlertsAndUpdateMonitorStatus({
|
|
294
|
+
criteriaInstance: criteriaInstance({
|
|
295
|
+
createIncidents: false,
|
|
296
|
+
createAlerts: input.createAlerts,
|
|
297
|
+
}),
|
|
298
|
+
monitor: monitor(),
|
|
299
|
+
dataToProcess: dataToProcess,
|
|
300
|
+
rootCause: "Monitor is offline",
|
|
301
|
+
autoResolveCriteriaInstanceIdAlertIdsDictionary: NO_AUTO_RESOLVE,
|
|
302
|
+
evaluationSummary: input.summary,
|
|
303
|
+
dependencySuppression: input.dependencySuppression,
|
|
304
|
+
props: {},
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
async function runIncidentCreator(input: {
|
|
309
|
+
createIncidents: boolean;
|
|
310
|
+
dependencySuppression: DependencySuppressionResult | undefined;
|
|
311
|
+
summary: MonitorEvaluationSummary;
|
|
312
|
+
}): Promise<void> {
|
|
313
|
+
await MonitorIncident.criteriaMetCreateIncidentsAndUpdateMonitorStatus({
|
|
314
|
+
criteriaInstance: criteriaInstance({
|
|
315
|
+
createIncidents: input.createIncidents,
|
|
316
|
+
createAlerts: false,
|
|
317
|
+
}),
|
|
318
|
+
monitor: monitor(),
|
|
319
|
+
dataToProcess: dataToProcess,
|
|
320
|
+
rootCause: "Monitor is offline",
|
|
321
|
+
autoResolveCriteriaInstanceIdIncidentIdsDictionary: NO_AUTO_RESOLVE,
|
|
322
|
+
evaluationSummary: input.summary,
|
|
323
|
+
dependencySuppression: input.dependencySuppression,
|
|
324
|
+
props: {},
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
describe("MonitorAlert.criteriaMetCreateAlertsAndUpdateMonitorStatus", () => {
|
|
329
|
+
it("suppressed: never calls AlertService.create and pushes exactly one skip event naming the parent", async () => {
|
|
330
|
+
const summary: MonitorEvaluationSummary = emptyEvaluationSummary();
|
|
331
|
+
|
|
332
|
+
await runAlertCreator({
|
|
333
|
+
createAlerts: true,
|
|
334
|
+
dependencySuppression: suppressed(),
|
|
335
|
+
summary,
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
expect(createdAlerts).toHaveLength(0);
|
|
339
|
+
|
|
340
|
+
// Exactly one event total — the dependency skip — and nothing else.
|
|
341
|
+
expect(summary.events).toHaveLength(1);
|
|
342
|
+
|
|
343
|
+
const skipEvent: MonitorEvaluationEvent = summary.events[0]!;
|
|
344
|
+
expect(skipEvent.type).toBe("alert-skipped");
|
|
345
|
+
expect(skipEvent.title).toBe("Alert suppressed by monitor dependency");
|
|
346
|
+
expect(skipEvent.message).toContain(
|
|
347
|
+
`parent monitor "${SUPPRESSING_PARENT_NAME}" is Offline`,
|
|
348
|
+
);
|
|
349
|
+
expect(skipEvent.relatedCriteriaId).toBe("criteria-1");
|
|
350
|
+
|
|
351
|
+
// The skip block RETURNS: nothing after it (cluster context) runs.
|
|
352
|
+
expect(clusterContextSpy.mock.calls).toHaveLength(0);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it("suppressed: the open-alert resolve pass still runs before the skip block (resolution is never suppressed)", async () => {
|
|
356
|
+
const checkOpenSpy: SpyLike = jest
|
|
357
|
+
.spyOn(MonitorAlert, "checkOpenAlertsAndCloseIfResolved")
|
|
358
|
+
.mockResolvedValue([]) as unknown as SpyLike;
|
|
359
|
+
|
|
360
|
+
const summary: MonitorEvaluationSummary = emptyEvaluationSummary();
|
|
361
|
+
|
|
362
|
+
await runAlertCreator({
|
|
363
|
+
createAlerts: true,
|
|
364
|
+
dependencySuppression: suppressed(),
|
|
365
|
+
summary,
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
expect(checkOpenSpy.mock.calls).toHaveLength(1);
|
|
369
|
+
|
|
370
|
+
const callInput: { monitorId: ObjectID } = checkOpenSpy.mock
|
|
371
|
+
.calls[0]![0] as { monitorId: ObjectID };
|
|
372
|
+
expect(callInput.monitorId.toString()).toBe(MONITOR_ID.toString());
|
|
373
|
+
|
|
374
|
+
// Creation itself stayed suppressed.
|
|
375
|
+
expect(createdAlerts).toHaveLength(0);
|
|
376
|
+
expect(eventsOfType(summary, "alert-skipped")).toHaveLength(1);
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
it("undefined dependencySuppression: creates the alert exactly as before the feature", async () => {
|
|
380
|
+
const summary: MonitorEvaluationSummary = emptyEvaluationSummary();
|
|
381
|
+
|
|
382
|
+
await runAlertCreator({
|
|
383
|
+
createAlerts: true,
|
|
384
|
+
dependencySuppression: undefined,
|
|
385
|
+
summary,
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
expect(createdAlerts).toHaveLength(1);
|
|
389
|
+
expect(createdAlerts[0]!.title).toBe("API is down");
|
|
390
|
+
expect(eventsOfType(summary, "alert-skipped")).toHaveLength(0);
|
|
391
|
+
expect(eventsOfType(summary, "alert-created")).toHaveLength(1);
|
|
392
|
+
});
|
|
393
|
+
|
|
394
|
+
it("isSuppressed=false: creates the alert (an evaluated-but-clear dependency changes nothing)", async () => {
|
|
395
|
+
const summary: MonitorEvaluationSummary = emptyEvaluationSummary();
|
|
396
|
+
|
|
397
|
+
await runAlertCreator({
|
|
398
|
+
createAlerts: true,
|
|
399
|
+
dependencySuppression: notSuppressed(),
|
|
400
|
+
summary,
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
expect(createdAlerts).toHaveLength(1);
|
|
404
|
+
expect(eventsOfType(summary, "alert-skipped")).toHaveLength(0);
|
|
405
|
+
expect(eventsOfType(summary, "alert-created")).toHaveLength(1);
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
it("createAlerts=false: returns BEFORE the skip block — no skip event even when suppressed", async () => {
|
|
409
|
+
const summary: MonitorEvaluationSummary = emptyEvaluationSummary();
|
|
410
|
+
|
|
411
|
+
await runAlertCreator({
|
|
412
|
+
createAlerts: false,
|
|
413
|
+
dependencySuppression: suppressed(),
|
|
414
|
+
summary,
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
// Gate order pinned: the createAlerts gate wins, so no event at all.
|
|
418
|
+
expect(summary.events).toHaveLength(0);
|
|
419
|
+
expect(createdAlerts).toHaveLength(0);
|
|
420
|
+
|
|
421
|
+
// The resolve pass still ran (it sits above both gates) ...
|
|
422
|
+
expect(alertFindBySpy.mock.calls).toHaveLength(1);
|
|
423
|
+
// ... and nothing after the gates did.
|
|
424
|
+
expect(clusterContextSpy.mock.calls).toHaveLength(0);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it("resolve-only entry point resolves an open alert — suppression state cannot block resolution", async () => {
|
|
428
|
+
/*
|
|
429
|
+
* checkOpenAlertsAndCloseIfResolved takes no dependencySuppression
|
|
430
|
+
* input at all — the skip block lives only in the creator — so a
|
|
431
|
+
* suppressing parent can never pin an open alert open.
|
|
432
|
+
*/
|
|
433
|
+
const openAlert: Alert = new Alert();
|
|
434
|
+
openAlert._id = new ObjectID(
|
|
435
|
+
"aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
|
|
436
|
+
).toString();
|
|
437
|
+
openAlert.projectId = PROJECT_ID;
|
|
438
|
+
openAlert.title = "Raised before the parent went down";
|
|
439
|
+
openAlert.createdCriteriaId = "old-criteria";
|
|
440
|
+
|
|
441
|
+
jest.spyOn(AlertService, "findBy").mockResolvedValue([openAlert]);
|
|
442
|
+
|
|
443
|
+
const summary: MonitorEvaluationSummary = emptyEvaluationSummary();
|
|
444
|
+
|
|
445
|
+
const openAlerts: Array<Alert> =
|
|
446
|
+
await MonitorAlert.checkOpenAlertsAndCloseIfResolved({
|
|
447
|
+
monitorId: MONITOR_ID,
|
|
448
|
+
autoResolveCriteriaInstanceIdAlertIdsDictionary: {
|
|
449
|
+
"old-criteria": ["alert-template-1"],
|
|
450
|
+
},
|
|
451
|
+
rootCause: "Monitor is back online",
|
|
452
|
+
criteriaInstance: null,
|
|
453
|
+
dataToProcess: dataToProcess,
|
|
454
|
+
evaluationSummary: summary,
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
expect(openAlerts).toHaveLength(1);
|
|
458
|
+
expect(createdAlertStateTimelines).toHaveLength(1);
|
|
459
|
+
expect(createdAlertStateTimelines[0]!.alertId?.toString()).toBe(
|
|
460
|
+
openAlert.id!.toString(),
|
|
461
|
+
);
|
|
462
|
+
expect(createdAlertStateTimelines[0]!.alertStateId?.toString()).toBe(
|
|
463
|
+
RESOLVED_STATE_ID.toString(),
|
|
464
|
+
);
|
|
465
|
+
expect(eventsOfType(summary, "alert-resolved")).toHaveLength(1);
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
describe("MonitorIncident.criteriaMetCreateIncidentsAndUpdateMonitorStatus", () => {
|
|
470
|
+
it("suppressed: never calls IncidentService.create and pushes exactly one skip event naming the parent", async () => {
|
|
471
|
+
const summary: MonitorEvaluationSummary = emptyEvaluationSummary();
|
|
472
|
+
|
|
473
|
+
await runIncidentCreator({
|
|
474
|
+
createIncidents: true,
|
|
475
|
+
dependencySuppression: suppressed(),
|
|
476
|
+
summary,
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
expect(createdIncidents).toHaveLength(0);
|
|
480
|
+
|
|
481
|
+
expect(summary.events).toHaveLength(1);
|
|
482
|
+
|
|
483
|
+
const skipEvent: MonitorEvaluationEvent = summary.events[0]!;
|
|
484
|
+
expect(skipEvent.type).toBe("incident-skipped");
|
|
485
|
+
expect(skipEvent.title).toBe("Incident suppressed by monitor dependency");
|
|
486
|
+
expect(skipEvent.message).toContain(
|
|
487
|
+
`parent monitor "${SUPPRESSING_PARENT_NAME}" is Offline`,
|
|
488
|
+
);
|
|
489
|
+
expect(skipEvent.relatedCriteriaId).toBe("criteria-1");
|
|
490
|
+
|
|
491
|
+
expect(clusterContextSpy.mock.calls).toHaveLength(0);
|
|
492
|
+
});
|
|
493
|
+
|
|
494
|
+
it("suppressed: the open-incident resolve pass still runs before the skip block (resolution is never suppressed)", async () => {
|
|
495
|
+
const checkOpenSpy: SpyLike = jest
|
|
496
|
+
.spyOn(MonitorIncident, "checkOpenIncidentsAndCloseIfResolved")
|
|
497
|
+
.mockResolvedValue([]) as unknown as SpyLike;
|
|
498
|
+
|
|
499
|
+
const summary: MonitorEvaluationSummary = emptyEvaluationSummary();
|
|
500
|
+
|
|
501
|
+
await runIncidentCreator({
|
|
502
|
+
createIncidents: true,
|
|
503
|
+
dependencySuppression: suppressed(),
|
|
504
|
+
summary,
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
expect(checkOpenSpy.mock.calls).toHaveLength(1);
|
|
508
|
+
|
|
509
|
+
const callInput: { monitorId: ObjectID } = checkOpenSpy.mock
|
|
510
|
+
.calls[0]![0] as { monitorId: ObjectID };
|
|
511
|
+
expect(callInput.monitorId.toString()).toBe(MONITOR_ID.toString());
|
|
512
|
+
|
|
513
|
+
expect(createdIncidents).toHaveLength(0);
|
|
514
|
+
expect(eventsOfType(summary, "incident-skipped")).toHaveLength(1);
|
|
515
|
+
});
|
|
516
|
+
|
|
517
|
+
it("undefined dependencySuppression: creates the incident exactly as before the feature", async () => {
|
|
518
|
+
const summary: MonitorEvaluationSummary = emptyEvaluationSummary();
|
|
519
|
+
|
|
520
|
+
await runIncidentCreator({
|
|
521
|
+
createIncidents: true,
|
|
522
|
+
dependencySuppression: undefined,
|
|
523
|
+
summary,
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
expect(createdIncidents).toHaveLength(1);
|
|
527
|
+
expect(createdIncidents[0]!.title).toBe("API is down");
|
|
528
|
+
expect(eventsOfType(summary, "incident-skipped")).toHaveLength(0);
|
|
529
|
+
expect(eventsOfType(summary, "incident-created")).toHaveLength(1);
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
it("isSuppressed=false: creates the incident (an evaluated-but-clear dependency changes nothing)", async () => {
|
|
533
|
+
const summary: MonitorEvaluationSummary = emptyEvaluationSummary();
|
|
534
|
+
|
|
535
|
+
await runIncidentCreator({
|
|
536
|
+
createIncidents: true,
|
|
537
|
+
dependencySuppression: notSuppressed(),
|
|
538
|
+
summary,
|
|
539
|
+
});
|
|
540
|
+
|
|
541
|
+
expect(createdIncidents).toHaveLength(1);
|
|
542
|
+
expect(eventsOfType(summary, "incident-skipped")).toHaveLength(0);
|
|
543
|
+
expect(eventsOfType(summary, "incident-created")).toHaveLength(1);
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
it("createIncidents=false: returns BEFORE the skip block — no skip event even when suppressed", async () => {
|
|
547
|
+
const summary: MonitorEvaluationSummary = emptyEvaluationSummary();
|
|
548
|
+
|
|
549
|
+
await runIncidentCreator({
|
|
550
|
+
createIncidents: false,
|
|
551
|
+
dependencySuppression: suppressed(),
|
|
552
|
+
summary,
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
expect(summary.events).toHaveLength(0);
|
|
556
|
+
expect(createdIncidents).toHaveLength(0);
|
|
557
|
+
|
|
558
|
+
expect(incidentFindBySpy.mock.calls).toHaveLength(1);
|
|
559
|
+
expect(clusterContextSpy.mock.calls).toHaveLength(0);
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
it("resolve-only entry point resolves an open incident — suppression state cannot block resolution", async () => {
|
|
563
|
+
/*
|
|
564
|
+
* checkOpenIncidentsAndCloseIfResolved takes no dependencySuppression
|
|
565
|
+
* input at all — the skip block lives only in the creator — so a
|
|
566
|
+
* suppressing parent can never pin an open incident open.
|
|
567
|
+
*/
|
|
568
|
+
const openIncident: Incident = new Incident();
|
|
569
|
+
openIncident._id = new ObjectID(
|
|
570
|
+
"bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
|
|
571
|
+
).toString();
|
|
572
|
+
openIncident.projectId = PROJECT_ID;
|
|
573
|
+
openIncident.title = "Raised before the parent went down";
|
|
574
|
+
openIncident.createdCriteriaId = "old-criteria";
|
|
575
|
+
openIncident.createdIncidentTemplateId = "incident-template-1";
|
|
576
|
+
|
|
577
|
+
jest.spyOn(IncidentService, "findBy").mockResolvedValue([openIncident]);
|
|
578
|
+
|
|
579
|
+
const summary: MonitorEvaluationSummary = emptyEvaluationSummary();
|
|
580
|
+
|
|
581
|
+
const openIncidents: Array<Incident> =
|
|
582
|
+
await MonitorIncident.checkOpenIncidentsAndCloseIfResolved({
|
|
583
|
+
monitorId: MONITOR_ID,
|
|
584
|
+
autoResolveCriteriaInstanceIdIncidentIdsDictionary: {
|
|
585
|
+
"old-criteria": ["incident-template-1"],
|
|
586
|
+
},
|
|
587
|
+
rootCause: "Monitor is back online",
|
|
588
|
+
criteriaInstance: null,
|
|
589
|
+
dataToProcess: dataToProcess,
|
|
590
|
+
evaluationSummary: summary,
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
expect(openIncidents).toHaveLength(1);
|
|
594
|
+
expect(createdIncidentStateTimelines).toHaveLength(1);
|
|
595
|
+
expect(createdIncidentStateTimelines[0]!.incidentId?.toString()).toBe(
|
|
596
|
+
openIncident.id!.toString(),
|
|
597
|
+
);
|
|
598
|
+
expect(
|
|
599
|
+
createdIncidentStateTimelines[0]!.incidentStateId?.toString(),
|
|
600
|
+
).toBe(RESOLVED_STATE_ID.toString());
|
|
601
|
+
expect(eventsOfType(summary, "incident-resolved")).toHaveLength(1);
|
|
602
|
+
});
|
|
603
|
+
});
|
|
604
|
+
});
|