@oneuptime/common 14.0.8 → 14.0.10

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.
Files changed (976) hide show
  1. package/Models/DatabaseModels/AutoRemediationSuggestion.ts +60 -0
  2. package/Models/DatabaseModels/CephCluster.ts +213 -0
  3. package/Models/DatabaseModels/DatabaseServer.ts +213 -0
  4. package/Models/DatabaseModels/DockerHost.ts +213 -0
  5. package/Models/DatabaseModels/DockerSwarmCluster.ts +213 -0
  6. package/Models/DatabaseModels/GlobalConfig.ts +1 -1
  7. package/Models/DatabaseModels/Host.ts +213 -0
  8. package/Models/DatabaseModels/Index.ts +4 -0
  9. package/Models/DatabaseModels/KubernetesAiAgent.ts +364 -0
  10. package/Models/DatabaseModels/KubernetesCluster.ts +3 -3
  11. package/Models/DatabaseModels/PodmanHost.ts +213 -0
  12. package/Models/DatabaseModels/Project.ts +55 -5
  13. package/Models/DatabaseModels/ProxmoxCluster.ts +213 -0
  14. package/Models/DatabaseModels/ProxmoxResource.ts +49 -1
  15. package/Models/DatabaseModels/ResourceAiAgent.ts +419 -0
  16. package/Models/DatabaseModels/RunnerJob.ts +219 -0
  17. package/Models/DatabaseModels/TeamComplianceSetting.ts +143 -2
  18. package/Models/DatabaseModels/VMwareVCenter.ts +213 -0
  19. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +17 -0
  20. package/Server/API/AIChatAPI.ts +6 -3
  21. package/Server/API/AIInvestigationAPI.ts +17 -10
  22. package/Server/API/AutoRemediationAPI.ts +598 -25
  23. package/Server/API/KubernetesClusterAiAccessAPI.ts +623 -21
  24. package/Server/API/MicrosoftTeamsAPI.ts +93 -14
  25. package/Server/API/ProxmoxResourceAPI.ts +244 -14
  26. package/Server/API/ResourceAiAccessAPI.ts +1669 -0
  27. package/Server/Infrastructure/GlobalCache.ts +32 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.ts +99 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.ts +137 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.ts +42 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.ts +423 -0
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  33. package/Server/Infrastructure/Semaphore.ts +22 -0
  34. package/Server/Middleware/TelemetryIngest.ts +51 -18
  35. package/Server/Services/AIService.ts +70 -1
  36. package/Server/Services/AlertService.ts +352 -11
  37. package/Server/Services/AlertSeverityService.ts +65 -15
  38. package/Server/Services/AnalyticsDatabaseService.ts +45 -1
  39. package/Server/Services/AutoRemediationRuleEngineService.ts +940 -112
  40. package/Server/Services/AutoRemediationRuleService.ts +1 -1
  41. package/Server/Services/CephClusterService.ts +109 -1
  42. package/Server/Services/DatabaseServerService.ts +116 -1
  43. package/Server/Services/DockerHostService.ts +109 -1
  44. package/Server/Services/DockerSwarmClusterService.ts +113 -1
  45. package/Server/Services/HostService.ts +126 -4
  46. package/Server/Services/IncidentService.ts +280 -104
  47. package/Server/Services/IncidentSeverityService.ts +66 -15
  48. package/Server/Services/KubernetesAiAgentJobService.ts +185 -0
  49. package/Server/Services/KubernetesAiAgentService.ts +1634 -0
  50. package/Server/Services/KubernetesClusterAiAccessService.ts +1118 -451
  51. package/Server/Services/KubernetesClusterService.ts +129 -21
  52. package/Server/Services/MetricRecordingRuleService.ts +47 -0
  53. package/Server/Services/PodmanHostService.ts +109 -1
  54. package/Server/Services/ProjectService.ts +32 -0
  55. package/Server/Services/ProxmoxClusterService.ts +110 -1
  56. package/Server/Services/ProxmoxResourceService.ts +322 -5
  57. package/Server/Services/ResourceAiAccessService.ts +1439 -0
  58. package/Server/Services/ResourceAiAgentJobService.ts +202 -0
  59. package/Server/Services/ResourceAiAgentService.ts +2432 -0
  60. package/Server/Services/RunnerJobService.ts +852 -108
  61. package/Server/Services/RunnerService.ts +1 -1
  62. package/Server/Services/ScheduledMaintenanceService.ts +737 -1
  63. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +414 -56
  64. package/Server/Services/TeamComplianceSettingService.ts +1125 -9
  65. package/Server/Services/TelemetryUsageBillingService.ts +28 -0
  66. package/Server/Services/TraceRecordingRuleService.ts +33 -0
  67. package/Server/Services/VMwareVCenterService.ts +110 -1
  68. package/Server/Utils/AI/ClusterAccess/ClusterAccessContext.ts +67 -9
  69. package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +39 -10
  70. package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +14 -3
  71. package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +1475 -51
  72. package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +1000 -43
  73. package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +25 -1
  74. package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +577 -0
  75. package/Server/Utils/AI/ResourceAccess/ResourceAccessContext.ts +271 -0
  76. package/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.ts +45 -0
  77. package/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.ts +964 -0
  78. package/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.ts +333 -0
  79. package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +873 -0
  80. package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +120 -7
  81. package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +72 -5
  82. package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +72 -5
  83. package/Server/Utils/AI/SRE/IncidentPostmortemRunner.ts +40 -8
  84. package/Server/Utils/AI/SRE/InvestigationEligibility.ts +13 -2
  85. package/Server/Utils/AI/SRE/InvestigationGrader.ts +1 -1
  86. package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +402 -14
  87. package/Server/Utils/AutoRemediation/RemediationVerifier.ts +35 -2
  88. package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +9 -1
  89. package/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.ts +920 -0
  90. package/Server/Utils/SessionReplay/SessionReplayUsage.ts +84 -6
  91. package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +133 -7
  92. package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +58 -4
  93. package/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.ts +447 -0
  94. package/Server/Utils/Telemetry/ProxmoxNativePush.ts +903 -0
  95. package/Server/Utils/Telemetry/TelemetryEntity.ts +87 -27
  96. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +35 -15
  97. package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +33 -15
  98. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +21 -1
  99. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +298 -224
  100. package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +35 -15
  101. package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +389 -175
  102. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +1073 -213
  103. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.ts +163 -0
  104. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.ts +396 -0
  105. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.ts +418 -0
  106. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.ts +152 -0
  107. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.ts +251 -0
  108. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.ts +214 -0
  109. package/Tests/App/AdminDashboard/RowActionPlacementOverrides.test.tsx +278 -0
  110. package/Tests/App/Dashboard/AIChatChartWidgetZoom.test.tsx +738 -0
  111. package/Tests/App/Dashboard/AIFeaturesSettingsPointers.test.tsx +147 -0
  112. package/Tests/App/Dashboard/AIInsightsKubernetesClusterPage.test.tsx +1523 -0
  113. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +463 -3
  114. package/Tests/App/Dashboard/AffectedResourcesPickerDropdownPlacement.test.tsx +958 -0
  115. package/Tests/App/Dashboard/AffectedResourcesPickerFocusLeave.test.tsx +595 -0
  116. package/Tests/App/Dashboard/AskAiAvailability.test.ts +20 -3
  117. package/Tests/App/Dashboard/AskAiDisabled.test.tsx +8 -3
  118. package/Tests/App/Dashboard/CephRateChartReload.test.tsx +1456 -0
  119. package/Tests/App/Dashboard/CephTimeRangeZoom.test.tsx +1229 -0
  120. package/Tests/App/Dashboard/ChartCardTimeRangeZoom.test.tsx +151 -0
  121. package/Tests/App/Dashboard/ChartCardZoomAffordances.test.tsx +257 -0
  122. package/Tests/App/Dashboard/ChartRefetchFrame.test.tsx +141 -0
  123. package/Tests/App/Dashboard/ChartZoomHarness.tsx +249 -0
  124. package/Tests/App/Dashboard/ChartZoomStandIn.tsx +131 -0
  125. package/Tests/App/Dashboard/CloudServerlessSlowLoads.test.tsx +628 -0
  126. package/Tests/App/Dashboard/CloudServerlessTimeRangeZoom.test.tsx +607 -0
  127. package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +184 -19
  128. package/Tests/App/Dashboard/CompanionMetricsTabZoom.test.tsx +632 -0
  129. package/Tests/App/Dashboard/ContainerChartZoomStandIn.tsx +195 -0
  130. package/Tests/App/Dashboard/ContainerHostOverviewSlowLoads.test.tsx +542 -0
  131. package/Tests/App/Dashboard/ContainerHostOverviewTimeRangeZoom.test.tsx +848 -0
  132. package/Tests/App/Dashboard/ContainerMetricsTimeRangeZoom.test.tsx +561 -0
  133. package/Tests/App/Dashboard/DashboardBoardWideZoomShell.test.tsx +1147 -0
  134. package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +3 -2
  135. package/Tests/App/Dashboard/DashboardHistogramWidgetDragCursor.test.tsx +399 -0
  136. package/Tests/App/Dashboard/DashboardHistogramWidgetZoom.test.tsx +985 -0
  137. package/Tests/App/Dashboard/DashboardHistogramWidgetZoomHint.test.tsx +803 -0
  138. package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +1 -0
  139. package/Tests/App/Dashboard/DashboardSettingsPreviewZoom.test.tsx +679 -0
  140. package/Tests/App/Dashboard/DashboardSloAndDataSourceChartZoom.test.tsx +881 -0
  141. package/Tests/App/Dashboard/DashboardTraceStatusWidgets.test.tsx +878 -0
  142. package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +18 -6
  143. package/Tests/App/Dashboard/DatabaseMetricChartModalTimeRangeZoom.test.tsx +442 -0
  144. package/Tests/App/Dashboard/DatabaseOverviewTimeRangeZoom.test.tsx +831 -0
  145. package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +43 -0
  146. package/Tests/App/Dashboard/DockerSwarmInsightsTimeRangeZoom.test.tsx +524 -0
  147. package/Tests/App/Dashboard/DockerSwarmRateChartRefresh.test.tsx +259 -0
  148. package/Tests/App/Dashboard/EdgeDetailPanelHistory.test.tsx +763 -0
  149. package/Tests/App/Dashboard/EdgeDetailPanelTimeRangeZoom.test.tsx +547 -0
  150. package/Tests/App/Dashboard/EdgeHistoryBucketsCases.tsx +565 -0
  151. package/Tests/App/Dashboard/EdgeHistoryBucketsKathmandu.test.tsx +73 -0
  152. package/Tests/App/Dashboard/EdgeHistoryBucketsKolkata.test.tsx +74 -0
  153. package/Tests/App/Dashboard/EdgeHistoryBucketsNewYork.test.tsx +72 -0
  154. package/Tests/App/Dashboard/EdgeHistoryBucketsUtc.test.tsx +72 -0
  155. package/Tests/App/Dashboard/EmbeddedMetricCardRefresh.test.tsx +310 -0
  156. package/Tests/App/Dashboard/EmbeddedMetricCardTimeRangeZoom.test.tsx +536 -0
  157. package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +3 -1
  158. package/Tests/App/Dashboard/EscalationRuleRowActions.test.tsx +660 -0
  159. package/Tests/App/Dashboard/EventNotes.test.tsx +2 -2
  160. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +587 -13
  161. package/Tests/App/Dashboard/EventOverviewSnapshotExplorerZoom.test.tsx +1139 -0
  162. package/Tests/App/Dashboard/EventOverviewSnapshotZoomAcrossTabs.test.tsx +1057 -0
  163. package/Tests/App/Dashboard/EventOverviewTelemetrySnapshotZoom.test.tsx +757 -0
  164. package/Tests/App/Dashboard/ExceptionOccurrenceTrendZoom.test.tsx +675 -0
  165. package/Tests/App/Dashboard/ExceptionOccurrencesZoomSurvivesViewSwitch.test.tsx +405 -0
  166. package/Tests/App/Dashboard/ExceptionSignalPages.test.tsx +67 -3
  167. package/Tests/App/Dashboard/ExceptionTablesSpanStatus.test.tsx +515 -0
  168. package/Tests/App/Dashboard/ExplorerOwnZoomRegression.test.tsx +739 -0
  169. package/Tests/App/Dashboard/FlowBandwidthAxisCases.tsx +461 -0
  170. package/Tests/App/Dashboard/FlowBandwidthAxisKathmandu.test.tsx +25 -0
  171. package/Tests/App/Dashboard/FlowBandwidthAxisKolkata.test.tsx +25 -0
  172. package/Tests/App/Dashboard/FlowBandwidthAxisNewYork.test.tsx +25 -0
  173. package/Tests/App/Dashboard/FlowBandwidthAxisUtc.test.tsx +24 -0
  174. package/Tests/App/Dashboard/FlowTopTalkersZoomRefetch.test.tsx +722 -0
  175. package/Tests/App/Dashboard/FlowViewportGuard.test.tsx +2526 -0
  176. package/Tests/App/Dashboard/HostPagesSlowLoads.test.tsx +872 -0
  177. package/Tests/App/Dashboard/HostPagesTimeRangeZoom.test.tsx +1208 -0
  178. package/Tests/App/Dashboard/IncidentRootCauseTimeRangeZoom.test.tsx +358 -0
  179. package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +100 -9
  180. package/Tests/App/Dashboard/InfrastructureMetricsTabTimeRangeZoom.test.tsx +485 -0
  181. package/Tests/App/Dashboard/InvestigationDrawerCompanionZoom.test.tsx +655 -0
  182. package/Tests/App/Dashboard/InvestigationDrawerZoom.test.tsx +830 -0
  183. package/Tests/App/Dashboard/InvestigationInfrastructureTools.test.tsx +506 -0
  184. package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +338 -2
  185. package/Tests/App/Dashboard/InvoicesPayInvoice.test.tsx +454 -16
  186. package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +799 -819
  187. package/Tests/App/Dashboard/KubernetesClusterAiAgentOverviewCard.test.tsx +367 -0
  188. package/Tests/App/Dashboard/KubernetesClusterAiAgentStatus.test.ts +1202 -0
  189. package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +106 -0
  190. package/Tests/App/Dashboard/KubernetesClusterAiNavigation.test.tsx +354 -0
  191. package/Tests/App/Dashboard/KubernetesClusterAiPage.test.tsx +1884 -2054
  192. package/Tests/App/Dashboard/KubernetesClusterAiPageServerParity.test.ts +478 -179
  193. package/Tests/App/Dashboard/KubernetesClusterMetricTooltips.test.ts +50 -0
  194. package/Tests/App/Dashboard/KubernetesClusterOverviewTooltips.test.tsx +2 -1
  195. package/Tests/App/Dashboard/KubernetesClusterOverviewZoom.test.tsx +1217 -0
  196. package/Tests/App/Dashboard/KubernetesClusterPagesZoom.test.tsx +731 -0
  197. package/Tests/App/Dashboard/KubernetesCostsLoadRecovery.test.tsx +869 -0
  198. package/Tests/App/Dashboard/KubernetesCostsZoom.test.tsx +1214 -0
  199. package/Tests/App/Dashboard/KubernetesCostsZoomExactHours.test.tsx +692 -0
  200. package/Tests/App/Dashboard/KubernetesNetworkThroughputReload.test.tsx +902 -0
  201. package/Tests/App/Dashboard/KubernetesNetworkZoomBucketEdges.test.tsx +571 -0
  202. package/Tests/App/Dashboard/KubernetesOverviewZoomBucketEdges.test.tsx +697 -0
  203. package/Tests/App/Dashboard/KubernetesResourceMetricsTabZoom.test.tsx +633 -0
  204. package/Tests/App/Dashboard/LogsExplorerTimeRangeZoom.test.tsx +470 -0
  205. package/Tests/App/Dashboard/LogsInsightsTimeRangeZoom.test.tsx +948 -0
  206. package/Tests/App/Dashboard/LogsViewerPinnedWindowZoom.test.tsx +486 -0
  207. package/Tests/App/Dashboard/MetricChartsBucketInspectorDoubleClick.test.tsx +1001 -0
  208. package/Tests/App/Dashboard/MetricExplorerInvestigationAutoRefresh.test.tsx +514 -0
  209. package/Tests/App/Dashboard/MetricExplorerSavedViewZoomRoundTrip.test.tsx +581 -0
  210. package/Tests/App/Dashboard/MetricExplorerTimeRangeZoom.test.tsx +1162 -0
  211. package/Tests/App/Dashboard/MetricMonitorPreviewZoomLabel.test.ts +72 -0
  212. package/Tests/App/Dashboard/MetricRowSparklineTimeRangeZoom.test.tsx +204 -0
  213. package/Tests/App/Dashboard/MetricViewFirstResultLands.test.tsx +408 -0
  214. package/Tests/App/Dashboard/MetricViewOwnZoomResetPlacement.test.tsx +952 -0
  215. package/Tests/App/Dashboard/MetricViewTimeRange.test.ts +139 -0
  216. package/Tests/App/Dashboard/MetricViewTimeRangeZoom.test.tsx +556 -0
  217. package/Tests/App/Dashboard/MonitorMetricsChartWrappersZoom.test.tsx +552 -0
  218. package/Tests/App/Dashboard/MonitorMetricsTabsTimeRangeZoom.test.tsx +740 -0
  219. package/Tests/App/Dashboard/MonitorOverviewChartsTimeRangeZoom.test.tsx +735 -0
  220. package/Tests/App/Dashboard/MonitorStepPreviewsTimeRangeZoom.test.tsx +835 -0
  221. package/Tests/App/Dashboard/NetworkDeviceTimeRangeZoom.test.tsx +1115 -0
  222. package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +186 -17
  223. package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +155 -46
  224. package/Tests/App/Dashboard/PasskeySettings.test.tsx +87 -2
  225. package/Tests/App/Dashboard/ProjectAISettingsPages.test.tsx +884 -0
  226. package/Tests/App/Dashboard/ProxmoxNodeRemove.test.tsx +621 -0
  227. package/Tests/App/Dashboard/ProxmoxOverviewSlowLoads.test.tsx +584 -0
  228. package/Tests/App/Dashboard/ProxmoxPagesTimeRangeZoom.test.tsx +823 -0
  229. package/Tests/App/Dashboard/ProxmoxRateChartReload.test.tsx +1253 -0
  230. package/Tests/App/Dashboard/PublicDashboardBoardWideZoom.test.tsx +605 -0
  231. package/Tests/App/Dashboard/RealRowsLineChart.tsx +250 -0
  232. package/Tests/App/Dashboard/RechartsHostsPlotCursor.test.tsx +513 -0
  233. package/Tests/App/Dashboard/RemediationSuggestionCardDescription.test.tsx +209 -0
  234. package/Tests/App/Dashboard/RemediationSuggestionCardResource.test.tsx +317 -0
  235. package/Tests/App/Dashboard/ResourceAiAccessSettingsUtil.test.ts +921 -0
  236. package/Tests/App/Dashboard/ResourceAiAgentInstall.test.ts +860 -0
  237. package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +1721 -0
  238. package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +1002 -0
  239. package/Tests/App/Dashboard/ResourceAiInsightsPage.test.tsx +931 -0
  240. package/Tests/App/Dashboard/ResourceAiNavigation.test.tsx +575 -0
  241. package/Tests/App/Dashboard/RowActionPlacementOverrides.test.tsx +865 -0
  242. package/Tests/App/Dashboard/RumOverviewTimeRangeZoom.test.tsx +877 -0
  243. package/Tests/App/Dashboard/RunbookStepTypeMaps.test.ts +38 -7
  244. package/Tests/App/Dashboard/RunnerKubernetesAgentForm.test.tsx +20 -4
  245. package/Tests/App/Dashboard/RunnerSupersededByAiAgentNote.test.tsx +296 -0
  246. package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +146 -36
  247. package/Tests/App/Dashboard/ServiceDatabaseSlowLoads.test.tsx +1166 -0
  248. package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +1243 -104
  249. package/Tests/App/Dashboard/ServiceOverviewTimeRangeZoom.test.tsx +792 -0
  250. package/Tests/App/Dashboard/SloBudgetBurnDownZoom.test.tsx +771 -0
  251. package/Tests/App/Dashboard/SloBudgetBurnDownZoomAffordances.test.tsx +380 -0
  252. package/Tests/App/Dashboard/SloEventMetricsBarChartZoom.test.tsx +369 -0
  253. package/Tests/App/Dashboard/SloHistoryChartsTimeRangeZoom.test.tsx +694 -0
  254. package/Tests/App/Dashboard/SloHistoryChartsZoomAffordances.test.tsx +497 -0
  255. package/Tests/App/Dashboard/SloMetricsTimeRangeZoom.test.tsx +541 -0
  256. package/Tests/App/Dashboard/SlowLoadHarness.ts +123 -0
  257. package/Tests/App/Dashboard/SnapshotExplorerPrimaryZoom.test.tsx +1194 -0
  258. package/Tests/App/Dashboard/SnapshotViewerPinnedWindow.test.tsx +620 -0
  259. package/Tests/App/Dashboard/TelemetrySnapshotPanelTimeRangeZoom.test.tsx +765 -0
  260. package/Tests/App/Dashboard/TelemetrySnapshotZoom.test.tsx +516 -0
  261. package/Tests/App/Dashboard/TelemetrySnapshotZoomAcrossTabs.test.tsx +827 -0
  262. package/Tests/App/Dashboard/TimeRangeZoomPageHarness.tsx +463 -0
  263. package/Tests/App/Dashboard/TraceChartEditorStatusSplit.test.tsx +543 -0
  264. package/Tests/App/Dashboard/TraceStatusPresentation.test.tsx +967 -0
  265. package/Tests/App/Dashboard/TraceTimelineMinimapZoom.test.tsx +315 -0
  266. package/Tests/App/Dashboard/TracesAnalyticsStatusSplit.test.tsx +778 -0
  267. package/Tests/App/Dashboard/TracesAnalyticsViewZoom.test.tsx +349 -0
  268. package/Tests/App/Dashboard/TracesExplorerTimeRangeZoom.test.tsx +551 -0
  269. package/Tests/App/Dashboard/TracesStatusChartAndFacet.test.tsx +687 -0
  270. package/Tests/App/Dashboard/TracesViewerStaleResponses.test.tsx +458 -0
  271. package/Tests/App/Dashboard/UptimeStripsExcludedFromZoom.test.tsx +406 -0
  272. package/Tests/App/Dashboard/VMwareOverviewSlowLoads.test.tsx +535 -0
  273. package/Tests/App/Dashboard/VMwarePagesTimeRangeZoom.test.tsx +606 -0
  274. package/Tests/App/Dashboard/ValueWidgetSparklineStaleHover.test.tsx +1292 -0
  275. package/Tests/App/Dashboard/ValueWidgetSparklineZoom.test.tsx +765 -0
  276. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +98 -0
  277. package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +33 -1
  278. package/Tests/Models/DatabaseModels/KubernetesAiAgentModel.test.ts +295 -0
  279. package/Tests/Models/DatabaseModels/ResourceAiAccessColumns.test.ts +738 -0
  280. package/Tests/Models/DatabaseModels/ResourceAiAgentModel.test.ts +842 -0
  281. package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +347 -0
  282. package/Tests/Server/API/AIChatRouteAuthorization.test.ts +58 -0
  283. package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +1 -1
  284. package/Tests/Server/API/AIInvestigationAPI.test.ts +123 -45
  285. package/Tests/Server/API/AutoRemediationApproveClusterRound.test.ts +1329 -0
  286. package/Tests/Server/API/AutoRemediationApproveKubectlRecheck.test.ts +25 -2
  287. package/Tests/Server/API/AutoRemediationApproveResourceRound.test.ts +835 -0
  288. package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -0
  289. package/Tests/Server/API/KubernetesClusterAiAccessAPIAgent.test.ts +903 -0
  290. package/Tests/Server/API/MicrosoftTeamsChatsRefreshRoute.test.ts +667 -0
  291. package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +294 -6
  292. package/Tests/Server/API/ProxmoxResourceAPIRemoveNode.test.ts +1932 -0
  293. package/Tests/Server/API/ResourceAiAccessAPI.test.ts +2730 -0
  294. package/Tests/Server/Infrastructure/GlobalCache.test.ts +195 -0
  295. package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +60 -0
  296. package/Tests/Server/Infrastructure/Postgres/AddKubernetesAiAgentAndAiDefaultsMigration.test.ts +623 -0
  297. package/Tests/Server/Infrastructure/Postgres/AddKubernetesClusterAiAccessMigration.test.ts +87 -10
  298. package/Tests/Server/Infrastructure/Postgres/AddResourceAiAgentsMigration.test.ts +659 -0
  299. package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleScopeMigration.test.ts +622 -0
  300. package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +31 -0
  301. package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +119 -4
  302. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +196 -2
  303. package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +123 -2
  304. package/Tests/Server/Services/AIServiceBalanceBlocker.test.ts +282 -0
  305. package/Tests/Server/Services/AlertMonitorClearWritesNull.test.ts +409 -0
  306. package/Tests/Server/Services/AlertMonitorEditFeed.test.ts +474 -0
  307. package/Tests/Server/Services/AlertMonitorEditGuard.test.ts +610 -0
  308. package/Tests/Server/Services/AutoRemediationClusterRuleEngine.test.ts +2 -0
  309. package/Tests/Server/Services/AutoRemediationResourceRuleEngine.test.ts +1279 -0
  310. package/Tests/Server/Services/AutoRemediationRuleCommandRunners.test.ts +2 -1
  311. package/Tests/Server/Services/DatabaseServerService.test.ts +55 -0
  312. package/Tests/Server/Services/GroupTelemetryUsageExcludeNames.test.ts +299 -0
  313. package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +44 -0
  314. package/Tests/Server/Services/IncidentAffectedMonitorsEdit.test.ts +1360 -0
  315. package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +3 -1
  316. package/Tests/Server/Services/IncidentSeverityDeletePausesComplianceRules.test.ts +488 -0
  317. package/Tests/Server/Services/KubernetesAiAgentJobService.test.ts +329 -0
  318. package/Tests/Server/Services/KubernetesAiAgentServiceHelpers.test.ts +618 -0
  319. package/Tests/Server/Services/KubernetesAiAgentServiceLifecycle.test.ts +1444 -0
  320. package/Tests/Server/Services/KubernetesAiAgentServiceRegister.test.ts +1666 -0
  321. package/Tests/Server/Services/KubernetesClusterAiAccessDeletedRunnerRemedy.test.ts +140 -111
  322. package/Tests/Server/Services/KubernetesClusterAiAccessGapNextSteps.test.ts +267 -105
  323. package/Tests/Server/Services/KubernetesClusterAiAccessLegacySuperseded.test.ts +440 -0
  324. package/Tests/Server/Services/KubernetesClusterAiAccessService.test.ts +567 -411
  325. package/Tests/Server/Services/KubernetesClusterAiAccessTarget.test.ts +1168 -0
  326. package/Tests/Server/Services/KubernetesClusterAiSettingsPermission.test.ts +410 -12
  327. package/Tests/Server/Services/KubernetesClusterServiceAiAccessFeed.test.ts +55 -0
  328. package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +45 -6
  329. package/Tests/Server/Services/ProjectServiceNewProjectAiDefaults.test.ts +288 -0
  330. package/Tests/Server/Services/ProxmoxResourcePostgres.test.ts +5633 -0
  331. package/Tests/Server/Services/ProxmoxResourceService.test.ts +6458 -5
  332. package/Tests/Server/Services/RecordingRuleReservedMetricName.test.ts +171 -0
  333. package/Tests/Server/Services/ResourceAiAccessChangeAuthorization.test.ts +256 -0
  334. package/Tests/Server/Services/ResourceAiAccessService.test.ts +1373 -0
  335. package/Tests/Server/Services/ResourceAiAgentJobService.test.ts +375 -0
  336. package/Tests/Server/Services/ResourceAiAgentServiceHelpers.test.ts +1114 -0
  337. package/Tests/Server/Services/ResourceAiAgentServiceLifecycle.test.ts +1050 -0
  338. package/Tests/Server/Services/ResourceAiAgentServiceRegister.test.ts +2251 -0
  339. package/Tests/Server/Services/ResourceAiSettingsCreate.test.ts +373 -0
  340. package/Tests/Server/Services/ResourceAiSettingsPermission.test.ts +1042 -0
  341. package/Tests/Server/Services/ResourceServiceDeleteCleansUpAi.test.ts +319 -0
  342. package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +153 -15
  343. package/Tests/Server/Services/RunnerJobEnqueueKubectlAiAgent.test.ts +620 -0
  344. package/Tests/Server/Services/RunnerJobEnqueueResourceCommand.test.ts +986 -0
  345. package/Tests/Server/Services/RunnerJobKubectlWriteScope.test.ts +170 -3
  346. package/Tests/Server/Services/RunnerJobResourceCommandLane.test.ts +211 -0
  347. package/Tests/Server/Services/RunnerJobResourceCommandTimeoutAndRedaction.test.ts +352 -0
  348. package/Tests/Server/Services/RunnerJobTimeoutReason.test.ts +72 -0
  349. package/Tests/Server/Services/RunnerServiceAgentName.test.ts +6 -4
  350. package/Tests/Server/Services/ScheduledMaintenanceAttachmentEdit.test.ts +2113 -0
  351. package/Tests/Server/Services/ScheduledMaintenanceMonitorRelease.test.ts +972 -0
  352. package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +2237 -0
  353. package/Tests/Server/Services/TeamComplianceSettingService.test.ts +3988 -138
  354. package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +218 -0
  355. package/Tests/Server/TestingUtils/Services/FakeRunnerJobCount.ts +145 -0
  356. package/Tests/Server/Utils/AI/ClusterAccessContext.test.ts +107 -1
  357. package/Tests/Server/Utils/AI/IncidentPostmortemRunner.test.ts +351 -0
  358. package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +2 -0
  359. package/Tests/Server/Utils/AI/InvestigationEligibility.test.ts +310 -0
  360. package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +453 -0
  361. package/Tests/Server/Utils/AI/InvestigationInfrastructureReport.test.ts +721 -0
  362. package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +70 -0
  363. package/Tests/Server/Utils/AI/KubectlJobRunnerFinishedJob.test.ts +58 -0
  364. package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +94 -1
  365. package/Tests/Server/Utils/AI/RemediationCommandToolsKubectl.test.ts +2 -0
  366. package/Tests/Server/Utils/AI/RemediationCommandToolsKubectlOutcome.test.ts +2 -0
  367. package/Tests/Server/Utils/AI/RemediationCommandToolsLiveCluster.test.ts +2 -0
  368. package/Tests/Server/Utils/AI/RemediationCommandToolsResource.test.ts +1530 -0
  369. package/Tests/Server/Utils/AI/RemediationCommandToolsRunnerScope.test.ts +125 -1
  370. package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +252 -3
  371. package/Tests/Server/Utils/AI/RemediationExecutionRunnerClusterMode.test.ts +2 -0
  372. package/Tests/Server/Utils/AI/RemediationExecutionRunnerProjectGates.test.ts +240 -0
  373. package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +1249 -0
  374. package/Tests/Server/Utils/AI/RemediationKubectlCopyParity.test.ts +2 -0
  375. package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +117 -0
  376. package/Tests/Server/Utils/AI/RemediationResourceCopyParity.test.ts +463 -0
  377. package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +722 -0
  378. package/Tests/Server/Utils/AI/ResourceAccess/ResourceAccessContext.test.ts +266 -0
  379. package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.test.ts +1220 -0
  380. package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.test.ts +569 -0
  381. package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +830 -0
  382. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutor.test.ts +2 -0
  383. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorResource.test.ts +717 -0
  384. package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorUnknownRun.test.ts +2 -0
  385. package/Tests/Server/Utils/AutoRemediation/CommandPlanVerification.test.ts +2 -0
  386. package/Tests/Server/Utils/AutoRemediation/RemediationVerifierResourceFollowUp.test.ts +338 -0
  387. package/Tests/Server/Utils/Monitor/Criteria/SessionReplayBudgetTemplateCriteria.test.ts +422 -0
  388. package/Tests/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.test.ts +1647 -0
  389. package/Tests/Server/Utils/SessionReplay/SessionReplayUsage.test.ts +143 -1
  390. package/Tests/Server/Utils/Telemetry/HostAssetAttributesFromOtlp.test.ts +68 -0
  391. package/Tests/Server/Utils/Telemetry/InventoryMirrorPostgres.test.ts +370 -0
  392. package/Tests/Server/Utils/Telemetry/NetworkDeviceInventoryAttributes.test.ts +522 -0
  393. package/Tests/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.test.ts +155 -0
  394. package/Tests/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.test.ts +8631 -0
  395. package/Tests/Server/Utils/Telemetry/ProxmoxNativePush.test.ts +2852 -0
  396. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +367 -1
  397. package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +75 -3
  398. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsAccountNotLinked.test.ts +1093 -0
  399. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.test.ts +1049 -0
  400. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.test.ts +1676 -0
  401. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCards.test.ts +2884 -0
  402. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.test.ts +2490 -0
  403. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmit.test.ts +2293 -0
  404. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmitServerTimezone.test.ts +386 -0
  405. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.test.ts +1477 -0
  406. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.test.ts +1967 -0
  407. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsStripHtmlTags.test.ts +92 -0
  408. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsSubmittedFormRemoval.test.ts +1819 -0
  409. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.test.ts +1033 -0
  410. package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezoneServerZone.test.ts +610 -0
  411. package/Tests/Server/Utils/Workspace/MicrosoftTeamsBotMessageHandling.test.ts +2610 -0
  412. package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +25 -0
  413. package/Tests/Server/Utils/Workspace/MicrosoftTeamsCreateCommandsEndToEnd.test.ts +4672 -0
  414. package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNames.test.ts +3119 -0
  415. package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNamesPostgres.test.ts +1721 -0
  416. package/Tests/Server/Utils/Workspace/WorkspaceCreateProjectReferences.test.ts +190 -65
  417. package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +10 -4
  418. package/Tests/Types/AutoRemediation/AiRemediationCommandPlanResourceCommand.test.ts +305 -0
  419. package/Tests/Types/Kubernetes/KubernetesAgentChartAiAccess.test.ts +581 -113
  420. package/Tests/Types/Kubernetes/KubernetesAiAgentAccessContract.test.ts +510 -0
  421. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +277 -13
  422. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +113 -0
  423. package/Tests/Types/Monitor/RumAlertTemplates.test.ts +773 -2
  424. package/Tests/Types/ResourceAiAgent/AiResourceType.test.ts +419 -0
  425. package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +517 -0
  426. package/Tests/Types/Runbook/RunbookStepType.test.ts +147 -8
  427. package/Tests/Types/Team/ComplianceRule.test.ts +1029 -0
  428. package/Tests/Types/Team/TeamComplianceStatus.test.ts +176 -0
  429. package/Tests/UI/Components/ActionButton/RowActions.test.tsx +641 -0
  430. package/Tests/UI/Components/ActionButton/RowActionsAccessibility.test.tsx +414 -0
  431. package/Tests/UI/Components/ActionButton/SplitActionButtons.test.ts +565 -0
  432. package/Tests/UI/Components/Charts/BarChartDragToSelect.test.tsx +386 -0
  433. package/Tests/UI/Components/Charts/ChartDoubleClickResetWithoutDblclick.test.tsx +1025 -0
  434. package/Tests/UI/Components/Charts/ChartGroupPageZoomHint.test.tsx +196 -0
  435. package/Tests/UI/Components/Charts/ChartPlaceholdersTakeDoubleClick.test.tsx +1861 -0
  436. package/Tests/UI/Components/Charts/ChartPlotClicksWhileResetArmed.test.tsx +382 -0
  437. package/Tests/UI/Components/Charts/ChartRangeSelection.test.tsx +704 -0
  438. package/Tests/UI/Components/Charts/ChartRangeSelectionDoubleClickReset.test.tsx +1481 -0
  439. package/Tests/UI/Components/Charts/ChartRangeSelectionRealRecharts.test.tsx +918 -0
  440. package/Tests/UI/Components/Charts/ChartRowBucketStart.test.ts +350 -0
  441. package/Tests/UI/Components/Charts/DoubleClickReset.test.tsx +996 -0
  442. package/Tests/UI/Components/Charts/HistogramDoubleClickResetRealRecharts.test.tsx +965 -0
  443. package/Tests/UI/Components/Charts/HistogramDriftThenRefetch.test.tsx +277 -0
  444. package/Tests/UI/Components/Charts/HistogramRangeSelectionDataChange.test.tsx +1757 -0
  445. package/Tests/UI/Components/Charts/HistogramRangeSelectionRealRecharts.test.tsx +560 -0
  446. package/Tests/UI/Components/Charts/TimeRangeZoom/ChartPageTimeRangeZoom.test.tsx +513 -0
  447. package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.test.tsx +845 -0
  448. package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.test.tsx +119 -0
  449. package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHintTailwind.test.tsx +274 -0
  450. package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.test.ts +433 -0
  451. package/Tests/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.test.tsx +863 -0
  452. package/Tests/UI/Components/Charts/TimeRangeZoom/ZoomDocsPromises.test.tsx +1147 -0
  453. package/Tests/UI/Components/DisabledButtonTooltip.test.tsx +14 -3
  454. package/Tests/UI/Components/EntityDropdownEscape.test.tsx +454 -0
  455. package/Tests/UI/Components/EntityDropdownFocusLeave.test.tsx +420 -0
  456. package/Tests/UI/Components/Forms/FormFieldDropdownDisabled.test.tsx +233 -0
  457. package/Tests/UI/Components/Input.test.tsx +80 -1
  458. package/Tests/UI/Components/LogsAnalyticsViewZoom.test.tsx +947 -0
  459. package/Tests/UI/Components/LogsHistogramDragTooltip.test.tsx +17 -5
  460. package/Tests/UI/Components/LogsViewerAnalyticsZoom.test.tsx +501 -0
  461. package/Tests/UI/Components/LogsViewerHistogramZoom.test.tsx +1 -1
  462. package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +6 -4
  463. package/Tests/UI/Components/ModelTable/BaseModelTablePermissionGating.test.tsx +60 -8
  464. package/Tests/UI/Components/ModelTable/BaseModelTableRowActions.test.tsx +476 -0
  465. package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +7 -5
  466. package/Tests/UI/Components/MoreMenuPortal.test.tsx +623 -0
  467. package/Tests/UI/Components/StatusPage/ResourceGridActions.test.tsx +538 -0
  468. package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +14 -4
  469. package/Tests/UI/Components/TableCellWrapping.test.tsx +3 -3
  470. package/Tests/UI/Components/TableRowActions.test.tsx +472 -0
  471. package/Tests/UI/Components/TelemetryHistogramDragTooltip.test.tsx +1 -1
  472. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerHistogramClickZoom.test.tsx +1 -1
  473. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerZoomScope.test.tsx +470 -0
  474. package/Tests/UI/Components/TelemetryViewer/UseViewerTimeRangeZoom.test.tsx +571 -0
  475. package/Tests/UI/Components/TelemetryViewer/ViewerDoubleClickResetUnderDataChange.test.tsx +928 -0
  476. package/Tests/UI/Components/TelemetryViewer/ViewerFollowsEnclosingZoom.test.tsx +1569 -0
  477. package/Tests/UI/Components/Toggle.test.tsx +66 -0
  478. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardRefreshNames.test.tsx +1023 -0
  479. package/Tests/UI/Rum/ChunkLoader.test.ts +201 -0
  480. package/Tests/UI/Rum/FidelityNotices.test.ts +54 -0
  481. package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +769 -1
  482. package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +72 -0
  483. package/Tests/UI/Rum/ReplayFrameCapture.test.ts +1009 -9
  484. package/Tests/UI/Rum/ReplayRecordedAssets.test.ts +1069 -0
  485. package/Tests/UI/Rum/ReplayStage.test.tsx +913 -2
  486. package/Tests/UI/Rum/SessionReplayTable.test.tsx +443 -8
  487. package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +439 -9
  488. package/Tests/UI/Rum/UserFlowTablesRowActions.test.tsx +501 -0
  489. package/Tests/Utils/AiRemediation/KubectlPolicyChartRbacParity.test.ts +47 -19
  490. package/Tests/Utils/AiRemediation/KubectlWriteScopeCallerParity.test.ts +2 -0
  491. package/Tests/Utils/AiRemediation/KubernetesAiAgentPolicyCopyParity.test.ts +396 -0
  492. package/Tests/Utils/AiRemediation/Resource/CephCommandPolicy.test.ts +1653 -0
  493. package/Tests/Utils/AiRemediation/Resource/CephOutputRedaction.test.ts +204 -0
  494. package/Tests/Utils/AiRemediation/Resource/DatabaseCommandPolicy.test.ts +1077 -0
  495. package/Tests/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.test.ts +558 -0
  496. package/Tests/Utils/AiRemediation/Resource/DatabaseQueryRedactor.test.ts +834 -0
  497. package/Tests/Utils/AiRemediation/Resource/DockerCliGrammar.test.ts +747 -0
  498. package/Tests/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.test.ts +1259 -0
  499. package/Tests/Utils/AiRemediation/Resource/DockerOutputRedaction.test.ts +386 -0
  500. package/Tests/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.test.ts +782 -0
  501. package/Tests/Utils/AiRemediation/Resource/GovcCommandPolicy.test.ts +2259 -0
  502. package/Tests/Utils/AiRemediation/Resource/HostCommandPolicy.test.ts +2019 -0
  503. package/Tests/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.test.ts +2497 -0
  504. package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicy.test.ts +1305 -0
  505. package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.test.ts +585 -0
  506. package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactor.test.ts +334 -0
  507. package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactorCopyParity.test.ts +98 -0
  508. package/Tests/Utils/AiRemediation/Resource/ResourcePolicyImportClosure.test.ts +391 -0
  509. package/Tests/Utils/AiRemediation/ResourceAiAgentPolicyCopyParity.test.ts +497 -0
  510. package/Tests/Utils/Dashboard/DashboardTimeRangeZoom.test.ts +104 -1
  511. package/Tests/Utils/SessionReplay/SessionReplayBudgetMetricType.test.ts +383 -0
  512. package/Types/AI/AIRunType.ts +9 -4
  513. package/Types/AI/InvestigationNotStartedReason.ts +6 -0
  514. package/Types/AI/ResourceAiAccessApi.ts +140 -0
  515. package/Types/AI/ResourceAiAccessPermissions.ts +126 -0
  516. package/Types/AutoRemediation/AiRemediationCommandPlan.ts +197 -18
  517. package/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.ts +28 -0
  518. package/Types/Dashboard/DashboardComponents/DashboardTraceChartComponent.ts +4 -2
  519. package/Types/Kubernetes/KubernetesClusterAiAccess.ts +263 -32
  520. package/Types/Kubernetes/KubernetesClusterAiAccessPermissions.ts +20 -16
  521. package/Types/Kubernetes/KubernetesClusterAiInsights.ts +81 -0
  522. package/Types/Monitor/ProxmoxAlertTemplates.ts +4 -4
  523. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +55 -22
  524. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +35 -3
  525. package/Types/Monitor/RumAlertTemplates.ts +351 -4
  526. package/Types/ResourceAiAgent/AiResourceType.ts +310 -0
  527. package/Types/ResourceAiAgent/ResourceAiAccess.ts +574 -0
  528. package/Types/Rum/SessionReplayBudgetMetricType.ts +47 -0
  529. package/Types/Runbook/RunbookStepType.ts +29 -0
  530. package/Types/Team/ComplianceNotificationChannel.ts +22 -0
  531. package/Types/Team/ComplianceRule.ts +434 -0
  532. package/Types/Team/ComplianceRuleType.ts +21 -0
  533. package/Types/Team/TeamComplianceStatus.ts +81 -0
  534. package/Types/Telemetry/TelemetryIngestSurface.ts +40 -0
  535. package/UI/Components/ActionButton/ActionButtonSchema.ts +21 -0
  536. package/UI/Components/ActionButton/RowActions.tsx +238 -0
  537. package/UI/Components/ActionButton/SplitActionButtons.ts +173 -0
  538. package/UI/Components/Charts/Area/AreaChart.tsx +32 -2
  539. package/UI/Components/Charts/Bar/BarChart.tsx +40 -3
  540. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +37 -11
  541. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +80 -243
  542. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +122 -31
  543. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +95 -244
  544. package/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.ts +214 -0
  545. package/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.ts +32 -0
  546. package/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.ts +599 -0
  547. package/UI/Components/Charts/Line/LineChart.tsx +32 -2
  548. package/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.tsx +70 -0
  549. package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.tsx +226 -0
  550. package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.tsx +73 -0
  551. package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.ts +163 -0
  552. package/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.ts +215 -0
  553. package/UI/Components/Charts/Utils/DataPoint.ts +20 -8
  554. package/UI/Components/Charts/Utils/XAxis.ts +75 -0
  555. package/UI/Components/Charts/Utils/useHistogramRangeSelection.ts +493 -59
  556. package/UI/Components/EntityDropdown/EntityDropdown.tsx +107 -11
  557. package/UI/Components/Forms/Fields/FormField.tsx +10 -0
  558. package/UI/Components/Input/Input.tsx +90 -57
  559. package/UI/Components/List/ListRow.tsx +8 -74
  560. package/UI/Components/LogsViewer/LogsViewer.tsx +40 -11
  561. package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +22 -6
  562. package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +209 -6
  563. package/UI/Components/LogsViewer/components/LogsHistogram.tsx +127 -84
  564. package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +3 -0
  565. package/UI/Components/ModelTable/BaseModelTable.tsx +12 -1
  566. package/UI/Components/MoreMenu/MoreMenu.tsx +365 -30
  567. package/UI/Components/MoreMenu/MoreMenuItem.tsx +70 -17
  568. package/UI/Components/OrderedStatesList/Item.tsx +7 -72
  569. package/UI/Components/StatusPage/ResourceGrid.tsx +126 -77
  570. package/UI/Components/Table/TableBody.tsx +8 -2
  571. package/UI/Components/Table/TableRow.tsx +20 -140
  572. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +41 -10
  573. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +47 -9
  574. package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +25 -6
  575. package/UI/Components/TelemetryViewer/types.ts +2 -0
  576. package/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.ts +448 -0
  577. package/UI/Components/Toggle/Toggle.tsx +26 -0
  578. package/UI/Components/Tooltip/Tooltip.tsx +8 -1
  579. package/UI/Styles/Theme.css +14 -2
  580. package/Utils/AI/InvestigationReport.ts +121 -15
  581. package/Utils/AiRemediation/CommandPolicy.ts +1 -1
  582. package/Utils/AiRemediation/KubectlPolicy.ts +1 -1
  583. package/Utils/AiRemediation/Resource/CephCommandPolicy.ts +1936 -0
  584. package/Utils/AiRemediation/Resource/DatabaseCommandPolicy.ts +166 -0
  585. package/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.ts +1532 -0
  586. package/Utils/AiRemediation/Resource/DatabaseQueryRedactor.ts +1394 -0
  587. package/Utils/AiRemediation/Resource/DockerCliGrammar.ts +1839 -0
  588. package/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.ts +490 -0
  589. package/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.ts +687 -0
  590. package/Utils/AiRemediation/Resource/GovcCommandPolicy.ts +2096 -0
  591. package/Utils/AiRemediation/Resource/HostCommandPolicy.ts +2982 -0
  592. package/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.ts +1679 -0
  593. package/Utils/AiRemediation/Resource/ResourceCommandPolicy.ts +851 -0
  594. package/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.ts +593 -0
  595. package/Utils/AiRemediation/Resource/ResourceOutputRedactor.ts +2812 -0
  596. package/Utils/Dashboard/DashboardTimeRangeZoom.ts +46 -2
  597. package/Utils/SessionReplay/SessionReplayBudgetMetricType.ts +184 -0
  598. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +62 -0
  599. package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -1
  600. package/build/dist/Models/DatabaseModels/CephCluster.js +219 -0
  601. package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
  602. package/build/dist/Models/DatabaseModels/DatabaseServer.js +219 -0
  603. package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
  604. package/build/dist/Models/DatabaseModels/DockerHost.js +219 -0
  605. package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
  606. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +219 -0
  607. package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
  608. package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
  609. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  610. package/build/dist/Models/DatabaseModels/Host.js +219 -0
  611. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  612. package/build/dist/Models/DatabaseModels/Index.js +4 -0
  613. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  614. package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js +385 -0
  615. package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js.map +1 -0
  616. package/build/dist/Models/DatabaseModels/KubernetesCluster.js +3 -3
  617. package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
  618. package/build/dist/Models/DatabaseModels/PodmanHost.js +219 -0
  619. package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
  620. package/build/dist/Models/DatabaseModels/Project.js +56 -5
  621. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  622. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +219 -0
  623. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
  624. package/build/dist/Models/DatabaseModels/ProxmoxResource.js +51 -1
  625. package/build/dist/Models/DatabaseModels/ProxmoxResource.js.map +1 -1
  626. package/build/dist/Models/DatabaseModels/ResourceAiAgent.js +439 -0
  627. package/build/dist/Models/DatabaseModels/ResourceAiAgent.js.map +1 -0
  628. package/build/dist/Models/DatabaseModels/RunnerJob.js +219 -0
  629. package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
  630. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +134 -3
  631. package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
  632. package/build/dist/Models/DatabaseModels/VMwareVCenter.js +219 -0
  633. package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
  634. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  635. package/build/dist/Server/API/AIChatAPI.js +6 -1
  636. package/build/dist/Server/API/AIChatAPI.js.map +1 -1
  637. package/build/dist/Server/API/AIInvestigationAPI.js +17 -10
  638. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  639. package/build/dist/Server/API/AutoRemediationAPI.js +374 -24
  640. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
  641. package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js +436 -22
  642. package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js.map +1 -1
  643. package/build/dist/Server/API/MicrosoftTeamsAPI.js +69 -13
  644. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  645. package/build/dist/Server/API/ProxmoxResourceAPI.js +187 -14
  646. package/build/dist/Server/API/ProxmoxResourceAPI.js.map +1 -1
  647. package/build/dist/Server/API/ResourceAiAccessAPI.js +1119 -0
  648. package/build/dist/Server/API/ResourceAiAccessAPI.js.map +1 -0
  649. package/build/dist/Server/Infrastructure/GlobalCache.js +27 -0
  650. package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
  651. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js +50 -0
  652. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js.map +1 -0
  653. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js +84 -0
  654. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js.map +1 -0
  655. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js +31 -0
  656. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js.map +1 -0
  657. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js +168 -0
  658. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js.map +1 -0
  659. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  660. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  661. package/build/dist/Server/Infrastructure/Semaphore.js +6 -0
  662. package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
  663. package/build/dist/Server/Middleware/TelemetryIngest.js +41 -19
  664. package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
  665. package/build/dist/Server/Services/AIService.js +59 -1
  666. package/build/dist/Server/Services/AIService.js.map +1 -1
  667. package/build/dist/Server/Services/AlertService.js +248 -13
  668. package/build/dist/Server/Services/AlertService.js.map +1 -1
  669. package/build/dist/Server/Services/AlertSeverityService.js +51 -15
  670. package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
  671. package/build/dist/Server/Services/AnalyticsDatabaseService.js +26 -1
  672. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  673. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +601 -3
  674. package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
  675. package/build/dist/Server/Services/AutoRemediationRuleService.js +1 -1
  676. package/build/dist/Server/Services/AutoRemediationRuleService.js.map +1 -1
  677. package/build/dist/Server/Services/CephClusterService.js +104 -0
  678. package/build/dist/Server/Services/CephClusterService.js.map +1 -1
  679. package/build/dist/Server/Services/DatabaseServerService.js +99 -0
  680. package/build/dist/Server/Services/DatabaseServerService.js.map +1 -1
  681. package/build/dist/Server/Services/DockerHostService.js +104 -0
  682. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  683. package/build/dist/Server/Services/DockerSwarmClusterService.js +104 -0
  684. package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
  685. package/build/dist/Server/Services/HostService.js +114 -2
  686. package/build/dist/Server/Services/HostService.js.map +1 -1
  687. package/build/dist/Server/Services/IncidentService.js +199 -72
  688. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  689. package/build/dist/Server/Services/IncidentSeverityService.js +51 -15
  690. package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
  691. package/build/dist/Server/Services/KubernetesAiAgentJobService.js +158 -0
  692. package/build/dist/Server/Services/KubernetesAiAgentJobService.js.map +1 -0
  693. package/build/dist/Server/Services/KubernetesAiAgentService.js +1145 -0
  694. package/build/dist/Server/Services/KubernetesAiAgentService.js.map +1 -0
  695. package/build/dist/Server/Services/KubernetesClusterAiAccessService.js +842 -371
  696. package/build/dist/Server/Services/KubernetesClusterAiAccessService.js.map +1 -1
  697. package/build/dist/Server/Services/KubernetesClusterService.js +86 -17
  698. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  699. package/build/dist/Server/Services/MetricRecordingRuleService.js +46 -0
  700. package/build/dist/Server/Services/MetricRecordingRuleService.js.map +1 -1
  701. package/build/dist/Server/Services/PodmanHostService.js +104 -0
  702. package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
  703. package/build/dist/Server/Services/ProjectService.js +22 -0
  704. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  705. package/build/dist/Server/Services/ProxmoxClusterService.js +104 -0
  706. package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
  707. package/build/dist/Server/Services/ProxmoxResourceService.js +258 -3
  708. package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -1
  709. package/build/dist/Server/Services/ResourceAiAccessService.js +1028 -0
  710. package/build/dist/Server/Services/ResourceAiAccessService.js.map +1 -0
  711. package/build/dist/Server/Services/ResourceAiAgentJobService.js +173 -0
  712. package/build/dist/Server/Services/ResourceAiAgentJobService.js.map +1 -0
  713. package/build/dist/Server/Services/ResourceAiAgentService.js +1687 -0
  714. package/build/dist/Server/Services/ResourceAiAgentService.js.map +1 -0
  715. package/build/dist/Server/Services/RunnerJobService.js +522 -97
  716. package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
  717. package/build/dist/Server/Services/RunnerService.js +1 -1
  718. package/build/dist/Server/Services/RunnerService.js.map +1 -1
  719. package/build/dist/Server/Services/ScheduledMaintenanceService.js +535 -3
  720. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  721. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +316 -46
  722. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  723. package/build/dist/Server/Services/TeamComplianceSettingService.js +833 -7
  724. package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
  725. package/build/dist/Server/Services/TelemetryUsageBillingService.js +26 -0
  726. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  727. package/build/dist/Server/Services/TraceRecordingRuleService.js +37 -0
  728. package/build/dist/Server/Services/TraceRecordingRuleService.js.map +1 -1
  729. package/build/dist/Server/Services/VMwareVCenterService.js +104 -0
  730. package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -1
  731. package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js +52 -9
  732. package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js.map +1 -1
  733. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +13 -9
  734. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
  735. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +7 -3
  736. package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
  737. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +1056 -43
  738. package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
  739. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +683 -42
  740. package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
  741. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +21 -1
  742. package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
  743. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +330 -0
  744. package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -0
  745. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js +160 -0
  746. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js.map +1 -0
  747. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js +33 -0
  748. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js.map +1 -0
  749. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js +640 -0
  750. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js.map +1 -0
  751. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js +226 -0
  752. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js.map +1 -0
  753. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +600 -0
  754. package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -0
  755. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +89 -9
  756. package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
  757. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +55 -4
  758. package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
  759. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +55 -4
  760. package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
  761. package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js +30 -3
  762. package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js.map +1 -1
  763. package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js +13 -2
  764. package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js.map +1 -1
  765. package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +1 -1
  766. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +294 -15
  767. package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
  768. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +29 -1
  769. package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -1
  770. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +9 -1
  771. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
  772. package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js +627 -0
  773. package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js.map +1 -0
  774. package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js +60 -5
  775. package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js.map +1 -1
  776. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +111 -6
  777. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -1
  778. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +40 -4
  779. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -1
  780. package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js +296 -0
  781. package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js.map +1 -0
  782. package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js +699 -0
  783. package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js.map +1 -0
  784. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +77 -19
  785. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  786. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +19 -15
  787. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
  788. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +19 -15
  789. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
  790. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +17 -1
  791. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
  792. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +183 -209
  793. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
  794. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +19 -15
  795. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
  796. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +233 -167
  797. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -1
  798. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +768 -152
  799. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  800. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js +129 -0
  801. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js.map +1 -0
  802. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js +266 -0
  803. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js.map +1 -0
  804. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js +258 -0
  805. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js.map +1 -0
  806. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js +104 -0
  807. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js.map +1 -0
  808. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js +183 -0
  809. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js.map +1 -0
  810. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js +123 -0
  811. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js.map +1 -0
  812. package/build/dist/Types/AI/AIRunType.js +9 -4
  813. package/build/dist/Types/AI/AIRunType.js.map +1 -1
  814. package/build/dist/Types/AI/ResourceAiAccessApi.js +30 -0
  815. package/build/dist/Types/AI/ResourceAiAccessApi.js.map +1 -0
  816. package/build/dist/Types/AI/ResourceAiAccessPermissions.js +98 -0
  817. package/build/dist/Types/AI/ResourceAiAccessPermissions.js.map +1 -0
  818. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +126 -45
  819. package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
  820. package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js +28 -0
  821. package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js.map +1 -0
  822. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +72 -16
  823. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
  824. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js +20 -16
  825. package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js.map +1 -1
  826. package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js +17 -0
  827. package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js.map +1 -0
  828. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +4 -4
  829. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -1
  830. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +47 -21
  831. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
  832. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +5 -0
  833. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
  834. package/build/dist/Types/Monitor/RumAlertTemplates.js +199 -3
  835. package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
  836. package/build/dist/Types/ResourceAiAgent/AiResourceType.js +242 -0
  837. package/build/dist/Types/ResourceAiAgent/AiResourceType.js.map +1 -0
  838. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +275 -0
  839. package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -0
  840. package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js +45 -0
  841. package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js.map +1 -0
  842. package/build/dist/Types/Runbook/RunbookStepType.js +27 -0
  843. package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
  844. package/build/dist/Types/Team/ComplianceNotificationChannel.js +23 -0
  845. package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -0
  846. package/build/dist/Types/Team/ComplianceRule.js +304 -0
  847. package/build/dist/Types/Team/ComplianceRule.js.map +1 -0
  848. package/build/dist/Types/Team/ComplianceRuleType.js +21 -0
  849. package/build/dist/Types/Team/ComplianceRuleType.js.map +1 -1
  850. package/build/dist/Types/Team/TeamComplianceStatus.js +2 -0
  851. package/build/dist/Types/Team/TeamComplianceStatus.js.map +1 -0
  852. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +36 -0
  853. package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
  854. package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js +20 -1
  855. package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js.map +1 -1
  856. package/build/dist/UI/Components/ActionButton/RowActions.js +113 -0
  857. package/build/dist/UI/Components/ActionButton/RowActions.js.map +1 -0
  858. package/build/dist/UI/Components/ActionButton/SplitActionButtons.js +71 -0
  859. package/build/dist/UI/Components/ActionButton/SplitActionButtons.js.map +1 -0
  860. package/build/dist/UI/Components/Charts/Area/AreaChart.js +16 -1
  861. package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
  862. package/build/dist/UI/Components/Charts/Bar/BarChart.js +16 -1
  863. package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
  864. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +27 -5
  865. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  866. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +61 -194
  867. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  868. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +84 -26
  869. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  870. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +75 -196
  871. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  872. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js +133 -0
  873. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js.map +1 -1
  874. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js +26 -0
  875. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js.map +1 -0
  876. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js +371 -0
  877. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js.map +1 -0
  878. package/build/dist/UI/Components/Charts/Line/LineChart.js +16 -1
  879. package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
  880. package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js +35 -0
  881. package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js.map +1 -0
  882. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js +107 -0
  883. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js.map +1 -0
  884. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js +41 -0
  885. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js.map +1 -0
  886. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js +117 -0
  887. package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js.map +1 -0
  888. package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js +121 -0
  889. package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js.map +1 -0
  890. package/build/dist/UI/Components/Charts/Utils/DataPoint.js +15 -7
  891. package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
  892. package/build/dist/UI/Components/Charts/Utils/XAxis.js +70 -0
  893. package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
  894. package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js +305 -38
  895. package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js.map +1 -1
  896. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +89 -14
  897. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  898. package/build/dist/UI/Components/Forms/Fields/FormField.js +11 -2
  899. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  900. package/build/dist/UI/Components/Input/Input.js +69 -54
  901. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  902. package/build/dist/UI/Components/List/ListRow.js +4 -39
  903. package/build/dist/UI/Components/List/ListRow.js.map +1 -1
  904. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +31 -8
  905. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  906. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +10 -1
  907. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
  908. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +139 -21
  909. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
  910. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +30 -8
  911. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
  912. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +1 -1
  913. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
  914. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +10 -0
  915. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  916. package/build/dist/UI/Components/MoreMenu/MoreMenu.js +253 -14
  917. package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
  918. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +43 -13
  919. package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
  920. package/build/dist/UI/Components/OrderedStatesList/Item.js +2 -38
  921. package/build/dist/UI/Components/OrderedStatesList/Item.js.map +1 -1
  922. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +53 -15
  923. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
  924. package/build/dist/UI/Components/Table/TableBody.js +6 -2
  925. package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
  926. package/build/dist/UI/Components/Table/TableRow.js +12 -75
  927. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  928. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +32 -7
  929. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  930. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +27 -9
  931. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  932. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +11 -1
  933. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
  934. package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js +272 -0
  935. package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js.map +1 -0
  936. package/build/dist/UI/Components/Toggle/Toggle.js +14 -1
  937. package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
  938. package/build/dist/UI/Components/Tooltip/Tooltip.js +1 -1
  939. package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
  940. package/build/dist/Utils/AI/InvestigationReport.js +71 -11
  941. package/build/dist/Utils/AI/InvestigationReport.js.map +1 -1
  942. package/build/dist/Utils/AiRemediation/CommandPolicy.js +1 -1
  943. package/build/dist/Utils/AiRemediation/CommandPolicy.js.map +1 -1
  944. package/build/dist/Utils/AiRemediation/KubectlPolicy.js +1 -1
  945. package/build/dist/Utils/AiRemediation/KubectlPolicy.js.map +1 -1
  946. package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js +1462 -0
  947. package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js.map +1 -0
  948. package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js +122 -0
  949. package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js.map +1 -0
  950. package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js +1139 -0
  951. package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js.map +1 -0
  952. package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js +1060 -0
  953. package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js.map +1 -0
  954. package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js +1301 -0
  955. package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js.map +1 -0
  956. package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js +370 -0
  957. package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js.map +1 -0
  958. package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js +498 -0
  959. package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js.map +1 -0
  960. package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js +1565 -0
  961. package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js.map +1 -0
  962. package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js +2206 -0
  963. package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js.map +1 -0
  964. package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js +1129 -0
  965. package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js.map +1 -0
  966. package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js +565 -0
  967. package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js.map +1 -0
  968. package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js +408 -0
  969. package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js.map +1 -0
  970. package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js +1910 -0
  971. package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js.map +1 -0
  972. package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js +27 -1
  973. package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js.map +1 -1
  974. package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js +160 -0
  975. package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js.map +1 -0
  976. package/package.json +1 -1
