@oneuptime/common 12.0.8 → 12.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.ts +1 -1
- package/Models/AnalyticsModels/MetricItemAggMV1mByService.ts +1 -1
- package/Models/DatabaseModels/AIConversation.ts +32 -0
- package/Models/DatabaseModels/AIConversationMessage.ts +41 -0
- package/Models/DatabaseModels/AlertEpisodeMember.ts +27 -0
- package/Models/DatabaseModels/IncidentEpisodeMember.ts +28 -0
- package/Models/DatabaseModels/Index.ts +12 -4
- package/Models/DatabaseModels/{TelemetryEntity.ts → InventoryItem.ts} +139 -9
- package/Models/DatabaseModels/InventoryItemCustomField.ts +434 -0
- package/Models/DatabaseModels/{TelemetryEntityRelationship.ts → InventoryItemRelationship.ts} +8 -8
- package/Models/DatabaseModels/NetworkDevice.ts +141 -0
- package/Models/DatabaseModels/NetworkDeviceLink.ts +699 -0
- package/Models/DatabaseModels/NetworkDeviceLinkRule.ts +467 -0
- package/Models/DatabaseModels/NetworkTopologySuppression.ts +429 -0
- package/Models/DatabaseModels/OnCallDutyPolicyFeed.ts +9 -0
- package/Models/DatabaseModels/Project.ts +78 -0
- package/Models/DatabaseModels/UserCall.ts +42 -0
- package/Models/DatabaseModels/UserEmail.ts +44 -0
- package/Models/DatabaseModels/UserNotificationRule.ts +425 -55
- package/Models/DatabaseModels/UserOnCallLogTimeline.ts +24 -2
- package/Models/DatabaseModels/UserPush.ts +49 -0
- package/Models/DatabaseModels/UserSMS.ts +43 -0
- package/Models/DatabaseModels/UserTelegram.ts +59 -0
- package/Models/DatabaseModels/UserWebhook.ts +52 -0
- package/Models/DatabaseModels/UserWhatsApp.ts +41 -0
- package/Models/DatabaseModels/WorkflowVariable.ts +12 -0
- package/Server/API/AIChatAPI.ts +315 -1
- package/Server/API/DashboardAPI.ts +217 -1
- package/Server/API/OnCallReadinessAPI.ts +841 -0
- package/Server/API/TeamComplianceAPI.ts +69 -17
- package/Server/API/TelemetryAPI.ts +220 -12
- package/Server/EnvironmentConfig.ts +52 -0
- package/Server/Infrastructure/Postgres/DataSourceOptions.ts +22 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.ts +4 -4
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786200000000-RestoreDroppedUniqueIndexes.ts +5 -5
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.ts +35 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.ts +82 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.ts +91 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.ts +255 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.ts +107 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.ts +90 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.ts +39 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.ts +59 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +20 -0
- package/Server/Infrastructure/Queue.ts +78 -13
- package/Server/Middleware/PublicDashboardRateLimit.ts +593 -0
- package/Server/Services/AIService.ts +7 -0
- package/Server/Services/AlertEpisodeStateTimelineService.ts +29 -0
- package/Server/Services/AlertSeverityService.ts +63 -0
- package/Server/Services/DashboardService.ts +9 -10
- package/Server/Services/DatabaseService.ts +32 -2
- package/Server/Services/IncidentEpisodeStateTimelineService.ts +29 -0
- package/Server/Services/IncidentSeverityService.ts +76 -0
- package/Server/Services/Index.ts +12 -4
- package/Server/Services/InventoryItemCustomFieldService.ts +9 -0
- package/Server/Services/{TelemetryEntityRelationshipService.ts → InventoryItemRelationshipService.ts} +4 -4
- package/Server/Services/{TelemetryEntityService.ts → InventoryItemService.ts} +89 -20
- package/Server/Services/LogAggregationService.ts +45 -8
- package/Server/Services/MetricAggregationService.ts +121 -0
- package/Server/Services/MetricService.ts +7 -7
- package/Server/Services/NetworkDeviceLinkRuleService.ts +10 -0
- package/Server/Services/NetworkDeviceLinkService.ts +84 -0
- package/Server/Services/NetworkDeviceService.ts +140 -0
- package/Server/Services/NetworkSiteService.ts +77 -25
- package/Server/Services/NetworkTopologySuppressionService.ts +84 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +41 -29
- package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +8 -0
- package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +62 -13
- package/Server/Services/OnCallDutyPolicyScheduleService.ts +61 -1
- package/Server/Services/OnCallNotificationAlertingService.ts +742 -0
- package/Server/Services/OnCallReadinessService.ts +2803 -0
- package/Server/Services/OnCallSetupReminderService.ts +955 -0
- package/Server/Services/ProfileAggregationService.ts +123 -0
- package/Server/Services/StatusPageService.ts +9 -10
- package/Server/Services/TeamComplianceService.ts +429 -252
- package/Server/Services/UserCallService.ts +26 -1
- package/Server/Services/UserEmailService.ts +26 -1
- package/Server/Services/UserNotificationRuleAdminService.ts +1183 -0
- package/Server/Services/UserNotificationRuleService.ts +3812 -333
- package/Server/Services/UserOnCallLogService.ts +561 -48
- package/Server/Services/UserPushService.ts +29 -0
- package/Server/Services/UserService.ts +11 -0
- package/Server/Services/UserSmsService.ts +26 -1
- package/Server/Services/UserTelegramService.ts +24 -1
- package/Server/Services/UserWebhookService.ts +28 -1
- package/Server/Services/UserWhatsAppService.ts +24 -1
- package/Server/Types/Database/Permissions/BasePermission.ts +19 -0
- package/Server/Types/Database/Permissions/CreatePermission.ts +164 -0
- package/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.ts +340 -0
- package/Server/Types/Database/Permissions/QueryPermission.ts +48 -0
- package/Server/Types/Database/Permissions/TenantPermission.ts +8 -1
- package/Server/Types/Workflow/Components/API/Delete.ts +1 -1
- package/Server/Types/Workflow/Components/API/Get.ts +1 -1
- package/Server/Types/Workflow/Components/API/Patch.ts +1 -1
- package/Server/Types/Workflow/Components/API/Post.ts +1 -1
- package/Server/Types/Workflow/Components/API/Put.ts +1 -1
- package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +29 -5
- package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +18 -10
- package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +55 -0
- package/Server/Types/Workflow/Components/Conditions/IfElse.ts +3 -17
- package/Server/Types/Workflow/Components/Email.ts +25 -7
- package/Server/Types/Workflow/Components/JavaScript.ts +10 -3
- package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +1 -1
- package/Server/Utils/AI/Chat/ChatAgentRunner.ts +643 -48
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +32 -3
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +20 -6
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +7 -0
- package/Server/Utils/AI/Toolbox/AIActionTools.ts +2 -2
- package/Server/Utils/AI/Toolbox/AIMetaTools.ts +863 -0
- package/Server/Utils/AI/Toolbox/AlertTools.ts +177 -15
- package/Server/Utils/AI/Toolbox/IncidentTools.ts +191 -10
- package/Server/Utils/AI/Toolbox/Index.ts +48 -0
- package/Server/Utils/AI/Toolbox/MonitorTools.ts +298 -11
- package/Server/Utils/AI/Toolbox/NoteWriteTools.ts +295 -0
- package/Server/Utils/AI/Toolbox/OnCallTools.ts +1246 -0
- package/Server/Utils/AI/Toolbox/RunbookTools.ts +424 -0
- package/Server/Utils/AI/Toolbox/SloTools.ts +456 -0
- package/Server/Utils/AI/Toolbox/StatusPageTools.ts +559 -0
- package/Server/Utils/AI/Toolbox/TeamTools.ts +327 -0
- package/Server/Utils/AI/Toolbox/TimelineTools.ts +615 -0
- package/Server/Utils/AI/Toolbox/WorkflowProbeTools.ts +664 -0
- package/Server/Utils/ClientIp.ts +221 -0
- package/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.ts +47 -0
- package/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.ts +163 -0
- package/Server/Utils/Dashboard/PublicDashboardSloWidget.ts +147 -0
- package/Server/Utils/Express.ts +12 -17
- package/Server/Utils/LLM/LLMService.ts +85 -8
- package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +204 -10
- package/Server/Utils/SSRFProtection.ts +98 -23
- package/Server/Utils/StartServer.ts +12 -3
- package/Server/Utils/Telemetry/EntityRegistry.ts +205 -18
- package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +25 -25
- package/Server/Utils/Telemetry/TelemetryEntity.ts +160 -52
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +7 -3
- package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +2146 -0
- package/Tests/App/Dashboard/CreateWorkflowModal.test.tsx +561 -0
- package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +2470 -0
- package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +1897 -0
- package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +3606 -0
- package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +784 -0
- package/Tests/App/Dashboard/OnCallRulesTable.test.tsx +1119 -0
- package/Tests/App/Dashboard/SloWidgetFetching.test.tsx +531 -0
- package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +1312 -0
- package/Tests/App/Dashboard/UserSettingsSetupChecklistPage.test.tsx +1390 -0
- package/Tests/Models/InventoryItemModel.test.ts +174 -0
- package/Tests/Models/InventoryItemNaming.test.ts +302 -0
- package/Tests/Server/API/AIChatCancelAndFeedback.test.ts +437 -0
- package/Tests/Server/API/DashboardPublicRateLimit.test.ts +659 -0
- package/Tests/Server/API/DashboardPublicResourceListAPI.test.ts +18 -0
- package/Tests/Server/API/DashboardPublicSloAPI.test.ts +880 -0
- package/Tests/Server/API/Helpers.ts +24 -15
- package/Tests/Server/API/OnCallReadinessAPI.test.ts +2680 -0
- package/Tests/Server/API/OnCallSetupReminderAPI.test.ts +915 -0
- package/Tests/Server/Infrastructure/Postgres/EpisodeMemberNotifyIndexesMigration.test.ts +533 -0
- package/Tests/Server/Infrastructure/Postgres/InventoryItemArchiveMigration.test.ts +213 -0
- package/Tests/Server/Infrastructure/Postgres/RenameInventoryItemMigration.test.ts +432 -0
- package/Tests/Server/Infrastructure/Queue.test.ts +293 -0
- package/Tests/Server/Middleware/PublicDashboardRateLimit.test.ts +1645 -0
- package/Tests/Server/Services/AdminRuleEditGuards.test.ts +2848 -0
- package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +1393 -0
- package/Tests/Server/Services/EpisodeRuleSeverityRepair.test.ts +1802 -0
- package/Tests/Server/Services/EpisodeStateTimelineNote.test.ts +304 -0
- package/Tests/Server/Services/InventoryItemDisplayName.test.ts +339 -0
- package/Tests/Server/Services/{TelemetryEntityManualCreate.test.ts → InventoryItemManualCreate.test.ts} +27 -27
- package/Tests/Server/Services/IpAllowlistSpoofing.test.ts +450 -0
- package/Tests/Server/Services/LogAggregationService.test.ts +235 -1
- package/Tests/Server/Services/MetricAggregationService.test.ts +231 -0
- package/Tests/Server/Services/MetricEntityMVKeyParity.test.ts +80 -29
- package/Tests/Server/Services/MetricServiceAggregate.test.ts +30 -30
- package/Tests/Server/Services/NetworkSiteService.test.ts +18 -3
- package/Tests/Server/Services/NotificationChannelEventCoverage.test.ts +1728 -0
- package/Tests/Server/Services/NotificationDeletionImpact.test.ts +2402 -0
- package/Tests/Server/Services/OnCallDutyPolicyExecutionLogTimelineGapFeed.test.ts +394 -0
- package/Tests/Server/Services/OnCallNotificationFallback.test.ts +1744 -0
- package/Tests/Server/Services/OnCallReadinessService.test.ts +4295 -0
- package/Tests/Server/Services/OnCallSetupReminder.test.ts +1272 -0
- package/Tests/Server/Services/OnCallWeeklyReadinessDigest.test.ts +1021 -0
- package/Tests/Server/Services/ProfileAggregationService.test.ts +296 -0
- package/Tests/Server/Services/SeverityCreationRuleBackfill.test.ts +1536 -0
- package/Tests/Server/Services/SeverityRuleBackfill.test.ts +1818 -0
- package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +1845 -0
- package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +1394 -0
- package/Tests/Server/Services/UserNotificationRuleDefaultCreation.test.ts +1166 -0
- package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +1468 -0
- package/Tests/Server/Services/UserOnCallLogNoNotificationRules.test.ts +1457 -0
- package/Tests/Server/Types/Database/Permissions/AdminNotificationRuleAccess.test.ts +1546 -0
- package/Tests/Server/Types/Database/Permissions/CreateOwnershipScoping.test.ts +529 -0
- package/Tests/Server/Types/Database/Permissions/OwnerOnlyColumns.test.ts +1219 -0
- package/Tests/Server/Types/Database/Permissions/UserNotificationRuleScoping.test.ts +1089 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +2 -1
- package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +190 -0
- package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +44 -14
- package/Tests/Server/Types/Workflow/Components/Email.test.ts +151 -0
- package/Tests/Server/Types/Workflow/Components/IfElse.test.ts +98 -0
- package/Tests/Server/Types/Workflow/Components/JavaScript.test.ts +51 -0
- package/Tests/Server/Utils/AI/AIMetaTools.test.ts +586 -0
- package/Tests/Server/Utils/AI/AlertMonitorFilters.test.ts +582 -0
- package/Tests/Server/Utils/AI/ChatAgentRunner.test.ts +726 -0
- package/Tests/Server/Utils/AI/IncidentToolsFilters.test.ts +315 -0
- package/Tests/Server/Utils/AI/LLMServiceStopReason.test.ts +314 -0
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +26 -3
- package/Tests/Server/Utils/AI/NoteWriteTools.test.ts +268 -0
- package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +169 -0
- package/Tests/Server/Utils/AI/OnCallTools.test.ts +664 -0
- package/Tests/Server/Utils/AI/RunbookTools.test.ts +325 -0
- package/Tests/Server/Utils/AI/SloTools.test.ts +306 -0
- package/Tests/Server/Utils/AI/StatusPageTools.test.ts +391 -0
- package/Tests/Server/Utils/AI/TeamTools.test.ts +257 -0
- package/Tests/Server/Utils/AI/TimelineTools.test.ts +472 -0
- package/Tests/Server/Utils/AI/WorkflowProbeTools.test.ts +428 -0
- package/Tests/Server/Utils/ClientIp.test.ts +438 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +171 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.test.ts +383 -0
- package/Tests/Server/Utils/EntityRegistryRowFence.test.ts +23 -25
- package/Tests/Server/Utils/MicrosoftTeamsWebhookUrlValidation.test.ts +6 -0
- package/Tests/Server/Utils/Monitor/Criteria/DnssecMonitorCriteria.test.ts +307 -0
- package/Tests/Server/Utils/Monitor/Criteria/SSLMonitorCriteria.test.ts +468 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorTelemetryDeepLinks.test.ts +460 -0
- package/Tests/Server/Utils/ResponseRateLimitStatusCodes.test.ts +137 -0
- package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +40 -8
- package/Tests/Server/Utils/SSRFProtectionUserInfo.test.ts +351 -0
- package/Tests/Server/Utils/Telemetry/EntityRegistryRetirement.test.ts +531 -0
- package/Tests/Server/Utils/Telemetry/InventoryEntityRegistry.test.ts +15 -15
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +356 -39
- package/Tests/Types/IP/IP.test.ts +263 -0
- package/Tests/Types/IP/IPWhitelist.test.ts +197 -0
- package/Tests/Types/IP/IPv6.test.ts +12 -1
- package/Tests/Types/Monitor/SnmpOid.test.ts +64 -0
- package/Tests/Types/NetworkDevice/NetworkDeviceMonitoringMethod.test.ts +110 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeAudit.test.ts +106 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilMergeDifferential.test.ts +511 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageEndToEnd.test.ts +489 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageGapTolerance.test.ts +479 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleCoverageState.test.ts +822 -0
- package/Tests/Types/Telemetry/EntityTypeGroups.test.ts +6 -6
- package/Tests/Types/Workflow/BaseModelComponents.test.ts +429 -0
- package/Tests/Types/Workflow/Components/BaseModel.test.ts +225 -0
- package/Tests/Types/Workflow/IntegrationCredentialMetadata.test.ts +100 -0
- package/Tests/Types/Workflow/TemplateSyntax.test.ts +112 -0
- package/Tests/Types/Workflow/Templates.test.ts +916 -101
- package/Tests/UI/Components/ActiveFilterChipsOpenRoute.test.tsx +82 -0
- package/Tests/UI/Components/ComponentsModal.test.tsx +564 -7
- package/Tests/UI/Components/KeyboardShortcut.test.tsx +95 -0
- package/Tests/UI/Components/LogDetailsPanelCrossSignal.test.tsx +448 -0
- package/Tests/UI/Components/LogsTableCrossLinks.test.tsx +263 -0
- package/Tests/UI/Components/PendingProjectInvitations.test.tsx +913 -0
- package/Tests/UI/Components/SimpleLogViewer.test.tsx +228 -0
- package/Tests/UI/Components/TableRowSelectability.test.tsx +312 -0
- package/Tests/UI/Components/Workflow/GraphLint.test.ts +72 -0
- package/Tests/UI/Components/Workflow/GraphLintSummary.test.ts +755 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditor.test.ts +242 -7
- package/Tests/UI/Components/Workflow/ModelColumnEditorServerContract.test.ts +15 -7
- package/Tests/UI/Components/Workflow/ModelSchema.test.ts +242 -28
- package/Tests/UI/Components/Workflow/RunStatusWatcher.test.ts +59 -1
- package/Tests/UI/Components/Workflow/StepTraceViewer.test.tsx +256 -0
- package/Tests/UI/Components/Workflow/UseRunWatch.test.tsx +665 -0
- package/Tests/UI/Components/Workflow/WorkflowIssuesModal.test.tsx +485 -0
- package/Tests/UI/Components/Workflow/WorkflowLogModal.test.tsx +478 -0
- package/Tests/UI/Components/Workflow/WorkflowStatusBar.test.tsx +379 -0
- package/Tests/UI/EsbuildConfig.test.ts +607 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +5 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +11 -4
- package/Tests/UI/Utils/ModelAPICreateMiscData.test.ts +94 -0
- package/Tests/UI/Utils/Platform.test.ts +147 -0
- package/Tests/UI/Utils/ProjectInvitationDisplay.test.ts +357 -0
- package/Tests/Utils/Monitor/NetworkDeviceLinkRuleUtil.test.ts +198 -0
- package/Tests/Utils/Monitor/NetworkTopologyUtil.test.ts +487 -0
- package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +698 -0
- package/Tests/__mocks__/bullmq.js +55 -0
- package/Types/AI/AIChatMessageStatus.ts +8 -1
- package/Types/AI/AIChatTypes.ts +12 -0
- package/Types/Database/AccessControl/OwnerOnlyColumn.ts +88 -0
- package/Types/Exception/ExceptionCode.ts +2 -0
- package/Types/Exception/ServiceUnavailableException.ts +8 -0
- package/Types/Exception/TooManyRequestsException.ts +8 -0
- package/Types/IP/IP.ts +93 -47
- package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +49 -3
- package/Types/NetworkDevice/NetworkDeviceMonitoringMethod.ts +55 -0
- package/Types/OnCallDutyPolicy/Layer.ts +203 -149
- package/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.ts +13 -0
- package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +155 -10
- package/Types/Permission.ts +193 -0
- package/Types/Telemetry/EntityRelationshipType.ts +1 -1
- package/Types/Telemetry/EntitySource.ts +1 -1
- package/Types/Telemetry/EntityType.ts +1 -1
- package/Types/Telemetry/EntityTypeGroups.ts +1 -1
- package/Types/Workflow/Components/BaseModel.ts +75 -29
- package/Types/Workflow/Components/Discord.ts +1 -0
- package/Types/Workflow/Components/Email.ts +12 -3
- package/Types/Workflow/Components/JavaScript.ts +7 -0
- package/Types/Workflow/Components/MicrosoftTeams.ts +3 -2
- package/Types/Workflow/Components/Slack.ts +1 -0
- package/Types/Workflow/Components/Telegram.ts +1 -0
- package/Types/Workflow/TemplateSyntax.ts +44 -0
- package/Types/Workflow/Templates.ts +2097 -45
- package/UI/Components/Calendar/Calendar.css +43 -0
- package/UI/Components/Calendar/Calendar.tsx +8 -0
- package/UI/Components/Card/Card.tsx +2 -2
- package/UI/Components/Checkbox/Checkbox.tsx +16 -0
- package/UI/Components/Dictionary/Dictionary.tsx +48 -9
- package/UI/Components/FormModal/BasicFormModal.tsx +2 -1
- package/UI/Components/Header/HeaderIconDropdownButton.tsx +53 -3
- package/UI/Components/Input/Input.tsx +1 -0
- package/UI/Components/KeyboardShortcut/KeyboardKey.ts +185 -0
- package/UI/Components/KeyboardShortcut/KeyboardShortcut.tsx +87 -0
- package/UI/Components/LogsViewer/LogsViewer.tsx +28 -0
- package/UI/Components/LogsViewer/components/ActiveFilterChips.tsx +31 -0
- package/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.tsx +18 -18
- package/UI/Components/LogsViewer/components/LogDetailsPanel.tsx +363 -14
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +11 -0
- package/UI/Components/LogsViewer/components/LogsTable.tsx +155 -12
- package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +29 -0
- package/UI/Components/LogsViewer/types.ts +23 -0
- package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +9 -2
- package/UI/Components/Navbar/NavBarMenuModal.tsx +15 -30
- package/UI/Components/ProjectInvitations/PendingProjectInvitations.tsx +442 -0
- package/UI/Components/SimpleLogViewer/SimpleLogViewer.tsx +23 -1
- package/UI/Components/Table/Table.tsx +49 -16
- package/UI/Components/Table/TableBody.tsx +53 -28
- package/UI/Components/Table/TableHeader.tsx +13 -0
- package/UI/Components/Table/TableRow.tsx +58 -26
- package/UI/Components/Workflow/ArgumentsForm.tsx +155 -9
- package/UI/Components/Workflow/ComponentReturnValueViewer.tsx +26 -0
- package/UI/Components/Workflow/ComponentSettingsModal.tsx +10 -1
- package/UI/Components/Workflow/ComponentValuePickerModal.tsx +135 -7
- package/UI/Components/Workflow/ComponentsModal.tsx +116 -22
- package/UI/Components/Workflow/DocumentationViewer.tsx +59 -9
- package/UI/Components/Workflow/GraphLint.ts +42 -5
- package/UI/Components/Workflow/GraphLintSummary.ts +390 -0
- package/UI/Components/Workflow/ModelColumnEditor.tsx +154 -22
- package/UI/Components/Workflow/ModelSchema.ts +115 -33
- package/UI/Components/Workflow/RunStatusWatcher.ts +1 -1
- package/UI/Components/Workflow/StepTraceViewer.tsx +1 -1
- package/UI/Components/Workflow/UseRunWatch.ts +212 -0
- package/UI/Components/Workflow/VariableModal.tsx +6 -2
- package/UI/Components/Workflow/Workflow.tsx +49 -3
- package/UI/Components/Workflow/WorkflowIssuesModal.tsx +255 -0
- package/UI/Components/Workflow/WorkflowLogModal.tsx +128 -0
- package/UI/Components/Workflow/WorkflowStatusBar.tsx +224 -0
- package/UI/Utils/AIChatExport/ConversationMarkdown.ts +10 -0
- package/UI/Utils/ModelAPI/ModelAPI.ts +7 -1
- package/UI/Utils/Platform.ts +149 -0
- package/UI/Utils/ProjectInvitationDisplay.ts +118 -0
- package/UI/esbuild-config.js +22 -1
- package/Utils/Monitor/NetworkDeviceLinkRuleUtil.ts +187 -0
- package/Utils/Monitor/NetworkTopologyUtil.ts +888 -164
- package/Utils/Telemetry/CrossSignalScope.ts +502 -0
- package/Utils/Telemetry/EntityKey.ts +5 -5
- package/Utils/Telemetry/EntityRelationship.ts +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByK8sCluster.js +1 -1
- package/build/dist/Models/AnalyticsModels/MetricItemAggMV1mByService.js +1 -1
- package/build/dist/Models/DatabaseModels/AIConversation.js +32 -0
- package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AIConversationMessage.js +42 -0
- package/build/dist/Models/DatabaseModels/AIConversationMessage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js +28 -0
- package/build/dist/Models/DatabaseModels/AlertEpisodeMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js +29 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeMember.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +12 -4
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/{TelemetryEntity.js → InventoryItem.js} +167 -31
- package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -0
- package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js +454 -0
- package/build/dist/Models/DatabaseModels/InventoryItemCustomField.js.map +1 -0
- package/build/dist/Models/DatabaseModels/{TelemetryEntityRelationship.js → InventoryItemRelationship.js} +27 -27
- package/build/dist/Models/DatabaseModels/InventoryItemRelationship.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +141 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js +719 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js +475 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceLinkRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkTopologySuppression.js +446 -0
- package/build/dist/Models/DatabaseModels/NetworkTopologySuppression.js.map +1 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js +9 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyFeed.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +80 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserCall.js +46 -2
- package/build/dist/Models/DatabaseModels/UserCall.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserEmail.js +48 -2
- package/build/dist/Models/DatabaseModels/UserEmail.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationRule.js +424 -55
- package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +24 -2
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserPush.js +51 -1
- package/build/dist/Models/DatabaseModels/UserPush.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserSMS.js +47 -2
- package/build/dist/Models/DatabaseModels/UserSMS.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserTelegram.js +65 -3
- package/build/dist/Models/DatabaseModels/UserTelegram.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWebhook.js +56 -2
- package/build/dist/Models/DatabaseModels/UserWebhook.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js +45 -2
- package/build/dist/Models/DatabaseModels/UserWhatsApp.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js +12 -0
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +237 -1
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardAPI.js +165 -13
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/OnCallReadinessAPI.js +599 -0
- package/build/dist/Server/API/OnCallReadinessAPI.js.map +1 -0
- package/build/dist/Server/API/TeamComplianceAPI.js +68 -9
- package/build/dist/Server/API/TeamComplianceAPI.js.map +1 -1
- package/build/dist/Server/API/TelemetryAPI.js +129 -18
- package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +45 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/DataSourceOptions.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786100000000-RestoreServiceLowerNameIndex.js +4 -4
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786625176831-AddMonitoringMethodToNetworkDevice.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.js +39 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786634985763-AddNetworkDeviceLink.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.js +38 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639512056-AddNetworkDeviceLinkRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.js +22 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786639972982-AddNetworkTopologySuppression.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.js +150 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786800000000-RenameTelemetryEntityToInventoryItem.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.js +57 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786900000000-AddInventoryItemArchiveAndCustomFields.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.js +69 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787000000000-AddOnCallNotificationFallbackColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.js +32 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787100000000-AddAIConversationPageContext.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787200000000-AddAIChatMessageFeedback.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.js +48 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787300000000-AddEpisodeMemberNotifyIndexes.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Queue.js +72 -13
- package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
- package/build/dist/Server/Middleware/PublicDashboardRateLimit.js +399 -0
- package/build/dist/Server/Middleware/PublicDashboardRateLimit.js.map +1 -0
- package/build/dist/Server/Services/AIService.js +1 -0
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js +24 -3
- package/build/dist/Server/Services/AlertEpisodeStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/AlertSeverityService.js +54 -0
- package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
- package/build/dist/Server/Services/DashboardService.js +10 -9
- package/build/dist/Server/Services/DashboardService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +24 -2
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +24 -3
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentSeverityService.js +67 -0
- package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +12 -4
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemCustomFieldService.js +9 -0
- package/build/dist/Server/Services/InventoryItemCustomFieldService.js.map +1 -0
- package/build/dist/Server/Services/{TelemetryEntityRelationshipService.js → InventoryItemRelationshipService.js} +6 -6
- package/build/dist/Server/Services/InventoryItemRelationshipService.js.map +1 -0
- package/build/dist/Server/Services/{TelemetryEntityService.js → InventoryItemService.js} +68 -23
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -0
- package/build/dist/Server/Services/LogAggregationService.js +27 -8
- package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricAggregationService.js +80 -0
- package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
- package/build/dist/Server/Services/MetricService.js +6 -6
- package/build/dist/Server/Services/MetricService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceLinkRuleService.js +9 -0
- package/build/dist/Server/Services/NetworkDeviceLinkRuleService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceLinkService.js +71 -0
- package/build/dist/Server/Services/NetworkDeviceLinkService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceService.js +113 -0
- package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
- package/build/dist/Server/Services/NetworkSiteService.js +53 -13
- package/build/dist/Server/Services/NetworkSiteService.js.map +1 -1
- package/build/dist/Server/Services/NetworkTopologySuppressionService.js +85 -0
- package/build/dist/Server/Services/NetworkTopologySuppressionService.js.map +1 -0
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +48 -32
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +8 -0
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +51 -12
- package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +57 -13
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallNotificationAlertingService.js +548 -0
- package/build/dist/Server/Services/OnCallNotificationAlertingService.js.map +1 -0
- package/build/dist/Server/Services/OnCallReadinessService.js +1961 -0
- package/build/dist/Server/Services/OnCallReadinessService.js.map +1 -0
- package/build/dist/Server/Services/OnCallSetupReminderService.js +738 -0
- package/build/dist/Server/Services/OnCallSetupReminderService.js.map +1 -0
- package/build/dist/Server/Services/ProfileAggregationService.js +68 -4
- package/build/dist/Server/Services/ProfileAggregationService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +11 -10
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TeamComplianceService.js +312 -160
- package/build/dist/Server/Services/TeamComplianceService.js.map +1 -1
- package/build/dist/Server/Services/UserCallService.js +24 -1
- package/build/dist/Server/Services/UserCallService.js.map +1 -1
- package/build/dist/Server/Services/UserEmailService.js +24 -1
- package/build/dist/Server/Services/UserEmailService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleAdminService.js +858 -0
- package/build/dist/Server/Services/UserNotificationRuleAdminService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js +2830 -175
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserOnCallLogService.js +488 -43
- package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
- package/build/dist/Server/Services/UserPushService.js +26 -0
- package/build/dist/Server/Services/UserPushService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +10 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Services/UserSmsService.js +24 -1
- package/build/dist/Server/Services/UserSmsService.js.map +1 -1
- package/build/dist/Server/Services/UserTelegramService.js +22 -1
- package/build/dist/Server/Services/UserTelegramService.js.map +1 -1
- package/build/dist/Server/Services/UserWebhookService.js +25 -1
- package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
- package/build/dist/Server/Services/UserWhatsAppService.js +22 -1
- package/build/dist/Server/Services/UserWhatsAppService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js +12 -1
- package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +126 -0
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.js +254 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerOnlyColumnPermission.js.map +1 -0
- package/build/dist/Server/Types/Database/Permissions/QueryPermission.js +47 -2
- package/build/dist/Server/Types/Database/Permissions/QueryPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TenantPermission.js +7 -0
- package/build/dist/Server/Types/Database/Permissions/TenantPermission.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +21 -5
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +14 -10
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +31 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js +3 -9
- package/build/dist/Server/Types/Workflow/Components/Conditions/IfElse.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Email.js +15 -4
- package/build/dist/Server/Types/Workflow/Components/Email.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js +7 -2
- package/build/dist/Server/Types/Workflow/Components/JavaScript.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +1 -1
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +514 -56
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +20 -3
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +19 -6
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +7 -0
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js +2 -2
- package/build/dist/Server/Utils/AI/Toolbox/AIActionTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/AIMetaTools.js +692 -0
- package/build/dist/Server/Utils/AI/Toolbox/AIMetaTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js +148 -12
- package/build/dist/Server/Utils/AI/Toolbox/AlertTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js +157 -10
- package/build/dist/Server/Utils/AI/Toolbox/IncidentTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/Index.js +37 -0
- package/build/dist/Server/Utils/AI/Toolbox/Index.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js +259 -14
- package/build/dist/Server/Utils/AI/Toolbox/MonitorTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/NoteWriteTools.js +235 -0
- package/build/dist/Server/Utils/AI/Toolbox/NoteWriteTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +1000 -0
- package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/RunbookTools.js +356 -0
- package/build/dist/Server/Utils/AI/Toolbox/RunbookTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +394 -0
- package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/StatusPageTools.js +465 -0
- package/build/dist/Server/Utils/AI/Toolbox/StatusPageTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/TeamTools.js +280 -0
- package/build/dist/Server/Utils/AI/Toolbox/TeamTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js +527 -0
- package/build/dist/Server/Utils/AI/Toolbox/TimelineTools.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/WorkflowProbeTools.js +548 -0
- package/build/dist/Server/Utils/AI/Toolbox/WorkflowProbeTools.js.map +1 -0
- package/build/dist/Server/Utils/ClientIp.js +137 -0
- package/build/dist/Server/Utils/ClientIp.js.map +1 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js +38 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.js.map +1 -1
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js +89 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloHistoryPolicy.js.map +1 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js +77 -0
- package/build/dist/Server/Utils/Dashboard/PublicDashboardSloWidget.js.map +1 -0
- package/build/dist/Server/Utils/Express.js +12 -12
- package/build/dist/Server/Utils/Express.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +70 -7
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +121 -11
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +82 -21
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +12 -4
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +165 -18
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +11 -11
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +122 -47
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +7 -3
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/AI/AIChatMessageStatus.js +8 -1
- package/build/dist/Types/AI/AIChatMessageStatus.js.map +1 -1
- package/build/dist/Types/AI/AIChatTypes.js +12 -0
- package/build/dist/Types/AI/AIChatTypes.js.map +1 -1
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +60 -0
- package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -0
- package/build/dist/Types/Exception/ExceptionCode.js +2 -0
- package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
- package/build/dist/Types/Exception/ServiceUnavailableException.js +8 -0
- package/build/dist/Types/Exception/ServiceUnavailableException.js.map +1 -0
- package/build/dist/Types/Exception/TooManyRequestsException.js +8 -0
- package/build/dist/Types/Exception/TooManyRequestsException.js.map +1 -0
- package/build/dist/Types/IP/IP.js +87 -43
- package/build/dist/Types/IP/IP.js.map +1 -1
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js +50 -0
- package/build/dist/Types/NetworkDevice/NetworkDeviceMonitoringMethod.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/Layer.js +186 -123
- package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.js +13 -0
- package/build/dist/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +105 -11
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
- package/build/dist/Types/Permission.js +174 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Telemetry/EntityRelationshipType.js +1 -1
- package/build/dist/Types/Telemetry/EntitySource.js +1 -1
- package/build/dist/Types/Telemetry/EntityType.js +1 -1
- package/build/dist/Types/Telemetry/EntityTypeGroups.js +1 -1
- package/build/dist/Types/Telemetry/EntityTypeGroups.js.map +1 -1
- package/build/dist/Types/Workflow/Components/BaseModel.js +66 -28
- package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Discord.js +1 -0
- package/build/dist/Types/Workflow/Components/Discord.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Email.js +12 -3
- package/build/dist/Types/Workflow/Components/Email.js.map +1 -1
- package/build/dist/Types/Workflow/Components/JavaScript.js +7 -0
- package/build/dist/Types/Workflow/Components/JavaScript.js.map +1 -1
- package/build/dist/Types/Workflow/Components/MicrosoftTeams.js +3 -2
- package/build/dist/Types/Workflow/Components/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Slack.js +1 -0
- package/build/dist/Types/Workflow/Components/Slack.js.map +1 -1
- package/build/dist/Types/Workflow/Components/Telegram.js +1 -0
- package/build/dist/Types/Workflow/Components/Telegram.js.map +1 -1
- package/build/dist/Types/Workflow/TemplateSyntax.js +12 -0
- package/build/dist/Types/Workflow/TemplateSyntax.js.map +1 -1
- package/build/dist/Types/Workflow/Templates.js +1931 -38
- package/build/dist/Types/Workflow/Templates.js.map +1 -1
- package/build/dist/UI/Components/Calendar/Calendar.js +1 -1
- package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
- package/build/dist/UI/Components/Checkbox/Checkbox.js +1 -1
- package/build/dist/UI/Components/Checkbox/Checkbox.js.map +1 -1
- package/build/dist/UI/Components/Dictionary/Dictionary.js +25 -11
- package/build/dist/UI/Components/Dictionary/Dictionary.js.map +1 -1
- package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js +27 -4
- package/build/dist/UI/Components/Header/HeaderIconDropdownButton.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +1 -0
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardKey.js +163 -0
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardKey.js.map +1 -0
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcut.js +47 -0
- package/build/dist/UI/Components/KeyboardShortcut/KeyboardShortcut.js.map +1 -0
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +4 -4
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js +11 -1
- package/build/dist/UI/Components/LogsViewer/components/ActiveFilterChips.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js +10 -8
- package/build/dist/UI/Components/LogsViewer/components/KeyboardShortcutsHelp.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js +227 -14
- package/build/dist/UI/Components/LogsViewer/components/LogDetailsPanel.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +5 -0
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js +69 -5
- package/build/dist/UI/Components/LogsViewer/components/LogsTable.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +8 -0
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/types.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +9 -2
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +8 -21
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Components/ProjectInvitations/PendingProjectInvitations.js +251 -0
- package/build/dist/UI/Components/ProjectInvitations/PendingProjectInvitations.js.map +1 -0
- package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js +9 -2
- package/build/dist/UI/Components/SimpleLogViewer/SimpleLogViewer.js.map +1 -1
- package/build/dist/UI/Components/Table/Table.js +27 -15
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableBody.js +24 -18
- package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
- package/build/dist/UI/Components/Table/TableHeader.js +9 -1
- package/build/dist/UI/Components/Table/TableHeader.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +29 -21
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js +130 -12
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js +10 -1
- package/build/dist/UI/Components/Workflow/ComponentReturnValueViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js +4 -4
- package/build/dist/UI/Components/Workflow/ComponentSettingsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js +57 -7
- package/build/dist/UI/Components/Workflow/ComponentValuePickerModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentsModal.js +53 -18
- package/build/dist/UI/Components/Workflow/ComponentsModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/DocumentationViewer.js +19 -6
- package/build/dist/UI/Components/Workflow/DocumentationViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/GraphLint.js +33 -4
- package/build/dist/UI/Components/Workflow/GraphLint.js.map +1 -1
- package/build/dist/UI/Components/Workflow/GraphLintSummary.js +231 -0
- package/build/dist/UI/Components/Workflow/GraphLintSummary.js.map +1 -0
- package/build/dist/UI/Components/Workflow/ModelColumnEditor.js +116 -21
- package/build/dist/UI/Components/Workflow/ModelColumnEditor.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ModelSchema.js +72 -34
- package/build/dist/UI/Components/Workflow/ModelSchema.js.map +1 -1
- package/build/dist/UI/Components/Workflow/RunStatusWatcher.js +1 -1
- package/build/dist/UI/Components/Workflow/RunStatusWatcher.js.map +1 -1
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js +1 -1
- package/build/dist/UI/Components/Workflow/StepTraceViewer.js.map +1 -1
- package/build/dist/UI/Components/Workflow/UseRunWatch.js +123 -0
- package/build/dist/UI/Components/Workflow/UseRunWatch.js.map +1 -0
- package/build/dist/UI/Components/Workflow/VariableModal.js +3 -2
- package/build/dist/UI/Components/Workflow/VariableModal.js.map +1 -1
- package/build/dist/UI/Components/Workflow/Workflow.js +41 -1
- package/build/dist/UI/Components/Workflow/Workflow.js.map +1 -1
- package/build/dist/UI/Components/Workflow/WorkflowIssuesModal.js +99 -0
- package/build/dist/UI/Components/Workflow/WorkflowIssuesModal.js.map +1 -0
- package/build/dist/UI/Components/Workflow/WorkflowLogModal.js +56 -0
- package/build/dist/UI/Components/Workflow/WorkflowLogModal.js.map +1 -0
- package/build/dist/UI/Components/Workflow/WorkflowStatusBar.js +92 -0
- package/build/dist/UI/Components/Workflow/WorkflowStatusBar.js.map +1 -0
- package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js +9 -0
- package/build/dist/UI/Utils/AIChatExport/ConversationMarkdown.js.map +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +1 -1
- package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
- package/build/dist/UI/Utils/Platform.js +118 -0
- package/build/dist/UI/Utils/Platform.js.map +1 -0
- package/build/dist/UI/Utils/ProjectInvitationDisplay.js +106 -0
- package/build/dist/UI/Utils/ProjectInvitationDisplay.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js +108 -0
- package/build/dist/Utils/Monitor/NetworkDeviceLinkRuleUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +642 -136
- package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
- package/build/dist/Utils/Telemetry/CrossSignalScope.js +328 -0
- package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +5 -5
- package/build/dist/Utils/Telemetry/EntityRelationship.js +1 -1
- package/jest.config.json +1 -0
- package/package.json +1 -1
- package/build/dist/Models/DatabaseModels/TelemetryEntity.js.map +0 -1
- package/build/dist/Models/DatabaseModels/TelemetryEntityRelationship.js.map +0 -1
- package/build/dist/Server/Services/TelemetryEntityRelationshipService.js.map +0 -1
- package/build/dist/Server/Services/TelemetryEntityService.js.map +0 -1
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
import { normalizeMac } from "./EndpointAttachmentUtil";
|
|
2
2
|
import { classifyDeviceRole, classifyEndpointRole, } from "./NetworkDeviceRoleUtil";
|
|
3
|
+
const MATCH_KEY_KINDS_STRONGEST_FIRST = [
|
|
4
|
+
"name",
|
|
5
|
+
"serial",
|
|
6
|
+
"mac",
|
|
7
|
+
"shortHost",
|
|
8
|
+
];
|
|
9
|
+
/*
|
|
10
|
+
* The kinds strong enough to say "these two reports describe one peer".
|
|
11
|
+
*
|
|
12
|
+
* shortHost is excluded on purpose: `sw01.site-a` and `sw01.site-b` share
|
|
13
|
+
* one, and merging those would invent a device nobody owns. Against a
|
|
14
|
+
* MANAGED device the same key is safe, because a key two devices both
|
|
15
|
+
* claim is dropped from the index entirely rather than guessed at.
|
|
16
|
+
*/
|
|
17
|
+
const PEER_IDENTITY_KINDS = new Set([
|
|
18
|
+
"name",
|
|
19
|
+
"serial",
|
|
20
|
+
"mac",
|
|
21
|
+
]);
|
|
22
|
+
/*
|
|
23
|
+
* Hoisted so the literal is not the object of a member expression, which
|
|
24
|
+
* `wrap-regex` and Prettier cannot agree on.
|
|
25
|
+
*/
|
|
26
|
+
const IPV4_PATTERN = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;
|
|
3
27
|
// A device not seen within this window is treated as not currently up.
|
|
4
28
|
const FRESH_WINDOW_MS = 15 * 60 * 1000;
|
|
5
29
|
// Endpoint nodes rendered per graph; the slice is deterministic (by MAC).
|
|
@@ -7,9 +31,11 @@ const ENDPOINT_RENDER_CAP = 2000;
|
|
|
7
31
|
export default class NetworkTopologyUtil {
|
|
8
32
|
/*
|
|
9
33
|
* Builds the topology graph from every device in a project. Nodes are the
|
|
10
|
-
* devices; LLDP and CDP neighbors that match another device (by
|
|
11
|
-
*
|
|
12
|
-
*
|
|
34
|
+
* devices; LLDP and CDP neighbors that match another device (by name,
|
|
35
|
+
* serial, interface MAC or FQDN short form — see MatchKeyKind) become
|
|
36
|
+
* edges, and neighbors that match nothing become lightweight "unmanaged"
|
|
37
|
+
* nodes so links don't dead-end. Reports that share an identity-grade
|
|
38
|
+
* alias are one unmanaged node, however many switches saw it. Edges are
|
|
13
39
|
* undirected and deduplicated — a link reported from both ends, or by
|
|
14
40
|
* both protocols, appears once with the union of what each report knew
|
|
15
41
|
* (ports, protocols, per-end interface state). When `interfaces` rows are
|
|
@@ -19,15 +45,32 @@ export default class NetworkTopologyUtil {
|
|
|
19
45
|
* "endpoint" node linked by an "fdb" edge (capped, deterministic by MAC);
|
|
20
46
|
* the rest are dropped and counted in droppedEndpointCount.
|
|
21
47
|
*/
|
|
22
|
-
static buildTopology(devices, now, interfaces = [], endpoints = []) {
|
|
48
|
+
static buildTopology(devices, now, interfaces = [], endpoints = [], manualLinks = [], suppressedNodeKeys = new Set()) {
|
|
49
|
+
var _a;
|
|
23
50
|
const nodes = [];
|
|
24
|
-
|
|
51
|
+
/*
|
|
52
|
+
* Index managed devices by every identifier a neighbor entry could
|
|
53
|
+
* reference. A key TWO devices both claim is deleted rather than
|
|
54
|
+
* resolved: last-writer-wins would quietly draw the link to whichever
|
|
55
|
+
* device happened to be indexed second, and a wrong cable on a network
|
|
56
|
+
* map is worse than a missing one.
|
|
57
|
+
*/
|
|
25
58
|
const deviceByMatchKey = new Map();
|
|
59
|
+
const ambiguousMatchKeyIds = new Set();
|
|
26
60
|
for (const device of devices) {
|
|
27
61
|
for (const key of NetworkTopologyUtil.matchKeysForDevice(device)) {
|
|
28
|
-
|
|
62
|
+
const keyId = NetworkTopologyUtil.matchKeyId(key);
|
|
63
|
+
const existing = deviceByMatchKey.get(keyId);
|
|
64
|
+
if (existing && existing.id !== device.id) {
|
|
65
|
+
ambiguousMatchKeyIds.add(keyId);
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
deviceByMatchKey.set(keyId, device);
|
|
29
69
|
}
|
|
30
70
|
}
|
|
71
|
+
for (const keyId of ambiguousMatchKeyIds) {
|
|
72
|
+
deviceByMatchKey.delete(keyId);
|
|
73
|
+
}
|
|
31
74
|
// Index interface rows by (device, index) and by (device, name).
|
|
32
75
|
const interfaceByDeviceAndIndex = new Map();
|
|
33
76
|
const interfaceByDeviceAndName = new Map();
|
|
@@ -38,7 +81,10 @@ export default class NetworkTopologyUtil {
|
|
|
38
81
|
interfaceByDeviceAndName.set(`${row.networkDeviceId}::${nameKey}`, row);
|
|
39
82
|
}
|
|
40
83
|
}
|
|
84
|
+
// Kept aside so the diagnostics pass below can read it back per node.
|
|
85
|
+
const isNeighborDiscoveryEnabledById = new Map();
|
|
41
86
|
for (const device of devices) {
|
|
87
|
+
isNeighborDiscoveryEnabledById.set(device.id, device.isNeighborDiscoveryEnabled);
|
|
42
88
|
nodes.push({
|
|
43
89
|
id: device.id,
|
|
44
90
|
name: device.name,
|
|
@@ -60,142 +106,242 @@ export default class NetworkTopologyUtil {
|
|
|
60
106
|
deviceModel: device.deviceModel,
|
|
61
107
|
});
|
|
62
108
|
}
|
|
63
|
-
const unmanagedNodeById = new Map();
|
|
64
109
|
const edgeByKey = new Map();
|
|
110
|
+
/*
|
|
111
|
+
* Resolve every neighbor report before drawing anything.
|
|
112
|
+
*
|
|
113
|
+
* A managed match is decidable from one report, but the IDENTITY of an
|
|
114
|
+
* unmanaged peer is not: the switch at one end may know its neighbor's
|
|
115
|
+
* sysName while the switch at the other end knows only its chassis MAC,
|
|
116
|
+
* and only the whole set of reports says those two describe one box.
|
|
117
|
+
*/
|
|
118
|
+
const resolvedClaims = [];
|
|
65
119
|
for (const device of devices) {
|
|
66
120
|
for (const claim of NetworkTopologyUtil.neighborClaimsForDevice(device)) {
|
|
67
|
-
|
|
121
|
+
const candidates = NetworkTopologyUtil.candidateKeysForClaim(claim);
|
|
122
|
+
if (candidates.length === 0) {
|
|
68
123
|
continue;
|
|
69
124
|
}
|
|
70
|
-
|
|
71
|
-
let
|
|
125
|
+
// Candidates arrive strongest-first, so the first hit is the best one.
|
|
126
|
+
let matched = undefined;
|
|
127
|
+
for (const candidate of candidates) {
|
|
128
|
+
matched = deviceByMatchKey.get(NetworkTopologyUtil.matchKeyId(candidate));
|
|
129
|
+
if (matched) {
|
|
130
|
+
break;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
72
133
|
if (matched) {
|
|
73
134
|
if (matched.id === device.id) {
|
|
74
135
|
// Self-referential neighbor entry; skip.
|
|
75
136
|
continue;
|
|
76
137
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (!existingUnmanaged) {
|
|
83
|
-
const unmanagedName = claim.displayName || "Unknown device";
|
|
84
|
-
const unmanagedNode = {
|
|
85
|
-
id: toNodeId,
|
|
86
|
-
name: unmanagedName,
|
|
87
|
-
isManaged: false,
|
|
88
|
-
kind: "unmanaged",
|
|
89
|
-
role: classifyDeviceRole({
|
|
90
|
-
platform: claim.remotePlatform,
|
|
91
|
-
name: unmanagedName,
|
|
92
|
-
}),
|
|
93
|
-
status: "unknown",
|
|
94
|
-
deviceModel: claim.remotePlatform,
|
|
95
|
-
};
|
|
96
|
-
unmanagedNodeById.set(toNodeId, unmanagedNode);
|
|
97
|
-
nodes.push(unmanagedNode);
|
|
98
|
-
}
|
|
99
|
-
else if (!existingUnmanaged.deviceModel && claim.remotePlatform) {
|
|
100
|
-
/*
|
|
101
|
-
* A later CDP claim may know the platform the first one didn't
|
|
102
|
-
* — which is usually the only evidence a peer's role rests on,
|
|
103
|
-
* so the role is re-derived rather than left at whatever the
|
|
104
|
-
* name alone produced.
|
|
105
|
-
*/
|
|
106
|
-
existingUnmanaged.deviceModel = claim.remotePlatform;
|
|
107
|
-
existingUnmanaged.role = classifyDeviceRole({
|
|
108
|
-
platform: claim.remotePlatform,
|
|
109
|
-
name: existingUnmanaged.name,
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
// The reporting device's own end, enriched from its interface row.
|
|
114
|
-
let localEndpoint = undefined;
|
|
115
|
-
let localPortLabel = undefined;
|
|
116
|
-
if (claim.localInterfaceIndex !== undefined) {
|
|
117
|
-
const localInterface = interfaceByDeviceAndIndex.get(`${device.id}::${claim.localInterfaceIndex}`);
|
|
118
|
-
localEndpoint = {
|
|
119
|
-
interfaceIndex: claim.localInterfaceIndex,
|
|
120
|
-
interfaceName: localInterface === null || localInterface === void 0 ? void 0 : localInterface.name,
|
|
121
|
-
isOperationallyUp: localInterface === null || localInterface === void 0 ? void 0 : localInterface.isOperationallyUp,
|
|
122
|
-
isAdministrativelyUp: localInterface === null || localInterface === void 0 ? void 0 : localInterface.isAdministrativelyUp,
|
|
123
|
-
utilizationPercent: localInterface === null || localInterface === void 0 ? void 0 : localInterface.utilizationPercent,
|
|
124
|
-
inRateMbps: localInterface === null || localInterface === void 0 ? void 0 : localInterface.inRateMbps,
|
|
125
|
-
outRateMbps: localInterface === null || localInterface === void 0 ? void 0 : localInterface.outRateMbps,
|
|
126
|
-
errorsPerSecond: localInterface === null || localInterface === void 0 ? void 0 : localInterface.errorsPerSecond,
|
|
127
|
-
};
|
|
128
|
-
localPortLabel =
|
|
129
|
-
(localInterface === null || localInterface === void 0 ? void 0 : localInterface.name) || `if${claim.localInterfaceIndex}`;
|
|
130
|
-
}
|
|
131
|
-
/*
|
|
132
|
-
* The far end: best-effort — the advertised remote port id often
|
|
133
|
-
* matches the remote device's interface name (e.g. "GigabitEthernet
|
|
134
|
-
* 0/1"). Only attach data when it does; a bare port id string stays
|
|
135
|
-
* in toPort.
|
|
136
|
-
*/
|
|
137
|
-
let remoteEndpoint = undefined;
|
|
138
|
-
if (matched && claim.remotePortId) {
|
|
139
|
-
const remotePortKey = NetworkTopologyUtil.normalizeKey(claim.remotePortId);
|
|
140
|
-
const remoteInterface = remotePortKey
|
|
141
|
-
? interfaceByDeviceAndName.get(`${matched.id}::${remotePortKey}`)
|
|
142
|
-
: undefined;
|
|
143
|
-
if (remoteInterface) {
|
|
144
|
-
remoteEndpoint = {
|
|
145
|
-
interfaceIndex: remoteInterface.interfaceIndex,
|
|
146
|
-
interfaceName: remoteInterface.name,
|
|
147
|
-
isOperationallyUp: remoteInterface.isOperationallyUp,
|
|
148
|
-
isAdministrativelyUp: remoteInterface.isAdministrativelyUp,
|
|
149
|
-
utilizationPercent: remoteInterface.utilizationPercent,
|
|
150
|
-
inRateMbps: remoteInterface.inRateMbps,
|
|
151
|
-
outRateMbps: remoteInterface.outRateMbps,
|
|
152
|
-
errorsPerSecond: remoteInterface.errorsPerSecond,
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
// Undirected dedupe: canonicalize the endpoint pair.
|
|
157
|
-
const edgeKey = [device.id, toNodeId].sort().join("::");
|
|
158
|
-
const existing = edgeByKey.get(edgeKey);
|
|
159
|
-
if (!existing) {
|
|
160
|
-
edgeByKey.set(edgeKey, {
|
|
161
|
-
fromNodeId: device.id,
|
|
162
|
-
toNodeId: toNodeId,
|
|
163
|
-
fromPort: localPortLabel,
|
|
164
|
-
toPort: claim.remotePortId,
|
|
165
|
-
protocols: [claim.protocol],
|
|
166
|
-
fromInterface: localEndpoint,
|
|
167
|
-
toInterface: remoteEndpoint,
|
|
138
|
+
resolvedClaims.push({
|
|
139
|
+
device: device,
|
|
140
|
+
claim: claim,
|
|
141
|
+
matchedDeviceId: matched.id,
|
|
142
|
+
peerAliases: [],
|
|
168
143
|
});
|
|
169
144
|
continue;
|
|
170
145
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
146
|
+
resolvedClaims.push({
|
|
147
|
+
device: device,
|
|
148
|
+
claim: claim,
|
|
149
|
+
matchedDeviceId: undefined,
|
|
150
|
+
peerAliases: candidates.filter((candidate) => {
|
|
151
|
+
return PEER_IDENTITY_KINDS.has(candidate.kind);
|
|
152
|
+
}),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const peerNodeIdByClaim = NetworkTopologyUtil.buildUnmanagedPeerNodes(resolvedClaims, nodes);
|
|
157
|
+
for (const resolved of resolvedClaims) {
|
|
158
|
+
const device = resolved.device;
|
|
159
|
+
const claim = resolved.claim;
|
|
160
|
+
const matchedId = resolved.matchedDeviceId;
|
|
161
|
+
const toNodeId = matchedId || peerNodeIdByClaim.get(resolved);
|
|
162
|
+
if (!toNodeId) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
// The reporting device's own end, enriched from its interface row.
|
|
166
|
+
let localEndpoint = undefined;
|
|
167
|
+
let localPortLabel = undefined;
|
|
168
|
+
if (claim.localInterfaceIndex !== undefined) {
|
|
169
|
+
const localInterface = interfaceByDeviceAndIndex.get(`${device.id}::${claim.localInterfaceIndex}`);
|
|
170
|
+
localEndpoint = {
|
|
171
|
+
interfaceIndex: claim.localInterfaceIndex,
|
|
172
|
+
interfaceName: localInterface === null || localInterface === void 0 ? void 0 : localInterface.name,
|
|
173
|
+
isOperationallyUp: localInterface === null || localInterface === void 0 ? void 0 : localInterface.isOperationallyUp,
|
|
174
|
+
isAdministrativelyUp: localInterface === null || localInterface === void 0 ? void 0 : localInterface.isAdministrativelyUp,
|
|
175
|
+
utilizationPercent: localInterface === null || localInterface === void 0 ? void 0 : localInterface.utilizationPercent,
|
|
176
|
+
inRateMbps: localInterface === null || localInterface === void 0 ? void 0 : localInterface.inRateMbps,
|
|
177
|
+
outRateMbps: localInterface === null || localInterface === void 0 ? void 0 : localInterface.outRateMbps,
|
|
178
|
+
errorsPerSecond: localInterface === null || localInterface === void 0 ? void 0 : localInterface.errorsPerSecond,
|
|
179
|
+
};
|
|
180
|
+
localPortLabel =
|
|
181
|
+
(localInterface === null || localInterface === void 0 ? void 0 : localInterface.name) || `if${claim.localInterfaceIndex}`;
|
|
182
|
+
}
|
|
183
|
+
/*
|
|
184
|
+
* The far end: best-effort — the advertised remote port id often
|
|
185
|
+
* matches the remote device's interface name (e.g. "GigabitEthernet
|
|
186
|
+
* 0/1"). Only attach data when it does; a bare port id string stays
|
|
187
|
+
* in toPort.
|
|
188
|
+
*/
|
|
189
|
+
let remoteEndpoint = undefined;
|
|
190
|
+
if (matchedId && claim.remotePortId) {
|
|
191
|
+
const remotePortKey = NetworkTopologyUtil.normalizeKey(claim.remotePortId);
|
|
192
|
+
const remoteInterface = remotePortKey
|
|
193
|
+
? interfaceByDeviceAndName.get(`${matchedId}::${remotePortKey}`)
|
|
194
|
+
: undefined;
|
|
195
|
+
if (remoteInterface) {
|
|
196
|
+
remoteEndpoint = {
|
|
197
|
+
interfaceIndex: remoteInterface.interfaceIndex,
|
|
198
|
+
interfaceName: remoteInterface.name,
|
|
199
|
+
isOperationallyUp: remoteInterface.isOperationallyUp,
|
|
200
|
+
isAdministrativelyUp: remoteInterface.isAdministrativelyUp,
|
|
201
|
+
utilizationPercent: remoteInterface.utilizationPercent,
|
|
202
|
+
inRateMbps: remoteInterface.inRateMbps,
|
|
203
|
+
outRateMbps: remoteInterface.outRateMbps,
|
|
204
|
+
errorsPerSecond: remoteInterface.errorsPerSecond,
|
|
205
|
+
};
|
|
191
206
|
}
|
|
192
207
|
}
|
|
208
|
+
// Undirected dedupe: canonicalize the endpoint pair.
|
|
209
|
+
const edgeKey = [device.id, toNodeId].sort().join("::");
|
|
210
|
+
const existing = edgeByKey.get(edgeKey);
|
|
211
|
+
if (!existing) {
|
|
212
|
+
edgeByKey.set(edgeKey, {
|
|
213
|
+
fromNodeId: device.id,
|
|
214
|
+
toNodeId: toNodeId,
|
|
215
|
+
fromPort: localPortLabel,
|
|
216
|
+
toPort: claim.remotePortId,
|
|
217
|
+
protocols: [claim.protocol],
|
|
218
|
+
fromInterface: localEndpoint,
|
|
219
|
+
toInterface: remoteEndpoint,
|
|
220
|
+
});
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
/*
|
|
224
|
+
* Same link reported again — from the other end, or by the other
|
|
225
|
+
* protocol. Merge instead of dropping so both ends keep the best
|
|
226
|
+
* data anyone reported about them.
|
|
227
|
+
*/
|
|
228
|
+
if (existing.protocols && !existing.protocols.includes(claim.protocol)) {
|
|
229
|
+
existing.protocols.push(claim.protocol);
|
|
230
|
+
}
|
|
231
|
+
if (existing.fromNodeId === device.id) {
|
|
232
|
+
existing.fromPort = existing.fromPort || localPortLabel;
|
|
233
|
+
existing.toPort = existing.toPort || claim.remotePortId;
|
|
234
|
+
existing.fromInterface = NetworkTopologyUtil.mergeEndpoints(existing.fromInterface, localEndpoint);
|
|
235
|
+
existing.toInterface = NetworkTopologyUtil.mergeEndpoints(existing.toInterface, remoteEndpoint);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
existing.toPort = existing.toPort || localPortLabel;
|
|
239
|
+
existing.fromPort = existing.fromPort || claim.remotePortId;
|
|
240
|
+
existing.toInterface = NetworkTopologyUtil.mergeEndpoints(existing.toInterface, localEndpoint);
|
|
241
|
+
existing.fromInterface = NetworkTopologyUtil.mergeEndpoints(existing.fromInterface, remoteEndpoint);
|
|
242
|
+
}
|
|
193
243
|
}
|
|
194
|
-
const edges = Array.from(edgeByKey.values());
|
|
195
|
-
// --- Endpoint nodes + fdb edges ---
|
|
196
244
|
const deviceNodeIds = new Set(devices.map((device) => {
|
|
197
245
|
return device.id;
|
|
198
246
|
}));
|
|
247
|
+
/*
|
|
248
|
+
* --- Operator-declared links ---
|
|
249
|
+
*
|
|
250
|
+
* Merged into the SAME edge map the discovery protocols write to, so a
|
|
251
|
+
* cable somebody drew by hand and the same cable LLDP later reports are
|
|
252
|
+
* one line carrying both protocols — not two lines between one pair of
|
|
253
|
+
* boxes, which is exactly the duplicate an operator would read as a
|
|
254
|
+
* second physical link.
|
|
255
|
+
*
|
|
256
|
+
* Ends outside this graph are skipped rather than drawn: a link to a
|
|
257
|
+
* device in another site (or one since archived) has nothing to attach
|
|
258
|
+
* to here.
|
|
259
|
+
*/
|
|
260
|
+
for (const link of manualLinks) {
|
|
261
|
+
if (!deviceNodeIds.has(link.fromDeviceId) ||
|
|
262
|
+
!deviceNodeIds.has(link.toDeviceId) ||
|
|
263
|
+
link.fromDeviceId === link.toDeviceId) {
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
const edgeKey = [link.fromDeviceId, link.toDeviceId]
|
|
267
|
+
.sort()
|
|
268
|
+
.join("::");
|
|
269
|
+
const existing = edgeByKey.get(edgeKey);
|
|
270
|
+
if (!existing) {
|
|
271
|
+
edgeByKey.set(edgeKey, {
|
|
272
|
+
fromNodeId: link.fromDeviceId,
|
|
273
|
+
toNodeId: link.toDeviceId,
|
|
274
|
+
fromPort: link.fromPortName,
|
|
275
|
+
toPort: link.toPortName,
|
|
276
|
+
protocols: ["manual"],
|
|
277
|
+
monitorState: link.monitorStatus,
|
|
278
|
+
name: link.name,
|
|
279
|
+
});
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (existing.protocols && !existing.protocols.includes("manual")) {
|
|
283
|
+
existing.protocols.push("manual");
|
|
284
|
+
}
|
|
285
|
+
/*
|
|
286
|
+
* Discovered data wins on the shared fields — it is measured, and the
|
|
287
|
+
* hand-typed port is a best recollection. The operator's name and the
|
|
288
|
+
* monitor's verdict have no discovered counterpart, so they always
|
|
289
|
+
* apply.
|
|
290
|
+
*/
|
|
291
|
+
if (existing.fromNodeId === link.fromDeviceId) {
|
|
292
|
+
existing.fromPort = existing.fromPort || link.fromPortName;
|
|
293
|
+
existing.toPort = existing.toPort || link.toPortName;
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
existing.toPort = existing.toPort || link.fromPortName;
|
|
297
|
+
existing.fromPort = existing.fromPort || link.toPortName;
|
|
298
|
+
}
|
|
299
|
+
existing.name = existing.name || link.name;
|
|
300
|
+
existing.monitorState = (_a = existing.monitorState) !== null && _a !== void 0 ? _a : link.monitorStatus;
|
|
301
|
+
}
|
|
302
|
+
const edges = Array.from(edgeByKey.values());
|
|
303
|
+
/*
|
|
304
|
+
* --- Why a device has no links ---
|
|
305
|
+
*
|
|
306
|
+
* Attached to every managed node, so the detail panel can answer "the
|
|
307
|
+
* router is not linked to anything" with a cause instead of a shrug.
|
|
308
|
+
* Built from the claims that were just resolved: the unmatched ones are
|
|
309
|
+
* the actionable evidence — a renamed peer, a device nobody has added
|
|
310
|
+
* yet — and they are otherwise thrown away here.
|
|
311
|
+
*/
|
|
312
|
+
const reportedNeighborCountByDeviceId = new Map();
|
|
313
|
+
const unmatchedIdentifiersByDeviceId = new Map();
|
|
314
|
+
for (const resolved of resolvedClaims) {
|
|
315
|
+
const deviceId = resolved.device.id;
|
|
316
|
+
reportedNeighborCountByDeviceId.set(deviceId, (reportedNeighborCountByDeviceId.get(deviceId) || 0) + 1);
|
|
317
|
+
if (resolved.matchedDeviceId) {
|
|
318
|
+
continue;
|
|
319
|
+
}
|
|
320
|
+
const identifier = resolved.claim.displayName || resolved.claim.identifiers[0];
|
|
321
|
+
if (!identifier) {
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
const bucket = unmatchedIdentifiersByDeviceId.get(deviceId);
|
|
325
|
+
if (bucket) {
|
|
326
|
+
if (!bucket.includes(identifier)) {
|
|
327
|
+
bucket.push(identifier);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
else {
|
|
331
|
+
unmatchedIdentifiersByDeviceId.set(deviceId, [identifier]);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
for (const node of nodes) {
|
|
335
|
+
if (node.kind !== "device") {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
node.diagnostics = {
|
|
339
|
+
isNeighborDiscoveryEnabled: isNeighborDiscoveryEnabledById.get(node.id),
|
|
340
|
+
reportedNeighborCount: reportedNeighborCountByDeviceId.get(node.id) || 0,
|
|
341
|
+
unmatchedNeighborIdentifiers: unmatchedIdentifiersByDeviceId.get(node.id) || [],
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
// --- Endpoint nodes + fdb edges ---
|
|
199
345
|
/*
|
|
200
346
|
* Deterministic render order: by normalized MAC, then id, so the capped
|
|
201
347
|
* slice is stable across rebuilds regardless of query order.
|
|
@@ -273,11 +419,39 @@ export default class NetworkTopologyUtil {
|
|
|
273
419
|
: undefined,
|
|
274
420
|
});
|
|
275
421
|
}
|
|
422
|
+
/*
|
|
423
|
+
* --- Hidden nodes ---
|
|
424
|
+
*
|
|
425
|
+
* Applied last, on the finished graph, so a suppressed node cannot
|
|
426
|
+
* change how anything else resolved. Hiding a switch must not silently
|
|
427
|
+
* re-route its neighbours' links or turn its peers into strangers — it
|
|
428
|
+
* takes the box off the map and nothing more. Its edges go with it,
|
|
429
|
+
* because a line to a node that is not drawn is a line into empty space.
|
|
430
|
+
*/
|
|
431
|
+
if (suppressedNodeKeys.size === 0) {
|
|
432
|
+
return {
|
|
433
|
+
nodes,
|
|
434
|
+
edges,
|
|
435
|
+
droppedEndpointCount,
|
|
436
|
+
endpointsTruncated,
|
|
437
|
+
suppressedNodeCount: 0,
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
const visibleNodes = nodes.filter((node) => {
|
|
441
|
+
return !suppressedNodeKeys.has(node.id);
|
|
442
|
+
});
|
|
443
|
+
const visibleNodeIds = new Set(visibleNodes.map((node) => {
|
|
444
|
+
return node.id;
|
|
445
|
+
}));
|
|
276
446
|
return {
|
|
277
|
-
nodes,
|
|
278
|
-
edges
|
|
447
|
+
nodes: visibleNodes,
|
|
448
|
+
edges: edges.filter((edge) => {
|
|
449
|
+
return (visibleNodeIds.has(edge.fromNodeId) &&
|
|
450
|
+
visibleNodeIds.has(edge.toNodeId));
|
|
451
|
+
}),
|
|
279
452
|
droppedEndpointCount,
|
|
280
453
|
endpointsTruncated,
|
|
454
|
+
suppressedNodeCount: nodes.length - visibleNodes.length,
|
|
281
455
|
};
|
|
282
456
|
}
|
|
283
457
|
/*
|
|
@@ -288,11 +462,25 @@ export default class NetworkTopologyUtil {
|
|
|
288
462
|
static neighborClaimsForDevice(device) {
|
|
289
463
|
const claims = [];
|
|
290
464
|
for (const neighbor of device.lldpNeighbors || []) {
|
|
465
|
+
/*
|
|
466
|
+
* Both identifiers are carried, not just the first non-empty one.
|
|
467
|
+
* The chassis id used to be a fallback that only applied when the
|
|
468
|
+
* peer advertised no sysName; it is in fact an identifier in its own
|
|
469
|
+
* right — a MAC or a serial — and the device it names is very often
|
|
470
|
+
* one we already manage.
|
|
471
|
+
*/
|
|
472
|
+
const identifiers = [];
|
|
473
|
+
if (neighbor.remoteSysName) {
|
|
474
|
+
identifiers.push(neighbor.remoteSysName);
|
|
475
|
+
}
|
|
476
|
+
if (neighbor.remoteChassisId) {
|
|
477
|
+
identifiers.push(neighbor.remoteChassisId);
|
|
478
|
+
}
|
|
291
479
|
claims.push({
|
|
292
480
|
protocol: "lldp",
|
|
293
|
-
|
|
294
|
-
NetworkTopologyUtil.normalizeKey(neighbor.remoteChassisId),
|
|
481
|
+
identifiers: identifiers,
|
|
295
482
|
displayName: neighbor.remoteSysName || neighbor.remoteChassisId,
|
|
483
|
+
hasAdvertisedName: Boolean(neighbor.remoteSysName),
|
|
296
484
|
localInterfaceIndex: neighbor.localInterfaceIndex,
|
|
297
485
|
remotePortId: neighbor.remotePortId,
|
|
298
486
|
remotePlatform: undefined,
|
|
@@ -301,8 +489,9 @@ export default class NetworkTopologyUtil {
|
|
|
301
489
|
for (const neighbor of device.cdpNeighbors || []) {
|
|
302
490
|
claims.push({
|
|
303
491
|
protocol: "cdp",
|
|
304
|
-
|
|
492
|
+
identifiers: neighbor.remoteDeviceId ? [neighbor.remoteDeviceId] : [],
|
|
305
493
|
displayName: neighbor.remoteDeviceId,
|
|
494
|
+
hasAdvertisedName: Boolean(neighbor.remoteDeviceId),
|
|
306
495
|
localInterfaceIndex: neighbor.localInterfaceIndex,
|
|
307
496
|
remotePortId: neighbor.remotePortId,
|
|
308
497
|
remotePlatform: neighbor.remotePlatform,
|
|
@@ -310,6 +499,84 @@ export default class NetworkTopologyUtil {
|
|
|
310
499
|
}
|
|
311
500
|
return claims;
|
|
312
501
|
}
|
|
502
|
+
/*
|
|
503
|
+
* Every key a claim could be resolved by, strongest kind first and, within
|
|
504
|
+
* a kind, strongest SOURCE first (an advertised sysName ahead of a chassis
|
|
505
|
+
* id). Sorting by kind before source is deliberate: a MAC read off a
|
|
506
|
+
* chassis id identifies a box far more precisely than the first label of
|
|
507
|
+
* somebody's FQDN, whichever field it arrived in.
|
|
508
|
+
*/
|
|
509
|
+
static candidateKeysForClaim(claim) {
|
|
510
|
+
const byKind = new Map();
|
|
511
|
+
const seen = new Set();
|
|
512
|
+
for (const identifier of claim.identifiers) {
|
|
513
|
+
for (const key of NetworkTopologyUtil.candidateKeysForIdentifier(identifier)) {
|
|
514
|
+
const keyId = NetworkTopologyUtil.matchKeyId(key);
|
|
515
|
+
if (seen.has(keyId)) {
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
seen.add(keyId);
|
|
519
|
+
const bucket = byKind.get(key.kind);
|
|
520
|
+
if (bucket) {
|
|
521
|
+
bucket.push(key);
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
byKind.set(key.kind, [key]);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
const ordered = [];
|
|
529
|
+
for (const kind of MATCH_KEY_KINDS_STRONGEST_FIRST) {
|
|
530
|
+
ordered.push(...(byKind.get(kind) || []));
|
|
531
|
+
}
|
|
532
|
+
return ordered;
|
|
533
|
+
}
|
|
534
|
+
/*
|
|
535
|
+
* One identifier string, offered as every kind it could be.
|
|
536
|
+
*
|
|
537
|
+
* A chassis id is just bytes on the wire — nothing in the protocol says
|
|
538
|
+
* whether it is a name, a serial or a MAC — so it is offered as all of
|
|
539
|
+
* them, and only a key some device actually published can match.
|
|
540
|
+
*/
|
|
541
|
+
static candidateKeysForIdentifier(raw) {
|
|
542
|
+
const normalized = NetworkTopologyUtil.normalizeKey(raw);
|
|
543
|
+
if (!normalized) {
|
|
544
|
+
return [];
|
|
545
|
+
}
|
|
546
|
+
const keys = [
|
|
547
|
+
{ kind: "name", value: normalized },
|
|
548
|
+
{ kind: "serial", value: normalized },
|
|
549
|
+
];
|
|
550
|
+
const mac = normalizeMac(normalized);
|
|
551
|
+
if (mac) {
|
|
552
|
+
keys.push({ kind: "mac", value: mac });
|
|
553
|
+
}
|
|
554
|
+
const shortHost = NetworkTopologyUtil.shortHostKey(normalized);
|
|
555
|
+
if (shortHost) {
|
|
556
|
+
keys.push({ kind: "shortHost", value: shortHost });
|
|
557
|
+
}
|
|
558
|
+
return keys;
|
|
559
|
+
}
|
|
560
|
+
/*
|
|
561
|
+
* The first label of a hostname, or undefined when taking one would be
|
|
562
|
+
* nonsense. An IPv4 literal would shorten to "10" and a MAC to its first
|
|
563
|
+
* octet pair — both of which would collide half the estate into one node,
|
|
564
|
+
* so both are refused outright.
|
|
565
|
+
*/
|
|
566
|
+
static shortHostKey(normalized) {
|
|
567
|
+
if (IPV4_PATTERN.test(normalized) || normalizeMac(normalized)) {
|
|
568
|
+
return undefined;
|
|
569
|
+
}
|
|
570
|
+
const firstLabel = normalized.split(".")[0] || "";
|
|
571
|
+
return firstLabel.length > 0 ? firstLabel : undefined;
|
|
572
|
+
}
|
|
573
|
+
static matchKeyId(key) {
|
|
574
|
+
/*
|
|
575
|
+
* A NUL separator, because every kind shares one namespace and a
|
|
576
|
+
* hostname may legitimately contain a colon-ish character.
|
|
577
|
+
*/
|
|
578
|
+
return `${key.kind}\u0000${key.value}`;
|
|
579
|
+
}
|
|
313
580
|
// Existing fields win; the incoming report only fills what's missing.
|
|
314
581
|
static mergeEndpoints(existing, incoming) {
|
|
315
582
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
@@ -330,21 +597,251 @@ export default class NetworkTopologyUtil {
|
|
|
330
597
|
errorsPerSecond: (_h = existing.errorsPerSecond) !== null && _h !== void 0 ? _h : incoming.errorsPerSecond,
|
|
331
598
|
};
|
|
332
599
|
}
|
|
600
|
+
/*
|
|
601
|
+
* Every key this device answers to.
|
|
602
|
+
*
|
|
603
|
+
* Unlike a claim's candidates, these are NOT speculative: we know which
|
|
604
|
+
* column each value came from, so a serial is only ever registered as a
|
|
605
|
+
* serial. That asymmetry is the whole point — a claim may offer its
|
|
606
|
+
* chassis id as a name, a serial and a MAC, but only the kind a device
|
|
607
|
+
* actually published can be the one that matches.
|
|
608
|
+
*/
|
|
333
609
|
static matchKeysForDevice(device) {
|
|
334
|
-
/*
|
|
335
|
-
* sysName / hostname / name — the identifiers LLDP remoteSysName and
|
|
336
|
-
* CDP remoteDeviceId advertise. Order matters only across devices
|
|
337
|
-
* (last writer wins on a collision), not within one device.
|
|
338
|
-
*/
|
|
339
610
|
const keys = [];
|
|
611
|
+
const seen = new Set();
|
|
612
|
+
const add = (key) => {
|
|
613
|
+
const keyId = NetworkTopologyUtil.matchKeyId(key);
|
|
614
|
+
if (seen.has(keyId)) {
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
seen.add(keyId);
|
|
618
|
+
keys.push(key);
|
|
619
|
+
};
|
|
620
|
+
// sysName / hostname / name — what both protocols advertise.
|
|
340
621
|
for (const candidate of [device.sysName, device.hostname, device.name]) {
|
|
341
|
-
const
|
|
342
|
-
if (
|
|
343
|
-
|
|
622
|
+
const normalized = NetworkTopologyUtil.normalizeKey(candidate);
|
|
623
|
+
if (!normalized) {
|
|
624
|
+
continue;
|
|
625
|
+
}
|
|
626
|
+
add({ kind: "name", value: normalized });
|
|
627
|
+
/*
|
|
628
|
+
* The short form is registered for EVERY name, dotted or not, so the
|
|
629
|
+
* two halves of the comparison meet: an FQDN on the wire has to be
|
|
630
|
+
* able to find a bare sysName here, and a bare name on the wire has
|
|
631
|
+
* to be able to find an FQDN.
|
|
632
|
+
*/
|
|
633
|
+
const shortHost = NetworkTopologyUtil.shortHostKey(normalized);
|
|
634
|
+
if (shortHost) {
|
|
635
|
+
add({ kind: "shortHost", value: shortHost });
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
const serial = NetworkTopologyUtil.normalizeKey(device.serialNumber);
|
|
639
|
+
if (serial) {
|
|
640
|
+
add({ kind: "serial", value: serial });
|
|
641
|
+
}
|
|
642
|
+
for (const rawMac of device.macAddresses || []) {
|
|
643
|
+
const mac = normalizeMac(rawMac);
|
|
644
|
+
if (mac) {
|
|
645
|
+
add({ kind: "mac", value: mac });
|
|
344
646
|
}
|
|
345
647
|
}
|
|
346
648
|
return keys;
|
|
347
649
|
}
|
|
650
|
+
/*
|
|
651
|
+
* Turns the unmatched claims into unmanaged peer NODES, one per box.
|
|
652
|
+
*
|
|
653
|
+
* Reports are merged when they share any identity-grade alias, so the
|
|
654
|
+
* neighbor one switch knows as "ap-lobby" and another knows only by its
|
|
655
|
+
* chassis MAC lands on a single node instead of the two strangers the map
|
|
656
|
+
* used to draw. Appends the nodes it mints to `nodes` and returns the node
|
|
657
|
+
* id each claim should draw its edge to.
|
|
658
|
+
*/
|
|
659
|
+
static buildUnmanagedPeerNodes(resolvedClaims, nodes) {
|
|
660
|
+
const unmanagedClaims = resolvedClaims.filter((resolved) => {
|
|
661
|
+
return !resolved.matchedDeviceId && resolved.peerAliases.length > 0;
|
|
662
|
+
});
|
|
663
|
+
const rootByAliasId = NetworkTopologyUtil.groupPeerAliases(unmanagedClaims);
|
|
664
|
+
// Claims per peer, in first-encounter order so the output is stable.
|
|
665
|
+
const claimsByRoot = new Map();
|
|
666
|
+
for (const resolved of unmanagedClaims) {
|
|
667
|
+
const root = rootByAliasId.get(NetworkTopologyUtil.matchKeyId(resolved.peerAliases[0]));
|
|
668
|
+
if (!root) {
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
const bucket = claimsByRoot.get(root);
|
|
672
|
+
if (bucket) {
|
|
673
|
+
bucket.push(resolved);
|
|
674
|
+
}
|
|
675
|
+
else {
|
|
676
|
+
claimsByRoot.set(root, [resolved]);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
const nodeIdByClaim = new Map();
|
|
680
|
+
const usedNodeIds = new Set();
|
|
681
|
+
for (const groupClaims of claimsByRoot.values()) {
|
|
682
|
+
/*
|
|
683
|
+
* The nicest label anyone reported: a name the peer advertises about
|
|
684
|
+
* itself beats a bare chassis id, whichever report arrived first.
|
|
685
|
+
*/
|
|
686
|
+
let displayName = undefined;
|
|
687
|
+
let platform = undefined;
|
|
688
|
+
for (const resolved of groupClaims) {
|
|
689
|
+
if (!displayName && resolved.claim.hasAdvertisedName) {
|
|
690
|
+
displayName = resolved.claim.displayName;
|
|
691
|
+
}
|
|
692
|
+
if (!platform && resolved.claim.remotePlatform) {
|
|
693
|
+
platform = resolved.claim.remotePlatform;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
if (!displayName) {
|
|
697
|
+
for (const resolved of groupClaims) {
|
|
698
|
+
if (resolved.claim.displayName) {
|
|
699
|
+
displayName = resolved.claim.displayName;
|
|
700
|
+
break;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
/*
|
|
705
|
+
* The id keeps its historic `unmanaged:<value>` shape — it is the key
|
|
706
|
+
* saved arrangements are stored under, so changing it would scatter
|
|
707
|
+
* every pinned peer on the map. It is named after the label wherever
|
|
708
|
+
* that label is one of the peer's own aliases, so merging a report
|
|
709
|
+
* that knew a sysName with one that knew only a chassis MAC still
|
|
710
|
+
* produces `unmanaged:ap-lobby` rather than an id made of hex.
|
|
711
|
+
*/
|
|
712
|
+
const nodeId = NetworkTopologyUtil.uniqueNodeId(`unmanaged:${NetworkTopologyUtil.canonicalPeerValue(groupClaims, displayName)}`, usedNodeIds);
|
|
713
|
+
usedNodeIds.add(nodeId);
|
|
714
|
+
const unmanagedName = displayName || "Unknown device";
|
|
715
|
+
nodes.push({
|
|
716
|
+
id: nodeId,
|
|
717
|
+
name: unmanagedName,
|
|
718
|
+
isManaged: false,
|
|
719
|
+
kind: "unmanaged",
|
|
720
|
+
/*
|
|
721
|
+
* Classified from the whole group rather than from whichever
|
|
722
|
+
* report happened to be first: the platform string is usually the
|
|
723
|
+
* only real evidence about a peer, and it may well arrive on the
|
|
724
|
+
* second report of it.
|
|
725
|
+
*/
|
|
726
|
+
role: classifyDeviceRole({
|
|
727
|
+
platform: platform,
|
|
728
|
+
name: unmanagedName,
|
|
729
|
+
}),
|
|
730
|
+
status: "unknown",
|
|
731
|
+
deviceModel: platform,
|
|
732
|
+
});
|
|
733
|
+
for (const resolved of groupClaims) {
|
|
734
|
+
nodeIdByClaim.set(resolved, nodeId);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
return nodeIdByClaim;
|
|
738
|
+
}
|
|
739
|
+
/*
|
|
740
|
+
* The alias a merged peer is named after.
|
|
741
|
+
*
|
|
742
|
+
* The chosen label wins whenever it is genuinely one of the peer's own
|
|
743
|
+
* aliases; otherwise the strongest kind present decides, and within it
|
|
744
|
+
* the lexicographically smallest value, so the id never depends on which
|
|
745
|
+
* switch happened to be polled first.
|
|
746
|
+
*/
|
|
747
|
+
static canonicalPeerValue(groupClaims, displayName) {
|
|
748
|
+
const valuesByKind = new Map();
|
|
749
|
+
for (const resolved of groupClaims) {
|
|
750
|
+
for (const alias of resolved.peerAliases) {
|
|
751
|
+
const bucket = valuesByKind.get(alias.kind);
|
|
752
|
+
if (bucket) {
|
|
753
|
+
if (!bucket.includes(alias.value)) {
|
|
754
|
+
bucket.push(alias.value);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
else {
|
|
758
|
+
valuesByKind.set(alias.kind, [alias.value]);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
const preferred = NetworkTopologyUtil.normalizeKey(displayName);
|
|
763
|
+
if (preferred && (valuesByKind.get("name") || []).includes(preferred)) {
|
|
764
|
+
return preferred;
|
|
765
|
+
}
|
|
766
|
+
for (const kind of MATCH_KEY_KINDS_STRONGEST_FIRST) {
|
|
767
|
+
const values = valuesByKind.get(kind);
|
|
768
|
+
if (values && values.length > 0) {
|
|
769
|
+
return [...values].sort()[0];
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
return "unknown-peer";
|
|
773
|
+
}
|
|
774
|
+
/*
|
|
775
|
+
* Two peers could in principle canonicalize to the same string (one by
|
|
776
|
+
* name, one by serial). Suffixing rather than merging keeps them the
|
|
777
|
+
* distinct boxes they are.
|
|
778
|
+
*/
|
|
779
|
+
static uniqueNodeId(preferred, used) {
|
|
780
|
+
if (!used.has(preferred)) {
|
|
781
|
+
return preferred;
|
|
782
|
+
}
|
|
783
|
+
let suffix = 2;
|
|
784
|
+
while (used.has(`${preferred}#${suffix}`)) {
|
|
785
|
+
suffix++;
|
|
786
|
+
}
|
|
787
|
+
return `${preferred}#${suffix}`;
|
|
788
|
+
}
|
|
789
|
+
/*
|
|
790
|
+
* Union-find over peer aliases: two reports that share ANY identity-grade
|
|
791
|
+
* alias describe one box. Returns the representative alias id for every
|
|
792
|
+
* alias seen.
|
|
793
|
+
*/
|
|
794
|
+
static groupPeerAliases(unmanagedClaims) {
|
|
795
|
+
const parent = new Map();
|
|
796
|
+
const find = (key) => {
|
|
797
|
+
let root = key;
|
|
798
|
+
let next = parent.get(root);
|
|
799
|
+
while (next !== undefined && next !== root) {
|
|
800
|
+
root = next;
|
|
801
|
+
next = parent.get(root);
|
|
802
|
+
}
|
|
803
|
+
// Path compression, so repeated lookups stay flat.
|
|
804
|
+
let cursor = key;
|
|
805
|
+
while (cursor !== root) {
|
|
806
|
+
const following = parent.get(cursor) || root;
|
|
807
|
+
parent.set(cursor, root);
|
|
808
|
+
cursor = following;
|
|
809
|
+
}
|
|
810
|
+
return root;
|
|
811
|
+
};
|
|
812
|
+
const union = (a, b) => {
|
|
813
|
+
const rootA = find(a);
|
|
814
|
+
const rootB = find(b);
|
|
815
|
+
if (rootA === rootB) {
|
|
816
|
+
return;
|
|
817
|
+
}
|
|
818
|
+
// Lexicographic tie-break, so the result ignores input order.
|
|
819
|
+
if (rootA < rootB) {
|
|
820
|
+
parent.set(rootB, rootA);
|
|
821
|
+
}
|
|
822
|
+
else {
|
|
823
|
+
parent.set(rootA, rootB);
|
|
824
|
+
}
|
|
825
|
+
};
|
|
826
|
+
for (const resolved of unmanagedClaims) {
|
|
827
|
+
const aliasIds = resolved.peerAliases.map((alias) => {
|
|
828
|
+
return NetworkTopologyUtil.matchKeyId(alias);
|
|
829
|
+
});
|
|
830
|
+
for (const aliasId of aliasIds) {
|
|
831
|
+
if (!parent.has(aliasId)) {
|
|
832
|
+
parent.set(aliasId, aliasId);
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
for (let index = 1; index < aliasIds.length; index++) {
|
|
836
|
+
union(aliasIds[0], aliasIds[index]);
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
const rootByAliasId = new Map();
|
|
840
|
+
for (const aliasId of parent.keys()) {
|
|
841
|
+
rootByAliasId.set(aliasId, find(aliasId));
|
|
842
|
+
}
|
|
843
|
+
return rootByAliasId;
|
|
844
|
+
}
|
|
348
845
|
static normalizeKey(value) {
|
|
349
846
|
if (!value) {
|
|
350
847
|
return undefined;
|
|
@@ -352,7 +849,16 @@ export default class NetworkTopologyUtil {
|
|
|
352
849
|
const trimmed = value.trim().toLowerCase();
|
|
353
850
|
return trimmed.length > 0 ? trimmed : undefined;
|
|
354
851
|
}
|
|
852
|
+
/*
|
|
853
|
+
* A stamped monitor status beats SNMP freshness, and freshness is the
|
|
854
|
+
* fallback — the same precedence SiteStatusRollupUtil already applies when
|
|
855
|
+
* it rolls devices up into a site, so a device cannot read "up" on the map
|
|
856
|
+
* and "down" on the site card above it.
|
|
857
|
+
*/
|
|
355
858
|
static deviceStatus(device, now) {
|
|
859
|
+
if (device.monitorStatus) {
|
|
860
|
+
return device.monitorStatus;
|
|
861
|
+
}
|
|
356
862
|
return NetworkTopologyUtil.statusFromLastSeen(device.lastSeenAt, now);
|
|
357
863
|
}
|
|
358
864
|
// The shared freshness rule: seen within the window = up, stale = down.
|