@oneuptime/common 12.0.6 → 12.0.8
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/TelemetryEntity.ts +45 -0
- package/Models/DatabaseModels/TelemetryEntityRelationship.ts +26 -0
- package/Models/DatabaseModels/WorkflowLog.ts +38 -0
- 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/API/UserAPI.ts +16 -1
- 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/1786551733814-MigrationName.ts +41 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786559879134-AddWorkflowLogStepTrace.ts +17 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Middleware/MasterAdminAuthorization.ts +11 -6
- 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/TelemetryEntityRelationshipService.ts +3 -0
- package/Server/Services/TelemetryEntityService.ts +114 -1
- 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 +85 -3
- 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/Types/Workflow/TriggerCode.ts +12 -0
- package/Server/Types/Workflow/Workflow.ts +5 -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/Telemetry/InventoryEntityRegistry.ts +689 -0
- package/Server/Utils/VM/VMAPI.ts +56 -8
- 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/Dashboard/MonitorCriteriaAttributeFilter.test.tsx +574 -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/API/UserProjectsAPI.test.ts +478 -4
- 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/TelemetryEntityManualCreate.test.ts +248 -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/ApiComponentHeaders.test.ts +192 -0
- 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/AnalyticsDatabase/QuerySettingsHelper.test.ts +152 -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/Telemetry/InventoryEntityRegistry.test.ts +322 -0
- package/Tests/Server/Utils/VM/VMAPISubstitution.test.ts +243 -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/Types/SerializableObjectDictionaryImportCycle.test.ts +197 -0
- package/Tests/Types/Telemetry/EntityTypeGroups.test.ts +140 -0
- package/Tests/Types/Workflow/StepTrace.test.ts +235 -0
- package/Tests/Types/Workflow/TemplateSyntax.test.ts +379 -0
- package/Tests/Types/Workflow/Templates.test.ts +403 -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/CustomTimeRangeModal.test.tsx +459 -0
- package/Tests/UI/Components/DictionaryAttributeFilterRow.test.tsx +477 -0
- 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/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/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 +43 -1
- package/Tests/UI/Components/MasterPage.test.tsx +1 -1
- package/Tests/UI/Components/ModalPortalDismissal.test.tsx +579 -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 +50 -8
- package/Tests/UI/Components/TextArea.test.tsx +1 -1
- package/Tests/UI/Components/TimeRangePickerDropdown.test.tsx +325 -0
- 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/Components/Workflow/GraphLint.test.ts +821 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditor.test.ts +287 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditorServerContract.test.ts +185 -0
- package/Tests/UI/Components/Workflow/ModelSchema.test.ts +174 -0
- package/Tests/UI/Components/Workflow/RunStatusWatcher.test.ts +152 -0
- package/Tests/UI/Components/Workflow/Utils.test.ts +192 -0
- package/Tests/UI/Monitor/MonitorStepCriteriaView.test.tsx +432 -0
- 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/Monitor/NetworkDeviceRoleUtil.test.ts +514 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +240 -0
- package/Tests/Utils/Realtime.test.ts +78 -0
- package/Tests/Utils/Schema/AnalyticsModelSchema.test.ts +469 -0
- package/Tests/Utils/Schema/ModelSchema.test.ts +268 -0
- package/Tests/Utils/Telemetry/EntityKeyNonTelemetry.test.ts +193 -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/Monitor/SnmpMonitor/NetworkTopology.ts +31 -0
- package/Types/SerializableObjectDictionary.ts +133 -39
- package/Types/Telemetry/EntitySource.ts +40 -0
- package/Types/Telemetry/EntityType.ts +27 -0
- package/Types/Telemetry/EntityTypeGroups.ts +65 -0
- package/Types/Telemetry/TelemetrySavedViewState.ts +9 -1
- package/Types/Workflow/Component.ts +29 -0
- package/Types/Workflow/Components/API.ts +35 -0
- package/Types/Workflow/Components/BaseModel.ts +96 -28
- package/Types/Workflow/StepTrace.ts +181 -0
- package/Types/Workflow/TemplateSyntax.ts +499 -0
- package/Types/Workflow/Templates.ts +316 -0
- package/Typings/Index.d.ts +12 -0
- package/UI/Components/Date/CustomTimeRangeModal.tsx +278 -0
- package/UI/Components/Date/TimeRangePickerDropdown.tsx +250 -0
- package/UI/Components/Dictionary/Dictionary.tsx +23 -6
- 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/GanttChart/ChartContainer.tsx +4 -3
- package/UI/Components/Input/Input.tsx +31 -3
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +11 -216
- package/UI/Components/Modal/ConfirmModal.tsx +10 -5
- package/UI/Components/Modal/Modal.tsx +64 -51
- package/UI/Components/ModelDelete/ModelDelete.tsx +23 -6
- package/UI/Components/SideOver/SideOver.tsx +195 -68
- package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +11 -210
- package/UI/Components/Workflow/ArgumentsForm.tsx +194 -7
- package/UI/Components/Workflow/Component.tsx +28 -26
- package/UI/Components/Workflow/ComponentSettingsModal.tsx +69 -8
- package/UI/Components/Workflow/GraphLint.ts +591 -0
- package/UI/Components/Workflow/ModelColumnEditor.tsx +396 -0
- package/UI/Components/Workflow/ModelSchema.ts +196 -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/Utils.ts +93 -1
- package/UI/Components/Workflow/Workflow.tsx +77 -4
- package/UI/Types/LayeredDismissal.ts +31 -0
- package/UI/Types/UseAnchoredFieldPopup.ts +99 -0
- 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/Monitor/NetworkDeviceRoleUtil.ts +533 -0
- package/Utils/Monitor/NetworkTopologyUtil.ts +45 -7
- package/Utils/Telemetry/EntityKey.ts +66 -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/TelemetryEntity.js +47 -0
- package/build/dist/Models/DatabaseModels/TelemetryEntity.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js +27 -0
- package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.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/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/API/UserAPI.js +16 -1
- package/build/dist/Server/API/UserAPI.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/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/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.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/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/TelemetryEntityRelationshipService.js +3 -0
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryEntityService.js +91 -1
- package/build/dist/Server/Services/TelemetryEntityService.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 +63 -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/Types/Workflow/TriggerCode.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/Telemetry/InventoryEntityRegistry.js +507 -0
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -0
- 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/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/SerializableObjectDictionary.js +133 -39
- package/build/dist/Types/SerializableObjectDictionary.js.map +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 +27 -0
- 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 +87 -28
- package/build/dist/Types/Workflow/Components/BaseModel.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 +326 -0
- package/build/dist/Types/Workflow/TemplateSyntax.js.map +1 -0
- package/build/dist/Types/Workflow/Templates.js +218 -0
- package/build/dist/Types/Workflow/Templates.js.map +1 -0
- 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 +22 -6
- package/build/dist/UI/Components/Dictionary/Dictionary.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/GanttChart/ChartContainer.js +4 -3
- package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +12 -4
- package/build/dist/UI/Components/Input/Input.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/Modal/ConfirmModal.js +3 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +55 -39
- 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/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 +140 -11
- 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/ComponentSettingsModal.js +31 -3
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/GraphLint.js +396 -0
- package/build/dist/UI/Components/Workflow/GraphLint.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ModelColumnEditor.js +225 -0
- package/build/dist/UI/Components/Workflow/ModelColumnEditor.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ModelSchema.js +118 -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/Utils.js +73 -1
- package/build/dist/UI/Components/Workflow/Utils.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Workflow.js +51 -6
- package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
- 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/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/Monitor/NetworkDeviceRoleUtil.js +386 -0
- package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +35 -6
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/Telemetry/EntityKey.js +52 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- 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
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import CreateBy from "../Types/Database/CreateBy";
|
|
2
2
|
import DeleteBy from "../Types/Database/DeleteBy";
|
|
3
|
-
import
|
|
3
|
+
import UpdateBy from "../Types/Database/UpdateBy";
|
|
4
|
+
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
|
|
4
5
|
import GreenlockUtil from "../Utils/Greenlock/Greenlock";
|
|
5
6
|
import logger, { LogAttributes } from "../Utils/Logger";
|
|
6
7
|
import DatabaseService from "./DatabaseService";
|
|
7
8
|
import DomainService from "./DomainService";
|
|
8
9
|
import HTTPErrorResponse from "../../Types/API/HTTPErrorResponse";
|
|
9
10
|
import HTTPResponse from "../../Types/API/HTTPResponse";
|
|
10
|
-
import URL from "../../Types/API/URL";
|
|
11
11
|
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
12
12
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
13
13
|
import { JSONObject } from "../../Types/JSON";
|
|
14
14
|
import ObjectID from "../../Types/ObjectID";
|
|
15
|
-
import API from "../../Utils/API";
|
|
16
15
|
import AcmeCertificate from "../../Models/DatabaseModels/AcmeCertificate";
|
|
17
16
|
import DomainModel from "../../Models/DatabaseModels/Domain";
|
|
18
17
|
import StatusPageDomain from "../../Models/DatabaseModels/StatusPageDomain";
|
|
@@ -22,11 +21,60 @@ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
|
22
21
|
import { StatusPageCNameRecord } from "../EnvironmentConfig";
|
|
23
22
|
import Domain from "../Types/Domain";
|
|
24
23
|
|
|
24
|
+
const STATUS_PAGE_DOMAIN_EGRESS_LABEL: string = "Status page domain";
|
|
25
|
+
|
|
25
26
|
export class Service extends DatabaseService<StatusPageDomain> {
|
|
26
27
|
public constructor() {
|
|
27
28
|
super(StatusPageDomain);
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
/*
|
|
32
|
+
* Normalize a submitted subdomain and reject anything that is not a plain
|
|
33
|
+
* DNS label chain.
|
|
34
|
+
*
|
|
35
|
+
* fullDomain is built as `${subdomain}.${baseDomain}` and then interpolated
|
|
36
|
+
* into "https://" + fullDomain + "/status-page-api/..." — and URL parsing
|
|
37
|
+
* treats everything before the first "/" as the host. Without this check a
|
|
38
|
+
* subdomain of "169.254.169.254/latest/meta-data/#" hands an attacker the
|
|
39
|
+
* host, the port and the path of a request the certificate cron then makes
|
|
40
|
+
* unattended, every 15 minutes, from inside the cluster.
|
|
41
|
+
*/
|
|
42
|
+
private static normalizeAndValidateSubdomain(
|
|
43
|
+
subdomain: string | undefined,
|
|
44
|
+
): string {
|
|
45
|
+
const normalized: string = subdomain?.trim().toLowerCase() || "";
|
|
46
|
+
|
|
47
|
+
// "@" is the documented way to ask for the root domain.
|
|
48
|
+
if (normalized === "" || normalized === "@") {
|
|
49
|
+
return "";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!Domain.isValidSubdomain(normalized)) {
|
|
53
|
+
throw new BadDataException(
|
|
54
|
+
`Subdomain ${normalized} is not valid. Use a plain subdomain such as "status" — schemes, ports, paths and "/" are not allowed.`,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return normalized;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@CaptureSpan()
|
|
62
|
+
protected override async onBeforeUpdate(
|
|
63
|
+
updateBy: UpdateBy<StatusPageDomain>,
|
|
64
|
+
): Promise<OnUpdate<StatusPageDomain>> {
|
|
65
|
+
/*
|
|
66
|
+
* Create-time validation alone leaves the value editable afterwards —
|
|
67
|
+
* subdomain is ProjectMember-updatable.
|
|
68
|
+
*/
|
|
69
|
+
if (updateBy.data.subdomain !== undefined) {
|
|
70
|
+
updateBy.data.subdomain = Service.normalizeAndValidateSubdomain(
|
|
71
|
+
updateBy.data.subdomain as string,
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return { updateBy, carryForward: null };
|
|
76
|
+
}
|
|
77
|
+
|
|
30
78
|
@CaptureSpan()
|
|
31
79
|
protected override async onBeforeCreate(
|
|
32
80
|
createBy: CreateBy<StatusPageDomain>,
|
|
@@ -48,14 +96,11 @@ export class Service extends DatabaseService<StatusPageDomain> {
|
|
|
48
96
|
);
|
|
49
97
|
}
|
|
50
98
|
|
|
51
|
-
|
|
52
|
-
createBy.data.subdomain
|
|
53
|
-
|
|
54
|
-
if (normalizedSubdomain === "@") {
|
|
55
|
-
normalizedSubdomain = "";
|
|
56
|
-
}
|
|
99
|
+
createBy.data.subdomain = Service.normalizeAndValidateSubdomain(
|
|
100
|
+
createBy.data.subdomain,
|
|
101
|
+
);
|
|
57
102
|
|
|
58
|
-
createBy.data.subdomain
|
|
103
|
+
const normalizedSubdomain: string = createBy.data.subdomain;
|
|
59
104
|
|
|
60
105
|
if (domain) {
|
|
61
106
|
const baseDomain: string =
|
|
@@ -231,13 +276,13 @@ export class Service extends DatabaseService<StatusPageDomain> {
|
|
|
231
276
|
): Promise<boolean> {
|
|
232
277
|
try {
|
|
233
278
|
const result: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
234
|
-
await
|
|
235
|
-
url:
|
|
279
|
+
await Domain.getForDomainVerification({
|
|
280
|
+
url:
|
|
236
281
|
"https://" +
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
282
|
+
fulldomain +
|
|
283
|
+
"/status-page-api/cname-verification/" +
|
|
284
|
+
token,
|
|
285
|
+
targetLabel: STATUS_PAGE_DOMAIN_EGRESS_LABEL,
|
|
241
286
|
});
|
|
242
287
|
|
|
243
288
|
if (result.isFailure()) {
|
|
@@ -320,13 +365,13 @@ export class Service extends DatabaseService<StatusPageDomain> {
|
|
|
320
365
|
|
|
321
366
|
try {
|
|
322
367
|
const result: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
323
|
-
await
|
|
324
|
-
url:
|
|
368
|
+
await Domain.getForDomainVerification({
|
|
369
|
+
url:
|
|
325
370
|
"http://" +
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
371
|
+
fullDomain +
|
|
372
|
+
"/status-page-api/cname-verification/" +
|
|
373
|
+
token,
|
|
374
|
+
targetLabel: STATUS_PAGE_DOMAIN_EGRESS_LABEL,
|
|
330
375
|
});
|
|
331
376
|
|
|
332
377
|
logger.debug("CNAME verification result", {
|
|
@@ -353,13 +398,13 @@ export class Service extends DatabaseService<StatusPageDomain> {
|
|
|
353
398
|
|
|
354
399
|
try {
|
|
355
400
|
const resultHttps: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
|
356
|
-
await
|
|
357
|
-
url:
|
|
401
|
+
await Domain.getForDomainVerification({
|
|
402
|
+
url:
|
|
358
403
|
"https://" +
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
404
|
+
fullDomain +
|
|
405
|
+
"/status-page-api/cname-verification/" +
|
|
406
|
+
token,
|
|
407
|
+
targetLabel: STATUS_PAGE_DOMAIN_EGRESS_LABEL,
|
|
363
408
|
});
|
|
364
409
|
|
|
365
410
|
logger.debug("CNAME verification result for https", {
|
|
@@ -120,10 +120,40 @@ export class TeamMemberService extends DatabaseService<TeamMember> {
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
|
|
123
|
+
/*
|
|
124
|
+
* Only internal writes (isRoot) and a master admin acting from the Admin
|
|
125
|
+
* Dashboard may create a membership that is already accepted - that is the
|
|
126
|
+
* "accept the invitation automatically" checkbox on the admin invite forms.
|
|
127
|
+
*
|
|
128
|
+
* Everyone else invites, and the invited person accepts for themselves. A
|
|
129
|
+
* project admin who could accept on someone's behalf would be able to pull
|
|
130
|
+
* an account into their project - and into whatever the team's permissions
|
|
131
|
+
* grant - without that person ever agreeing to it.
|
|
132
|
+
*/
|
|
133
|
+
const canCreateAcceptedInvitation: boolean = Boolean(
|
|
134
|
+
createBy.props.isRoot || createBy.props.isMasterAdmin,
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
if (!canCreateAcceptedInvitation) {
|
|
124
138
|
createBy.data.hasAcceptedInvitation = false;
|
|
125
139
|
}
|
|
126
140
|
|
|
141
|
+
const isInvitationAcceptedOnCreate: boolean = Boolean(
|
|
142
|
+
createBy.data.hasAcceptedInvitation,
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
/*
|
|
146
|
+
* The acceptance timestamp is stamped here rather than taken from the
|
|
147
|
+
* request, so it can never disagree with hasAcceptedInvitation - a row that
|
|
148
|
+
* says "Member" with no accepted-at date, or an accepted-at date on a row
|
|
149
|
+
* that is still only invited.
|
|
150
|
+
*/
|
|
151
|
+
if (isInvitationAcceptedOnCreate) {
|
|
152
|
+
createBy.data.invitationAcceptedAt = OneUptimeDate.getCurrentDate();
|
|
153
|
+
} else {
|
|
154
|
+
delete createBy.data.invitationAcceptedAt;
|
|
155
|
+
}
|
|
156
|
+
|
|
127
157
|
if (createBy.miscDataProps && createBy.miscDataProps["email"]) {
|
|
128
158
|
const email: Email = new Email(createBy.miscDataProps["email"] as string);
|
|
129
159
|
|
|
@@ -221,10 +251,18 @@ export class TeamMemberService extends DatabaseService<TeamMember> {
|
|
|
221
251
|
.addQueryParam("email", email.toString(), true)
|
|
222
252
|
.toString(),
|
|
223
253
|
isNewUser: isNewUser.toString(),
|
|
254
|
+
/*
|
|
255
|
+
* An auto-accepted member has nothing left to accept, so the
|
|
256
|
+
* template drops the "sign in to accept your invitation" framing
|
|
257
|
+
* and tells them they are already in.
|
|
258
|
+
*/
|
|
259
|
+
isInvitationAccepted: isInvitationAcceptedOnCreate.toString(),
|
|
224
260
|
projectName: project.name!,
|
|
225
261
|
homeUrl: new URL(httpProtocol, host).toString(),
|
|
226
262
|
},
|
|
227
|
-
subject:
|
|
263
|
+
subject: isInvitationAcceptedOnCreate
|
|
264
|
+
? "You have been added to " + project.name
|
|
265
|
+
: "You have been invited to " + project.name,
|
|
228
266
|
},
|
|
229
267
|
{
|
|
230
268
|
projectId: createBy.data.projectId!,
|
|
@@ -283,6 +321,65 @@ export class TeamMemberService extends DatabaseService<TeamMember> {
|
|
|
283
321
|
);
|
|
284
322
|
}
|
|
285
323
|
|
|
324
|
+
/*
|
|
325
|
+
* The per-project notification defaults a member gets the moment their
|
|
326
|
+
* membership becomes accepted, whether that happened by them accepting the
|
|
327
|
+
* invitation or by a master admin accepting it for them on create. Without
|
|
328
|
+
* these, an auto-accepted member is a member who is never notified about
|
|
329
|
+
* anything.
|
|
330
|
+
*
|
|
331
|
+
* Skipped for an unverified email: UserService adds the defaults for every
|
|
332
|
+
* accepted membership once the address is verified.
|
|
333
|
+
*
|
|
334
|
+
* Best effort. Both helpers below are idempotent, and by the time either
|
|
335
|
+
* caller runs, the membership row is already committed - failing the write
|
|
336
|
+
* that created it would report "invite failed" for a member who exists.
|
|
337
|
+
*/
|
|
338
|
+
@CaptureSpan()
|
|
339
|
+
private async addDefaultNotificationSettingsAndRules(data: {
|
|
340
|
+
userId: ObjectID;
|
|
341
|
+
projectId: ObjectID;
|
|
342
|
+
user?: User | undefined;
|
|
343
|
+
}): Promise<void> {
|
|
344
|
+
try {
|
|
345
|
+
const user: User | null =
|
|
346
|
+
data.user ||
|
|
347
|
+
(await UserService.findOneById({
|
|
348
|
+
id: data.userId,
|
|
349
|
+
select: {
|
|
350
|
+
email: true,
|
|
351
|
+
isEmailVerified: true,
|
|
352
|
+
},
|
|
353
|
+
props: {
|
|
354
|
+
isRoot: true,
|
|
355
|
+
},
|
|
356
|
+
}));
|
|
357
|
+
|
|
358
|
+
if (!user || !user.isEmailVerified || !user.email) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
await UserNotificationSettingService.addDefaultNotificationSettingsForUser(
|
|
363
|
+
data.userId,
|
|
364
|
+
data.projectId,
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
await UserNotificationRuleService.addDefaultNotificationRuleForUser(
|
|
368
|
+
data.projectId,
|
|
369
|
+
data.userId,
|
|
370
|
+
user.email,
|
|
371
|
+
);
|
|
372
|
+
} catch (err) {
|
|
373
|
+
logger.error(
|
|
374
|
+
err as Error,
|
|
375
|
+
{
|
|
376
|
+
projectId: data.projectId.toString(),
|
|
377
|
+
userId: data.userId.toString(),
|
|
378
|
+
} as LogAttributes,
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
286
383
|
@CaptureSpan()
|
|
287
384
|
protected override async onCreateSuccess(
|
|
288
385
|
onCreate: OnCreate<TeamMember>,
|
|
@@ -297,6 +394,18 @@ export class TeamMemberService extends DatabaseService<TeamMember> {
|
|
|
297
394
|
onCreate.createBy.data.projectId!,
|
|
298
395
|
);
|
|
299
396
|
|
|
397
|
+
/*
|
|
398
|
+
* A membership created already accepted never goes through the
|
|
399
|
+
* accept-invitation update, so it would otherwise miss the defaults that
|
|
400
|
+
* hook adds.
|
|
401
|
+
*/
|
|
402
|
+
if (createdItem.hasAcceptedInvitation) {
|
|
403
|
+
await this.addDefaultNotificationSettingsAndRules({
|
|
404
|
+
userId: onCreate.createBy.data.userId!,
|
|
405
|
+
projectId: onCreate.createBy.data.projectId!,
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
300
409
|
// Activation event for marketing funnels, attributed to the inviter.
|
|
301
410
|
ProductAnalytics.captureForUser({
|
|
302
411
|
userId: onCreate.createBy.props.userId,
|
|
@@ -339,16 +448,12 @@ export class TeamMemberService extends DatabaseService<TeamMember> {
|
|
|
339
448
|
for (const item of items) {
|
|
340
449
|
await this.refreshTokens(item.userId!, item.projectId!);
|
|
341
450
|
|
|
342
|
-
if (updateBy.data.hasAcceptedInvitation
|
|
343
|
-
await
|
|
344
|
-
item.userId!,
|
|
345
|
-
item.projectId!,
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
item.projectId!,
|
|
349
|
-
item.userId!,
|
|
350
|
-
item.user?.email as Email,
|
|
351
|
-
);
|
|
451
|
+
if (updateBy.data.hasAcceptedInvitation) {
|
|
452
|
+
await this.addDefaultNotificationSettingsAndRules({
|
|
453
|
+
userId: item.userId!,
|
|
454
|
+
projectId: item.projectId!,
|
|
455
|
+
user: item.user,
|
|
456
|
+
});
|
|
352
457
|
}
|
|
353
458
|
}
|
|
354
459
|
|
|
@@ -5,6 +5,7 @@ import OneUptimeDate from "../../Types/Date";
|
|
|
5
5
|
import logger from "../Utils/Logger";
|
|
6
6
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
7
7
|
import { EntityRelationshipEdge } from "../../Utils/Telemetry/EntityRelationship";
|
|
8
|
+
import EntitySource from "../../Types/Telemetry/EntitySource";
|
|
8
9
|
import { reconcileByNaturalKey } from "../Utils/Telemetry/EntityRegistry";
|
|
9
10
|
import QueryDeepPartialEntity from "../../Types/Database/PartialEntity";
|
|
10
11
|
|
|
@@ -62,6 +63,8 @@ export class TelemetryEntityRelationshipService extends DatabaseService<Model> {
|
|
|
62
63
|
model.fromEntityKey = edge.fromEntityKey;
|
|
63
64
|
model.toEntityKey = edge.toEntityKey;
|
|
64
65
|
model.relationshipType = edge.relationshipType;
|
|
66
|
+
// Explicit: this is what makes the edge eligible for stale pruning.
|
|
67
|
+
model.source = EntitySource.Discovered;
|
|
65
68
|
model.firstSeenAt = now;
|
|
66
69
|
model.lastSeenAt = now;
|
|
67
70
|
if (edge.metrics) {
|
|
@@ -8,8 +8,19 @@ import ObjectID from "../../Types/ObjectID";
|
|
|
8
8
|
import OneUptimeDate from "../../Types/Date";
|
|
9
9
|
import ColumnLength from "../../Types/Database/ColumnLength";
|
|
10
10
|
import QueryDeepPartialEntity from "../../Types/Database/PartialEntity";
|
|
11
|
+
import CreateBy from "../Types/Database/CreateBy";
|
|
12
|
+
import { OnCreate } from "../Types/Database/Hooks";
|
|
13
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
14
|
+
import Dictionary from "../../Types/Dictionary";
|
|
11
15
|
import { JSONObject } from "../../Types/JSON";
|
|
16
|
+
import EntitySource from "../../Types/Telemetry/EntitySource";
|
|
12
17
|
import EntityType from "../../Types/Telemetry/EntityType";
|
|
18
|
+
import { MANUAL_ENTITY_TYPES } from "../../Types/Telemetry/EntityTypeGroups";
|
|
19
|
+
import {
|
|
20
|
+
canonicalizeEntityValue,
|
|
21
|
+
computeEntityKey,
|
|
22
|
+
MANUAL_ENTITY_IDENTITY_ATTRIBUTE,
|
|
23
|
+
} from "../../Utils/Telemetry/EntityKey";
|
|
13
24
|
import logger from "../Utils/Logger";
|
|
14
25
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
15
26
|
import { ExtractedEntity } from "../Utils/Telemetry/TelemetryEntity";
|
|
@@ -25,6 +36,91 @@ export class TelemetryEntityService extends DatabaseService<Model> {
|
|
|
25
36
|
super(Model);
|
|
26
37
|
}
|
|
27
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Completes a manually created CI.
|
|
41
|
+
*
|
|
42
|
+
* Every machine writer — the ingest reconciler and the inventory mirror —
|
|
43
|
+
* computes `entityKey` itself and passes an explicit `source`, because
|
|
44
|
+
* both derive identity from something the user never sees (a canonicalized
|
|
45
|
+
* semconv attribute set, or the owning row's id). A create arriving
|
|
46
|
+
* WITHOUT a key is therefore a user create by construction, and this hook
|
|
47
|
+
* is what turns the two fields a human can reasonably supply (type and
|
|
48
|
+
* name) into the identity the registry needs.
|
|
49
|
+
*
|
|
50
|
+
* Deriving the key here rather than in the dashboard keeps it enforced for
|
|
51
|
+
* API clients too, and keeps the one identity rule — canonicalize, then
|
|
52
|
+
* hash — in the module that owns it.
|
|
53
|
+
*/
|
|
54
|
+
@CaptureSpan()
|
|
55
|
+
protected override async onBeforeCreate(
|
|
56
|
+
createBy: CreateBy<Model>,
|
|
57
|
+
): Promise<OnCreate<Model>> {
|
|
58
|
+
const data: Model = createBy.data;
|
|
59
|
+
|
|
60
|
+
if (!data.entityKey) {
|
|
61
|
+
data.source = EntitySource.Manual;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (data.source !== EntitySource.Manual) {
|
|
65
|
+
return { createBy, carryForward: null };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (!data.projectId) {
|
|
69
|
+
throw new BadDataException("Project ID is required.");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!data.entityType) {
|
|
73
|
+
throw new BadDataException("Entity Type is required.");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/*
|
|
77
|
+
* Confined to the manual-only vocabulary. A hand-made row of an
|
|
78
|
+
* observable type would key off the manual identity attribute and so
|
|
79
|
+
* could never converge with the row ingest derives for the same thing —
|
|
80
|
+
* it would just sit beside it forever. See MANUAL_ENTITY_TYPES.
|
|
81
|
+
*/
|
|
82
|
+
if (!MANUAL_ENTITY_TYPES.has(data.entityType)) {
|
|
83
|
+
throw new BadDataException(
|
|
84
|
+
`Entities of type ${data.entityType} are discovered automatically and cannot be created manually. Manually creatable types are: ${Array.from(
|
|
85
|
+
MANUAL_ENTITY_TYPES,
|
|
86
|
+
).join(", ")}.`,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const displayName: string = (data.displayName || "").trim();
|
|
91
|
+
|
|
92
|
+
if (!displayName) {
|
|
93
|
+
throw new BadDataException(
|
|
94
|
+
"Name is required for a manually created entity.",
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
data.displayName = displayName.substring(0, ColumnLength.ShortText);
|
|
99
|
+
|
|
100
|
+
const identifyingAttributes: Dictionary<string> = {
|
|
101
|
+
[MANUAL_ENTITY_IDENTITY_ATTRIBUTE]: canonicalizeEntityValue(displayName),
|
|
102
|
+
};
|
|
103
|
+
data.identifyingAttributes = identifyingAttributes as JSONObject;
|
|
104
|
+
|
|
105
|
+
data.entityKey = computeEntityKey({
|
|
106
|
+
projectId: data.projectId.toString(),
|
|
107
|
+
entityType: data.entityType,
|
|
108
|
+
identifyingAttributes,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
/*
|
|
112
|
+
* Stamped so the explorer can sort manual CIs alongside discovered ones
|
|
113
|
+
* on the same columns. `lastSeenAt` never moves again for these rows —
|
|
114
|
+
* it means "created", not "observed" — which is exactly why the prune
|
|
115
|
+
* sweep excludes them.
|
|
116
|
+
*/
|
|
117
|
+
const now: Date = OneUptimeDate.getCurrentDate();
|
|
118
|
+
data.firstSeenAt = data.firstSeenAt || now;
|
|
119
|
+
data.lastSeenAt = data.lastSeenAt || now;
|
|
120
|
+
|
|
121
|
+
return { createBy, carryForward: null };
|
|
122
|
+
}
|
|
123
|
+
|
|
28
124
|
/**
|
|
29
125
|
* Forward-only registry reconciliation: upsert a catalog row per
|
|
30
126
|
* discovered entity, bump `lastSeenAt`, merge descriptive attributes
|
|
@@ -169,7 +265,18 @@ export class TelemetryEntityService extends DatabaseService<Model> {
|
|
|
169
265
|
if (count === undefined) {
|
|
170
266
|
count = (
|
|
171
267
|
await this.countBy({
|
|
172
|
-
query: {
|
|
268
|
+
query: {
|
|
269
|
+
projectId,
|
|
270
|
+
entityType: entity.entityType,
|
|
271
|
+
/*
|
|
272
|
+
* The budget exists to bound rows minted by ingest, so it
|
|
273
|
+
* counts only those. Manual CIs and inventory mirrors are
|
|
274
|
+
* bounded by their own creators and must not consume it —
|
|
275
|
+
* otherwise registering enough devices could stop new
|
|
276
|
+
* telemetry entities being recorded at all.
|
|
277
|
+
*/
|
|
278
|
+
source: EntitySource.Discovered,
|
|
279
|
+
},
|
|
173
280
|
props: { isRoot: true },
|
|
174
281
|
})
|
|
175
282
|
).toNumber();
|
|
@@ -198,6 +305,12 @@ export class TelemetryEntityService extends DatabaseService<Model> {
|
|
|
198
305
|
model.projectId = projectId;
|
|
199
306
|
model.entityType = entity.entityType;
|
|
200
307
|
model.entityKey = entity.entityKey;
|
|
308
|
+
/*
|
|
309
|
+
* Explicit rather than leaning on the column default: this is the
|
|
310
|
+
* flag that makes the row eligible for stale-entity pruning, and a
|
|
311
|
+
* silently-defaulted value is a poor way to carry that.
|
|
312
|
+
*/
|
|
313
|
+
model.source = EntitySource.Discovered;
|
|
201
314
|
model.identifyingAttributes = entity.identifyingAttributes;
|
|
202
315
|
if (
|
|
203
316
|
entity.descriptiveAttributes &&
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import CreateBy from "../Types/Database/CreateBy";
|
|
2
2
|
import DeleteBy from "../Types/Database/DeleteBy";
|
|
3
|
-
import
|
|
3
|
+
import UpdateBy from "../Types/Database/UpdateBy";
|
|
4
|
+
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
|
|
4
5
|
import DatabaseService from "./DatabaseService";
|
|
5
6
|
import UserNotificationRuleService from "./UserNotificationRuleService";
|
|
6
7
|
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
@@ -8,8 +9,19 @@ import BadDataException from "../../Types/Exception/BadDataException";
|
|
|
8
9
|
import Model from "../../Models/DatabaseModels/UserWebhook";
|
|
9
10
|
import URL from "../../Types/API/URL";
|
|
10
11
|
import logger from "../Utils/Logger";
|
|
12
|
+
import SSRFProtection from "../Utils/SSRFProtection";
|
|
11
13
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
12
14
|
|
|
15
|
+
/*
|
|
16
|
+
* URL validation here used to be a hand-rolled copy of the SSRF blocklist that
|
|
17
|
+
* had drifted weaker than the original (it compared the host with the port
|
|
18
|
+
* still attached, and never resolved DNS). Everything that actually sends one
|
|
19
|
+
* of these webhooks goes through WebhookService, which calls
|
|
20
|
+
* SSRFProtection.validateWebhookTargetIsSafe — so the copy bought nothing and
|
|
21
|
+
* would have been read as "this is checked". Both hooks now call the same
|
|
22
|
+
* guard the sender does, which fails the write early instead of at delivery.
|
|
23
|
+
*/
|
|
24
|
+
|
|
13
25
|
export class Service extends DatabaseService<Model> {
|
|
14
26
|
public constructor() {
|
|
15
27
|
super(Model);
|
|
@@ -27,7 +39,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
27
39
|
throw new BadDataException("Webhook name is required");
|
|
28
40
|
}
|
|
29
41
|
|
|
30
|
-
|
|
42
|
+
await SSRFProtection.validateWebhookTargetIsSafe(createBy.data.webhookUrl);
|
|
31
43
|
|
|
32
44
|
return {
|
|
33
45
|
createBy,
|
|
@@ -35,6 +47,26 @@ export class Service extends DatabaseService<Model> {
|
|
|
35
47
|
};
|
|
36
48
|
}
|
|
37
49
|
|
|
50
|
+
@CaptureSpan()
|
|
51
|
+
protected override async onBeforeUpdate(
|
|
52
|
+
updateBy: UpdateBy<Model>,
|
|
53
|
+
): Promise<OnUpdate<Model>> {
|
|
54
|
+
/*
|
|
55
|
+
* Create-time validation on its own is not a control: the URL is
|
|
56
|
+
* editable afterwards.
|
|
57
|
+
*/
|
|
58
|
+
const webhookUrl: unknown = updateBy.data.webhookUrl;
|
|
59
|
+
|
|
60
|
+
if (typeof webhookUrl === "string" || webhookUrl instanceof URL) {
|
|
61
|
+
await SSRFProtection.validateWebhookTargetIsSafe(webhookUrl);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
updateBy,
|
|
66
|
+
carryForward: null,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
38
70
|
@CaptureSpan()
|
|
39
71
|
protected override async onCreateSuccess(
|
|
40
72
|
_onCreate: OnCreate<Model>,
|
|
@@ -96,113 +128,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
96
128
|
carryForward: null,
|
|
97
129
|
};
|
|
98
130
|
}
|
|
99
|
-
|
|
100
|
-
private validateWebhookUrl(rawUrl: string): void {
|
|
101
|
-
let parsed: URL;
|
|
102
|
-
try {
|
|
103
|
-
parsed = URL.fromString(rawUrl);
|
|
104
|
-
} catch {
|
|
105
|
-
throw new BadDataException("Webhook URL is not a valid URL");
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const protocolValue: string = parsed.protocol.toString().toLowerCase();
|
|
109
|
-
if (protocolValue !== "http://" && protocolValue !== "https://") {
|
|
110
|
-
throw new BadDataException(
|
|
111
|
-
"Webhook URL must use http or https protocol.",
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const hostname: string = parsed.hostname.hostname.toLowerCase();
|
|
116
|
-
|
|
117
|
-
if (!hostname) {
|
|
118
|
-
throw new BadDataException("Webhook URL must include a host.");
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (isBlockedHostnameLiteral(hostname)) {
|
|
122
|
-
throw new BadDataException(
|
|
123
|
-
"Webhook URL points to a private, loopback, or link-local address and is not allowed.",
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function isBlockedHostnameLiteral(hostname: string): boolean {
|
|
130
|
-
if (
|
|
131
|
-
hostname === "localhost" ||
|
|
132
|
-
hostname.endsWith(".localhost") ||
|
|
133
|
-
hostname === "metadata.google.internal"
|
|
134
|
-
) {
|
|
135
|
-
return true;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// IPv4 literal check
|
|
139
|
-
const ipv4Match: RegExpMatchArray | null = hostname.match(
|
|
140
|
-
/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/,
|
|
141
|
-
);
|
|
142
|
-
if (ipv4Match) {
|
|
143
|
-
const octets: Array<number> = [
|
|
144
|
-
Number(ipv4Match[1]),
|
|
145
|
-
Number(ipv4Match[2]),
|
|
146
|
-
Number(ipv4Match[3]),
|
|
147
|
-
Number(ipv4Match[4]),
|
|
148
|
-
];
|
|
149
|
-
|
|
150
|
-
if (
|
|
151
|
-
octets.some((o: number) => {
|
|
152
|
-
return o < 0 || o > 255;
|
|
153
|
-
})
|
|
154
|
-
) {
|
|
155
|
-
return true;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// 0.0.0.0/8
|
|
159
|
-
if (octets[0] === 0) {
|
|
160
|
-
return true;
|
|
161
|
-
}
|
|
162
|
-
// 127.0.0.0/8 loopback
|
|
163
|
-
if (octets[0] === 127) {
|
|
164
|
-
return true;
|
|
165
|
-
}
|
|
166
|
-
// 10.0.0.0/8
|
|
167
|
-
if (octets[0] === 10) {
|
|
168
|
-
return true;
|
|
169
|
-
}
|
|
170
|
-
// 172.16.0.0/12
|
|
171
|
-
if (octets[0] === 172 && (octets[1]! & 0xf0) === 16) {
|
|
172
|
-
return true;
|
|
173
|
-
}
|
|
174
|
-
// 192.168.0.0/16
|
|
175
|
-
if (octets[0] === 192 && octets[1] === 168) {
|
|
176
|
-
return true;
|
|
177
|
-
}
|
|
178
|
-
// 169.254.0.0/16 link-local (incl. cloud metadata)
|
|
179
|
-
if (octets[0] === 169 && octets[1] === 254) {
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
// 100.64.0.0/10 carrier-grade NAT
|
|
183
|
-
if (octets[0] === 100 && (octets[1]! & 0xc0) === 64) {
|
|
184
|
-
return true;
|
|
185
|
-
}
|
|
186
|
-
return false;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// IPv6 literal — block loopback, link-local, unique-local
|
|
190
|
-
if (hostname.includes(":")) {
|
|
191
|
-
const stripped: string = hostname.replace(/^\[|\]$/g, "");
|
|
192
|
-
if (stripped === "::1" || stripped === "::") {
|
|
193
|
-
return true;
|
|
194
|
-
}
|
|
195
|
-
if (stripped.startsWith("fe80:") || stripped.startsWith("fe80::")) {
|
|
196
|
-
return true;
|
|
197
|
-
}
|
|
198
|
-
if (IPV6_UNIQUE_LOCAL_REGEX.test(stripped)) {
|
|
199
|
-
return true;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
return false;
|
|
204
131
|
}
|
|
205
132
|
|
|
206
|
-
const IPV6_UNIQUE_LOCAL_REGEX: RegExp = /^f[cd][0-9a-f]{2}:/;
|
|
207
|
-
|
|
208
133
|
export default new Service();
|