@@ -0,0 +1,1910 @@
1
+ /*
2
+ * Redacts credential-looking material from the output of a command a
3
+ * resource AI agent ran, before it leaves the agent, before the server
4
+ * stores it next to an AI run, and before a language model reads it.
5
+ *
6
+ * Two layers, applied in this order:
7
+ * 1. Per-program hooks (RESOURCE_OUTPUT_REDACTION_HOOKS) for material only
8
+ * one tool prints: every value of a `docker inspect` "Env" list, a Ceph
9
+ * keyring's `key`. Each tool's kit extends its program's entry.
10
+ * 2. The generic rules (GenericOutputRedactor): any `key: value` or
11
+ * `key=value` whose key looks credential-like, credential flags and
12
+ * their values, env name/value pairs, `scheme://user:password@`, Bearer
13
+ * and Basic tokens, JWTs, PEM private keys and long or padded base64.
14
+ *
15
+ * GenericOutputRedactor is a COPY of Utils/AiRemediation/
16
+ * KubectlOutputRedactor (everything from its KubectlOutputRedaction
17
+ * interface on), with only these renames: KubectlOutputRedactor ->
18
+ * GenericOutputRedactor (and `export default class` -> `export class`),
19
+ * KubectlOutputRedaction -> GenericOutputRedaction, KUBECTL_REDACTED_MARKER
20
+ * -> GENERIC_REDACTED_MARKER. It is copied, not imported, because this
21
+ * directory is import-closed (the resource AI agent carries a
22
+ * byte-identical copy of it); ResourceOutputRedactorCopyParity.test.ts
23
+ * fails the moment the two drift, so fix KubectlOutputRedactor and re-copy.
24
+ * Its Kubernetes-specific rules (data blocks, describe output,
25
+ * last-applied-configuration) are harmless on other tools' output.
26
+ *
27
+ * Over-masking is accepted; under-masking is not.
28
+ */
29
+ import { redactDatabaseOutput } from "./DatabaseQueryRedactor";
30
+ export const GENERIC_REDACTED_MARKER = "[redacted]";
31
+ // Every marker this module writes starts with it: "[redacted-jwt]" too.
32
+ const REDACTED_PREFIX = "[redacted";
33
+ const DATA_BLOCK_KEYS = new Set([
34
+ "data",
35
+ "stringData",
36
+ "binaryData",
37
+ ]);
38
+ const LAST_APPLIED_CONFIGURATION_ANNOTATION = "kubectl.kubernetes.io/last-applied-configuration";
39
+ /*
40
+ * A key or env name that names credential material. Deliberately broad:
41
+ * `auth` also catches "authorization-mode", which is harmless to hide,
42
+ * while a narrow list would miss "DB_PASSWORD". A bare `key` is NOT
43
+ * credential-like (taints, tolerations and secretKeyRef all have one), but
44
+ * `tls.key`, `KEY_ID`, `api_key` and `private-key-file` are.
45
+ *
46
+ * `pass`, `pw` and `creds` count as a whole segment only — DB_PASS,
47
+ * RABBITMQ_DEFAULT_PASS, LDAP_BIND_PW, DB_CREDS, `--pass` — so "bypass",
48
+ * "compass", "passed", "MAX_PASSES" and "ssl-passthrough" stay readable,
49
+ * and "pass-through" is spelled out as not a credential. A few names glue
50
+ * a prefix on instead: Redis's `requirepass`, "dbpass", "smtppass".
51
+ */
52
+ const CREDENTIAL_NAME_REGEX = /passw(?:or)?d|passwd|pwd|passphrase|passcode|(?:^|[-_./])pass(?:$|[-_.](?!through))|(?:require|db|user|admin|root|smtp|mail|redis|ldap|bind|sasl|ftp)pass(?![a-z])|(?:^|[-_./])(?:pw|creds?)(?:$|[-_.])|secret|token|credential|auth|cert|bearer|cookie|dockerconfig|dockercfg|webhook|(?:api|access|private|priv|encryption|signing|client|ssh|master|license|service|account|session|app|consumer|shared)[-_.]?key|(?:^|[-_./])key[-_.]|[-_./]key$|(?:^|[-_./])(?:dsn|salt|otp)(?:[-_.]|$)|\.(?:crt|cer|pem|p12|pfx|jks)$/i;
53
+ /*
54
+ * Keys that match the pattern above but only ever REFER to a credential —
55
+ * the name of a Secret a volume mounts, whether a token is automounted —
56
+ * and that an on-call engineer needs when a pod cannot start. Compared
57
+ * lowercase, with leading dashes stripped so flag names match too.
58
+ */
59
+ const REFERENCE_ONLY_KEYS = new Set([
60
+ "secretname",
61
+ "secretnamespace",
62
+ "secretproviderclass",
63
+ "secretkeyref",
64
+ "secretref",
65
+ "configmapkeyref",
66
+ "tokenexpirationseconds",
67
+ "expirationseconds",
68
+ "serviceaccounttoken",
69
+ "automountserviceaccounttoken",
70
+ "imagepullsecrets",
71
+ "image pull secrets",
72
+ "mountable secrets",
73
+ "tokens",
74
+ "audience",
75
+ "authorization-mode",
76
+ "anonymous-auth",
77
+ "tls-min-version",
78
+ "tls-cipher-suites",
79
+ "cert-manager.io/cluster-issuer",
80
+ "cert-manager.io/issuer",
81
+ ]);
82
+ /*
83
+ * Values that carry no material and read better untouched: an absent
84
+ * value, and describe's own "<set to the key 'x' in secret 'y'>" reference
85
+ * for an env entry that comes from a Secret.
86
+ */
87
+ const EXEMPT_VALUES = new Set([
88
+ "",
89
+ '""',
90
+ "''",
91
+ "null",
92
+ "~",
93
+ "{}",
94
+ "[]",
95
+ "{",
96
+ "[",
97
+ "<none>",
98
+ "<nil>",
99
+ "<unset>",
100
+ "<invalid>",
101
+ "<empty>",
102
+ ]);
103
+ const EXEMPT_VALUE_PREFIX = "<set to the key ";
104
+ // YAML block scalar indicators: |, |-, |+, >, >-, >2 ...
105
+ const BLOCK_SCALAR_REGEX = /^[|>][+-]?[0-9]*$/;
106
+ /*
107
+ * `key: value`, `key:` and `"key": value,` at the start of a line's content.
108
+ * Unquoted keys may contain spaces (describe prints "Image ID:") but never
109
+ * a colon, so "2026-09-22T10:00:00Z" and "http://…" are not keys. The colon
110
+ * must be followed by whitespace or end the line for the same reason.
111
+ */
112
+ const KEY_VALUE_LINE_REGEX = /^(?:"([^"]*)"|'([^']*)'|([^\s"'#:{}[\],][^:"']*?))[ \t]*:(?:[ \t]+|$)/;
113
+ /*
114
+ * An unquoted key with whitespace or `=` in it may be free text rather than
115
+ * a name: "connecting DB_PASSWORD=hunter2 host: db" parses as the key
116
+ * "connecting DB_PASSWORD=hunter2 host". Such a key is scanned for inline
117
+ * material too.
118
+ */
119
+ const FREE_TEXT_KEY_REGEX = /[\s=]/;
120
+ const LIST_ITEM_PREFIX_REGEX = /^-(?:[ \t]+|$)/;
121
+ const LEADING_WHITESPACE_REGEX = /^[ \t]*/;
122
+ /*
123
+ * scheme://user:password@host — the password only; an empty user still
124
+ * counts. The match starts at "://" and the scheme is checked by a
125
+ * lookbehind, so the scan stays linear: a pattern that STARTS with the
126
+ * scheme retries `[a-z][a-z0-9+.-]*` from every word boundary of a long
127
+ * dotted run ("eyJ.eyJ.eyJ…", "a.b.c.…") and backtracks through the whole
128
+ * run each time — 200 KB of pod log took over 30 seconds on one thread.
129
+ */
130
+ const URL_CREDENTIAL_REGEX = /:\/\/(?<=\b[a-z][a-z0-9+.-]*:\/\/)([^\s/:@"']*):([^\s/@"']+)@/gi;
131
+ const BEARER_TOKEN_REGEX = /\b(Bearer)[ \t]+([A-Za-z0-9._~+/-]{8,}=*)/g;
132
+ // Prose ("Basic configuration", "Bearer authentication") is lowercase letters only.
133
+ const LOWERCASE_WORD_REGEX = /^[a-z]+$/;
134
+ const BASIC_TOKEN_REGEX = /\b(Basic)[ \t]+([A-Za-z0-9+/]{8,}={0,2})(?![A-Za-z0-9+/=])/g;
135
+ const JWT_REGEX = /eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{5,}/g;
136
+ /*
137
+ * PEM private key blocks. A block whose END line was truncated away is
138
+ * masked to the end of the output rather than left standing.
139
+ */
140
+ const PRIVATE_KEY_BLOCK_REGEX = /-----BEGIN (?:[A-Z0-9]+ )*PRIVATE KEY-----[\s\S]*?(?:-----END (?:[A-Z0-9]+ )*PRIVATE KEY-----|$)/g;
141
+ /*
142
+ * Compact JSON, as in a one-line `"data":{...}` — the quote may be escaped
143
+ * when the JSON itself sits inside a JSON string.
144
+ */
145
+ const INLINE_JSON_DATA_OBJECT_REGEX = /("|\\")(?:data|stringData|binaryData)(?:"|\\")\s*:\s*\{/g;
146
+ /*
147
+ * A JSON string body: anything but an unescaped quote. Two spellings, for
148
+ * plain JSON and for JSON escaped inside another JSON string.
149
+ */
150
+ const JSON_STRING_BODY = '(?:[^"\\\\]|\\\\.)*';
151
+ const ESCAPED_JSON_STRING_BODY = '(?:[^"\\\\]|\\\\[^"])*';
152
+ const JSON_QUOTE = '"';
153
+ const ESCAPED_JSON_QUOTE = '\\\\"';
154
+ function buildJsonEnvPairRegexes(isEscaped) {
155
+ const body = isEscaped ? ESCAPED_JSON_STRING_BODY : JSON_STRING_BODY;
156
+ const q = isEscaped ? ESCAPED_JSON_QUOTE : JSON_QUOTE;
157
+ return {
158
+ nameFirst: new RegExp(`(${q}name${q}\\s*:\\s*${q}(${body})${q}\\s*,\\s*${q}value${q}\\s*:\\s*${q})(${body})(${q})`, "g"),
159
+ valueFirst: new RegExp(`(${q}value${q}\\s*:\\s*${q})(${body})(${q}\\s*,\\s*${q}name${q}\\s*:\\s*${q}(${body})${q})`, "g"),
160
+ };
161
+ }
162
+ const JSON_ENV_PAIR_REGEXES = [buildJsonEnvPairRegexes(false), buildJsonEnvPairRegexes(true)];
163
+ function buildJsonCredentialPairRule(isEscaped) {
164
+ const body = isEscaped ? ESCAPED_JSON_STRING_BODY : JSON_STRING_BODY;
165
+ const q = isEscaped ? ESCAPED_JSON_QUOTE : JSON_QUOTE;
166
+ return {
167
+ quote: isEscaped ? '\\"' : '"',
168
+ regex: new RegExp(`(${q}([^"\\\\\\n]{1,256})${q}\\s*:\\s*)(?:(${q})(${body})(${q}|$)|(-?[0-9][0-9.eE+-]*))`, "g"),
169
+ };
170
+ }
171
+ const JSON_CREDENTIAL_PAIR_RULES = [
172
+ buildJsonCredentialPairRule(false),
173
+ buildJsonCredentialPairRule(true),
174
+ ];
175
+ /*
176
+ * `key=value` / `key: value` / `key:value` anywhere in a line — logs, args,
177
+ * Go-formatted maps (`map[password:cGFz…]`). The key is judged by
178
+ * isCredentialKey, so this never touches "timeout=1s" or "op=Exists". A
179
+ * JSON-escaped line break (`…\npassword: x\nuser: bob` inside a log
180
+ * message) separates pairs like a real one.
181
+ */
182
+ const INLINE_PAIR_REGEX = /(^|[\s[,{("']|\\[nrt])([A-Za-z0-9_./-]+)([ \t]*[:=][ \t]*)("(?:[^"\\]|\\.)*"|'[^']*'|(?:[^\s,;&\]})"'\\]|\\(?![nrt]))+)/g;
183
+ /*
184
+ * An image reference — `registry.example.com/auth:1.2.3`,
185
+ * `ghcr.io/org/secret-service:2.0` — has the shape of an inline pair whose
186
+ * key is a path and whose separator is a bare colon with no whitespace
187
+ * after it. A real pair with a path-shaped key (an annotation in describe
188
+ * output, `vault.hashicorp.com/agent-inject-token: abc123`) always has the
189
+ * space. The tag is what an on-call engineer needs most, so it stays.
190
+ */
191
+ function isImageReferencePair(key, separator) {
192
+ return key.includes("/") && separator === ":";
193
+ }
194
+ /*
195
+ * A command-line flag standing alone as one argv element: "--db-password",
196
+ * "-password". A credential flag's value is then the NEXT element, which
197
+ * the pair rules above never see.
198
+ */
199
+ const FLAG_TOKEN_REGEX = /^-{1,2}[A-Za-z][A-Za-z0-9_.-]*$/;
200
+ /*
201
+ * A flag's value inside one line: a quoted string, or a bare word that is
202
+ * neither the next flag ("-…") nor a marker this module already wrote.
203
+ */
204
+ const INLINE_FLAG_VALUE_PATTERN = /("(?:[^"\\]|\\.)*"|'[^']*'|[^\s"'[\-,;&|`\])}][^\s"',;&|`\])}]*)/;
205
+ const INLINE_FLAG_VALUE_SOURCE = INLINE_FLAG_VALUE_PATTERN.source;
206
+ // Where a flag can start inside a line.
207
+ const INLINE_FLAG_BOUNDARY_PATTERN = /(^|[\s"'[(,;&|`])/;
208
+ const INLINE_FLAG_BOUNDARY_SOURCE = INLINE_FLAG_BOUNDARY_PATTERN.source;
209
+ /*
210
+ * `--requirepass value` / `-password value` in one line: a command in a
211
+ * log, describe's probe line, an `sh -c` script. The flag is judged by
212
+ * isCredentialKey, so "--port 8080" and "--tail 100" stay.
213
+ */
214
+ const INLINE_SPLIT_FLAG_REGEX = new RegExp(`${INLINE_FLAG_BOUNDARY_SOURCE}(--?[A-Za-z][A-Za-z0-9_.-]*)([ \\t]+)${INLINE_FLAG_VALUE_SOURCE}`, "g");
215
+ /*
216
+ * `"--db-password","value"` — a flag and its value as neighbouring JSON
217
+ * array strings (jsonpath `{.spec.containers[*].args}`), plain, escaped
218
+ * inside another JSON string, or single-quoted as a Python list prints it.
219
+ */
220
+ function buildQuotedFlagPairRegex(quote, body) {
221
+ return new RegExp(`(${quote}(--?[A-Za-z][A-Za-z0-9_.-]*)${quote}\\s*,\\s*${quote})(${body})(${quote})`, "g");
222
+ }
223
+ const QUOTED_FLAG_PAIR_REGEXES = [
224
+ buildQuotedFlagPairRegex(JSON_QUOTE, JSON_STRING_BODY),
225
+ buildQuotedFlagPairRegex(ESCAPED_JSON_QUOTE, ESCAPED_JSON_STRING_BODY),
226
+ buildQuotedFlagPairRegex("'", "[^']*"),
227
+ ];
228
+ /*
229
+ * Tools whose single-letter flag carries a password: `mysql -pS3cret`,
230
+ * `mongosh -p S3cret`, `sshpass -p S3cret`, `redis-cli -a S3cret`. The
231
+ * same letters mean something else everywhere else — `-p` is a port for
232
+ * ssh, psql and redis-cli and "make parents" for mkdir — so a short flag
233
+ * is judged only where the command names one of these tools: earlier on
234
+ * the same line, or earlier in the same one-element-per-line argv list.
235
+ */
236
+ const SHORT_PASSWORD_FLAG_BY_TOOL = new Map([
237
+ ["mysql", "p"],
238
+ ["mysqladmin", "p"],
239
+ ["mysqldump", "p"],
240
+ ["mysqlcheck", "p"],
241
+ ["mysqlimport", "p"],
242
+ ["mysqlshow", "p"],
243
+ ["mysqlpump", "p"],
244
+ ["mysqlsh", "p"],
245
+ ["mariadb", "p"],
246
+ ["mariadb-admin", "p"],
247
+ ["mariadb-dump", "p"],
248
+ ["mariadb-check", "p"],
249
+ ["mariadb-import", "p"],
250
+ ["mongo", "p"],
251
+ ["mongosh", "p"],
252
+ ["mongodump", "p"],
253
+ ["mongorestore", "p"],
254
+ ["mongoexport", "p"],
255
+ ["mongoimport", "p"],
256
+ ["mongostat", "p"],
257
+ ["mongotop", "p"],
258
+ ["sshpass", "p"],
259
+ ["redis-cli", "a"],
260
+ ["keydb-cli", "a"],
261
+ ["valkey-cli", "a"],
262
+ ]);
263
+ // One of those tools named inside a line, a path in front of it allowed.
264
+ const TOOL_NAME_REGEX = new RegExp(`(^|[\\s/"'[(,;&|=\`])(${Array.from(SHORT_PASSWORD_FLAG_BY_TOOL.keys()).join("|")})(?=$|[\\s"'\\]),;&|\`\\\\])`, "g");
265
+ // Where the command a tool starts ends inside a line.
266
+ const COMMAND_END_REGEX = /[\];|&)`]/;
267
+ // The password glued to a short flag ("-pS3cret"): a bare word.
268
+ const SHORT_PASSWORD_ATTACHED_VALUE_PATTERN = /([^\s"'[\-,;&|`\])}][^\s"',;&|`\])}]*)/;
269
+ // What separates a short flag from its password: blanks, or a list's ",".
270
+ const SHORT_PASSWORD_SEPARATOR_PATTERN = /([ \t]+|"\s*,\s*"|\\"\s*,\s*\\"|'\s*,\s*')/;
271
+ function buildShortPasswordFlagRegexes(letter) {
272
+ return {
273
+ attached: new RegExp(`${INLINE_FLAG_BOUNDARY_SOURCE}(-${letter})${SHORT_PASSWORD_ATTACHED_VALUE_PATTERN.source}`, "g"),
274
+ separated: new RegExp(`${INLINE_FLAG_BOUNDARY_SOURCE}(-${letter})${SHORT_PASSWORD_SEPARATOR_PATTERN.source}${INLINE_FLAG_VALUE_SOURCE}`, "g"),
275
+ };
276
+ }
277
+ const SHORT_PASSWORD_FLAG_REGEXES = new Map(Array.from(new Set(SHORT_PASSWORD_FLAG_BY_TOOL.values())).map((letter) => {
278
+ return [letter, buildShortPasswordFlagRegexes(letter)];
279
+ }));
280
+ /*
281
+ * `kubectl describe configmap` prints each data entry as "KEY:", this rule
282
+ * on the next line, and the value verbatim below it; the entries end with
283
+ * a "BinaryData" heading underlined the same way.
284
+ */
285
+ const DESCRIBE_DATA_ENTRY_RULE = "----";
286
+ const DESCRIBE_BINARY_DATA_HEADING = "BinaryData";
287
+ const DESCRIBE_SECTION_RULE = "====";
288
+ /*
289
+ * Base64 runs. A padded run of any length is base64 by construction
290
+ * ("cGFzc3dvcmQ=" is "password"); an unpadded run must be long and mixed to
291
+ * count, so identifiers, hashes and hex ids stay legible. The padding must
292
+ * end the token: "--feature-gates=Foo=true" is a flag, not a secret.
293
+ */
294
+ const BASE64_PADDED_REGEX = /(?<![A-Za-z0-9+/])([A-Za-z0-9+/]{4,})(={1,2})(?![A-Za-z0-9+/=])/g;
295
+ const BASE64_LONG_REGEX = /(?<![A-Za-z0-9+/])([A-Za-z0-9+/]{32,})(?![A-Za-z0-9+/=])/g;
296
+ function parseLine(raw) {
297
+ var _a, _b, _c;
298
+ const whitespaceMatch = LEADING_WHITESPACE_REGEX.exec(raw);
299
+ const indent = whitespaceMatch ? whitespaceMatch[0].length : 0;
300
+ let content = raw.slice(indent);
301
+ if (content.trim() === "") {
302
+ return { raw, isBlank: true, indent, isListItem: false, contentIndent: 0 };
303
+ }
304
+ let isListItem = false;
305
+ let contentIndent = indent;
306
+ const listMatch = LIST_ITEM_PREFIX_REGEX.exec(content);
307
+ if (listMatch) {
308
+ isListItem = true;
309
+ contentIndent = indent + listMatch[0].length;
310
+ content = content.slice(listMatch[0].length);
311
+ }
312
+ const keyMatch = KEY_VALUE_LINE_REGEX.exec(content);
313
+ if (!keyMatch) {
314
+ return { raw, isBlank: false, indent, isListItem, contentIndent };
315
+ }
316
+ const key = ((_c = (_b = (_a = keyMatch[1]) !== null && _a !== void 0 ? _a : keyMatch[2]) !== null && _b !== void 0 ? _b : keyMatch[3]) !== null && _c !== void 0 ? _c : "").trim();
317
+ const valueStart = contentIndent + keyMatch[0].length;
318
+ return {
319
+ raw,
320
+ isBlank: false,
321
+ indent,
322
+ isListItem,
323
+ contentIndent,
324
+ key,
325
+ keyIsFreeText: keyMatch[3] !== undefined && FREE_TEXT_KEY_REGEX.test(keyMatch[3]),
326
+ value: raw.slice(valueStart).trim(),
327
+ valueStart,
328
+ };
329
+ }
330
+ // Strip a JSON trailing comma and surrounding quotes from a scalar.
331
+ function unquote(value) {
332
+ let body = value.trim();
333
+ if (body.endsWith(",")) {
334
+ body = body.slice(0, -1).trimEnd();
335
+ }
336
+ if (body.length >= 2 &&
337
+ ((body.startsWith('"') && body.endsWith('"')) ||
338
+ (body.startsWith("'") && body.endsWith("'")))) {
339
+ body = body.slice(1, -1);
340
+ }
341
+ return body;
342
+ }
343
+ function isDocumentSeparator(line) {
344
+ return line.raw.trim() === "---";
345
+ }
346
+ function isBlockScalar(value) {
347
+ return BLOCK_SCALAR_REGEX.test(value);
348
+ }
349
+ // "data:" or "\"data\": {" — a mapping whose entries follow on later lines.
350
+ function isContainerStart(value) {
351
+ return value === "" || value === "{";
352
+ }
353
+ // A value with no material in it, including a marker an earlier pass wrote.
354
+ function isExemptValue(value) {
355
+ let body = value.trim();
356
+ if (body.endsWith(",")) {
357
+ body = body.slice(0, -1).trimEnd();
358
+ }
359
+ return (EXEMPT_VALUES.has(body) ||
360
+ body.startsWith(EXEMPT_VALUE_PREFIX) ||
361
+ unquote(body).startsWith(REDACTED_PREFIX));
362
+ }
363
+ function looksLikeCredentialName(name) {
364
+ return CREDENTIAL_NAME_REGEX.test(name.trim());
365
+ }
366
+ // A key that names credential material, minus the reference-only keys.
367
+ function isCredentialKey(key) {
368
+ const normalized = key.trim().replace(/^-+/, "").toLowerCase();
369
+ if (REFERENCE_ONLY_KEYS.has(normalized)) {
370
+ return false;
371
+ }
372
+ return looksLikeCredentialName(normalized);
373
+ }
374
+ /*
375
+ * An argv element that can be a flag's value: not the next flag, not
376
+ * empty, not a marker this module already wrote.
377
+ */
378
+ function isArgvValue(element) {
379
+ return !element.startsWith("-") && !isExemptValue(element);
380
+ }
381
+ // The short password flag of the tool an argv element names, if any.
382
+ function shortPasswordFlagOfTool(element) {
383
+ return SHORT_PASSWORD_FLAG_BY_TOOL.get(element.slice(element.lastIndexOf("/") + 1));
384
+ }
385
+ /*
386
+ * A scalar replaced by the marker, keeping its quotes, a JSON trailing
387
+ * comma and `keptPrefix` (the "-p" of "-pS3cret").
388
+ */
389
+ function maskScalar(value, keptPrefix = "") {
390
+ const trailingComma = value.trimEnd().endsWith(",") ? "," : "";
391
+ const body = trailingComma
392
+ ? value.trimEnd().slice(0, -1).trimEnd()
393
+ : value.trim();
394
+ if (body.startsWith('"')) {
395
+ return `"${keptPrefix}${GENERIC_REDACTED_MARKER}"${trailingComma}`;
396
+ }
397
+ if (body.startsWith("'")) {
398
+ return `'${keptPrefix}${GENERIC_REDACTED_MARKER}'${trailingComma}`;
399
+ }
400
+ return `${keptPrefix}${GENERIC_REDACTED_MARKER}${trailingComma}`;
401
+ }
402
+ /*
403
+ * A bare value found inside a line, replaced by the marker. When the value
404
+ * ends the body of an escaped JSON string (`…=S3cret\"`), the backslash
405
+ * belongs to the closing quote and stays.
406
+ */
407
+ function maskInlineValue(value) {
408
+ if (value.startsWith('"') || value.startsWith("'")) {
409
+ return maskScalar(value);
410
+ }
411
+ return `${GENERIC_REDACTED_MARKER}${value.endsWith("\\") ? "\\" : ""}`;
412
+ }
413
+ /*
414
+ * The part of a `key: value` line before its value. A key that may be free
415
+ * text gets the inline rules; an ordinary key is returned as it is.
416
+ */
417
+ function redactKeyPrefix(line) {
418
+ var _a;
419
+ const prefix = line.raw.slice(0, (_a = line.valueStart) !== null && _a !== void 0 ? _a : 0);
420
+ if (!line.keyIsFreeText) {
421
+ return { text: prefix, count: 0 };
422
+ }
423
+ const inline = applyInlineRules(prefix.slice(line.contentIndent));
424
+ return {
425
+ text: prefix.slice(0, line.contentIndent) + inline.text,
426
+ count: inline.count,
427
+ };
428
+ }
429
+ function maskValueInPlace(line) {
430
+ if (line.valueStart === undefined || line.value === undefined) {
431
+ return {
432
+ text: " ".repeat(line.indent) + GENERIC_REDACTED_MARKER,
433
+ count: 1,
434
+ };
435
+ }
436
+ const prefix = redactKeyPrefix(line);
437
+ return {
438
+ text: prefix.text + maskScalar(line.value),
439
+ count: prefix.count + 1,
440
+ };
441
+ }
442
+ // The first line at or above `indent` — the end of a nested block.
443
+ function skipDeeperLines(parsed, from, indent) {
444
+ let index = from;
445
+ while (index < parsed.length) {
446
+ const line = parsed[index];
447
+ if (!line.isBlank && line.indent <= indent) {
448
+ break;
449
+ }
450
+ index++;
451
+ }
452
+ return index;
453
+ }
454
+ const UPPERCASE_REGEX = /[A-Z]/;
455
+ const LOWERCASE_REGEX = /[a-z]/;
456
+ const DIGIT_REGEX = /[0-9]/;
457
+ function hasUpperAndLower(text) {
458
+ return UPPERCASE_REGEX.test(text) && LOWERCASE_REGEX.test(text);
459
+ }
460
+ function hasDigit(text) {
461
+ return DIGIT_REGEX.test(text);
462
+ }
463
+ // `Bearer …` / `Basic …`: the token after the scheme, unless it is prose.
464
+ function maskAuthorizationTokens(text, regex) {
465
+ let count = 0;
466
+ const result = text.replace(regex, (match, scheme, token) => {
467
+ if (LOWERCASE_WORD_REGEX.test(token)) {
468
+ return match;
469
+ }
470
+ count++;
471
+ return `${scheme} ${GENERIC_REDACTED_MARKER}`;
472
+ });
473
+ return { text: result, count };
474
+ }
475
+ /*
476
+ * One-line JSON env pairs, `"name":"X","value":"Y"` in either order: the
477
+ * value is masked when the name looks credential-like and the value holds
478
+ * something (an empty value, or one already masked, stays as it is).
479
+ */
480
+ function maskJsonEnvPairs(text, regexes) {
481
+ let count = 0;
482
+ let result = text.replace(regexes.nameFirst, (match, prefix, name, value, closingQuote) => {
483
+ if (!looksLikeCredentialName(name) || isExemptValue(value)) {
484
+ return match;
485
+ }
486
+ count++;
487
+ return `${prefix}${GENERIC_REDACTED_MARKER}${closingQuote}`;
488
+ });
489
+ result = result.replace(regexes.valueFirst, (match, prefix, value, suffix, name) => {
490
+ if (!looksLikeCredentialName(name) || isExemptValue(value)) {
491
+ return match;
492
+ }
493
+ count++;
494
+ return `${prefix}${GENERIC_REDACTED_MARKER}${suffix}`;
495
+ });
496
+ return { text: result, count };
497
+ }
498
+ /*
499
+ * One-line JSON `"key":"value"` pairs whose key looks credential-like, and
500
+ * the last-applied-configuration annotation as jsonpath prints it. The
501
+ * quotes stay, so the JSON still parses; a bare number becomes a string.
502
+ */
503
+ function maskJsonCredentialPairs(text, rule) {
504
+ let count = 0;
505
+ const result = text.replace(rule.regex, (match, prefix, key, openingQuote, body, closingQuote, bare) => {
506
+ if (key !== LAST_APPLIED_CONFIGURATION_ANNOTATION &&
507
+ !isCredentialKey(key)) {
508
+ return match;
509
+ }
510
+ if (openingQuote !== undefined) {
511
+ if (isExemptValue(body !== null && body !== void 0 ? body : "")) {
512
+ return match;
513
+ }
514
+ count++;
515
+ return `${prefix}${openingQuote}${GENERIC_REDACTED_MARKER}${closingQuote !== null && closingQuote !== void 0 ? closingQuote : ""}`;
516
+ }
517
+ if (bare === undefined) {
518
+ return match;
519
+ }
520
+ count++;
521
+ return `${prefix}${rule.quote}${GENERIC_REDACTED_MARKER}${rule.quote}`;
522
+ });
523
+ return { text: result, count };
524
+ }
525
+ // `"--db-password","value"` in a one-line array: the value is masked.
526
+ function maskQuotedFlagPairs(text, regex) {
527
+ let count = 0;
528
+ const result = text.replace(regex, (match, prefix, flag, value, closingQuote) => {
529
+ if (!isCredentialKey(flag) || !isArgvValue(value)) {
530
+ return match;
531
+ }
532
+ count++;
533
+ return `${prefix}${GENERIC_REDACTED_MARKER}${closingQuote}`;
534
+ });
535
+ return { text: result, count };
536
+ }
537
+ // `--requirepass value` inside one line: the value is masked.
538
+ function maskInlineSplitFlags(text) {
539
+ let count = 0;
540
+ const result = text.replace(INLINE_SPLIT_FLAG_REGEX, (match, boundary, flag, separator, value) => {
541
+ if (!isCredentialKey(flag) || !isArgvValue(unquote(value))) {
542
+ return match;
543
+ }
544
+ count++;
545
+ return `${boundary}${flag}${separator}${maskInlineValue(value)}`;
546
+ });
547
+ return { text: result, count };
548
+ }
549
+ // A tool's short password flag within the stretch of a line that is its command.
550
+ function maskShortPasswordFlag(text, letter) {
551
+ const regexes = SHORT_PASSWORD_FLAG_REGEXES.get(letter);
552
+ if (!regexes) {
553
+ return { text, count: 0 };
554
+ }
555
+ let count = 0;
556
+ let result = text.replace(regexes.separated, (match, boundary, flag, separator, value) => {
557
+ if (!isArgvValue(unquote(value))) {
558
+ return match;
559
+ }
560
+ count++;
561
+ return `${boundary}${flag}${separator}${maskInlineValue(value)}`;
562
+ });
563
+ result = result.replace(regexes.attached, (_match, boundary, flag, value) => {
564
+ count++;
565
+ return `${boundary}${flag}${maskInlineValue(value)}`;
566
+ });
567
+ return { text: result, count };
568
+ }
569
+ /*
570
+ * `mysql -pS3cret`, `mongosh -p S3cret`, `redis-cli -a S3cret`: a tool's
571
+ * short password flag, judged only in the stretch of the line from the
572
+ * tool's name to the next tool or the end of its command (`]`, `)`, `;`,
573
+ * `|`, `&`, a backtick).
574
+ */
575
+ function maskToolPasswordFlags(text) {
576
+ var _a, _b, _c;
577
+ const tools = [];
578
+ TOOL_NAME_REGEX.lastIndex = 0;
579
+ let match = TOOL_NAME_REGEX.exec(text);
580
+ while (match) {
581
+ const start = match.index + ((_a = match[1]) !== null && _a !== void 0 ? _a : "").length;
582
+ const name = (_b = match[2]) !== null && _b !== void 0 ? _b : "";
583
+ tools.push({
584
+ start,
585
+ end: start + name.length,
586
+ letter: (_c = SHORT_PASSWORD_FLAG_BY_TOOL.get(name)) !== null && _c !== void 0 ? _c : "",
587
+ });
588
+ match = TOOL_NAME_REGEX.exec(text);
589
+ }
590
+ TOOL_NAME_REGEX.lastIndex = 0;
591
+ if (tools.length === 0) {
592
+ return { text, count: 0 };
593
+ }
594
+ let result = "";
595
+ let count = 0;
596
+ let cursor = 0;
597
+ tools.forEach((tool, toolIndex) => {
598
+ /*
599
+ * Only the stretch up to the next tool is searched for the command's
600
+ * end, so a line naming a tool many times is still scanned once.
601
+ */
602
+ const nextTool = tools[toolIndex + 1];
603
+ const stretch = text.slice(tool.end, nextTool ? nextTool.start : text.length);
604
+ const commandEnd = stretch.search(COMMAND_END_REGEX);
605
+ const command = commandEnd === -1 ? stretch : stretch.slice(0, commandEnd);
606
+ result += text.slice(cursor, tool.end);
607
+ const masked = maskShortPasswordFlag(command, tool.letter);
608
+ result += masked.text;
609
+ count += masked.count;
610
+ cursor = tool.end + command.length;
611
+ });
612
+ result += text.slice(cursor);
613
+ return { text: result, count };
614
+ }
615
+ /*
616
+ * Mask the body of every one-line `"data":{…}` object. Braces are matched
617
+ * by depth; an object the line truncated away is masked to the end.
618
+ */
619
+ function maskInlineJsonDataObjects(text) {
620
+ var _a;
621
+ let result = text;
622
+ let count = 0;
623
+ let searchFrom = 0;
624
+ while (searchFrom < result.length) {
625
+ INLINE_JSON_DATA_OBJECT_REGEX.lastIndex = searchFrom;
626
+ const match = INLINE_JSON_DATA_OBJECT_REGEX.exec(result);
627
+ if (!match) {
628
+ break;
629
+ }
630
+ const quote = (_a = match[1]) !== null && _a !== void 0 ? _a : '"';
631
+ const bodyStart = match.index + match[0].length;
632
+ let depth = 1;
633
+ let position = bodyStart;
634
+ while (position < result.length && depth > 0) {
635
+ const character = result[position];
636
+ if (character === "{") {
637
+ depth++;
638
+ }
639
+ else if (character === "}") {
640
+ depth--;
641
+ }
642
+ position++;
643
+ }
644
+ // `position` is just past the closing brace, or the end of the text.
645
+ const bodyEnd = depth === 0 ? position - 1 : result.length;
646
+ if (result.slice(bodyStart, bodyEnd).trim() === "") {
647
+ searchFrom = position;
648
+ continue;
649
+ }
650
+ const replacement = `${quote}${GENERIC_REDACTED_MARKER}${quote}:${quote}${GENERIC_REDACTED_MARKER}${quote}`;
651
+ result = result.slice(0, bodyStart) + replacement + result.slice(bodyEnd);
652
+ count++;
653
+ searchFrom = bodyStart + replacement.length;
654
+ }
655
+ INLINE_JSON_DATA_OBJECT_REGEX.lastIndex = 0;
656
+ return { text: result, count };
657
+ }
658
+ // The rules that apply to any line regardless of its YAML/JSON structure.
659
+ function applyInlineRules(text) {
660
+ let count = 0;
661
+ let result = text;
662
+ const apply = (masked) => {
663
+ result = masked.text;
664
+ count += masked.count;
665
+ };
666
+ result = result.replace(URL_CREDENTIAL_REGEX, (_match, user) => {
667
+ count++;
668
+ return `://${user}:${GENERIC_REDACTED_MARKER}@`;
669
+ });
670
+ for (const tokenRegex of [BEARER_TOKEN_REGEX, BASIC_TOKEN_REGEX]) {
671
+ apply(maskAuthorizationTokens(result, tokenRegex));
672
+ }
673
+ result = result.replace(JWT_REGEX, () => {
674
+ count++;
675
+ return "[redacted-jwt]";
676
+ });
677
+ apply(maskInlineJsonDataObjects(result));
678
+ for (const pair of JSON_ENV_PAIR_REGEXES) {
679
+ apply(maskJsonEnvPairs(result, pair));
680
+ }
681
+ for (const rule of JSON_CREDENTIAL_PAIR_RULES) {
682
+ apply(maskJsonCredentialPairs(result, rule));
683
+ }
684
+ for (const regex of QUOTED_FLAG_PAIR_REGEXES) {
685
+ apply(maskQuotedFlagPairs(result, regex));
686
+ }
687
+ result = result.replace(INLINE_PAIR_REGEX, (match, boundary, key, separator, value) => {
688
+ if (isImageReferencePair(key, separator) ||
689
+ !isCredentialKey(key) ||
690
+ isExemptValue(value)) {
691
+ return match;
692
+ }
693
+ count++;
694
+ return `${boundary}${key}${separator}${GENERIC_REDACTED_MARKER}${value.endsWith("\\") ? "\\" : ""}`;
695
+ });
696
+ apply(maskInlineSplitFlags(result));
697
+ apply(maskToolPasswordFlags(result));
698
+ result = result.replace(BASE64_PADDED_REGEX, (match, run) => {
699
+ if (!hasUpperAndLower(run) && !hasDigit(run)) {
700
+ return match;
701
+ }
702
+ count++;
703
+ return "[redacted-base64]";
704
+ });
705
+ result = result.replace(BASE64_LONG_REGEX, (match, run) => {
706
+ if (!hasUpperAndLower(run) || !hasDigit(run)) {
707
+ return match;
708
+ }
709
+ count++;
710
+ return "[redacted-base64]";
711
+ });
712
+ return { text: result, count };
713
+ }
714
+ /*
715
+ * The inline rules over one line. A line that already parsed as
716
+ * `key: value` has its value examined, and its key only when the key may
717
+ * be free text: its key was judged by isCredentialKey (and possibly
718
+ * exempted), and re-reading "Image pull secrets:" as the pair "secrets:
719
+ * <none>" must not undo that.
720
+ */
721
+ function applyInlineRulesToLine(line) {
722
+ if (line.valueStart === undefined || line.value === undefined) {
723
+ return applyInlineRules(line.raw);
724
+ }
725
+ const prefix = redactKeyPrefix(line);
726
+ const inline = applyInlineRules(line.raw.slice(line.valueStart));
727
+ return {
728
+ text: prefix.text + inline.text,
729
+ count: prefix.count + inline.count,
730
+ };
731
+ }
732
+ export class GenericOutputRedactor {
733
+ static redact(output) {
734
+ var _a;
735
+ if (!output) {
736
+ return { text: "", redactionCount: 0 };
737
+ }
738
+ const parsed = output
739
+ .replace(/\r\n?/g, "\n")
740
+ .split("\n")
741
+ .map(parseLine);
742
+ const masks = {
743
+ envValueLines: GenericOutputRedactor.findCredentialEnvValueLines(parsed),
744
+ argvValueLines: GenericOutputRedactor.findArgvValueLines(parsed),
745
+ };
746
+ const out = [];
747
+ let count = 0;
748
+ let index = 0;
749
+ while (index < parsed.length) {
750
+ const line = parsed[index];
751
+ let step;
752
+ if (GenericOutputRedactor.isDescribeDataEntry(parsed, index) &&
753
+ isCredentialKey((_a = line.key) !== null && _a !== void 0 ? _a : "")) {
754
+ step = GenericOutputRedactor.redactDescribeDataEntry(parsed, index);
755
+ }
756
+ else if (!line.isBlank &&
757
+ line.key !== undefined &&
758
+ DATA_BLOCK_KEYS.has(line.key) &&
759
+ isContainerStart(line.value)) {
760
+ step = GenericOutputRedactor.redactDataBlock(parsed, index, masks);
761
+ }
762
+ else {
763
+ step = GenericOutputRedactor.redactStandaloneLine(parsed, index, masks);
764
+ }
765
+ out.push(...step.lines);
766
+ count += step.count;
767
+ index = step.next;
768
+ }
769
+ let text = out.join("\n");
770
+ text = text.replace(PRIVATE_KEY_BLOCK_REGEX, () => {
771
+ count++;
772
+ return "[redacted-private-key]";
773
+ });
774
+ return { text, redactionCount: count };
775
+ }
776
+ /*
777
+ * Which `value:` lines belong to an env entry whose `name:` looks
778
+ * credential-like. Found up front because the value may precede the name
779
+ * inside its entry, and the main pass only ever moves forward.
780
+ */
781
+ static findCredentialEnvValueLines(parsed) {
782
+ const valueLines = new Set();
783
+ for (let index = 0; index < parsed.length; index++) {
784
+ const line = parsed[index];
785
+ if (line.isBlank || line.key !== "name" || line.value === undefined) {
786
+ continue;
787
+ }
788
+ const name = unquote(line.value);
789
+ if (!name || !looksLikeCredentialName(name)) {
790
+ continue;
791
+ }
792
+ const valueLine = GenericOutputRedactor.findSiblingValueLine(parsed, index);
793
+ if (valueLine !== undefined) {
794
+ valueLines.add(valueLine);
795
+ }
796
+ }
797
+ return valueLines;
798
+ }
799
+ /*
800
+ * Argv printed one element per line — `- --db-password` / `- value` in
801
+ * YAML, `"--db-password",` / `"value"` in pretty JSON, describe's Command
802
+ * and Args blocks — and the elements that are the value of a credential
803
+ * flag before them, each with its masked text. A list's elements are
804
+ * consecutive lines at the same indent and of the same shape; a
805
+ * `key: value` line ends it (describe prints an argument that contains
806
+ * ": " as is, so a flag's value may look like one). A tool's short
807
+ * password flag counts only once the list has named the tool.
808
+ */
809
+ static findArgvValueLines(parsed) {
810
+ const masked = new Map();
811
+ let list = undefined;
812
+ for (let index = 0; index < parsed.length; index++) {
813
+ const line = parsed[index];
814
+ if (line.isBlank) {
815
+ continue;
816
+ }
817
+ // "- key: value" is a mapping entry, never an argv element.
818
+ if (line.isListItem && line.key !== undefined) {
819
+ list = undefined;
820
+ continue;
821
+ }
822
+ if (list === undefined ||
823
+ list.indent !== line.indent ||
824
+ list.isListItem !== line.isListItem) {
825
+ list = {
826
+ indent: line.indent,
827
+ isListItem: line.isListItem,
828
+ shortPasswordFlag: undefined,
829
+ expectsValue: false,
830
+ };
831
+ }
832
+ const indentText = line.raw.slice(0, line.contentIndent);
833
+ const content = line.raw.slice(line.contentIndent);
834
+ const element = unquote(content);
835
+ if (list.expectsValue) {
836
+ list.expectsValue = false;
837
+ if (isArgvValue(element)) {
838
+ masked.set(index, indentText + maskScalar(content));
839
+ continue;
840
+ }
841
+ }
842
+ if (line.key !== undefined) {
843
+ list = undefined;
844
+ continue;
845
+ }
846
+ const shortFlag = list.shortPasswordFlag !== undefined
847
+ ? `-${list.shortPasswordFlag}`
848
+ : undefined;
849
+ if (shortFlag !== undefined && element.startsWith(shortFlag)) {
850
+ const attached = element.slice(shortFlag.length);
851
+ if (attached === "") {
852
+ list.expectsValue = true;
853
+ }
854
+ else if (isArgvValue(attached)) {
855
+ masked.set(index, indentText + maskScalar(content, shortFlag));
856
+ }
857
+ continue;
858
+ }
859
+ if (FLAG_TOKEN_REGEX.test(element) && isCredentialKey(element)) {
860
+ list.expectsValue = true;
861
+ continue;
862
+ }
863
+ const toolFlag = shortPasswordFlagOfTool(element);
864
+ if (toolFlag !== undefined) {
865
+ list.shortPasswordFlag = toolFlag;
866
+ }
867
+ }
868
+ return masked;
869
+ }
870
+ /*
871
+ * The `value:` sibling of a `name:` line inside the same list entry (YAML)
872
+ * or object (JSON). Siblings share the name line's content indent; a
873
+ * shallower line ends the entry, a deeper one is nested under a sibling.
874
+ */
875
+ static findSiblingValueLine(parsed, nameIndex) {
876
+ const nameLine = parsed[nameIndex];
877
+ const indent = nameLine.contentIndent;
878
+ for (let index = nameIndex + 1; index < parsed.length; index++) {
879
+ const line = parsed[index];
880
+ if (line.isBlank) {
881
+ continue;
882
+ }
883
+ if (line.indent < indent) {
884
+ break;
885
+ }
886
+ if (line.indent > indent || line.isListItem) {
887
+ continue;
888
+ }
889
+ if (line.key === "value") {
890
+ return index;
891
+ }
892
+ }
893
+ // "- name: X" is its entry's first line: nothing above it is a sibling.
894
+ if (nameLine.isListItem) {
895
+ return undefined;
896
+ }
897
+ for (let index = nameIndex - 1; index >= 0; index--) {
898
+ const line = parsed[index];
899
+ if (line.isBlank) {
900
+ continue;
901
+ }
902
+ if (line.isListItem && line.contentIndent === indent) {
903
+ // The entry's own "- …" line — a sibling, and the entry's start.
904
+ return line.key === "value" ? index : undefined;
905
+ }
906
+ if (line.indent < indent) {
907
+ break;
908
+ }
909
+ if (line.indent > indent || line.isListItem) {
910
+ continue;
911
+ }
912
+ if (line.key === "value") {
913
+ return index;
914
+ }
915
+ }
916
+ return undefined;
917
+ }
918
+ /*
919
+ * The `kind:` sibling of a data block: same indent, same object, on
920
+ * either side of the block. Undefined when the output does not say — a
921
+ * truncated object, or not a Kubernetes object at all.
922
+ */
923
+ static findSiblingKind(parsed, blockIndex) {
924
+ const indent = parsed[blockIndex].contentIndent;
925
+ for (let index = blockIndex - 1; index >= 0; index--) {
926
+ const line = parsed[index];
927
+ if (line.isBlank) {
928
+ continue;
929
+ }
930
+ if (isDocumentSeparator(line)) {
931
+ break;
932
+ }
933
+ if (line.indent > indent) {
934
+ continue;
935
+ }
936
+ if (line.isListItem && line.contentIndent === indent) {
937
+ // The entry's own "- …" line: its first key, and the entry's start.
938
+ if (line.key === "kind" && line.value !== undefined) {
939
+ return unquote(line.value);
940
+ }
941
+ break;
942
+ }
943
+ if (line.indent < indent) {
944
+ break;
945
+ }
946
+ if (line.isListItem) {
947
+ continue;
948
+ }
949
+ if (line.key === "kind" && line.value !== undefined) {
950
+ return unquote(line.value);
951
+ }
952
+ }
953
+ for (let index = blockIndex + 1; index < parsed.length; index++) {
954
+ const line = parsed[index];
955
+ if (line.isBlank) {
956
+ continue;
957
+ }
958
+ if (isDocumentSeparator(line)) {
959
+ break;
960
+ }
961
+ if (line.indent > indent) {
962
+ continue;
963
+ }
964
+ if (line.indent < indent) {
965
+ break;
966
+ }
967
+ if (line.isListItem) {
968
+ continue;
969
+ }
970
+ if (line.key === "kind" && line.value !== undefined) {
971
+ return unquote(line.value);
972
+ }
973
+ }
974
+ return undefined;
975
+ }
976
+ /*
977
+ * A `kubectl describe configmap` data entry: "KEY:" with nothing after
978
+ * the colon, then the "----" rule at the same indent on the next line.
979
+ */
980
+ static isDescribeDataEntry(parsed, index) {
981
+ const line = parsed[index];
982
+ const rule = parsed[index + 1];
983
+ return (line !== undefined &&
984
+ rule !== undefined &&
985
+ !line.isBlank &&
986
+ !line.isListItem &&
987
+ line.key !== undefined &&
988
+ line.value === "" &&
989
+ !rule.isBlank &&
990
+ rule.indent === line.indent &&
991
+ rule.raw.trim() === DESCRIBE_DATA_ENTRY_RULE);
992
+ }
993
+ /*
994
+ * Where a describe data entry's value ends: at the next entry or the
995
+ * "BinaryData" heading after the last one — each follows a blank line at
996
+ * the entry's indent — or at the end of the output.
997
+ */
998
+ static isDescribeDataValueEnd(parsed, index, indent) {
999
+ const line = parsed[index];
1000
+ const previous = parsed[index - 1];
1001
+ const next = parsed[index + 1];
1002
+ if (line.isBlank || line.indent !== indent || !(previous === null || previous === void 0 ? void 0 : previous.isBlank)) {
1003
+ return false;
1004
+ }
1005
+ if (GenericOutputRedactor.isDescribeDataEntry(parsed, index)) {
1006
+ return true;
1007
+ }
1008
+ return (line.raw.trim() === DESCRIBE_BINARY_DATA_HEADING &&
1009
+ next !== undefined &&
1010
+ next.raw.trim() === DESCRIBE_SECTION_RULE);
1011
+ }
1012
+ /*
1013
+ * A credential-like describe data entry. The key and the rule stay; the
1014
+ * whole value — every line of it, blank lines included, since a
1015
+ * properties file or a PEM block has them — becomes one marker, and the
1016
+ * blank lines that close the entry stay. A value the Runner truncated
1017
+ * is masked to the end of the output.
1018
+ */
1019
+ static redactDescribeDataEntry(parsed, headerIndex) {
1020
+ const header = parsed[headerIndex];
1021
+ const valueStart = headerIndex + 2;
1022
+ let end = valueStart;
1023
+ while (end < parsed.length &&
1024
+ !GenericOutputRedactor.isDescribeDataValueEnd(parsed, end, header.indent)) {
1025
+ end++;
1026
+ }
1027
+ let lastValueLine = valueStart - 1;
1028
+ for (let index = valueStart; index < end; index++) {
1029
+ if (!parsed[index].isBlank) {
1030
+ lastValueLine = index;
1031
+ }
1032
+ }
1033
+ const lines = [header.raw, parsed[headerIndex + 1].raw];
1034
+ let count = 0;
1035
+ if (lastValueLine >= valueStart) {
1036
+ const valueLines = parsed.slice(valueStart, lastValueLine + 1);
1037
+ const isAlreadyMasked = valueLines.every((line) => {
1038
+ return line.isBlank || line.raw.trim() === GENERIC_REDACTED_MARKER;
1039
+ });
1040
+ if (isAlreadyMasked) {
1041
+ lines.push(...valueLines.map((line) => {
1042
+ return line.raw;
1043
+ }));
1044
+ }
1045
+ else {
1046
+ lines.push(" ".repeat(header.indent) + GENERIC_REDACTED_MARKER);
1047
+ count++;
1048
+ }
1049
+ }
1050
+ for (let index = lastValueLine + 1; index < end; index++) {
1051
+ lines.push(parsed[index].raw);
1052
+ }
1053
+ return { lines, next: end, count };
1054
+ }
1055
+ /*
1056
+ * A `data:` / `stringData:` / `binaryData:` block. Every value is masked
1057
+ * for a Secret or an object of unknown kind; only credential-like keys
1058
+ * are masked for anything else. Keys are kept either way.
1059
+ */
1060
+ static redactDataBlock(parsed, blockIndex, masks) {
1061
+ const block = parsed[blockIndex];
1062
+ const kind = GenericOutputRedactor.findSiblingKind(parsed, blockIndex);
1063
+ const maskEveryValue = kind === undefined || kind.toLowerCase() === "secret";
1064
+ const lines = [block.raw];
1065
+ let count = 0;
1066
+ let index = blockIndex + 1;
1067
+ let entryIndent = undefined;
1068
+ let entryMasked = false;
1069
+ while (index < parsed.length) {
1070
+ const line = parsed[index];
1071
+ if (line.isBlank) {
1072
+ if (!entryMasked) {
1073
+ lines.push(line.raw);
1074
+ }
1075
+ index++;
1076
+ continue;
1077
+ }
1078
+ if (line.indent <= block.contentIndent) {
1079
+ break;
1080
+ }
1081
+ if (entryIndent === undefined) {
1082
+ entryIndent = line.indent;
1083
+ }
1084
+ // Deeper than an entry: a block scalar body or nested structure.
1085
+ if (line.indent > entryIndent) {
1086
+ if (maskEveryValue || entryMasked) {
1087
+ index++;
1088
+ continue;
1089
+ }
1090
+ const nested = GenericOutputRedactor.redactStandaloneLine(parsed, index, masks);
1091
+ lines.push(...nested.lines);
1092
+ count += nested.count;
1093
+ index = nested.next;
1094
+ continue;
1095
+ }
1096
+ if (line.key === undefined) {
1097
+ // Not "key: value" — an unexpected shape inside a data block.
1098
+ if (maskEveryValue) {
1099
+ lines.push(" ".repeat(line.indent) + GENERIC_REDACTED_MARKER);
1100
+ count++;
1101
+ entryMasked = true;
1102
+ }
1103
+ else {
1104
+ const inline = applyInlineRules(line.raw);
1105
+ lines.push(inline.text);
1106
+ count += inline.count;
1107
+ entryMasked = false;
1108
+ }
1109
+ index++;
1110
+ continue;
1111
+ }
1112
+ if (maskEveryValue || isCredentialKey(line.key)) {
1113
+ if (line.value !== undefined && !isExemptValue(line.value)) {
1114
+ const masked = maskValueInPlace(line);
1115
+ lines.push(masked.text);
1116
+ count += masked.count;
1117
+ }
1118
+ else {
1119
+ lines.push(line.raw);
1120
+ }
1121
+ entryMasked = true;
1122
+ index++;
1123
+ continue;
1124
+ }
1125
+ const inline = applyInlineRulesToLine(line);
1126
+ lines.push(inline.text);
1127
+ count += inline.count;
1128
+ entryMasked = false;
1129
+ index++;
1130
+ }
1131
+ return { lines, next: index, count };
1132
+ }
1133
+ /*
1134
+ * One line outside a data block: env value, argv value, credential-like
1135
+ * key, inline rules.
1136
+ */
1137
+ static redactStandaloneLine(parsed, index, masks) {
1138
+ var _a;
1139
+ const line = parsed[index];
1140
+ if (line.isBlank) {
1141
+ return { lines: [line.raw], next: index + 1, count: 0 };
1142
+ }
1143
+ if (masks.envValueLines.has(index) && line.value !== undefined) {
1144
+ if (isBlockScalar(line.value)) {
1145
+ const masked = maskValueInPlace(line);
1146
+ return {
1147
+ lines: [masked.text],
1148
+ next: skipDeeperLines(parsed, index + 1, line.contentIndent),
1149
+ count: masked.count,
1150
+ };
1151
+ }
1152
+ if (!isExemptValue(line.value)) {
1153
+ const masked = maskValueInPlace(line);
1154
+ return { lines: [masked.text], next: index + 1, count: masked.count };
1155
+ }
1156
+ }
1157
+ const argvValue = masks.argvValueLines.get(index);
1158
+ if (argvValue !== undefined) {
1159
+ return { lines: [argvValue], next: index + 1, count: 1 };
1160
+ }
1161
+ if (line.key !== undefined &&
1162
+ line.value !== undefined &&
1163
+ (line.key === LAST_APPLIED_CONFIGURATION_ANNOTATION ||
1164
+ isCredentialKey(line.key))) {
1165
+ if (isBlockScalar(line.value)) {
1166
+ const masked = maskValueInPlace(line);
1167
+ return {
1168
+ lines: [masked.text],
1169
+ next: skipDeeperLines(parsed, index + 1, line.contentIndent),
1170
+ count: masked.count,
1171
+ };
1172
+ }
1173
+ if (!isExemptValue(line.value)) {
1174
+ const masked = maskValueInPlace(line);
1175
+ return { lines: [masked.text], next: index + 1, count: masked.count };
1176
+ }
1177
+ /*
1178
+ * A credential-like key with nothing to hide on this line: its
1179
+ * children are judged on their own, and describe's "<set to the key
1180
+ * …>" reference must not be chewed up by the inline pair rule.
1181
+ */
1182
+ const prefix = redactKeyPrefix(line);
1183
+ return {
1184
+ lines: [prefix.text + line.raw.slice((_a = line.valueStart) !== null && _a !== void 0 ? _a : 0)],
1185
+ next: index + 1,
1186
+ count: prefix.count,
1187
+ };
1188
+ }
1189
+ const inline = applyInlineRulesToLine(line);
1190
+ return { lines: [inline.text], next: index + 1, count: inline.count };
1191
+ }
1192
+ }
1193
+ // The marker every masked value is replaced with.
1194
+ export const RESOURCE_REDACTED_MARKER = GENERIC_REDACTED_MARKER;
1195
+ /*
1196
+ * `"Env": [ ... ]` as docker inspect (and docker service inspect) prints
1197
+ * it, pretty-printed or compact, possibly escaped inside another JSON
1198
+ * string. Every entry's VALUE is masked — an environment is where
1199
+ * containers keep their secrets, and a name that does not look like one
1200
+ * (APP_CONFIG, DATABASE) holds one as often as not. Names stay, so the model
1201
+ * still knows which variables are set.
1202
+ */
1203
+ const DOCKER_ENV_LIST_REGEX = /(\\?)"Env\1"\s*:\s*\[/g;
1204
+ const FOUR_HEX_DIGITS_REGEX = /^[0-9A-Fa-f]{4}$/;
1205
+ // The character one escape sequence of an enclosing JSON string stands for.
1206
+ function decodeJsonEscape(text, index) {
1207
+ const next = text.charAt(index + 1);
1208
+ if (next === "u" &&
1209
+ FOUR_HEX_DIGITS_REGEX.test(text.slice(index + 2, index + 6))) {
1210
+ return {
1211
+ char: String.fromCharCode(parseInt(text.slice(index + 2, index + 6), 16)),
1212
+ width: 6,
1213
+ };
1214
+ }
1215
+ return { char: next, width: 2 };
1216
+ }
1217
+ /*
1218
+ * Where a JSON string literal's body ends: the index of its closing quote
1219
+ * (`"`, or `\"` when the literal is itself escaped one level inside another
1220
+ * JSON string), or text.length when it never closes.
1221
+ *
1222
+ * Escaped one level, the body is read through the enclosing string's
1223
+ * escapes: `\\\"` is the entry's own escaped quote (`\"` once decoded) and
1224
+ * `\\\\` its own escaped backslash, so neither is taken for the entry's end
1225
+ * — which would leave every entry after it unmasked. A bare `"` ends the
1226
+ * enclosing string, so the entry cannot go on past it either.
1227
+ */
1228
+ function readJsonStringEnd(text, start, isEscaped) {
1229
+ let index = start;
1230
+ if (!isEscaped) {
1231
+ while (index < text.length) {
1232
+ const ch = text.charAt(index);
1233
+ if (ch === '"') {
1234
+ return index;
1235
+ }
1236
+ index += ch === "\\" ? 2 : 1;
1237
+ }
1238
+ return text.length;
1239
+ }
1240
+ let innerEscape = false;
1241
+ while (index < text.length) {
1242
+ const ch = text.charAt(index);
1243
+ if (ch === '"') {
1244
+ return index;
1245
+ }
1246
+ const decoded = ch === "\\" ? decodeJsonEscape(text, index) : { char: ch, width: 1 };
1247
+ if (innerEscape) {
1248
+ innerEscape = false;
1249
+ }
1250
+ else if (decoded.char === "\\") {
1251
+ innerEscape = true;
1252
+ }
1253
+ else if (decoded.char === '"') {
1254
+ return index;
1255
+ }
1256
+ index += decoded.width;
1257
+ }
1258
+ return text.length;
1259
+ }
1260
+ function maskDockerEnvValues(data) {
1261
+ const text = data.text;
1262
+ let out = "";
1263
+ let cursor = 0;
1264
+ let count = 0;
1265
+ DOCKER_ENV_LIST_REGEX.lastIndex = 0;
1266
+ let match = DOCKER_ENV_LIST_REGEX.exec(text);
1267
+ while (match) {
1268
+ const isEscaped = match[1] === "\\";
1269
+ const quote = isEscaped ? '\\"' : '"';
1270
+ let index = match.index + match[0].length;
1271
+ out += text.slice(cursor, index);
1272
+ // Walk the list's string entries until its closing bracket (or the end).
1273
+ while (index < text.length) {
1274
+ const ch = text.charAt(index);
1275
+ if (ch === "]") {
1276
+ break;
1277
+ }
1278
+ if (!text.startsWith(quote, index)) {
1279
+ out += ch;
1280
+ index++;
1281
+ continue;
1282
+ }
1283
+ const bodyStart = index + quote.length;
1284
+ const bodyEnd = readJsonStringEnd(text, bodyStart, isEscaped);
1285
+ const entry = text.slice(bodyStart, bodyEnd);
1286
+ const equals = entry.indexOf("=");
1287
+ if (equals > 0 && equals < entry.length - 1) {
1288
+ out += `${quote}${entry.slice(0, equals + 1)}${RESOURCE_REDACTED_MARKER}`;
1289
+ count++;
1290
+ }
1291
+ else {
1292
+ out += `${quote}${entry}`;
1293
+ }
1294
+ if (bodyEnd >= text.length || !text.startsWith(quote, bodyEnd)) {
1295
+ // The text ended, or (escaped) the enclosing string closed first.
1296
+ index = bodyEnd;
1297
+ break;
1298
+ }
1299
+ out += quote;
1300
+ index = bodyEnd + quote.length;
1301
+ }
1302
+ cursor = index;
1303
+ DOCKER_ENV_LIST_REGEX.lastIndex = Math.max(index, match.index + 1);
1304
+ match = DOCKER_ENV_LIST_REGEX.exec(text);
1305
+ }
1306
+ out += text.slice(cursor);
1307
+ return { text: out, redactionCount: count };
1308
+ }
1309
+ /*
1310
+ * `docker service inspect --pretty` prints a service's environment on the
1311
+ * " Env:" line of its ContainerSpec section, where the JSON hook above
1312
+ * cannot see it:
1313
+ * " Env:\t\tAPP_KEY=abc LOG_LEVEL=debug JAVA_OPTS=-Xmx1g -Dx=y "
1314
+ * The CLI's template prints each entry raw, so a value holding a newline (a
1315
+ * PEM certificate, a JSON blob from a YAML block) carries the rest of the
1316
+ * list onto the next physical lines. Inside a ContainerSpec section the Env
1317
+ * block therefore runs until the next line the template itself starts
1318
+ * (" Dir:", " Init:", " User:", "Mounts:", ... and "Endpoint Mode:", which
1319
+ * it always prints), or to the end of the text.
1320
+ *
1321
+ * A value may hold spaces, so the block cannot be split back into its
1322
+ * entries reliably. Every word shaped like NAME= keeps its NAME and has the
1323
+ * rest of it masked, and every other word (the tail of a value that held a
1324
+ * space or a newline) is dropped: over-masking accepted, never a value left.
1325
+ */
1326
+ const DOCKER_PRETTY_ENV_LINE_REGEX = /^([ \t]*Env:[ \t]+)(\S.*?)(\r?)$/;
1327
+ const DOCKER_PRETTY_ENV_NAME_REGEX = /^[A-Za-z_][A-Za-z0-9_.-]*=/;
1328
+ const DOCKER_PRETTY_CONTAINER_SPEC_REGEX = /^ContainerSpec:[ \t]*\r?$/;
1329
+ // The lines the pretty template may start after the Env line (and the next service's ID).
1330
+ const DOCKER_PRETTY_SECTION_REGEX = /^(?: (?:Dir|Init|User|Healthcheck):|(?:ID|Capabilities|SysCtls|Ulimits|Mounts|Configs|Secrets|Log Driver|Resources|Networks|Endpoint Mode|Ports):)/;
1331
+ function maskDockerPrettyEnvEntries(entries) {
1332
+ const masked = [];
1333
+ let count = 0;
1334
+ for (const word of entries.split(/\s+/)) {
1335
+ const name = DOCKER_PRETTY_ENV_NAME_REGEX.exec(word);
1336
+ if (!name) {
1337
+ continue;
1338
+ }
1339
+ if (word.length > name[0].length) {
1340
+ count++;
1341
+ masked.push(`${name[0]}${RESOURCE_REDACTED_MARKER}`);
1342
+ }
1343
+ else {
1344
+ masked.push(word);
1345
+ }
1346
+ }
1347
+ return { text: masked.join(" "), count };
1348
+ }
1349
+ function maskDockerPrettyEnvLines(data) {
1350
+ const lines = data.text.split("\n");
1351
+ const out = [];
1352
+ let count = 0;
1353
+ let inContainerSpec = false;
1354
+ for (let index = 0; index < lines.length; index++) {
1355
+ const line = lines[index] || "";
1356
+ if (DOCKER_PRETTY_CONTAINER_SPEC_REGEX.test(line)) {
1357
+ inContainerSpec = true;
1358
+ }
1359
+ const match = DOCKER_PRETTY_ENV_LINE_REGEX.exec(line);
1360
+ if (!match) {
1361
+ out.push(line);
1362
+ continue;
1363
+ }
1364
+ const block = [match[2] || ""];
1365
+ // The lines a multi-line value carried the list onto.
1366
+ while (inContainerSpec &&
1367
+ index + 1 < lines.length &&
1368
+ !DOCKER_PRETTY_SECTION_REGEX.test(lines[index + 1] || "")) {
1369
+ index++;
1370
+ block.push(lines[index] || "");
1371
+ }
1372
+ const masked = maskDockerPrettyEnvEntries(block.join(" "));
1373
+ count += masked.count;
1374
+ out.push(`${match[1] || ""}${masked.text}${match[3] || ""}`);
1375
+ }
1376
+ return { text: out.join("\n"), redactionCount: count };
1377
+ }
1378
+ /*
1379
+ * A Ceph keyring's secret: `key = AQD...==` (ceph auth get, keyring files),
1380
+ * `key: AQD...` (ceph auth ls) and `"key": "AQD..."` (-f json). The generic
1381
+ * rules deliberately leave a bare `key` alone (taints and tolerations have
1382
+ * one), but for ceph it is always a cephx secret.
1383
+ */
1384
+ const CEPH_KEY_LINE_REGEX = /^([ \t]*key[ \t]*[:=][ \t]*)(\S.*)$/gm;
1385
+ const CEPH_KEY_JSON_REGEX = /("key"\s*:\s*")((?:[^"\\]|\\.)*)(")/g;
1386
+ function maskCephKeys(data) {
1387
+ let count = 0;
1388
+ const text = data.text
1389
+ .replace(CEPH_KEY_LINE_REGEX, (whole, prefix, value) => {
1390
+ if (value.trim() === RESOURCE_REDACTED_MARKER) {
1391
+ return whole;
1392
+ }
1393
+ count++;
1394
+ return `${prefix}${RESOURCE_REDACTED_MARKER}`;
1395
+ })
1396
+ .replace(CEPH_KEY_JSON_REGEX, (whole, prefix, value, suffix) => {
1397
+ if (!value || value === RESOURCE_REDACTED_MARKER) {
1398
+ return whole;
1399
+ }
1400
+ count++;
1401
+ return `${prefix}${RESOURCE_REDACTED_MARKER}${suffix}`;
1402
+ });
1403
+ return { text, redactionCount: count };
1404
+ }
1405
+ /*
1406
+ * govc (VMware vCenter). A VM's extraConfig holds guestinfo.* keys —
1407
+ * cloud-init user data and metadata, vendor data, OVF environments — that
1408
+ * routinely carry passwords and SSH keys under names the generic rules
1409
+ * cannot recognise. The govc policy refuses every command that prints
1410
+ * extraConfig (vm.info -e and -json, object.collect of config); this is the
1411
+ * second line. The value of every option whose key is a guestinfo.* key (or
1412
+ * names user data, vendor data or an OVF environment, or looks
1413
+ * credential-like) is masked in each shape govc prints one: -json
1414
+ * OptionValue objects (key before or after value, any key case, the value a
1415
+ * string, a number or a {"_typeName", "_value"} object), the text listing
1416
+ * (`guestinfo.userdata: ...`), a JSON map entry (`"guestinfo.x": "..."`)
1417
+ * and -dump's Go syntax (`Key: "...", Value: "..."`). A vSphere session id
1418
+ * or ticket in -json output (a login event's sessionId, a clone or console
1419
+ * ticket) authenticates as its user, and is masked too.
1420
+ */
1421
+ const GOVC_JSON_STRING = '"(?:[^"\\\\]|\\\\.)*"';
1422
+ const GOVC_JSON_NUMBER = "-?[0-9][0-9.eE+-]*";
1423
+ const GOVC_JSON_SCALAR = `(?:${GOVC_JSON_STRING}|${GOVC_JSON_NUMBER})`;
1424
+ const GOVC_TYPED_VALUE = `\\{\\s*(?:"_typeName"\\s*:\\s*"[^"]*"\\s*,\\s*)?"_value"\\s*:\\s*${GOVC_JSON_SCALAR}(?:\\s*,\\s*"_typeName"\\s*:\\s*"[^"]*")?\\s*\\}`;
1425
+ const GOVC_OPTION_VALUE = `(?:${GOVC_JSON_SCALAR}|${GOVC_TYPED_VALUE})`;
1426
+ const GOVC_OPTION_KEY_FIRST_REGEX = new RegExp(`("key"\\s*:\\s*")((?:[^"\\\\]|\\\\.)*)("\\s*,\\s*"value"\\s*:\\s*)(${GOVC_OPTION_VALUE})`, "gi");
1427
+ const GOVC_OPTION_VALUE_FIRST_REGEX = new RegExp(`("value"\\s*:\\s*)(${GOVC_OPTION_VALUE})(\\s*,\\s*"key"\\s*:\\s*")((?:[^"\\\\]|\\\\.)*)(")`, "gi");
1428
+ const GOVC_OPTION_DUMP_REGEX = /(\bKey:\s*")((?:[^"\\]|\\.)*)("\s*,\s*Value:\s*)("(?:[^"\\]|\\.)*"|[^,\n}]*)/g;
1429
+ const GOVC_GUESTINFO_LINE_REGEX = /^([ \t]*guestinfo\.[^\s:=]*[ \t]*[:=][ \t]*)(\S.*)$/gim;
1430
+ const GOVC_SECRET_JSON_PAIR_REGEX = /("(?:sessionId|ticket|cloneTicket|guestinfo\.[^"\\\n]*)"\s*:\s*")((?:[^"\\]|\\.)*)(")/gi;
1431
+ // An option key whose value is (or may hold) credential material.
1432
+ function isSensitiveGovcOptionKey(key) {
1433
+ const folded = key.trim().toLowerCase();
1434
+ return (folded.startsWith("guestinfo.") ||
1435
+ folded.includes("userdata") ||
1436
+ folded.includes("vendordata") ||
1437
+ folded.includes("ovfenv") ||
1438
+ looksLikeCredentialName(folded));
1439
+ }
1440
+ // A value this hook (or an earlier pass) has nothing left to mask in.
1441
+ function isMaskedOrEmptyGovcValue(value) {
1442
+ const body = value.trim();
1443
+ return (body === "" ||
1444
+ body === '""' ||
1445
+ body === RESOURCE_REDACTED_MARKER ||
1446
+ body === `"${RESOURCE_REDACTED_MARKER}"`);
1447
+ }
1448
+ function maskGovcSecrets(data) {
1449
+ let count = 0;
1450
+ const maskedJson = `"${RESOURCE_REDACTED_MARKER}"`;
1451
+ const text = data.text
1452
+ .replace(GOVC_OPTION_KEY_FIRST_REGEX, (whole, keyPrefix, key, separator, value) => {
1453
+ if (!isSensitiveGovcOptionKey(key) || isMaskedOrEmptyGovcValue(value)) {
1454
+ return whole;
1455
+ }
1456
+ count++;
1457
+ return `${keyPrefix}${key}${separator}${maskedJson}`;
1458
+ })
1459
+ .replace(GOVC_OPTION_VALUE_FIRST_REGEX, (whole, valuePrefix, value, separator, key, closingQuote) => {
1460
+ if (!isSensitiveGovcOptionKey(key) || isMaskedOrEmptyGovcValue(value)) {
1461
+ return whole;
1462
+ }
1463
+ count++;
1464
+ return `${valuePrefix}${maskedJson}${separator}${key}${closingQuote}`;
1465
+ })
1466
+ .replace(GOVC_OPTION_DUMP_REGEX, (whole, keyPrefix, key, separator, value) => {
1467
+ if (!isSensitiveGovcOptionKey(key) || isMaskedOrEmptyGovcValue(value)) {
1468
+ return whole;
1469
+ }
1470
+ count++;
1471
+ return `${keyPrefix}${key}${separator}${maskedJson}`;
1472
+ })
1473
+ .replace(GOVC_GUESTINFO_LINE_REGEX, (whole, prefix, value) => {
1474
+ if (isMaskedOrEmptyGovcValue(value)) {
1475
+ return whole;
1476
+ }
1477
+ count++;
1478
+ return `${prefix}${RESOURCE_REDACTED_MARKER}`;
1479
+ })
1480
+ .replace(GOVC_SECRET_JSON_PAIR_REGEX, (whole, prefix, value, suffix) => {
1481
+ if (isMaskedOrEmptyGovcValue(value)) {
1482
+ return whole;
1483
+ }
1484
+ count++;
1485
+ return `${prefix}${RESOURCE_REDACTED_MARKER}${suffix}`;
1486
+ });
1487
+ return { text, redactionCount: count };
1488
+ }
1489
+ /*
1490
+ * The rest of a Ceph secret's footprint, after maskCephKeys:
1491
+ * - a bare cephx secret wherever it appears (`ceph auth print-key` prints
1492
+ * one alone; an audit entry or an escaped JSON string can hold one). A
1493
+ * cephx secret is the base64 of a 28-byte key record whose type is 1, so
1494
+ * it starts "AQ" and is 40 characters long with "==" padding; the
1495
+ * pattern is looser than that on purpose;
1496
+ * - the value of a `"val"` or `"value"` field, plain or escaped inside
1497
+ * another JSON string: the audit channel (`ceph log last ... audit`)
1498
+ * records every `config-key set` and `config set` a client ran, value
1499
+ * included, and those values are where dashboard, RGW and cephadm
1500
+ * credentials live.
1501
+ */
1502
+ const CEPHX_SECRET_REGEX = /(^|[^A-Za-z0-9+/])AQ[A-Za-z0-9+/]{30,}={0,2}/g;
1503
+ const CEPH_VALUE_JSON_REGEX = /("(?:val|value)"\s*:\s*")((?:[^"\\]|\\.)*)(")/g;
1504
+ const CEPH_VALUE_ESCAPED_JSON_REGEX = /(\\"(?:val|value)\\"\s*:\s*\\")((?:[^"\\]|\\\\\\["\\]|\\\\[^"\\])*)(\\")/g;
1505
+ function maskCephSecretValues(data) {
1506
+ let count = 0;
1507
+ const maskValue = (whole, prefix, value, suffix) => {
1508
+ if (!value || value === RESOURCE_REDACTED_MARKER) {
1509
+ return whole;
1510
+ }
1511
+ count++;
1512
+ return `${prefix}${RESOURCE_REDACTED_MARKER}${suffix}`;
1513
+ };
1514
+ const text = data.text
1515
+ .replace(CEPH_VALUE_JSON_REGEX, maskValue)
1516
+ .replace(CEPH_VALUE_ESCAPED_JSON_REGEX, maskValue)
1517
+ .replace(CEPHX_SECRET_REGEX, (_whole, before) => {
1518
+ count++;
1519
+ return `${before}${RESOURCE_REDACTED_MARKER}`;
1520
+ });
1521
+ return { text, redactionCount: count };
1522
+ }
1523
+ /*
1524
+ * pvesh (Proxmox VE). A guest's config and pending changes carry
1525
+ * cloud-init's `cipassword`, and the cluster storage list can carry a
1526
+ * `password`, an RBD `keyring` or a PBS `encryption-key`. Masked in every
1527
+ * shape the agent prints the API's answer in: JSON pairs (plain, or escaped
1528
+ * inside another JSON string), `key: value` and `key value` lines, the rows
1529
+ * of pvesh's text tables (`│ cipassword │ ... │`), and /pending entries —
1530
+ * {"key": "cipassword", "value": ..., "pending": ...}, members in any order
1531
+ * — where the secret's NAME is itself a value, so the generic rules never
1532
+ * read it as a key. In the table and pending shapes any credential-looking
1533
+ * name (isCredentialKey) counts too; the generic rules cover it elsewhere.
1534
+ */
1535
+ const PROXMOX_SECRET_KEYS = [
1536
+ "cipassword",
1537
+ "password",
1538
+ "keyring",
1539
+ "encryption-key",
1540
+ ];
1541
+ const PROXMOX_SECRET_KEY_SOURCE = PROXMOX_SECRET_KEYS.join("|");
1542
+ const PROXMOX_SECRET_JSON_REGEX = new RegExp(`("(?:${PROXMOX_SECRET_KEY_SOURCE})"\\s*:\\s*")((?:[^"\\\\]|\\\\.)*)(")`, "gi");
1543
+ const PROXMOX_SECRET_ESCAPED_JSON_REGEX = new RegExp(`(\\\\"(?:${PROXMOX_SECRET_KEY_SOURCE})\\\\"\\s*:\\s*\\\\")((?:[^"\\\\]|\\\\[^"])*)(\\\\")`, "gi");
1544
+ const PROXMOX_SECRET_LINE_REGEX = new RegExp(`^([ \\t]*(?:-[ \\t]+)?(?:${PROXMOX_SECRET_KEY_SOURCE})(?:[ \\t]*[:=][ \\t]*|[ \\t]+))(\\S.*)$`, "gim");
1545
+ const PROXMOX_FLAT_JSON_OBJECT_REGEX = /\{[^{}]*\}/g;
1546
+ const PROXMOX_PENDING_KEY_REGEX = /"key"\s*:\s*"((?:[^"\\]|\\.)*)"/;
1547
+ const PROXMOX_PENDING_VALUE_REGEX = /("(?:value|pending)"\s*:\s*)("(?:[^"\\]|\\.)*"|-?[0-9][0-9.eE+-]*)/g;
1548
+ const PROXMOX_TABLE_ROW_REGEX = /^([ \t]*)([│|])(.*)$/gm;
1549
+ const PROXMOX_CELL_CONTENT_REGEX = /\S(?:.*\S)?/;
1550
+ function isProxmoxSecretName(name) {
1551
+ const folded = name.trim().toLowerCase();
1552
+ return PROXMOX_SECRET_KEYS.includes(folded) || isCredentialKey(folded);
1553
+ }
1554
+ // A value an earlier pass already masked, or one with nothing in it.
1555
+ function isMaskedOrEmptyProxmoxValue(value) {
1556
+ const body = unquote(value.trim().replace(/,$/, "").trim());
1557
+ return body === "" || body.startsWith(REDACTED_PREFIX);
1558
+ }
1559
+ function maskProxmoxSecrets(data) {
1560
+ let count = 0;
1561
+ const maskPair = (whole, prefix, value, suffix) => {
1562
+ if (isMaskedOrEmptyProxmoxValue(value)) {
1563
+ return whole;
1564
+ }
1565
+ count++;
1566
+ return `${prefix}${RESOURCE_REDACTED_MARKER}${suffix}`;
1567
+ };
1568
+ const text = data.text
1569
+ .replace(PROXMOX_SECRET_JSON_REGEX, maskPair)
1570
+ .replace(PROXMOX_SECRET_ESCAPED_JSON_REGEX, maskPair)
1571
+ .replace(PROXMOX_FLAT_JSON_OBJECT_REGEX, (entry) => {
1572
+ const key = PROXMOX_PENDING_KEY_REGEX.exec(entry);
1573
+ if (!key || !isProxmoxSecretName(key[1] || "")) {
1574
+ return entry;
1575
+ }
1576
+ return entry.replace(PROXMOX_PENDING_VALUE_REGEX, (whole, prefix, value) => {
1577
+ if (isMaskedOrEmptyProxmoxValue(value)) {
1578
+ return whole;
1579
+ }
1580
+ count++;
1581
+ return `${prefix}"${RESOURCE_REDACTED_MARKER}"`;
1582
+ });
1583
+ })
1584
+ .replace(PROXMOX_SECRET_LINE_REGEX, (whole, prefix, value) => {
1585
+ if (isMaskedOrEmptyProxmoxValue(value)) {
1586
+ return whole;
1587
+ }
1588
+ count++;
1589
+ return `${prefix}${RESOURCE_REDACTED_MARKER}`;
1590
+ })
1591
+ .replace(PROXMOX_TABLE_ROW_REGEX, (whole, indent, separator, rest) => {
1592
+ const cells = rest.split(separator);
1593
+ if (cells.length < 2 || !isProxmoxSecretName(cells[0] || "")) {
1594
+ return whole;
1595
+ }
1596
+ const masked = cells.map((cell, index) => {
1597
+ if (index === 0 || isMaskedOrEmptyProxmoxValue(cell)) {
1598
+ return cell;
1599
+ }
1600
+ count++;
1601
+ return cell.replace(PROXMOX_CELL_CONTENT_REGEX, RESOURCE_REDACTED_MARKER);
1602
+ });
1603
+ return `${indent}${separator}${masked.join(separator)}`;
1604
+ });
1605
+ return { text, redactionCount: count };
1606
+ }
1607
+ /*
1608
+ * Credentials on the command lines a process listing prints (ps, top -c,
1609
+ * the cgroup tree of systemctl status, journalctl):
1610
+ * the value after a credential-named flag (`--password=x`, `--token x`,
1611
+ * `-Dapp.db.password=x`), a credential-named assignment (`PASSWORD=x`,
1612
+ * `DB_TOKEN=x`) and the password half of `-u user:password` (curl, wget).
1613
+ * ps and top join a process's argv with single spaces and drop its quotes,
1614
+ * so a value is the run of characters up to the next whitespace. Names
1615
+ * are judged by the generic rules' own isCredentialKey, so both layers
1616
+ * agree on what a credential is called.
1617
+ */
1618
+ const PROCESS_USER_PASSWORD_FLAGS = [
1619
+ "-u",
1620
+ "--user",
1621
+ "-U",
1622
+ "--proxy-user",
1623
+ ];
1624
+ const PROCESS_NUMERIC_REGEX = /^[0-9]+$/;
1625
+ // One process line with its credential values masked, and how many.
1626
+ function maskProcessLine(line) {
1627
+ // Words at even indexes, the whitespace between them at odd ones.
1628
+ const parts = line.split(/(\s+)/);
1629
+ let count = 0;
1630
+ let maskNextWord = false;
1631
+ let userPasswordNext = false;
1632
+ for (let i = 0; i < parts.length; i += 2) {
1633
+ const word = parts[i] || "";
1634
+ if (!word) {
1635
+ continue;
1636
+ }
1637
+ if (maskNextWord) {
1638
+ maskNextWord = false;
1639
+ if (!word.startsWith("-") && !isExemptValue(word)) {
1640
+ parts[i] = RESOURCE_REDACTED_MARKER;
1641
+ count++;
1642
+ continue;
1643
+ }
1644
+ }
1645
+ if (userPasswordNext) {
1646
+ userPasswordNext = false;
1647
+ const colon = word.indexOf(":");
1648
+ const password = colon > 0 ? word.slice(colon + 1) : "";
1649
+ if (password &&
1650
+ !word.startsWith("-") &&
1651
+ !PROCESS_NUMERIC_REGEX.test(password) &&
1652
+ !isExemptValue(password)) {
1653
+ parts[i] = `${word.slice(0, colon + 1)}${RESOURCE_REDACTED_MARKER}`;
1654
+ count++;
1655
+ continue;
1656
+ }
1657
+ }
1658
+ const equals = word.indexOf("=");
1659
+ if (equals > 0) {
1660
+ const value = word.slice(equals + 1);
1661
+ if (value &&
1662
+ !isExemptValue(value) &&
1663
+ isCredentialKey(word.slice(0, equals))) {
1664
+ parts[i] = `${word.slice(0, equals + 1)}${RESOURCE_REDACTED_MARKER}`;
1665
+ count++;
1666
+ }
1667
+ continue;
1668
+ }
1669
+ if (!word.startsWith("-") || word.length < 2) {
1670
+ continue;
1671
+ }
1672
+ if (PROCESS_USER_PASSWORD_FLAGS.includes(word)) {
1673
+ userPasswordNext = true;
1674
+ continue;
1675
+ }
1676
+ if (isCredentialKey(word)) {
1677
+ maskNextWord = true;
1678
+ }
1679
+ }
1680
+ return { text: parts.join(""), count };
1681
+ }
1682
+ function maskProcessCredentialArguments(data) {
1683
+ let count = 0;
1684
+ const lines = data.text
1685
+ .split("\n")
1686
+ .map((line) => {
1687
+ const masked = maskProcessLine(line);
1688
+ count += masked.count;
1689
+ return masked.text;
1690
+ });
1691
+ return { text: lines.join("\n"), redactionCount: count };
1692
+ }
1693
+ /*
1694
+ * journalctl prints the command lines of the processes it logged: in a
1695
+ * message, and with -o json in each record's _CMDLINE field. A JSON record
1696
+ * (one per line) has each of its string values masked as a process line —
1697
+ * decoded first and re-encoded after, so the record stays valid JSON; any
1698
+ * other line is masked as a process line itself.
1699
+ */
1700
+ function maskJournalCredentialArguments(data) {
1701
+ let count = 0;
1702
+ const lines = data.text
1703
+ .split("\n")
1704
+ .map((line) => {
1705
+ const trimmed = line.trim();
1706
+ if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
1707
+ let record = null;
1708
+ try {
1709
+ record = JSON.parse(trimmed);
1710
+ }
1711
+ catch (_a) {
1712
+ record = null;
1713
+ }
1714
+ if (record && typeof record === "object" && !Array.isArray(record)) {
1715
+ const fields = record;
1716
+ let changed = false;
1717
+ for (const key of Object.keys(fields)) {
1718
+ const value = fields[key];
1719
+ if (typeof value !== "string") {
1720
+ continue;
1721
+ }
1722
+ const masked = maskProcessLine(value);
1723
+ if (masked.count > 0) {
1724
+ fields[key] = masked.text;
1725
+ count += masked.count;
1726
+ changed = true;
1727
+ }
1728
+ }
1729
+ if (!changed) {
1730
+ return line;
1731
+ }
1732
+ /*
1733
+ * Spliced in by position, never through String.replace: a
1734
+ * replacement string's "$&" (a MESSAGE may hold one) would paste
1735
+ * the original, unmasked record back in.
1736
+ */
1737
+ const start = line.indexOf(trimmed);
1738
+ return `${line.slice(0, start)}${JSON.stringify(fields)}${line.slice(start + trimmed.length)}`;
1739
+ }
1740
+ }
1741
+ const masked = maskProcessLine(line);
1742
+ count += masked.count;
1743
+ return masked.text;
1744
+ });
1745
+ return { text: lines.join("\n"), redactionCount: count };
1746
+ }
1747
+ /*
1748
+ * `ceph status` (and `ceph -s`) in its plain format calls its usage section
1749
+ * "data:" — pools, objects, usage and PG states — and the generic rules,
1750
+ * written for kubectl, read a "data:" block as a Kubernetes Secret's and
1751
+ * mask every line of it, which leaves the model blind to the one summary it
1752
+ * asks for first. For exactly that shape — a " data:" header after the
1753
+ * " cluster:" / " id: FSID" / " services:" headers, holding only
1754
+ * ceph's own usage lines and their continuation lines — the header is
1755
+ * renamed to a placeholder the generic rules read as an ordinary key while
1756
+ * they run, and written back afterwards. Every line under it still gets the
1757
+ * generic per-line rules. Any other shape (and output that already holds
1758
+ * the placeholder) is left to the generic rules whole: over-masking is
1759
+ * accepted, under-masking is not.
1760
+ */
1761
+ const CEPH_STATUS_DATA_PLACEHOLDER = "ceph-status-usage-section";
1762
+ const CEPH_STATUS_DATA_HEADER = " data:";
1763
+ const CEPH_STATUS_DATA_KEYS = [
1764
+ "volumes",
1765
+ "pools",
1766
+ "objects",
1767
+ "usage",
1768
+ "pgs",
1769
+ ];
1770
+ const CEPH_STATUS_FSID_LINE_REGEX = /^ {4}id: +[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
1771
+ const CEPH_STATUS_DATA_ENTRY_REGEX = /^ {4}([a-z]+):(?: |$)/;
1772
+ const CEPH_STATUS_PLACEHOLDER_LINE_REGEX = new RegExp(`^( {2})${CEPH_STATUS_DATA_PLACEHOLDER}:`);
1773
+ export function shieldCephStatusDataSection(text) {
1774
+ if (typeof text !== "string" || text.includes(CEPH_STATUS_DATA_PLACEHOLDER)) {
1775
+ return null;
1776
+ }
1777
+ const lines = text.split("\n");
1778
+ const bare = lines.map((line) => {
1779
+ return line.replace(/\r$/, "");
1780
+ });
1781
+ const clusterIndex = bare.indexOf(" cluster:");
1782
+ if (clusterIndex < 0 ||
1783
+ !CEPH_STATUS_FSID_LINE_REGEX.test(bare[clusterIndex + 1] || "")) {
1784
+ return null;
1785
+ }
1786
+ const servicesIndex = bare.indexOf(" services:", clusterIndex);
1787
+ const dataIndex = servicesIndex < 0
1788
+ ? -1
1789
+ : bare.indexOf(CEPH_STATUS_DATA_HEADER, servicesIndex);
1790
+ if (dataIndex < 0) {
1791
+ return null;
1792
+ }
1793
+ let entries = 0;
1794
+ for (let index = dataIndex + 1; index < bare.length; index++) {
1795
+ const line = bare[index];
1796
+ if (line.trim() === "") {
1797
+ break;
1798
+ }
1799
+ const indent = line.length - line.trimStart().length;
1800
+ if (indent <= 2) {
1801
+ break;
1802
+ }
1803
+ if (indent === 4) {
1804
+ const entry = CEPH_STATUS_DATA_ENTRY_REGEX.exec(line);
1805
+ if (!entry || !CEPH_STATUS_DATA_KEYS.includes(entry[1] || "")) {
1806
+ return null;
1807
+ }
1808
+ entries++;
1809
+ continue;
1810
+ }
1811
+ // Deeper: the continuation of the entry above (" 12 active+clean").
1812
+ if (indent > 4 && entries > 0) {
1813
+ continue;
1814
+ }
1815
+ return null;
1816
+ }
1817
+ if (entries === 0) {
1818
+ return null;
1819
+ }
1820
+ const shielded = lines.slice();
1821
+ shielded[dataIndex] = lines[dataIndex].replace("data:", `${CEPH_STATUS_DATA_PLACEHOLDER}:`);
1822
+ return {
1823
+ text: shielded.join("\n"),
1824
+ restore: (redacted) => {
1825
+ return redacted
1826
+ .split("\n")
1827
+ .map((line) => {
1828
+ return line.replace(CEPH_STATUS_PLACEHOLDER_LINE_REGEX, "$1data:");
1829
+ })
1830
+ .join("\n");
1831
+ },
1832
+ };
1833
+ }
1834
+ /*
1835
+ * Output a program prints that the generic rules misread, shielded while
1836
+ * they run (see shieldCephStatusDataSection); null for everything else.
1837
+ */
1838
+ function shieldFromGenericRules(program, text) {
1839
+ try {
1840
+ return program === "ceph" ? shieldCephStatusDataSection(text) : null;
1841
+ }
1842
+ catch (_a) {
1843
+ return null;
1844
+ }
1845
+ }
1846
+ /*
1847
+ * The per-program hooks, run on the raw output before the generic rules.
1848
+ * Keyed by argv[0]; a program with no entry gets the generic rules only.
1849
+ * Each tool's kit extends its program's list (pvesh `cipassword`, govc
1850
+ * credentials, db query literals, ...).
1851
+ */
1852
+ export const RESOURCE_OUTPUT_REDACTION_HOOKS = {
1853
+ ps: [maskProcessCredentialArguments],
1854
+ top: [maskProcessCredentialArguments],
1855
+ // systemctl status prints every process of a unit's cgroup, argv and all.
1856
+ systemctl: [maskProcessCredentialArguments],
1857
+ journalctl: [maskJournalCredentialArguments],
1858
+ docker: [maskDockerEnvValues, maskDockerPrettyEnvLines],
1859
+ ceph: [maskCephKeys, maskCephSecretValues],
1860
+ pvesh: [maskProxmoxSecrets],
1861
+ govc: [maskGovcSecrets],
1862
+ db: [redactDatabaseOutput],
1863
+ };
1864
+ // The hooks for one program; none for a program the table does not list.
1865
+ export function getResourceOutputRedactionHooks(program) {
1866
+ if (typeof program !== "string" ||
1867
+ !Object.prototype.hasOwnProperty.call(RESOURCE_OUTPUT_REDACTION_HOOKS, program)) {
1868
+ return [];
1869
+ }
1870
+ return RESOURCE_OUTPUT_REDACTION_HOOKS[program] || [];
1871
+ }
1872
+ /*
1873
+ * Redact one command's output: the program's hooks, then the generic rules.
1874
+ * Total: anything that is not text comes back as "", and a hook that throws
1875
+ * is skipped (the generic rules still run over what it was given).
1876
+ */
1877
+ export function redactResourceCommandOutputWithCount(data) {
1878
+ if (!data || typeof data.text !== "string" || !data.text) {
1879
+ return { text: "", redactionCount: 0 };
1880
+ }
1881
+ let text = data.text;
1882
+ let count = 0;
1883
+ for (const hook of getResourceOutputRedactionHooks(data.program)) {
1884
+ try {
1885
+ const hooked = hook({
1886
+ resourceType: data.resourceType,
1887
+ program: data.program,
1888
+ text,
1889
+ });
1890
+ if (hooked && typeof hooked.text === "string") {
1891
+ text = hooked.text;
1892
+ count +=
1893
+ typeof hooked.redactionCount === "number" ? hooked.redactionCount : 0;
1894
+ }
1895
+ }
1896
+ catch (_a) {
1897
+ // A broken hook must never leak the output unredacted by the generic rules.
1898
+ }
1899
+ }
1900
+ const shield = shieldFromGenericRules(data.program, text);
1901
+ const generic = GenericOutputRedactor.redact(shield ? shield.text : text);
1902
+ return {
1903
+ text: shield ? shield.restore(generic.text) : generic.text,
1904
+ redactionCount: count + generic.redactionCount,
1905
+ };
1906
+ }
1907
+ export function redactResourceCommandOutput(data) {
1908
+ return redactResourceCommandOutputWithCount(data).text;
1909
+ }
1910
+ //# sourceMappingURL=ResourceOutputRedactor.js.map