@oneuptime/common 14.0.6 → 14.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/Incident.ts +267 -1
- package/Models/DatabaseModels/IncidentCustomField.ts +202 -0
- package/Models/DatabaseModels/IncidentEpisode.ts +30 -0
- package/Models/DatabaseModels/IncidentTemplate.ts +126 -1
- package/Models/DatabaseModels/InventoryItem.ts +23 -12
- package/Models/DatabaseModels/StatusPage.ts +55 -0
- package/Models/DatabaseModels/StatusPageSubscriber.ts +128 -0
- package/Server/API/IncidentAPI.ts +162 -0
- package/Server/API/StatusPageAPI.ts +487 -171
- package/Server/API/StatusPageSubscriberAPI.ts +63 -15
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.ts +217 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.ts +49 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.ts +108 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.ts +51 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.ts +168 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.ts +44 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +16 -0
- package/Server/Infrastructure/Semaphore.ts +10 -0
- package/Server/Middleware/IdentityRateLimit.ts +108 -3
- package/Server/Middleware/SubscriberNotificationPreviewRateLimit.ts +237 -0
- package/Server/Middleware/SubscriberNotificationTestSendRateLimit.ts +304 -0
- package/Server/Services/AlertService.ts +32 -36
- package/Server/Services/DatabaseService.ts +93 -10
- package/Server/Services/IncidentAlertService.ts +609 -2
- package/Server/Services/IncidentCustomFieldService.ts +276 -1
- package/Server/Services/IncidentEpisodePublicNoteService.ts +28 -0
- package/Server/Services/IncidentEpisodeService.ts +15 -0
- package/Server/Services/IncidentEpisodeStateTimelineService.ts +27 -1
- package/Server/Services/IncidentPublicNoteService.ts +30 -1
- package/Server/Services/IncidentService.ts +1663 -103
- package/Server/Services/IncidentStateTimelineService.ts +13 -0
- package/Server/Services/IncidentTemplateService.ts +109 -0
- package/Server/Services/InventoryItemService.ts +38 -0
- package/Server/Services/IoTDeviceCredentialService.ts +13 -4
- package/Server/Services/ScheduledMaintenancePublicNoteService.ts +30 -1
- package/Server/Services/ScheduledMaintenanceService.ts +118 -64
- package/Server/Services/SmsService.ts +10 -0
- package/Server/Services/StatusPageService.ts +65 -8
- package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +299 -37
- package/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.ts +129 -0
- package/Server/Services/StatusPageSubscriberService.ts +1161 -64
- package/Server/Services/UserNotificationRuleService.ts +55 -53
- package/Server/Services/WorkspaceNotificationSummaryService.ts +38 -20
- package/Server/Types/Markdown.ts +153 -6
- package/Server/Types/Workflow/Components/Email.ts +61 -2
- package/Server/Utils/AffectedResources/LinkedAffectedResources.ts +576 -0
- package/Server/Utils/Alert/AlertStateChangeAuthorization.ts +129 -0
- package/Server/Utils/CustomField/CustomFieldRename.ts +378 -0
- package/Server/Utils/DataSource/EgressGuard.ts +66 -21
- package/Server/Utils/Inventory/InventoryOverviewAggregation.ts +111 -0
- package/Server/Utils/Mail/PinnedSmtpSocket.ts +130 -0
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +10 -0
- package/Server/Utils/Response.ts +31 -0
- package/Server/Utils/SSRFProtection.ts +76 -16
- package/Server/Utils/StatusPage/IncidentStatusPageScope.ts +948 -0
- package/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.ts +656 -0
- package/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.ts +805 -0
- package/Server/Utils/StatusPage/StatusPageExclusion.ts +18 -0
- package/Server/Utils/StatusPage/StatusPageReadAccess.ts +125 -0
- package/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.ts +151 -0
- package/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.ts +70 -0
- package/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.ts +421 -0
- package/Server/Utils/StatusPage/SubscriberNotificationClaim.ts +107 -0
- package/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.ts +1049 -0
- package/Server/Utils/StatusPage/SubscriberNotificationFanOut.ts +180 -0
- package/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.ts +839 -0
- package/Server/Utils/StatusPage/SubscriberNotificationResendAccess.ts +393 -0
- package/Server/Utils/StatusPage/SubscriberNotificationRunLimit.ts +246 -0
- package/Server/Utils/StatusPage/SubscriberNotificationTiming.ts +133 -0
- package/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.ts +215 -0
- package/Server/Utils/StatusPageResource.ts +51 -20
- package/Server/Utils/Topology/TopologyConcurrencyLimiter.ts +229 -0
- package/Server/Utils/Topology/TopologyQueries.ts +1350 -0
- package/Server/Utils/Topology/TopologyRequest.ts +463 -0
- package/Server/Utils/Topology/TopologyResponseCache.ts +183 -0
- package/Server/Utils/Topology/TopologySql.ts +1024 -0
- package/Server/Utils/VM/VMAPI.ts +1 -0
- package/Server/Utils/VM/VMRunner.ts +10 -0
- package/Server/Utils/Workflow/OAuth2TokenClient.ts +10 -0
- package/Server/Views/Partials/SensitiveUrlToken.ejs +8 -5
- package/Tests/App/Accounts/RegisterVerifyEmail.test.tsx +748 -0
- package/Tests/App/Accounts/ResendVerificationEmail.test.tsx +1222 -0
- package/Tests/App/Accounts/VerificationEmailResendUtils.test.ts +797 -0
- package/Tests/App/Accounts/VerifyEmailPending.test.tsx +538 -0
- package/Tests/App/Accounts/VerifyEmailResend.test.tsx +779 -0
- package/Tests/App/Dashboard/AcknowledgeAlertsOnDeclare.test.ts +369 -0
- package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +1 -1
- package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +510 -123
- package/Tests/App/Dashboard/AlertsTableAffectedResources.test.tsx +490 -0
- package/Tests/App/Dashboard/ChangeAlertStateDeclareIncident.test.tsx +886 -0
- package/Tests/App/Dashboard/CreateReviewStepRoleSummary.test.tsx +1250 -0
- package/Tests/App/Dashboard/CreateReviewStepSelectionSummary.test.tsx +738 -0
- package/Tests/App/Dashboard/CustomFieldsSettingsIncidentOptions.test.tsx +357 -0
- package/Tests/App/Dashboard/DeclareIncidentFromAlert.test.ts +417 -0
- package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +1948 -229
- package/Tests/App/Dashboard/EntityDetailPanelLifecycle.test.tsx +493 -0
- package/Tests/App/Dashboard/EntityDetailPanelNavigation.test.tsx +439 -0
- package/Tests/App/Dashboard/EventNotes.test.tsx +776 -0
- package/Tests/App/Dashboard/EventNotesPages.test.tsx +119 -0
- package/Tests/App/Dashboard/EventNotesUtil.test.ts +116 -17
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +534 -6
- package/Tests/App/Dashboard/EventStatusPanel.test.tsx +798 -2
- package/Tests/App/Dashboard/FetchStateAndSeverityElements.test.tsx +669 -0
- package/Tests/App/Dashboard/FetchUsers.test.tsx +230 -0
- package/Tests/App/Dashboard/IncidentChangeStateNotifyDefault.test.tsx +91 -1
- package/Tests/App/Dashboard/IncidentCreateAcknowledgeAlerts.test.tsx +1611 -0
- package/Tests/App/Dashboard/IncidentCreateDetailsStep.test.tsx +643 -0
- package/Tests/App/Dashboard/IncidentCreateFromAlerts.test.tsx +8 -1
- package/Tests/App/Dashboard/IncidentCreateStatusPageScope.test.tsx +601 -0
- package/Tests/App/Dashboard/IncidentCustomFieldTemplateVariables.test.tsx +386 -0
- package/Tests/App/Dashboard/IncidentNoteTemplatePlaceholders.test.tsx +124 -0
- package/Tests/App/Dashboard/IncidentNoteTemplateVariablesLoader.test.ts +305 -0
- package/Tests/App/Dashboard/IncidentOverviewNotifyDefault.test.tsx +112 -0
- package/Tests/App/Dashboard/IncidentSettingsRenotifyOnPublish.test.tsx +674 -0
- package/Tests/App/Dashboard/IncidentSettingsStatusPageScope.test.tsx +1051 -0
- package/Tests/App/Dashboard/IncidentTemplateCustomFields.test.tsx +384 -0
- package/Tests/App/Dashboard/IncidentTemplateStatusPageScopeCard.test.tsx +215 -0
- package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +1365 -57
- package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +964 -23
- package/Tests/App/Dashboard/InventoryRelationships.test.tsx +885 -0
- package/Tests/App/Dashboard/PublicNotePagesNotifyDefault.test.tsx +113 -1
- package/Tests/App/Dashboard/ServiceMapDatabaseLink.test.tsx +201 -15
- package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +508 -36
- package/Tests/App/Dashboard/SubscriberAudienceSummary.test.tsx +512 -0
- package/Tests/App/Dashboard/SubscriberNotificationPreviewModal.test.tsx +837 -0
- package/Tests/App/Dashboard/SubscriberNotificationStatusLabel.test.tsx +88 -0
- package/Tests/App/Dashboard/SubscriberNotificationStatusResend.test.tsx +473 -0
- package/Tests/App/Dashboard/SubscriberTemplateLivePreview.test.tsx +196 -0
- package/Tests/App/Dashboard/TeamAddedSubscribersUnsubscribedNotice.test.tsx +248 -0
- package/Tests/App/Dashboard/TopologyDataLifecycle.test.tsx +583 -0
- package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +982 -218
- package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +818 -114
- package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +64 -3
- package/Tests/App/StatusPage/StatusPageUnsubscribePage.test.tsx +412 -0
- package/Tests/Models/IncidentCustomFieldApiSchemaContract.test.ts +217 -0
- package/Tests/Models/IncidentCustomFieldCreateSettingsColumns.test.ts +252 -0
- package/Tests/Models/StatusPageSubscriberUnsubscribeColumns.test.ts +218 -0
- package/Tests/Server/API/ExpiredSessionRouteGuards.test.ts +7 -0
- package/Tests/Server/API/IncidentSubscriberAudienceAPI.test.ts +1408 -0
- package/Tests/Server/API/StatusPageIncidentScope.test.ts +1868 -0
- package/Tests/Server/API/StatusPageIncidentScopePostgres.test.ts +790 -0
- package/Tests/Server/API/StatusPageManageSubscriptionRecipient.test.ts +10 -1
- package/Tests/Server/API/StatusPageManageSubscriptionTemplateVariables.test.ts +206 -18
- package/Tests/Server/API/StatusPagePostmortemVisibility.test.ts +14 -2
- package/Tests/Server/API/StatusPageSubscriberCreateResponse.test.ts +217 -0
- package/Tests/Server/API/StatusPageSubscriberOwnership.test.ts +103 -2
- package/Tests/Server/API/StatusPageUnsubscribeAPI.test.ts +396 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentStatusPageScopeMigration.test.ts +395 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentTemplateStatusPageScopeFlagMigration.test.ts +150 -0
- package/Tests/Server/Infrastructure/Postgres/AddSubscriberNotificationClaimedAtMigration.test.ts +156 -0
- package/Tests/Server/Infrastructure/Postgres/RenameInventoryItemMigration.test.ts +90 -21
- package/Tests/Server/Infrastructure/Postgres/SkipHiddenIncidentCreatedNotificationsMigration.test.ts +410 -0
- package/Tests/Server/Middleware/IdentityRateLimit.test.ts +551 -1
- package/Tests/Server/Middleware/SubscriberNotificationPreviewRateLimit.test.ts +238 -0
- package/Tests/Server/Middleware/SubscriberNotificationTestSendRateLimit.test.ts +245 -0
- package/Tests/Server/Services/AddStatusPageSubscriberUnsubscribeTokenMigration.test.ts +152 -0
- package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +221 -36
- package/Tests/Server/Services/DatabaseServiceCompareAndSetColumns.test.ts +191 -0
- package/Tests/Server/Services/DomainService.test.ts +525 -0
- package/Tests/Server/Services/IncidentAlertAcknowledgeOnDeclare.test.ts +2630 -0
- package/Tests/Server/Services/IncidentAlertPostgres.test.ts +1625 -1
- package/Tests/Server/Services/IncidentCreatedRenotifyOnPublish.test.ts +681 -0
- package/Tests/Server/Services/IncidentCreatedResend.test.ts +775 -0
- package/Tests/Server/Services/IncidentCustomFieldRenamePostgres.test.ts +713 -0
- package/Tests/Server/Services/IncidentCustomFieldService.test.ts +751 -0
- package/Tests/Server/Services/IncidentCustomFieldValueValidation.test.ts +556 -0
- package/Tests/Server/Services/IncidentDeclareAcknowledgeAlerts.test.ts +2189 -0
- package/Tests/Server/Services/IncidentStatusPageScope.test.ts +2971 -0
- package/Tests/Server/Services/IncidentStatusPageScopeFeed.test.ts +131 -0
- package/Tests/Server/Services/IncidentStatusPageScopePostgres.test.ts +625 -0
- package/Tests/Server/Services/IncidentTemplateCustomFieldsCopy.test.ts +311 -0
- package/Tests/Server/Services/IncidentTemplateStatusPageScope.test.ts +363 -0
- package/Tests/Server/Services/InventoryItemServiceOverviewCounts.test.ts +345 -0
- package/Tests/Server/Services/InventoryOverviewPostgres.test.ts +254 -0
- package/Tests/Server/Services/IoTDeviceCredentialService.test.ts +819 -0
- package/Tests/Server/Services/LinkedAffectedResourcesCreatedFeed.test.ts +420 -0
- package/Tests/Server/Services/PublicNoteEditFeedEventType.test.ts +213 -0
- package/Tests/Server/Services/PublicNoteResendAccess.test.ts +994 -0
- package/Tests/Server/Services/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +289 -9
- package/Tests/Server/Services/SloAffectedResourceCreatedFeed.test.ts +92 -36
- package/Tests/Server/Services/SmsServiceFailIfNotSent.test.ts +67 -0
- package/Tests/Server/Services/StatusPageReportIncidentCounts.test.ts +610 -0
- package/Tests/Server/Services/StatusPageSubscriberAudienceCounts.test.ts +201 -0
- package/Tests/Server/Services/StatusPageSubscriberAudienceCountsPostgres.test.ts +271 -0
- package/Tests/Server/Services/StatusPageSubscriberConfirmationTemplateEscaping.test.ts +200 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationLogRedaction.test.ts +54 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateCompile.test.ts +37 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateIncidentRecordAccess.test.ts +772 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateLookup.test.ts +506 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateLookupPostgres.test.ts +261 -0
- package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +21 -5
- package/Tests/Server/Services/StatusPageSubscriberUnsubscribe.test.ts +1618 -0
- package/Tests/Server/Services/StatusPageSubscriberUnsubscribeLinkSenders.test.ts +373 -0
- package/Tests/Server/Services/StatusPageSubscriberUnsubscribePostgres.test.ts +388 -0
- package/Tests/Server/Services/SubscriberNotificationInFlightRequeue.test.ts +500 -0
- package/Tests/Server/Types/MarkdownEmailLinks.test.ts +320 -0
- package/Tests/Server/Types/Workflow/Components/Email.test.ts +491 -1
- package/Tests/Server/Types/Workflow/Components/EmailSmtpPinning.test.ts +398 -0
- package/Tests/Server/Utils/AffectedResources/LinkedAffectedResources.test.ts +858 -0
- package/Tests/Server/Utils/Alert/AlertStateChangeAuthorization.test.ts +1172 -0
- package/Tests/Server/Utils/CustomField/CustomFieldRename.test.ts +586 -0
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +246 -10
- package/Tests/Server/Utils/DataSource/EgressGuardDeploymentConfig.test.ts +226 -0
- package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +131 -0
- package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +4 -0
- package/Tests/Server/Utils/EgressPolicyEnvironment.ts +45 -0
- package/Tests/Server/Utils/Mail/PinnedSmtpSocket.test.ts +409 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +23 -0
- package/Tests/Server/Utils/SSRFProtection.test.ts +4 -0
- package/Tests/Server/Utils/SSRFProtectionCloudServiceAddresses.test.ts +4 -0
- package/Tests/Server/Utils/SSRFProtectionPrivateNetwork.test.ts +4 -0
- package/Tests/Server/Utils/SSRFProtectionResolutionDetail.test.ts +314 -0
- package/Tests/Server/Utils/StatusPage/IncidentStatusPageScope.test.ts +1699 -0
- package/Tests/Server/Utils/StatusPage/IncidentStatusPageScopeQueriesPostgres.test.ts +508 -0
- package/Tests/Server/Utils/StatusPage/IncidentSubscriberAudienceCallerPermission.test.ts +246 -0
- package/Tests/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.test.ts +1348 -0
- package/Tests/Server/Utils/StatusPage/StatusPageReadAccess.test.ts +221 -0
- package/Tests/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.test.ts +132 -0
- package/Tests/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.test.ts +155 -0
- package/Tests/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.test.ts +708 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationClaim.test.ts +255 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationClaimPostgres.test.ts +528 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.test.ts +1238 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationFanOut.test.ts +472 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.test.ts +1168 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationRunLimit.test.ts +275 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationTiming.test.ts +131 -0
- package/Tests/Server/Utils/StatusPageResource.test.ts +98 -0
- package/Tests/Server/Utils/Topology/InventoryItemEntityKeyIndexMigration.test.ts +386 -0
- package/Tests/Server/Utils/Topology/InventoryItemEntityKeyIndexMigrationPostgres.test.ts +430 -0
- package/Tests/Server/Utils/Topology/TopologyActivityParityPostgres.test.ts +279 -0
- package/Tests/Server/Utils/Topology/TopologyConcurrencyLimiter.test.ts +534 -0
- package/Tests/Server/Utils/Topology/TopologyEstateGenerator.ts +624 -0
- package/Tests/Server/Utils/Topology/TopologyJsonResponse.test.ts +90 -0
- package/Tests/Server/Utils/Topology/TopologyQueries.test.ts +1634 -0
- package/Tests/Server/Utils/Topology/TopologyQueriesDifferentialPostgres.test.ts +683 -0
- package/Tests/Server/Utils/Topology/TopologyQueriesPostgres.test.ts +2624 -0
- package/Tests/Server/Utils/Topology/TopologyReference.ts +1018 -0
- package/Tests/Server/Utils/Topology/TopologyRequest.test.ts +643 -0
- package/Tests/Server/Utils/Topology/TopologyResponseCache.test.ts +305 -0
- package/Tests/Server/Utils/Topology/TopologySql.test.ts +973 -0
- package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +17 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +75 -0
- package/Tests/Types/CustomField/CustomFieldSavedViews.test.ts +247 -0
- package/Tests/Types/CustomField/CustomFieldTemplateValues.test.ts +186 -0
- package/Tests/Types/CustomField/CustomFieldTypeCorrespondence.test.ts +48 -0
- package/Tests/Types/CustomField/CustomFieldValueFormat.test.ts +215 -0
- package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +343 -0
- package/Tests/Types/CustomField/CustomFieldVariableKey.test.ts +364 -0
- package/Tests/Types/SafeHtml.test.ts +102 -0
- package/Tests/Types/StatusPage/IncidentCreatedRenotify.test.ts +419 -0
- package/Tests/Types/StatusPage/IncidentCreatedResend.test.ts +118 -0
- package/Tests/Types/StatusPage/IncidentScopeAddedPagesNotification.test.ts +558 -0
- package/Tests/Types/StatusPage/IncidentSubscriberAudience.test.ts +284 -0
- package/Tests/Types/StatusPage/StatusPageSubscriberUnsubscribe.test.ts +341 -0
- package/Tests/Types/StatusPage/SubscriberNotificationPreview.test.ts +196 -0
- package/Tests/Types/StatusPage/SubscriberNotificationResend.test.ts +201 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplateCompiler.test.ts +277 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplatePreview.test.ts +179 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplateVariables.test.ts +324 -0
- package/Tests/Types/StatusPage/SubscriberUpdateNotification.test.ts +60 -13
- package/Tests/Types/Topology/TopologyTypeRules.test.ts +176 -0
- package/Tests/UI/Components/CustomFields/CustomFieldFormFields.test.ts +432 -0
- package/Tests/UI/Components/CustomFields/CustomFieldModelFormFields.test.tsx +685 -0
- package/Tests/UI/Components/CustomFields/CustomFieldsDetailOrder.test.tsx +469 -0
- package/Tests/UI/Components/Forms/ModelFormCustomFieldInputs.test.tsx +325 -0
- package/Tests/UI/Components/Forms/ModelFormDropdownOptionsRefused.test.tsx +358 -0
- package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +22 -0
- package/Tests/UI/Monitor/NetworkPathView.test.tsx +289 -0
- package/Tests/Utils/Incident/IncidentFromAlerts.test.ts +302 -0
- package/Tests/Utils/Incident/IncidentNoteTemplateVariables.test.ts +623 -0
- package/Tests/Utils/Markdown/MarkdownEscape.test.ts +89 -0
- package/Tests/Utils/ProbeNetworkFailureUtil.test.ts +992 -0
- package/Tests/Utils/RequestFailedDetails.test.ts +575 -0
- package/Types/CustomField/CustomFieldOrder.ts +55 -0
- package/Types/CustomField/CustomFieldSavedViews.ts +225 -0
- package/Types/CustomField/CustomFieldTemplateMerge.ts +71 -0
- package/Types/CustomField/CustomFieldType.ts +14 -0
- package/Types/CustomField/CustomFieldValueFormat.ts +161 -0
- package/Types/CustomField/CustomFieldValueValidator.ts +488 -0
- package/Types/CustomField/CustomFieldVariableKey.ts +211 -0
- package/Types/Incident/IncidentAlertLink.ts +19 -0
- package/Types/SafeHtml.ts +93 -0
- package/Types/StatusPage/IncidentCreatedRenotify.ts +224 -0
- package/Types/StatusPage/IncidentCreatedResend.ts +108 -0
- package/Types/StatusPage/IncidentScopeAddedPagesNotification.ts +343 -0
- package/Types/StatusPage/IncidentSubscriberAudience.ts +332 -0
- package/Types/StatusPage/StatusPageSubscriberUnsubscribe.ts +405 -0
- package/Types/StatusPage/SubscriberNotificationInterruption.ts +32 -0
- package/Types/StatusPage/SubscriberNotificationPreview.ts +322 -0
- package/Types/StatusPage/SubscriberNotificationResend.ts +132 -0
- package/Types/StatusPage/SubscriberNotificationTemplateCompiler.ts +180 -0
- package/Types/StatusPage/SubscriberNotificationTemplatePreview.ts +301 -0
- package/Types/StatusPage/SubscriberNotificationTemplateVariables.ts +217 -4
- package/Types/StatusPage/SubscriberUpdateNotification.ts +32 -11
- package/Types/Telemetry/InventoryLiveness.ts +26 -0
- package/Types/Topology/TopologyApi.ts +428 -0
- package/Types/Topology/TopologyTypeRules.ts +191 -0
- package/UI/Components/CustomFields/CustomFieldFormFields.ts +317 -0
- package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +395 -0
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +95 -55
- package/UI/Components/Forms/ModelForm.tsx +70 -8
- package/UI/Components/Forms/Validation.ts +1 -1
- package/UI/Components/ModelFormModal/ModelFormModal.tsx +2 -4
- package/UI/Components/ModelTable/AnalyticsModelTable.tsx +2 -6
- package/UI/Components/ModelTable/BaseModelTable.tsx +9 -8
- package/UI/Components/ModelTable/CustomFieldColumns.tsx +14 -1
- package/UI/Components/ModelTable/ModelTable.tsx +6 -7
- package/UI/Utils/SensitiveUrlToken.ts +10 -5
- package/Utils/API.ts +247 -2
- package/Utils/Incident/IncidentFromAlerts.ts +78 -0
- package/Utils/Incident/IncidentNoteTemplateVariables.ts +304 -0
- package/Utils/Markdown/MarkdownEscape.ts +65 -0
- package/Utils/ProbeNetworkFailureUtil.ts +673 -0
- package/build/dist/Models/DatabaseModels/Incident.js +267 -1
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js +207 -1
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js +31 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js +124 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/InventoryItem.js +20 -11
- package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +56 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +131 -0
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
- package/build/dist/Server/API/IncidentAPI.js +100 -1
- package/build/dist/Server/API/IncidentAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +417 -176
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageSubscriberAPI.js +52 -13
- package/build/dist/Server/API/StatusPageSubscriberAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.js +165 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.js +41 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.js +57 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.js +23 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.js +89 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.js +29 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +3 -0
- package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
- package/build/dist/Server/Middleware/IdentityRateLimit.js +89 -3
- package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
- package/build/dist/Server/Middleware/SubscriberNotificationPreviewRateLimit.js +149 -0
- package/build/dist/Server/Middleware/SubscriberNotificationPreviewRateLimit.js.map +1 -0
- package/build/dist/Server/Middleware/SubscriberNotificationTestSendRateLimit.js +190 -0
- package/build/dist/Server/Middleware/SubscriberNotificationTestSendRateLimit.js.map +1 -0
- package/build/dist/Server/Services/AlertService.js +21 -33
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +56 -7
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentAlertService.js +457 -3
- package/build/dist/Server/Services/IncidentAlertService.js.map +1 -1
- package/build/dist/Server/Services/IncidentCustomFieldService.js +204 -8
- package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +24 -0
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +14 -0
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +26 -0
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js +26 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +1148 -42
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +12 -0
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentTemplateService.js +83 -0
- package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemService.js +31 -0
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
- package/build/dist/Server/Services/IoTDeviceCredentialService.js +12 -5
- package/build/dist/Server/Services/IoTDeviceCredentialService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +26 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +84 -57
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/SmsService.js +2 -22
- package/build/dist/Server/Services/SmsService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +47 -9
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +237 -32
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.js +109 -0
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +925 -99
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +55 -51
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +42 -25
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
- package/build/dist/Server/Types/Markdown.js +110 -6
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Email.js +55 -6
- package/build/dist/Server/Types/Workflow/Components/Email.js.map +1 -1
- package/build/dist/Server/Utils/AffectedResources/LinkedAffectedResources.js +405 -0
- package/build/dist/Server/Utils/AffectedResources/LinkedAffectedResources.js.map +1 -0
- package/build/dist/Server/Utils/Alert/AlertStateChangeAuthorization.js +112 -0
- package/build/dist/Server/Utils/Alert/AlertStateChangeAuthorization.js.map +1 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldRename.js +211 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldRename.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +41 -12
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- package/build/dist/Server/Utils/Inventory/InventoryOverviewAggregation.js +81 -0
- package/build/dist/Server/Utils/Inventory/InventoryOverviewAggregation.js.map +1 -0
- package/build/dist/Server/Utils/Mail/PinnedSmtpSocket.js +101 -0
- package/build/dist/Server/Utils/Mail/PinnedSmtpSocket.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +9 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Response.js +30 -0
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +48 -6
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/StatusPage/IncidentStatusPageScope.js +631 -0
- package/build/dist/Server/Utils/StatusPage/IncidentStatusPageScope.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.js +403 -0
- package/build/dist/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.js +451 -0
- package/build/dist/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageExclusion.js +13 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageExclusion.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageReadAccess.js +91 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageReadAccess.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.js +101 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.js +47 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.js +273 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationClaim.js +73 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationClaim.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.js +722 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationFanOut.js +102 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationFanOut.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.js +527 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationResendAccess.js +278 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationResendAccess.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationRunLimit.js +137 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationRunLimit.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationTiming.js +103 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationTiming.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.js +114 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.js.map +1 -0
- package/build/dist/Server/Utils/StatusPageResource.js +39 -7
- package/build/dist/Server/Utils/StatusPageResource.js.map +1 -1
- package/build/dist/Server/Utils/Topology/TopologyConcurrencyLimiter.js +178 -0
- package/build/dist/Server/Utils/Topology/TopologyConcurrencyLimiter.js.map +1 -0
- package/build/dist/Server/Utils/Topology/TopologyQueries.js +884 -0
- package/build/dist/Server/Utils/Topology/TopologyQueries.js.map +1 -0
- package/build/dist/Server/Utils/Topology/TopologyRequest.js +275 -0
- package/build/dist/Server/Utils/Topology/TopologyRequest.js.map +1 -0
- package/build/dist/Server/Utils/Topology/TopologyResponseCache.js +146 -0
- package/build/dist/Server/Utils/Topology/TopologyResponseCache.js.map +1 -0
- package/build/dist/Server/Utils/Topology/TopologySql.js +688 -0
- package/build/dist/Server/Utils/Topology/TopologySql.js.map +1 -0
- package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +1 -0
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js +3 -0
- package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldOrder.js +36 -0
- package/build/dist/Types/CustomField/CustomFieldOrder.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldSavedViews.js +135 -0
- package/build/dist/Types/CustomField/CustomFieldSavedViews.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldTemplateMerge.js +27 -0
- package/build/dist/Types/CustomField/CustomFieldTemplateMerge.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldType.js +12 -0
- package/build/dist/Types/CustomField/CustomFieldType.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldValueFormat.js +126 -0
- package/build/dist/Types/CustomField/CustomFieldValueFormat.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js +280 -0
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldVariableKey.js +150 -0
- package/build/dist/Types/CustomField/CustomFieldVariableKey.js.map +1 -0
- package/build/dist/Types/Incident/IncidentAlertLink.js +17 -0
- package/build/dist/Types/Incident/IncidentAlertLink.js.map +1 -1
- package/build/dist/Types/SafeHtml.js +84 -0
- package/build/dist/Types/SafeHtml.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentCreatedRenotify.js +117 -0
- package/build/dist/Types/StatusPage/IncidentCreatedRenotify.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentCreatedResend.js +86 -0
- package/build/dist/Types/StatusPage/IncidentCreatedResend.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentScopeAddedPagesNotification.js +246 -0
- package/build/dist/Types/StatusPage/IncidentScopeAddedPagesNotification.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentSubscriberAudience.js +183 -0
- package/build/dist/Types/StatusPage/IncidentSubscriberAudience.js.map +1 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberUnsubscribe.js +277 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberUnsubscribe.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationInterruption.js +27 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationInterruption.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationPreview.js +190 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationPreview.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationResend.js +102 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationResend.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateCompiler.js +97 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateCompiler.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplatePreview.js +175 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplatePreview.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js +144 -4
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js.map +1 -1
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js +29 -9
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js.map +1 -1
- package/build/dist/Types/Telemetry/InventoryLiveness.js +23 -0
- package/build/dist/Types/Telemetry/InventoryLiveness.js.map +1 -1
- package/build/dist/Types/Topology/TopologyApi.js +55 -0
- package/build/dist/Types/Topology/TopologyApi.js.map +1 -0
- package/build/dist/Types/Topology/TopologyTypeRules.js +165 -0
- package/build/dist/Types/Topology/TopologyTypeRules.js.map +1 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldFormFields.js +169 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldFormFields.js.map +1 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js +212 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +64 -49
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +39 -5
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Validation.js +1 -1
- package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/AnalyticsModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +2 -2
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +13 -1
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
- package/build/dist/UI/Utils/SensitiveUrlToken.js +10 -5
- package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -1
- package/build/dist/Utils/API.js +177 -1
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Incident/IncidentFromAlerts.js +38 -0
- package/build/dist/Utils/Incident/IncidentFromAlerts.js.map +1 -1
- package/build/dist/Utils/Incident/IncidentNoteTemplateVariables.js +155 -0
- package/build/dist/Utils/Incident/IncidentNoteTemplateVariables.js.map +1 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js +48 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js.map +1 -1
- package/build/dist/Utils/ProbeNetworkFailureUtil.js +460 -0
- package/build/dist/Utils/ProbeNetworkFailureUtil.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,673 @@
|
|
|
1
|
+
import HostAddressUtil from "./HostAddressUtil";
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Tells a check that failed ON THE PROBE apart from one that failed at the
|
|
5
|
+
* destination, and words the probe-side case so it cannot be read as a
|
|
6
|
+
* verdict on the customer's host.
|
|
7
|
+
*
|
|
8
|
+
* The case this exists for: a probe with no usable IPv6. Every IPv6 check it
|
|
9
|
+
* runs fails before a single packet leaves the machine - ping6 answers
|
|
10
|
+
* "connect: Cannot assign requested address", traceroute -6 the same, a TCP
|
|
11
|
+
* connect EADDRNOTAVAIL - while every IPv4 monitor beside it keeps working.
|
|
12
|
+
* Reported as "Unable to reach host ... No ICMP echo reply", that sends the
|
|
13
|
+
* customer to debug a host that is answering perfectly well, which is exactly
|
|
14
|
+
* what happened with 2001:518:2800:9::2.
|
|
15
|
+
*
|
|
16
|
+
* What counts as probe-side, and how sure we can be:
|
|
17
|
+
*
|
|
18
|
+
* - EADDRNOTAVAIL ("Cannot assign requested address", "Can't assign
|
|
19
|
+
* requested address" on macOS/BSD). connect() found no local address to
|
|
20
|
+
* send from. Nothing was sent. Always the probe. From a TCP connect it
|
|
21
|
+
* can also mean the probe ran out of local ports, so the TCP wording
|
|
22
|
+
* does not state the missing IPv6 as fact (see isCauseAmbiguous).
|
|
23
|
+
* - EAFNOSUPPORT ("Address family not supported"). The probe's kernel has
|
|
24
|
+
* the family switched off. Nothing was sent. Always the probe.
|
|
25
|
+
* - ENETUNREACH ("Network is unreachable"). For ping and traceroute the
|
|
26
|
+
* connect() on a datagram/raw socket is only a lookup in the probe's own
|
|
27
|
+
* routing table, so it is the probe. For a TCP connect the SYN may already
|
|
28
|
+
* have left and a router's ICMPv6 "no route" reports the same errno, so
|
|
29
|
+
* there it is only LIKELY the probe and has to be worded that way.
|
|
30
|
+
* - "No route to host" in ping output. Kept from the markers PingMonitor
|
|
31
|
+
* already treated as the probe's own, but only as likely: macOS reports a
|
|
32
|
+
* failed neighbour lookup for an on-link host with the same text, which
|
|
33
|
+
* means the host is down. The IPv4 wording says the host may be down too.
|
|
34
|
+
*
|
|
35
|
+
* Deliberately NOT probe-side: "Destination Host Unreachable", "Destination
|
|
36
|
+
* Net Unreachable", "Destination unreachable: Address unreachable", and
|
|
37
|
+
* EHOSTUNREACH from a TCP connect. Those are ICMP errors a ROUTER sent back
|
|
38
|
+
* about the target, which is a real outage on the path, so they stay in the
|
|
39
|
+
* ordinary "could not reach the destination" bucket.
|
|
40
|
+
*
|
|
41
|
+
* Pure and isomorphic on purpose: Common/Utils/API.ts runs in the browser as
|
|
42
|
+
* well as on the probe and reuses this, so nothing here may import Node.
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
export enum ProbeNetworkFailureKind {
|
|
46
|
+
// EADDRNOTAVAIL: no local address of the destination's family to send from.
|
|
47
|
+
NoSourceAddress = "NoSourceAddress",
|
|
48
|
+
// EAFNOSUPPORT: the probe's kernel has the address family disabled.
|
|
49
|
+
AddressFamilyNotSupported = "AddressFamilyNotSupported",
|
|
50
|
+
// ENETUNREACH: no route for the destination's network.
|
|
51
|
+
NetworkUnreachable = "NetworkUnreachable",
|
|
52
|
+
// "No route to host" in ping/traceroute output.
|
|
53
|
+
NoRouteToHost = "NoRouteToHost",
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/*
|
|
57
|
+
* What the probe was doing when it failed. It only changes how sure the
|
|
58
|
+
* classification can be: see ENETUNREACH above.
|
|
59
|
+
*/
|
|
60
|
+
export enum ProbeNetworkOperation {
|
|
61
|
+
/*
|
|
62
|
+
* ping, ping6, traceroute: connect() on a datagram or raw socket is a
|
|
63
|
+
* route lookup in the probe's own kernel, and nothing is sent until it
|
|
64
|
+
* succeeds.
|
|
65
|
+
*/
|
|
66
|
+
PingOrTraceroute = "PingOrTraceroute",
|
|
67
|
+
/*
|
|
68
|
+
* A TCP connect (Port, SSL, HTTP): the SYN can already be on the wire when
|
|
69
|
+
* the error comes back, so ENETUNREACH may have come from a router.
|
|
70
|
+
*/
|
|
71
|
+
TcpConnect = "TcpConnect",
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface ProbeNetworkFailure {
|
|
75
|
+
kind: ProbeNetworkFailureKind;
|
|
76
|
+
/*
|
|
77
|
+
* True when the failure can only have happened on the probe. False when it
|
|
78
|
+
* most likely did but something on the path could have produced the same
|
|
79
|
+
* error, so the wording has to say "most likely".
|
|
80
|
+
*/
|
|
81
|
+
isCertain: boolean;
|
|
82
|
+
// The OS text that showed it: one line, as the operator should see it.
|
|
83
|
+
detail: string;
|
|
84
|
+
/*
|
|
85
|
+
* The address the failure was for, when the error said (a Node error's
|
|
86
|
+
* `address`). Lets a check against a DNS name know which family it was
|
|
87
|
+
* actually using. An aggregate (one attempt per address) sets it only when
|
|
88
|
+
* every attempt named an address of the same family: a dual-stack name
|
|
89
|
+
* whose IPv4 attempt failed as well is not an IPv6 problem.
|
|
90
|
+
*/
|
|
91
|
+
address?: string | undefined;
|
|
92
|
+
/*
|
|
93
|
+
* Set when the failure is certainly the probe's but the reason is not
|
|
94
|
+
* the usual one. From a TCP connect, EADDRNOTAVAIL also means the probe
|
|
95
|
+
* has run out of ephemeral ports for that destination, which a probe WITH
|
|
96
|
+
* working IPv6 can hit too. The host was still never contacted; only the
|
|
97
|
+
* explanation has to leave room for it.
|
|
98
|
+
*/
|
|
99
|
+
isCauseAmbiguous?: boolean | undefined;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/*
|
|
103
|
+
* Every describe() sentence opens with this, so a consumer holding only the
|
|
104
|
+
* stored text (an observation narrative on the server) can tell a probe-side
|
|
105
|
+
* cause from a verdict on the target without classifying it again.
|
|
106
|
+
*/
|
|
107
|
+
const PROBE_SIDE_CAUSE_PREFIX: string = "This probe ";
|
|
108
|
+
|
|
109
|
+
interface ProbeNetworkFailureMarker {
|
|
110
|
+
marker: string;
|
|
111
|
+
kind: ProbeNetworkFailureKind;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/*
|
|
115
|
+
* Lower-cased strerror text, most specific first. Matched on the strerror
|
|
116
|
+
* alone because the prefix before it varies: "ping6: connect:", "ping:
|
|
117
|
+
* sendmsg:", traceroute's bare "connect:".
|
|
118
|
+
*/
|
|
119
|
+
const OUTPUT_MARKERS: Array<ProbeNetworkFailureMarker> = [
|
|
120
|
+
{
|
|
121
|
+
marker: "cannot assign requested address",
|
|
122
|
+
kind: ProbeNetworkFailureKind.NoSourceAddress,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
marker: "can't assign requested address",
|
|
126
|
+
kind: ProbeNetworkFailureKind.NoSourceAddress,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
marker: "address family not supported",
|
|
130
|
+
kind: ProbeNetworkFailureKind.AddressFamilyNotSupported,
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
marker: "network is unreachable",
|
|
134
|
+
kind: ProbeNetworkFailureKind.NetworkUnreachable,
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
marker: "no route to host",
|
|
138
|
+
kind: ProbeNetworkFailureKind.NoRouteToHost,
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
marker: "unreachable host",
|
|
142
|
+
kind: ProbeNetworkFailureKind.NoRouteToHost,
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
|
|
146
|
+
/*
|
|
147
|
+
* Node error codes. EHOSTUNREACH is deliberately absent: from a socket it
|
|
148
|
+
* means a router or the neighbour lookup gave up on the target.
|
|
149
|
+
*/
|
|
150
|
+
const ERROR_CODE_KINDS: Record<string, ProbeNetworkFailureKind> = {
|
|
151
|
+
EADDRNOTAVAIL: ProbeNetworkFailureKind.NoSourceAddress,
|
|
152
|
+
EAFNOSUPPORT: ProbeNetworkFailureKind.AddressFamilyNotSupported,
|
|
153
|
+
ENETUNREACH: ProbeNetworkFailureKind.NetworkUnreachable,
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// Long enough for any strerror line; short enough for an SMS root cause.
|
|
157
|
+
const MAX_DETAIL_LENGTH: number = 200;
|
|
158
|
+
|
|
159
|
+
// How far down an error's `cause` chain classifyError looks.
|
|
160
|
+
const MAX_CAUSE_DEPTH: number = 5;
|
|
161
|
+
|
|
162
|
+
/*
|
|
163
|
+
* The fields classifyError reads, all optional because a thrown value can be
|
|
164
|
+
* anything. `errors` is AggregateError's, `cause` is the ES2022 one (fetch
|
|
165
|
+
* puts the socket error there), `address` is what Node sets on a socket error.
|
|
166
|
+
*/
|
|
167
|
+
interface ErrorLike {
|
|
168
|
+
code?: unknown;
|
|
169
|
+
message?: unknown;
|
|
170
|
+
address?: unknown;
|
|
171
|
+
errors?: unknown;
|
|
172
|
+
cause?: unknown;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export default class ProbeNetworkFailureUtil {
|
|
176
|
+
/*
|
|
177
|
+
* Classifies OS output or error text: ping's combined output, traceroute's
|
|
178
|
+
* stderr, an error message. Null when nothing in it says the probe was the
|
|
179
|
+
* one that failed.
|
|
180
|
+
*/
|
|
181
|
+
public static classifyOutput(data: {
|
|
182
|
+
output: string;
|
|
183
|
+
operation: ProbeNetworkOperation;
|
|
184
|
+
}): ProbeNetworkFailure | null {
|
|
185
|
+
const output: string = data.output || "";
|
|
186
|
+
const lowerOutput: string = output.toLowerCase();
|
|
187
|
+
|
|
188
|
+
for (const entry of OUTPUT_MARKERS) {
|
|
189
|
+
if (!lowerOutput.includes(entry.marker)) {
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const isCertain: boolean | null = ProbeNetworkFailureUtil.getCertainty(
|
|
194
|
+
entry.kind,
|
|
195
|
+
data.operation,
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
if (isCertain === null) {
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const failure: ProbeNetworkFailure = {
|
|
203
|
+
kind: entry.kind,
|
|
204
|
+
isCertain: isCertain,
|
|
205
|
+
detail: ProbeNetworkFailureUtil.getDetail(output, entry.marker),
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
if (
|
|
209
|
+
ProbeNetworkFailureUtil.isCauseAmbiguous(entry.kind, data.operation)
|
|
210
|
+
) {
|
|
211
|
+
failure.isCauseAmbiguous = true;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return failure;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/*
|
|
221
|
+
* Classifies a Node error code (err.code). `detail` is what the operator
|
|
222
|
+
* sees as the evidence; the code itself when the caller has nothing
|
|
223
|
+
* better. Anything that is not a string code (a child process's numeric
|
|
224
|
+
* exit status, undefined) is not classified.
|
|
225
|
+
*/
|
|
226
|
+
public static classifyErrorCode(data: {
|
|
227
|
+
code: unknown;
|
|
228
|
+
operation: ProbeNetworkOperation;
|
|
229
|
+
detail?: string | undefined;
|
|
230
|
+
address?: string | undefined;
|
|
231
|
+
}): ProbeNetworkFailure | null {
|
|
232
|
+
if (typeof data.code !== "string") {
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const kind: ProbeNetworkFailureKind | undefined =
|
|
237
|
+
ERROR_CODE_KINDS[data.code.toUpperCase()];
|
|
238
|
+
|
|
239
|
+
if (!kind) {
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const isCertain: boolean | null = ProbeNetworkFailureUtil.getCertainty(
|
|
244
|
+
kind,
|
|
245
|
+
data.operation,
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
if (isCertain === null) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const failure: ProbeNetworkFailure = {
|
|
253
|
+
kind: kind,
|
|
254
|
+
isCertain: isCertain,
|
|
255
|
+
detail: ProbeNetworkFailureUtil.getDetail(data.detail || data.code, ""),
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
if (data.address) {
|
|
259
|
+
failure.address = data.address;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
if (ProbeNetworkFailureUtil.isCauseAmbiguous(kind, data.operation)) {
|
|
263
|
+
failure.isCauseAmbiguous = true;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return failure;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/*
|
|
270
|
+
* Classifies a thrown value from a socket, TLS or fetch call.
|
|
271
|
+
*
|
|
272
|
+
* An AggregateError (Node's happy-eyeballs connect, one error per address
|
|
273
|
+
* tried) is probe-side only when EVERY attempt was: an IPv6 attempt that
|
|
274
|
+
* could not leave the probe next to an IPv4 attempt that timed out is an
|
|
275
|
+
* IPv4 outage, not a probe problem. It is checked before `code` because
|
|
276
|
+
* Node copies the first attempt's code onto the aggregate.
|
|
277
|
+
*
|
|
278
|
+
* Otherwise the error's own code decides, then its `cause` (fetch wraps
|
|
279
|
+
* the socket error in a TypeError "fetch failed"), and last its message.
|
|
280
|
+
*/
|
|
281
|
+
public static classifyError(data: {
|
|
282
|
+
error: unknown;
|
|
283
|
+
operation: ProbeNetworkOperation;
|
|
284
|
+
}): ProbeNetworkFailure | null {
|
|
285
|
+
return ProbeNetworkFailureUtil.classifyErrorAtDepth(
|
|
286
|
+
data.error,
|
|
287
|
+
data.operation,
|
|
288
|
+
0,
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/*
|
|
293
|
+
* Whether a failure is to be worded as an IPv6 one. In order: what the
|
|
294
|
+
* caller knows, the address the error named, the host itself. A DNS name
|
|
295
|
+
* with nothing else to go on is not assumed to be either.
|
|
296
|
+
*/
|
|
297
|
+
public static isIPv6Failure(data: {
|
|
298
|
+
host: string;
|
|
299
|
+
failure: ProbeNetworkFailure;
|
|
300
|
+
isIPv6Destination?: boolean | undefined;
|
|
301
|
+
}): boolean {
|
|
302
|
+
if (data.isIPv6Destination !== undefined) {
|
|
303
|
+
return data.isIPv6Destination;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (data.failure.address && HostAddressUtil.isIPv6(data.failure.address)) {
|
|
307
|
+
return true;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return HostAddressUtil.isIPv6(data.host || "");
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/*
|
|
314
|
+
* The failure cause, in full sentences, for a check against `host`.
|
|
315
|
+
*
|
|
316
|
+
* The IPv6 wording says outright that the host was never contacted and
|
|
317
|
+
* that this says nothing about whether it is up, because the thing being
|
|
318
|
+
* corrected is an operator (or an incident root cause, or an SMS) reading
|
|
319
|
+
* a probe's missing IPv6 as their host being down. The IPv4 wording makes
|
|
320
|
+
* no IPv6 claim at all.
|
|
321
|
+
*
|
|
322
|
+
* Every sentence opens with PROBE_SIDE_CAUSE_PREFIX; see isProbeSideCause.
|
|
323
|
+
*/
|
|
324
|
+
public static describe(data: {
|
|
325
|
+
host: string;
|
|
326
|
+
failure: ProbeNetworkFailure;
|
|
327
|
+
isIPv6Destination?: boolean | undefined;
|
|
328
|
+
}): string {
|
|
329
|
+
const host: string = data.host;
|
|
330
|
+
const detail: string = data.failure.detail;
|
|
331
|
+
|
|
332
|
+
if (ProbeNetworkFailureUtil.isIPv6Failure(data)) {
|
|
333
|
+
/*
|
|
334
|
+
* A TCP connect's EADDRNOTAVAIL: still certainly the probe, but a
|
|
335
|
+
* probe with IPv6 that has run out of local ports gets it too, so
|
|
336
|
+
* "has no usable IPv6" would be a false reason and a false remedy.
|
|
337
|
+
*/
|
|
338
|
+
if (data.failure.isCertain && data.failure.isCauseAmbiguous) {
|
|
339
|
+
return `This probe could not open an IPv6 connection from its own side (${detail}), so ${host} was never contacted. This usually means the probe has no usable IPv6 address or route (less often, that it has run out of local ports); this says nothing about whether ${host} is up. Monitor IPv6 destinations from a probe that has IPv6 connectivity.`;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (data.failure.isCertain) {
|
|
343
|
+
return `This probe cannot send IPv6 traffic (${detail}), so ${host} was never contacted. The probe has no usable IPv6 address or route; this says nothing about whether ${host} is up. Monitor IPv6 destinations from a probe that has IPv6 connectivity.`;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return `This probe could not reach ${host} over IPv6 (${detail}). Most likely this probe has no IPv6 route rather than ${host} being down. Monitor IPv6 destinations from a probe that has IPv6 connectivity.`;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (ProbeNetworkFailureUtil.isRouteFailure(data.failure.kind)) {
|
|
350
|
+
/*
|
|
351
|
+
* "No route to host" is also what a failed neighbour lookup for a
|
|
352
|
+
* dead on-link host prints, so an uncertain match must leave room for
|
|
353
|
+
* the host being the one that is down.
|
|
354
|
+
*/
|
|
355
|
+
if (!data.failure.isCertain) {
|
|
356
|
+
return `This probe may have no route to ${host} (${detail}); ${host} itself may also be down.`;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return `This probe has no route to ${host}: ${detail}.`;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return `This probe could not send traffic to ${host} (${detail}), so ${host} was never contacted. The failure is on the probe, not on ${host}.`;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/*
|
|
366
|
+
* The same cause as a lower-case clause with no trailing period, for a
|
|
367
|
+
* caller that has its own lead-in, e.g. "Traceroute could not run: " +
|
|
368
|
+
* clause + ".".
|
|
369
|
+
*/
|
|
370
|
+
public static describeClause(data: {
|
|
371
|
+
host: string;
|
|
372
|
+
failure: ProbeNetworkFailure;
|
|
373
|
+
isIPv6Destination?: boolean | undefined;
|
|
374
|
+
}): string {
|
|
375
|
+
const detail: string = data.failure.detail;
|
|
376
|
+
|
|
377
|
+
if (ProbeNetworkFailureUtil.isIPv6Failure(data)) {
|
|
378
|
+
return data.failure.isCertain
|
|
379
|
+
? `this probe cannot send IPv6 traffic (${detail})`
|
|
380
|
+
: `this probe most likely has no IPv6 route (${detail})`;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
if (ProbeNetworkFailureUtil.isRouteFailure(data.failure.kind)) {
|
|
384
|
+
return data.failure.isCertain
|
|
385
|
+
? `this probe has no route to ${data.host} (${detail})`
|
|
386
|
+
: `this probe may have no route to ${data.host} (${detail}); ${data.host} itself may also be down`;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return `this probe could not send traffic to ${data.host} (${detail})`;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/*
|
|
393
|
+
* True for a stored cause that opens the way every describe() sentence
|
|
394
|
+
* does: it is about this probe, not a verdict on the destination. Checks
|
|
395
|
+
* the text rather than classifying it, because a caller such as an SNMP
|
|
396
|
+
* send error ("send EADDRNOTAVAIL ...") carries no strerror marker.
|
|
397
|
+
*/
|
|
398
|
+
public static isProbeSideCause(text: string | null | undefined): boolean {
|
|
399
|
+
return Boolean(text && text.startsWith(PROBE_SIDE_CAUSE_PREFIX));
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// classifyOutput + describe, for a caller that only has the OS text.
|
|
403
|
+
public static describeOutput(data: {
|
|
404
|
+
host: string;
|
|
405
|
+
output: string;
|
|
406
|
+
operation: ProbeNetworkOperation;
|
|
407
|
+
isIPv6Destination?: boolean | undefined;
|
|
408
|
+
}): string | null {
|
|
409
|
+
const failure: ProbeNetworkFailure | null =
|
|
410
|
+
ProbeNetworkFailureUtil.classifyOutput({
|
|
411
|
+
output: data.output,
|
|
412
|
+
operation: data.operation,
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
if (!failure) {
|
|
416
|
+
return null;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return ProbeNetworkFailureUtil.describe({
|
|
420
|
+
host: data.host,
|
|
421
|
+
failure: failure,
|
|
422
|
+
isIPv6Destination: data.isIPv6Destination,
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// classifyError + describe, for a caller holding a thrown value.
|
|
427
|
+
public static describeError(data: {
|
|
428
|
+
host: string;
|
|
429
|
+
error: unknown;
|
|
430
|
+
operation: ProbeNetworkOperation;
|
|
431
|
+
isIPv6Destination?: boolean | undefined;
|
|
432
|
+
}): string | null {
|
|
433
|
+
const failure: ProbeNetworkFailure | null =
|
|
434
|
+
ProbeNetworkFailureUtil.classifyError({
|
|
435
|
+
error: data.error,
|
|
436
|
+
operation: data.operation,
|
|
437
|
+
});
|
|
438
|
+
|
|
439
|
+
if (!failure) {
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return ProbeNetworkFailureUtil.describe({
|
|
444
|
+
host: data.host,
|
|
445
|
+
failure: failure,
|
|
446
|
+
isIPv6Destination: data.isIPv6Destination,
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/*
|
|
451
|
+
* How sure a kind can be for an operation: true (certain), false (likely),
|
|
452
|
+
* or null (not the probe's failure at all for this operation).
|
|
453
|
+
*/
|
|
454
|
+
private static getCertainty(
|
|
455
|
+
kind: ProbeNetworkFailureKind,
|
|
456
|
+
operation: ProbeNetworkOperation,
|
|
457
|
+
): boolean | null {
|
|
458
|
+
switch (kind) {
|
|
459
|
+
case ProbeNetworkFailureKind.NoSourceAddress:
|
|
460
|
+
case ProbeNetworkFailureKind.AddressFamilyNotSupported:
|
|
461
|
+
return true;
|
|
462
|
+
case ProbeNetworkFailureKind.NetworkUnreachable:
|
|
463
|
+
return operation === ProbeNetworkOperation.PingOrTraceroute;
|
|
464
|
+
case ProbeNetworkFailureKind.NoRouteToHost:
|
|
465
|
+
/*
|
|
466
|
+
* From a TCP connect this is EHOSTUNREACH, a router or neighbour
|
|
467
|
+
* lookup giving up on the target: not the probe's failure.
|
|
468
|
+
*/
|
|
469
|
+
return operation === ProbeNetworkOperation.PingOrTraceroute
|
|
470
|
+
? false
|
|
471
|
+
: null;
|
|
472
|
+
default:
|
|
473
|
+
return null;
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
// See ProbeNetworkFailure.isCauseAmbiguous.
|
|
478
|
+
private static isCauseAmbiguous(
|
|
479
|
+
kind: ProbeNetworkFailureKind,
|
|
480
|
+
operation: ProbeNetworkOperation,
|
|
481
|
+
): boolean {
|
|
482
|
+
return (
|
|
483
|
+
kind === ProbeNetworkFailureKind.NoSourceAddress &&
|
|
484
|
+
operation === ProbeNetworkOperation.TcpConnect
|
|
485
|
+
);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// The kinds where "no route" is the honest summary rather than "could not send".
|
|
489
|
+
private static isRouteFailure(kind: ProbeNetworkFailureKind): boolean {
|
|
490
|
+
return (
|
|
491
|
+
kind === ProbeNetworkFailureKind.NetworkUnreachable ||
|
|
492
|
+
kind === ProbeNetworkFailureKind.NoRouteToHost
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/*
|
|
497
|
+
* The line of the text that carries the marker (the whole text when there
|
|
498
|
+
* is no marker), trimmed, without a trailing period so it can be quoted
|
|
499
|
+
* mid-sentence, and capped. ping's output mixes a banner and statistics in
|
|
500
|
+
* with the one line that matters.
|
|
501
|
+
*/
|
|
502
|
+
private static getDetail(text: string, marker: string): string {
|
|
503
|
+
const lines: Array<string> = (text || "")
|
|
504
|
+
.split(/\r?\n/)
|
|
505
|
+
.map((line: string) => {
|
|
506
|
+
return line.trim();
|
|
507
|
+
})
|
|
508
|
+
.filter((line: string) => {
|
|
509
|
+
return line.length > 0;
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
const line: string =
|
|
513
|
+
(marker
|
|
514
|
+
? lines.find((candidate: string) => {
|
|
515
|
+
return candidate.toLowerCase().includes(marker);
|
|
516
|
+
})
|
|
517
|
+
: undefined) ||
|
|
518
|
+
lines[0] ||
|
|
519
|
+
"";
|
|
520
|
+
|
|
521
|
+
return line.replace(/\.+$/, "").substring(0, MAX_DETAIL_LENGTH);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
private static classifyErrorAtDepth(
|
|
525
|
+
error: unknown,
|
|
526
|
+
operation: ProbeNetworkOperation,
|
|
527
|
+
depth: number,
|
|
528
|
+
): ProbeNetworkFailure | null {
|
|
529
|
+
if (!error || typeof error !== "object" || depth > MAX_CAUSE_DEPTH) {
|
|
530
|
+
return null;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
const errorLike: ErrorLike = error as ErrorLike;
|
|
534
|
+
|
|
535
|
+
if (Array.isArray(errorLike.errors) && errorLike.errors.length > 0) {
|
|
536
|
+
const failures: Array<ProbeNetworkFailure | null> = errorLike.errors.map(
|
|
537
|
+
(inner: unknown) => {
|
|
538
|
+
return ProbeNetworkFailureUtil.classifyErrorAtDepth(
|
|
539
|
+
inner,
|
|
540
|
+
operation,
|
|
541
|
+
depth + 1,
|
|
542
|
+
);
|
|
543
|
+
},
|
|
544
|
+
);
|
|
545
|
+
|
|
546
|
+
if (
|
|
547
|
+
failures.some((failure: ProbeNetworkFailure | null) => {
|
|
548
|
+
return failure === null;
|
|
549
|
+
})
|
|
550
|
+
) {
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
// The least certain one: the wording must not claim more than every attempt showed.
|
|
555
|
+
const classified: Array<ProbeNetworkFailure> =
|
|
556
|
+
failures as Array<ProbeNetworkFailure>;
|
|
557
|
+
const representative: ProbeNetworkFailure | undefined =
|
|
558
|
+
classified.find((failure: ProbeNetworkFailure) => {
|
|
559
|
+
return !failure.isCertain;
|
|
560
|
+
}) || classified[0];
|
|
561
|
+
|
|
562
|
+
if (!representative) {
|
|
563
|
+
return null;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/*
|
|
567
|
+
* Its address is what a caller words the family from, so it is kept
|
|
568
|
+
* only when every attempt named an address of that same family. A
|
|
569
|
+
* dual-stack name whose IPv4 attempt failed as well is not an IPv6
|
|
570
|
+
* problem: a mixed-family aggregate names no address, and the caller
|
|
571
|
+
* falls back to the host it was checking.
|
|
572
|
+
*/
|
|
573
|
+
if (
|
|
574
|
+
!ProbeNetworkFailureUtil.isSingleFamily(
|
|
575
|
+
classified,
|
|
576
|
+
representative.address,
|
|
577
|
+
)
|
|
578
|
+
) {
|
|
579
|
+
const withoutAddress: ProbeNetworkFailure = { ...representative };
|
|
580
|
+
delete withoutAddress.address;
|
|
581
|
+
|
|
582
|
+
return withoutAddress;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
return representative;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
/*
|
|
589
|
+
* A cause that carries its own code or attempts is the more specific
|
|
590
|
+
* account, and it decides - even when it says "not the probe". A wrapper
|
|
591
|
+
* such as an AxiosError copies its cause's code onto itself, and for an
|
|
592
|
+
* aggregate that is only the FIRST attempt's code.
|
|
593
|
+
*/
|
|
594
|
+
if (ProbeNetworkFailureUtil.carriesSocketError(errorLike.cause)) {
|
|
595
|
+
return ProbeNetworkFailureUtil.classifyErrorAtDepth(
|
|
596
|
+
errorLike.cause,
|
|
597
|
+
operation,
|
|
598
|
+
depth + 1,
|
|
599
|
+
);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
const message: string =
|
|
603
|
+
typeof errorLike.message === "string" ? errorLike.message : "";
|
|
604
|
+
|
|
605
|
+
if (typeof errorLike.code === "string") {
|
|
606
|
+
return ProbeNetworkFailureUtil.classifyErrorCode({
|
|
607
|
+
code: errorLike.code,
|
|
608
|
+
operation: operation,
|
|
609
|
+
detail: message || undefined,
|
|
610
|
+
address:
|
|
611
|
+
typeof errorLike.address === "string"
|
|
612
|
+
? HostAddressUtil.stripBrackets(errorLike.address)
|
|
613
|
+
: undefined,
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
if (errorLike.cause) {
|
|
618
|
+
const fromCause: ProbeNetworkFailure | null =
|
|
619
|
+
ProbeNetworkFailureUtil.classifyErrorAtDepth(
|
|
620
|
+
errorLike.cause,
|
|
621
|
+
operation,
|
|
622
|
+
depth + 1,
|
|
623
|
+
);
|
|
624
|
+
|
|
625
|
+
if (fromCause) {
|
|
626
|
+
return fromCause;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
return message
|
|
631
|
+
? ProbeNetworkFailureUtil.classifyOutput({
|
|
632
|
+
output: message,
|
|
633
|
+
operation: operation,
|
|
634
|
+
})
|
|
635
|
+
: null;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/*
|
|
639
|
+
* True when every attempt named an address in the same family as
|
|
640
|
+
* `address`. An attempt with no address could have been either family.
|
|
641
|
+
*/
|
|
642
|
+
private static isSingleFamily(
|
|
643
|
+
attempts: Array<ProbeNetworkFailure>,
|
|
644
|
+
address: string | undefined,
|
|
645
|
+
): boolean {
|
|
646
|
+
if (!address) {
|
|
647
|
+
return true;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
const isIPv6: boolean = HostAddressUtil.isIPv6(address);
|
|
651
|
+
|
|
652
|
+
return attempts.every((attempt: ProbeNetworkFailure) => {
|
|
653
|
+
return (
|
|
654
|
+
Boolean(attempt.address) &&
|
|
655
|
+
HostAddressUtil.isIPv6(attempt.address || "") === isIPv6
|
|
656
|
+
);
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
// True for a value that has a string code or a list of attempts to go on.
|
|
661
|
+
private static carriesSocketError(value: unknown): boolean {
|
|
662
|
+
if (!value || typeof value !== "object") {
|
|
663
|
+
return false;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
const errorLike: ErrorLike = value as ErrorLike;
|
|
667
|
+
|
|
668
|
+
return (
|
|
669
|
+
typeof errorLike.code === "string" ||
|
|
670
|
+
(Array.isArray(errorLike.errors) && errorLike.errors.length > 0)
|
|
671
|
+
);
|
|
672
|
+
}
|
|
673
|
+
}
|