@skyhook-io/k8s-ui 1.0.0

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 (193) hide show
  1. package/package.json +63 -0
  2. package/src/components/dock/BottomDock.tsx +204 -0
  3. package/src/components/dock/DockContext.tsx +212 -0
  4. package/src/components/dock/TerminalTab.tsx +333 -0
  5. package/src/components/dock/index.ts +3 -0
  6. package/src/components/gitops/GitOpsActions.tsx +227 -0
  7. package/src/components/gitops/GitOpsStatusBadge.tsx +221 -0
  8. package/src/components/gitops/ManagedResourcesList.tsx +210 -0
  9. package/src/components/gitops/SyncCountdown.tsx +146 -0
  10. package/src/components/gitops/index.ts +4 -0
  11. package/src/components/logs/JsonLogLine.tsx +90 -0
  12. package/src/components/logs/LogCore.tsx +553 -0
  13. package/src/components/logs/LogToolbarSelects.tsx +74 -0
  14. package/src/components/logs/LogsViewer.tsx +146 -0
  15. package/src/components/logs/WorkloadLogsViewer.tsx +263 -0
  16. package/src/components/logs/index.ts +13 -0
  17. package/src/components/logs/useLogBuffer.ts +138 -0
  18. package/src/components/logs/useLogSearch.ts +151 -0
  19. package/src/components/logs/useLogStream.ts +61 -0
  20. package/src/components/resources/ResourcesView.tsx +5494 -0
  21. package/src/components/resources/index.ts +17 -0
  22. package/src/components/resources/renderers/AlertRenderer.tsx +166 -0
  23. package/src/components/resources/renderers/ArgoApplicationRenderer.tsx +233 -0
  24. package/src/components/resources/renderers/CNPGBackupRenderer.tsx +89 -0
  25. package/src/components/resources/renderers/CNPGClusterRenderer.tsx +194 -0
  26. package/src/components/resources/renderers/CNPGPoolerRenderer.tsx +79 -0
  27. package/src/components/resources/renderers/CNPGScheduledBackupRenderer.tsx +68 -0
  28. package/src/components/resources/renderers/CertificateRenderer.tsx +209 -0
  29. package/src/components/resources/renderers/CertificateRequestRenderer.tsx +123 -0
  30. package/src/components/resources/renderers/ChallengeRenderer.tsx +111 -0
  31. package/src/components/resources/renderers/ClusterComplianceReportRenderer.tsx +164 -0
  32. package/src/components/resources/renderers/ClusterExternalSecretRenderer.tsx +140 -0
  33. package/src/components/resources/renderers/ClusterIssuerRenderer.tsx +153 -0
  34. package/src/components/resources/renderers/ConfigAuditReportRenderer.tsx +221 -0
  35. package/src/components/resources/renderers/ConfigMapRenderer.tsx +124 -0
  36. package/src/components/resources/renderers/CronJobRenderer.tsx +86 -0
  37. package/src/components/resources/renderers/EventRenderer.tsx +175 -0
  38. package/src/components/resources/renderers/ExposedSecretReportRenderer.tsx +119 -0
  39. package/src/components/resources/renderers/ExternalSecretRenderer.tsx +172 -0
  40. package/src/components/resources/renderers/FluxHelmReleaseRenderer.tsx +242 -0
  41. package/src/components/resources/renderers/GRPCRouteRenderer.tsx +263 -0
  42. package/src/components/resources/renderers/GatewayClassRenderer.tsx +68 -0
  43. package/src/components/resources/renderers/GatewayRenderer.tsx +218 -0
  44. package/src/components/resources/renderers/GenericRenderer.tsx +476 -0
  45. package/src/components/resources/renderers/GitRepositoryRenderer.tsx +154 -0
  46. package/src/components/resources/renderers/HPARenderer.tsx +164 -0
  47. package/src/components/resources/renderers/HTTPRouteRenderer.tsx +303 -0
  48. package/src/components/resources/renderers/HelmRepositoryRenderer.tsx +167 -0
  49. package/src/components/resources/renderers/IngressClassRenderer.tsx +49 -0
  50. package/src/components/resources/renderers/IngressRenderer.tsx +104 -0
  51. package/src/components/resources/renderers/IstioAuthorizationPolicyRenderer.tsx +175 -0
  52. package/src/components/resources/renderers/IstioDestinationRuleRenderer.tsx +176 -0
  53. package/src/components/resources/renderers/IstioGatewayRenderer.tsx +125 -0
  54. package/src/components/resources/renderers/IstioPeerAuthenticationRenderer.tsx +84 -0
  55. package/src/components/resources/renderers/IstioServiceEntryRenderer.tsx +112 -0
  56. package/src/components/resources/renderers/IstioVirtualServiceRenderer.tsx +288 -0
  57. package/src/components/resources/renderers/JobRenderer.tsx +103 -0
  58. package/src/components/resources/renderers/KarpenterEC2NodeClassRenderer.tsx +157 -0
  59. package/src/components/resources/renderers/KarpenterNodeClaimRenderer.tsx +188 -0
  60. package/src/components/resources/renderers/KarpenterNodePoolRenderer.tsx +148 -0
  61. package/src/components/resources/renderers/KedaScaledJobRenderer.tsx +90 -0
  62. package/src/components/resources/renderers/KedaScaledObjectRenderer.tsx +136 -0
  63. package/src/components/resources/renderers/KedaTriggerAuthRenderer.tsx +151 -0
  64. package/src/components/resources/renderers/KnativeConfigurationRenderer.tsx +70 -0
  65. package/src/components/resources/renderers/KnativeEventingRenderer.tsx +309 -0
  66. package/src/components/resources/renderers/KnativeFlowRenderer.tsx +142 -0
  67. package/src/components/resources/renderers/KnativeNetworkingRenderer.tsx +232 -0
  68. package/src/components/resources/renderers/KnativeRevisionRenderer.tsx +97 -0
  69. package/src/components/resources/renderers/KnativeRouteRenderer.tsx +74 -0
  70. package/src/components/resources/renderers/KnativeServiceRenderer.tsx +138 -0
  71. package/src/components/resources/renderers/KnativeSourceRenderer.tsx +220 -0
  72. package/src/components/resources/renderers/KustomizationRenderer.tsx +151 -0
  73. package/src/components/resources/renderers/KyvernoPolicyReportRenderer.tsx +352 -0
  74. package/src/components/resources/renderers/LeaseRenderer.tsx +93 -0
  75. package/src/components/resources/renderers/NetworkPolicyRenderer.tsx +208 -0
  76. package/src/components/resources/renderers/NodeRenderer.tsx +282 -0
  77. package/src/components/resources/renderers/OCIRepositoryRenderer.tsx +153 -0
  78. package/src/components/resources/renderers/OrderRenderer.tsx +108 -0
  79. package/src/components/resources/renderers/PVCRenderer.tsx +98 -0
  80. package/src/components/resources/renderers/PersistentVolumeRenderer.tsx +138 -0
  81. package/src/components/resources/renderers/PodDisruptionBudgetRenderer.tsx +126 -0
  82. package/src/components/resources/renderers/PodMonitorRenderer.tsx +63 -0
  83. package/src/components/resources/renderers/PodRenderer.tsx +677 -0
  84. package/src/components/resources/renderers/PriorityClassRenderer.tsx +50 -0
  85. package/src/components/resources/renderers/PrometheusRuleRenderer.tsx +62 -0
  86. package/src/components/resources/renderers/ReplicaSetRenderer.tsx +71 -0
  87. package/src/components/resources/renderers/RoleBindingRenderer.tsx +97 -0
  88. package/src/components/resources/renderers/RoleRenderer.tsx +192 -0
  89. package/src/components/resources/renderers/RolloutRenderer.tsx +227 -0
  90. package/src/components/resources/renderers/RuntimeClassRenderer.tsx +75 -0
  91. package/src/components/resources/renderers/SbomReportRenderer.tsx +98 -0
  92. package/src/components/resources/renderers/SealedSecretRenderer.tsx +121 -0
  93. package/src/components/resources/renderers/SecretRenderer.tsx +321 -0
  94. package/src/components/resources/renderers/SecretStoreRenderer.tsx +111 -0
  95. package/src/components/resources/renderers/ServiceAccountRenderer.tsx +81 -0
  96. package/src/components/resources/renderers/ServiceMonitorRenderer.tsx +65 -0
  97. package/src/components/resources/renderers/ServiceRenderer.tsx +98 -0
  98. package/src/components/resources/renderers/SimpleRouteRenderer.tsx +195 -0
  99. package/src/components/resources/renderers/StorageClassRenderer.tsx +82 -0
  100. package/src/components/resources/renderers/TraefikIngressRouteRenderer.tsx +257 -0
  101. package/src/components/resources/renderers/VPARenderer.tsx +193 -0
  102. package/src/components/resources/renderers/VeleroBSLRenderer.tsx +73 -0
  103. package/src/components/resources/renderers/VeleroBackupRenderer.tsx +193 -0
  104. package/src/components/resources/renderers/VeleroRestoreRenderer.tsx +161 -0
  105. package/src/components/resources/renderers/VeleroScheduleRenderer.tsx +134 -0
  106. package/src/components/resources/renderers/VeleroVSLRenderer.tsx +36 -0
  107. package/src/components/resources/renderers/VulnerabilityReportRenderer.tsx +347 -0
  108. package/src/components/resources/renderers/WebhookConfigRenderer.tsx +156 -0
  109. package/src/components/resources/renderers/WorkflowRenderer.tsx +202 -0
  110. package/src/components/resources/renderers/WorkflowTemplateRenderer.tsx +91 -0
  111. package/src/components/resources/renderers/WorkloadRenderer.tsx +311 -0
  112. package/src/components/resources/renderers/argo-cells.tsx +118 -0
  113. package/src/components/resources/renderers/certmanager-cells.tsx +164 -0
  114. package/src/components/resources/renderers/cnpg-cells.tsx +161 -0
  115. package/src/components/resources/renderers/eso-cells.tsx +115 -0
  116. package/src/components/resources/renderers/flux-cells.tsx +253 -0
  117. package/src/components/resources/renderers/index.ts +105 -0
  118. package/src/components/resources/renderers/istio-cells.tsx +210 -0
  119. package/src/components/resources/renderers/karpenter-cells.tsx +107 -0
  120. package/src/components/resources/renderers/keda-cells.tsx +94 -0
  121. package/src/components/resources/renderers/knative-cells.tsx +396 -0
  122. package/src/components/resources/renderers/kyverno-cells.tsx +85 -0
  123. package/src/components/resources/renderers/prometheus-cells.tsx +74 -0
  124. package/src/components/resources/renderers/traefik-cells.tsx +120 -0
  125. package/src/components/resources/renderers/trivy-cells.tsx +153 -0
  126. package/src/components/resources/renderers/trivy-shared.tsx +67 -0
  127. package/src/components/resources/renderers/velero-cells.tsx +164 -0
  128. package/src/components/resources/resource-utils-argo.ts +155 -0
  129. package/src/components/resources/resource-utils-certmanager.ts +198 -0
  130. package/src/components/resources/resource-utils-cnpg.ts +344 -0
  131. package/src/components/resources/resource-utils-eso.ts +385 -0
  132. package/src/components/resources/resource-utils-flux.ts +186 -0
  133. package/src/components/resources/resource-utils-istio.ts +372 -0
  134. package/src/components/resources/resource-utils-karpenter.ts +150 -0
  135. package/src/components/resources/resource-utils-keda.ts +203 -0
  136. package/src/components/resources/resource-utils-knative.ts +218 -0
  137. package/src/components/resources/resource-utils-kyverno.ts +224 -0
  138. package/src/components/resources/resource-utils-prometheus.ts +159 -0
  139. package/src/components/resources/resource-utils-traefik.ts +180 -0
  140. package/src/components/resources/resource-utils-trivy.ts +146 -0
  141. package/src/components/resources/resource-utils-velero.ts +293 -0
  142. package/src/components/resources/resource-utils.ts +1558 -0
  143. package/src/components/shared/EditableYamlView.tsx +302 -0
  144. package/src/components/shared/ResourceActionsBar.tsx +924 -0
  145. package/src/components/shared/ResourceRendererDispatch.tsx +557 -0
  146. package/src/components/shared/index.ts +3 -0
  147. package/src/components/timeline/index.ts +1 -0
  148. package/src/components/timeline/shared.tsx +614 -0
  149. package/src/components/topology/GroupNode.tsx +198 -0
  150. package/src/components/topology/K8sResourceNode.tsx +440 -0
  151. package/src/components/topology/TopologyControls.tsx +62 -0
  152. package/src/components/topology/TopologyFilterSidebar.tsx +377 -0
  153. package/src/components/topology/TopologyGraph.tsx +748 -0
  154. package/src/components/topology/TopologySearch.tsx +304 -0
  155. package/src/components/topology/index.ts +7 -0
  156. package/src/components/topology/layout.ts +734 -0
  157. package/src/components/topology/layout.worker.ts +272 -0
  158. package/src/components/topology/topology.css +129 -0
  159. package/src/components/ui/CodeViewer.tsx +451 -0
  160. package/src/components/ui/ConfirmDialog.tsx +188 -0
  161. package/src/components/ui/ForceDeleteConfirmDialog.tsx +57 -0
  162. package/src/components/ui/HealthRing.tsx +72 -0
  163. package/src/components/ui/MetricsChart.tsx +259 -0
  164. package/src/components/ui/ResourceBar.tsx +68 -0
  165. package/src/components/ui/Toast.tsx +225 -0
  166. package/src/components/ui/Tooltip.tsx +165 -0
  167. package/src/components/ui/YamlEditor.tsx +280 -0
  168. package/src/components/ui/drawer-components.tsx +792 -0
  169. package/src/components/ui/index.ts +10 -0
  170. package/src/components/workload/ResourceDetailDrawer.tsx +158 -0
  171. package/src/components/workload/WorkloadView.tsx +1109 -0
  172. package/src/components/workload/index.ts +2 -0
  173. package/src/hooks/index.ts +9 -0
  174. package/src/hooks/useAnimatedUnmount.ts +30 -0
  175. package/src/hooks/useKeyboardShortcuts.tsx +336 -0
  176. package/src/hooks/useRefreshAnimation.ts +58 -0
  177. package/src/index.ts +35 -0
  178. package/src/types/core.ts +894 -0
  179. package/src/types/gitops.ts +458 -0
  180. package/src/types/index.ts +2 -0
  181. package/src/utils/animation.ts +40 -0
  182. package/src/utils/api-resources.ts +185 -0
  183. package/src/utils/badge-colors.ts +399 -0
  184. package/src/utils/context-name.ts +72 -0
  185. package/src/utils/download.ts +19 -0
  186. package/src/utils/format.ts +233 -0
  187. package/src/utils/index.ts +10 -0
  188. package/src/utils/log-format.ts +300 -0
  189. package/src/utils/navigation.ts +119 -0
  190. package/src/utils/resource-hierarchy.ts +630 -0
  191. package/src/utils/resource-icons.ts +206 -0
  192. package/src/vite-env.d.ts +1 -0
  193. package/tsconfig.json +24 -0
@@ -0,0 +1,894 @@
1
+ // Topology types matching the Go backend
2
+
3
+ // Per-resource-type RBAC permissions (matches backend k8s.ResourcePermissions)
4
+ export interface ResourcePermissions {
5
+ pods: boolean
6
+ services: boolean
7
+ deployments: boolean
8
+ daemonSets: boolean
9
+ statefulSets: boolean
10
+ replicaSets: boolean
11
+ ingresses: boolean
12
+ configMaps: boolean
13
+ secrets: boolean
14
+ events: boolean
15
+ pvcs: boolean
16
+ nodes: boolean
17
+ namespaces: boolean
18
+ jobs: boolean
19
+ cronJobs: boolean
20
+ hpas: boolean
21
+ gateways: boolean
22
+ httpRoutes: boolean
23
+ }
24
+
25
+ // Feature capabilities based on RBAC permissions
26
+ export interface Capabilities {
27
+ exec: boolean // Terminal feature (pods/exec)
28
+ logs: boolean // Log viewer (pods/log)
29
+ portForward: boolean // Port forwarding (pods/portforward)
30
+ secrets: boolean // List secrets
31
+ secretsUpdate: boolean // Update secrets (inline editing)
32
+ helmWrite: boolean // Helm write operations (install, upgrade, rollback, uninstall, apply values)
33
+ mcpEnabled: boolean // MCP server is running
34
+ resources?: ResourcePermissions // Per-resource-type permissions
35
+ }
36
+
37
+ // Core node kinds that have specific UI handling
38
+ //
39
+ // When adding a new kind here, also update:
40
+ // - ALL_NODE_KINDS in App.tsx
41
+ // - TopologyFilterSidebar.tsx RESOURCE_KINDS array
42
+ // - index.css .topology-icon-* class
43
+ // - K8sResourceNode.tsx NODE_DIMENSIONS
44
+ // - resource-icons.ts KIND_ICON_MAP
45
+ // - kindToPlural in navigation.ts (if irregular plural)
46
+ // - badge-colors.ts KIND_BADGE_COLORS + KIND_BADGE_BORDERED
47
+ // - layout.ts kindPriority in pickGroupName()
48
+ // - resource-hierarchy.ts kindPriority maps + appLabelEligibleKinds
49
+ export type CoreNodeKind =
50
+ | 'Internet'
51
+ | 'Ingress'
52
+ | 'Gateway'
53
+ | 'HTTPRoute'
54
+ | 'GRPCRoute'
55
+ | 'TCPRoute'
56
+ | 'TLSRoute'
57
+ | 'Service'
58
+ | 'Deployment'
59
+ | 'Rollout'
60
+ | 'Application' // ArgoCD Application
61
+ | 'Kustomization' // FluxCD Kustomization
62
+ | 'HelmRelease' // FluxCD HelmRelease
63
+ | 'GitRepository' // FluxCD GitRepository
64
+ | 'DaemonSet'
65
+ | 'StatefulSet'
66
+ | 'ReplicaSet'
67
+ | 'Pod'
68
+ | 'PodGroup'
69
+ | 'ConfigMap'
70
+ | 'Secret'
71
+ | 'HorizontalPodAutoscaler'
72
+ | 'Job'
73
+ | 'CronJob'
74
+ | 'PersistentVolumeClaim'
75
+ | 'Node'
76
+ | 'Namespace'
77
+ | 'KnativeService'
78
+ | 'KnativeConfiguration'
79
+ | 'KnativeRevision'
80
+ | 'KnativeRoute'
81
+ | 'Broker'
82
+ | 'Trigger'
83
+ | 'PingSource'
84
+ | 'ApiServerSource'
85
+ | 'ContainerSource'
86
+ | 'SinkBinding'
87
+ | 'Channel'
88
+ | 'IngressRoute' // Traefik IngressRoute
89
+ | 'IngressRouteTCP' // Traefik IngressRouteTCP
90
+ | 'IngressRouteUDP' // Traefik IngressRouteUDP
91
+ | 'Middleware' // Traefik Middleware
92
+ | 'MiddlewareTCP' // Traefik MiddlewareTCP
93
+ | 'TraefikService' // Traefik TraefikService
94
+ | 'ServersTransport' // Traefik ServersTransport
95
+ | 'ServersTransportTCP' // Traefik ServersTransportTCP
96
+ | 'TLSOption' // Traefik TLSOption
97
+ | 'TLSStore' // Traefik TLSStore
98
+
99
+ // NodeKind can be a core kind or any arbitrary CRD kind string
100
+ export type NodeKind = CoreNodeKind | (string & {})
101
+
102
+ /** Short display names for verbose K8s kind names */
103
+ export function displayKind(kind: string): string {
104
+ const shortNames: Record<string, string> = {
105
+ HorizontalPodAutoscaler: 'HPA',
106
+ PersistentVolumeClaim: 'PVC',
107
+ EC2NodeClass: 'NodeClass',
108
+ KnativeService: 'Knative Svc',
109
+ KnativeConfiguration: 'Knative Config',
110
+ KnativeRevision: 'Revision',
111
+ KnativeRoute: 'Route',
112
+ ApiServerSource: 'ApiSrc',
113
+ ContainerSource: 'ContainerSrc',
114
+ IngressRouteTCP: 'TCP Route',
115
+ IngressRouteUDP: 'UDP Route',
116
+ MiddlewareTCP: 'MW TCP',
117
+ TraefikService: 'Traefik Svc',
118
+ ServersTransport: 'Transport',
119
+ ServersTransportTCP: 'Transport TCP',
120
+ }
121
+ return shortNames[kind] || kind
122
+ }
123
+
124
+ export type HealthStatus = 'healthy' | 'degraded' | 'unhealthy' | 'unknown'
125
+
126
+ export type EdgeType = 'routes-to' | 'exposes' | 'manages' | 'uses' | 'configures' | 'protects'
127
+
128
+ export interface TopologyNode {
129
+ id: string
130
+ kind: NodeKind
131
+ name: string
132
+ status: HealthStatus
133
+ data: Record<string, unknown>
134
+ }
135
+
136
+ export interface TopologyEdge {
137
+ id: string
138
+ source: string
139
+ target: string
140
+ type: EdgeType
141
+ label?: string
142
+ skipIfKindVisible?: string // Hide this edge if this kind is visible (for shortcut edges)
143
+ }
144
+
145
+ export interface Topology {
146
+ nodes: TopologyNode[]
147
+ edges: TopologyEdge[]
148
+ warnings?: string[] // Warnings about resources that failed to load
149
+ truncated?: boolean // True if topology was truncated due to size limit
150
+ totalNodes?: number // Total nodes before truncation (only set if truncated)
151
+ largeCluster?: boolean // True if cluster exceeds large cluster threshold
152
+ hiddenKinds?: string[] // Resource kinds auto-hidden for performance
153
+ crdDiscoveryStatus?: 'idle' | 'discovering' | 'ready' // CRD discovery status
154
+ }
155
+
156
+ // K8s Event (from SSE stream)
157
+ export interface K8sEvent {
158
+ kind: string
159
+ namespace: string
160
+ name: string
161
+ operation: 'add' | 'update' | 'delete'
162
+ timestamp?: number
163
+ diff?: DiffInfo
164
+ }
165
+
166
+ // Diff information for resource changes
167
+ export interface DiffInfo {
168
+ fields: FieldChange[]
169
+ summary: string
170
+ }
171
+
172
+ export interface FieldChange {
173
+ path: string
174
+ oldValue: unknown
175
+ newValue: unknown
176
+ }
177
+
178
+ // Owner information for managed resources
179
+ export interface OwnerInfo {
180
+ kind: string
181
+ name: string
182
+ }
183
+
184
+ // Event source types for the new timeline API
185
+ export type EventSource = 'informer' | 'k8s_event' | 'historical'
186
+
187
+ // Event types for the new timeline API
188
+ export type EventType = 'add' | 'update' | 'delete' | 'Normal' | 'Warning'
189
+
190
+ // Unified timeline event (from /api/changes and /api/timeline)
191
+ // Uses the canonical format from timeline.TimelineEvent in the backend
192
+ export interface TimelineEvent {
193
+ id: string
194
+ timestamp: string // ISO date string
195
+ source: EventSource // Where event originated: 'informer', 'k8s_event', 'historical'
196
+
197
+ // Resource identity
198
+ kind: string
199
+ namespace: string
200
+ name: string
201
+ uid?: string
202
+
203
+ // Resource metadata - when the resource was actually created in K8s
204
+ // This is different from timestamp which is when we observed the event
205
+ createdAt?: string // ISO date string
206
+
207
+ // Event details
208
+ eventType: EventType // 'add', 'update', 'delete', 'Normal', 'Warning'
209
+ reason?: string
210
+ message?: string
211
+
212
+ // Rich context
213
+ diff?: DiffInfo
214
+ healthState?: HealthStatus
215
+ owner?: OwnerInfo
216
+ labels?: Record<string, string> // For app-label grouping
217
+
218
+ // K8s Event specific
219
+ count?: number
220
+
221
+ // Correlation
222
+ correlationId?: string
223
+ }
224
+
225
+ // Helper to check if event is a change (vs K8s event)
226
+ export function isChangeEvent(event: TimelineEvent): boolean {
227
+ return event.source === 'informer' || event.source === 'historical'
228
+ }
229
+
230
+ // Helper to check if event is a K8s Event object
231
+ export function isK8sEvent(event: TimelineEvent): boolean {
232
+ return event.source === 'k8s_event'
233
+ }
234
+
235
+ // Helper to check if event is historical (reconstructed from metadata)
236
+ export function isHistoricalEvent(event: TimelineEvent): boolean {
237
+ return event.source === 'historical'
238
+ }
239
+
240
+ // Helper to check if event is an add/update/delete operation
241
+ export function isOperation(eventType: EventType): eventType is 'add' | 'update' | 'delete' {
242
+ return eventType === 'add' || eventType === 'update' || eventType === 'delete'
243
+ }
244
+
245
+ // Check if a resource kind is a top-level workload (representative in timeline)
246
+ // These are the "root" resources that own/manage others
247
+ export function isWorkloadKind(kind: string): boolean {
248
+ return [
249
+ 'Deployment', 'Rollout', 'DaemonSet', 'StatefulSet',
250
+ 'Service', 'Job', 'CronJob',
251
+ 'Workflow', 'CronWorkflow', // Argo Workflows
252
+ 'Application', // ArgoCD Application
253
+ 'Kustomization', 'HelmRelease', // FluxCD controllers
254
+ 'GitRepository', 'OCIRepository', 'HelmRepository', // FluxCD sources
255
+ 'KnativeService', // Knative Serving
256
+ ].includes(kind)
257
+ }
258
+
259
+ // Check if a resource kind is typically managed by another
260
+ export function isManagedKind(kind: string): boolean {
261
+ return ['ReplicaSet', 'Pod', 'Event'].includes(kind)
262
+ }
263
+
264
+ // Timeline filter options
265
+ export interface TimelineFilters {
266
+ namespace: string
267
+ kinds: string[]
268
+ eventTypes: ('change' | 'k8s_event')[]
269
+ healthStates: string[]
270
+ timeRange: TimeRange
271
+ }
272
+
273
+ export type TimeRange = '5m' | '30m' | '1h' | '6h' | '24h' | 'all'
274
+
275
+ // Cluster info
276
+ export interface ClusterInfo {
277
+ context: string
278
+ cluster: string
279
+ platform: string
280
+ kubernetesVersion: string
281
+ nodeCount: number
282
+ podCount: number
283
+ namespaceCount: number
284
+ inCluster: boolean
285
+ crdDiscoveryStatus?: 'idle' | 'discovering' | 'ready'
286
+ }
287
+
288
+ // Context info for context switching
289
+ export interface ContextInfo {
290
+ name: string
291
+ cluster: string
292
+ user: string
293
+ namespace: string
294
+ isCurrent: boolean
295
+ }
296
+
297
+ // Namespace
298
+ export interface Namespace {
299
+ name: string
300
+ status: string
301
+ }
302
+
303
+ // Main view type (which screen we're on)
304
+ export type MainView = 'home' | 'topology' | 'resources' | 'timeline' | 'helm'
305
+
306
+ // Topology view mode (for backwards compatibility, also exported as ViewMode)
307
+ // NOTE: Must match Go backend constants in internal/topology/types.go
308
+ export type TopologyMode = 'resources' | 'traffic'
309
+ export type ViewMode = 'resources' | 'traffic'
310
+
311
+ // Grouping mode
312
+ export type GroupingMode = 'none' | 'namespace' | 'app' | 'label'
313
+
314
+ // Group info for topology
315
+ export interface TopologyGroup {
316
+ id: string
317
+ type: 'namespace' | 'app' | 'label'
318
+ name: string
319
+ label?: string // for label-based grouping
320
+ nodeCount: number
321
+ collapsed?: boolean
322
+ }
323
+
324
+ // Selected resource (for resources view drawer)
325
+ export interface SelectedResource {
326
+ kind: string
327
+ namespace: string
328
+ name: string
329
+ group?: string // API group for CRDs (e.g., 'metrics.k8s.io')
330
+ }
331
+
332
+ // Resource reference (for relationships)
333
+ export interface ResourceRef {
334
+ kind: string
335
+ namespace: string
336
+ name: string
337
+ group?: string // API group for CRDs (e.g., 'cert-manager.io')
338
+ }
339
+
340
+ // Computed relationships for a resource
341
+ export interface Relationships {
342
+ owner?: ResourceRef
343
+ deployment?: ResourceRef // Grandparent Deployment (for Pods owned by ReplicaSets)
344
+ children?: ResourceRef[]
345
+ services?: ResourceRef[]
346
+ ingresses?: ResourceRef[]
347
+ gateways?: ResourceRef[]
348
+ routes?: ResourceRef[]
349
+ configRefs?: ResourceRef[]
350
+ consumers?: ResourceRef[]
351
+ scalers?: ResourceRef[]
352
+ scaleTarget?: ResourceRef
353
+ policies?: ResourceRef[]
354
+ pods?: ResourceRef[]
355
+ }
356
+
357
+ // Parsed X.509 certificate metadata (from backend cert parsing)
358
+ export interface CertificateInfo {
359
+ subject: string
360
+ sans?: string[]
361
+ issuer: string
362
+ selfSigned?: boolean
363
+ keyType: string
364
+ serialNumber: string
365
+ notBefore: string
366
+ notAfter: string
367
+ daysLeft: number
368
+ expired?: boolean
369
+ }
370
+
371
+ export interface SecretCertificateInfo {
372
+ certificates: CertificateInfo[]
373
+ }
374
+
375
+ // Resource with computed relationships and optional certificate info (API response wrapper)
376
+ export interface ResourceWithRelationships<T = unknown> {
377
+ resource: T
378
+ relationships?: Relationships
379
+ certificateInfo?: SecretCertificateInfo
380
+ }
381
+
382
+ // API Resource (from discovery endpoint)
383
+ export interface APIResource {
384
+ group: string
385
+ version: string
386
+ kind: string
387
+ name: string // Plural name (e.g., "deployments")
388
+ namespaced: boolean
389
+ isCrd: boolean
390
+ verbs: string[]
391
+ }
392
+
393
+ // Helm release types
394
+ export interface HelmRelease {
395
+ name: string
396
+ namespace: string
397
+ chart: string
398
+ chartVersion: string
399
+ appVersion: string
400
+ status: string
401
+ revision: number
402
+ updated: string // ISO date string
403
+ // Health summary from owned resources
404
+ resourceHealth?: 'healthy' | 'degraded' | 'unhealthy' | 'unknown'
405
+ healthIssue?: string // Primary issue if unhealthy (e.g., "OOMKilled")
406
+ healthSummary?: string // Brief summary like "2/3 pods ready"
407
+ }
408
+
409
+ export interface HelmRevision {
410
+ revision: number
411
+ status: string
412
+ chart: string
413
+ appVersion: string
414
+ description: string
415
+ updated: string // ISO date string
416
+ }
417
+
418
+ export interface HelmReleaseDetail {
419
+ name: string
420
+ namespace: string
421
+ chart: string
422
+ chartVersion: string
423
+ appVersion: string
424
+ status: string
425
+ revision: number
426
+ updated: string
427
+ description: string
428
+ notes: string
429
+ history: HelmRevision[]
430
+ resources: HelmOwnedResource[]
431
+ hooks?: HelmHook[]
432
+ readme?: string
433
+ dependencies?: ChartDependency[]
434
+ }
435
+
436
+ export interface HelmHook {
437
+ name: string
438
+ kind: string
439
+ events: string[]
440
+ weight: number
441
+ status?: string
442
+ }
443
+
444
+ export interface ChartDependency {
445
+ name: string
446
+ version: string
447
+ repository?: string
448
+ condition?: string
449
+ enabled: boolean
450
+ }
451
+
452
+ export interface HelmOwnedResource {
453
+ kind: string
454
+ name: string
455
+ namespace: string
456
+ status?: string // Running, Pending, Failed, Active, etc.
457
+ ready?: string // e.g., "3/3" for deployments
458
+ message?: string // Status message or reason
459
+ summary?: string // Brief status like "0/3 OOMKilled"
460
+ issue?: string // Primary issue if unhealthy (e.g., "OOMKilled")
461
+ }
462
+
463
+ export interface HelmValues {
464
+ userSupplied: Record<string, unknown>
465
+ computed?: Record<string, unknown>
466
+ }
467
+
468
+ export interface ManifestDiff {
469
+ revision1: number
470
+ revision2: number
471
+ diff: string
472
+ }
473
+
474
+ // Selected Helm release (for drawer state)
475
+ export interface SelectedHelmRelease {
476
+ namespace: string
477
+ name: string
478
+ }
479
+
480
+ // Upgrade availability info
481
+ export interface UpgradeInfo {
482
+ currentVersion: string
483
+ latestVersion?: string
484
+ updateAvailable: boolean
485
+ repositoryName?: string
486
+ error?: string
487
+ }
488
+
489
+ // Batch upgrade info (map of "namespace/name" to UpgradeInfo)
490
+ export interface BatchUpgradeInfo {
491
+ releases: Record<string, UpgradeInfo>
492
+ }
493
+
494
+ // Request body for applying new values to a release
495
+ export interface ApplyValuesRequest {
496
+ values: Record<string, unknown>
497
+ }
498
+
499
+ // Response for previewing values changes
500
+ export interface ValuesPreviewResponse {
501
+ currentValues: Record<string, unknown>
502
+ newValues: Record<string, unknown>
503
+ manifestDiff: string
504
+ }
505
+
506
+ // ============================================================================
507
+ // Chart Browser Types
508
+ // ============================================================================
509
+
510
+ // Configured Helm repository
511
+ export interface HelmRepository {
512
+ name: string
513
+ url: string
514
+ lastUpdated?: string // ISO date string
515
+ }
516
+
517
+ // Basic chart information
518
+ export interface ChartInfo {
519
+ name: string
520
+ version: string
521
+ appVersion?: string
522
+ description?: string
523
+ icon?: string
524
+ repository: string
525
+ home?: string
526
+ deprecated?: boolean
527
+ }
528
+
529
+ // Detailed chart information
530
+ export interface ChartDetail extends ChartInfo {
531
+ readme?: string
532
+ values?: Record<string, unknown>
533
+ valuesSchema?: string
534
+ maintainers?: ChartMaintainer[]
535
+ sources?: string[]
536
+ keywords?: string[]
537
+ }
538
+
539
+ // Chart maintainer
540
+ export interface ChartMaintainer {
541
+ name: string
542
+ email?: string
543
+ url?: string
544
+ }
545
+
546
+ // Chart search result
547
+ export interface ChartSearchResult {
548
+ charts: ChartInfo[]
549
+ total: number
550
+ }
551
+
552
+ // Request body for installing a new chart
553
+ export interface InstallChartRequest {
554
+ releaseName: string
555
+ namespace: string
556
+ chartName: string
557
+ version: string
558
+ repository: string
559
+ values?: Record<string, unknown>
560
+ createNamespace?: boolean
561
+ }
562
+
563
+ // ============================================================================
564
+ // ArtifactHub Types
565
+ // ============================================================================
566
+
567
+ // ArtifactHub chart with rich metadata
568
+ export interface ArtifactHubChart {
569
+ packageId: string
570
+ name: string
571
+ version: string
572
+ appVersion?: string
573
+ description?: string
574
+ logoUrl?: string
575
+ homeUrl?: string
576
+ deprecated?: boolean
577
+ repository: ArtifactHubRepository
578
+ stars: number
579
+ license?: string
580
+ createdAt?: number // Unix timestamp
581
+ updatedAt?: number // Unix timestamp
582
+ signed?: boolean
583
+ security?: ArtifactHubSecurity
584
+ productionOrgsCount?: number
585
+ hasValuesSchema?: boolean
586
+ keywords?: string[]
587
+ }
588
+
589
+ // ArtifactHub repository info
590
+ export interface ArtifactHubRepository {
591
+ name: string
592
+ url: string
593
+ official?: boolean
594
+ verifiedPublisher?: boolean
595
+ organizationName?: string
596
+ }
597
+
598
+ // ArtifactHub security report summary
599
+ export interface ArtifactHubSecurity {
600
+ critical?: number
601
+ high?: number
602
+ medium?: number
603
+ low?: number
604
+ unknown?: number
605
+ }
606
+
607
+ // ArtifactHub search result
608
+ export interface ArtifactHubSearchResult {
609
+ charts: ArtifactHubChart[]
610
+ total: number
611
+ }
612
+
613
+ // ArtifactHub chart detail (extended)
614
+ export interface ArtifactHubChartDetail extends ArtifactHubChart {
615
+ readme?: string
616
+ values?: string // Default values as YAML string
617
+ valuesSchema?: string
618
+ maintainers?: ArtifactHubMaintainer[]
619
+ links?: ArtifactHubLink[]
620
+ availableVersions?: ArtifactHubVersionSummary[]
621
+ install?: string // Install instructions
622
+ }
623
+
624
+ // ArtifactHub maintainer
625
+ export interface ArtifactHubMaintainer {
626
+ name: string
627
+ email?: string
628
+ }
629
+
630
+ // ArtifactHub link
631
+ export interface ArtifactHubLink {
632
+ name: string
633
+ url: string
634
+ }
635
+
636
+ // ArtifactHub version summary
637
+ export interface ArtifactHubVersionSummary {
638
+ version: string
639
+ ts?: number // Unix timestamp
640
+ }
641
+
642
+ // Chart source type for UI toggling
643
+ export type ChartSource = 'local' | 'artifacthub'
644
+
645
+ // ============================================================================
646
+ // Metrics Types
647
+ // ============================================================================
648
+
649
+ // Top metrics types (bulk, for resource table view)
650
+ export interface TopPodMetrics {
651
+ namespace: string
652
+ name: string
653
+ cpu: number // nanocores (usage)
654
+ memory: number // bytes (usage)
655
+ cpuRequest: number // nanocores (sum across containers)
656
+ cpuLimit: number // nanocores (sum across containers)
657
+ memoryRequest: number // bytes (sum across containers)
658
+ memoryLimit: number // bytes (sum across containers)
659
+ }
660
+
661
+ export interface TopNodeMetrics {
662
+ name: string
663
+ cpu: number // nanocores (usage)
664
+ memory: number // bytes (usage)
665
+ podCount: number // pods scheduled on this node
666
+ cpuAllocatable: number // nanocores
667
+ memoryAllocatable: number // bytes
668
+ }
669
+
670
+ export interface MetricsDataPoint {
671
+ timestamp: string
672
+ cpu: number // CPU in nanocores
673
+ memory: number // Memory in bytes
674
+ }
675
+
676
+ // ============================================================================
677
+ // Traffic Types
678
+ // ============================================================================
679
+
680
+ // Traffic endpoint (source or destination in a flow)
681
+ export interface TrafficEndpoint {
682
+ name: string
683
+ namespace: string
684
+ kind: string // Pod, Service, External
685
+ ip?: string
686
+ labels?: Record<string, string>
687
+ workload?: string
688
+ port?: number
689
+ }
690
+
691
+ // Traffic flow between two endpoints
692
+ export interface TrafficFlow {
693
+ source: TrafficEndpoint
694
+ destination: TrafficEndpoint
695
+ protocol: string // tcp, udp, http, grpc
696
+ port: number
697
+ l7Protocol?: string // HTTP, gRPC, DNS
698
+ httpMethod?: string
699
+ httpPath?: string
700
+ httpStatus?: number
701
+ bytesSent: number
702
+ bytesRecv: number
703
+ connections: number
704
+ verdict: string // forwarded, dropped, error
705
+ lastSeen: string // ISO date string
706
+ }
707
+
708
+ // Aggregated flow by service pair
709
+ export interface AggregatedFlow {
710
+ source: TrafficEndpoint
711
+ destination: TrafficEndpoint
712
+ protocol: string
713
+ port: number
714
+ flowCount: number
715
+ bytesSent: number
716
+ bytesRecv: number
717
+ connections: number
718
+ lastSeen: string
719
+ requestCount?: number
720
+ errorCount?: number
721
+ avgLatencyMs?: number
722
+ }
723
+
724
+ // Cluster info for traffic detection
725
+ export interface TrafficClusterInfo {
726
+ platform: string // gke, eks, aks, generic
727
+ cni: string // cilium, calico, flannel, vpc-cni, azure-cni
728
+ dataplaneV2: boolean
729
+ clusterName?: string
730
+ k8sVersion?: string
731
+ }
732
+
733
+ // Traffic source status
734
+ export interface TrafficSourceStatus {
735
+ name: string
736
+ status: 'available' | 'not_found' | 'error'
737
+ version?: string
738
+ native: boolean
739
+ message?: string
740
+ }
741
+
742
+ // Helm chart info for one-click install
743
+ export interface TrafficHelmChartInfo {
744
+ repo: string
745
+ repoUrl: string
746
+ chartName: string
747
+ version?: string
748
+ }
749
+
750
+ // Recommendation for installing a traffic source
751
+ export interface TrafficRecommendation {
752
+ name: string
753
+ reason: string
754
+ installCommand?: string // For non-Helm installs (e.g., gcloud commands)
755
+ docsUrl?: string
756
+ // Helm chart info (for one-click install via Helm view)
757
+ helmChart?: TrafficHelmChartInfo
758
+ // Alternative option (for cases with two good choices)
759
+ alternativeName?: string
760
+ alternativeReason?: string
761
+ alternativeDocsUrl?: string
762
+ }
763
+
764
+ // Response from GET /api/traffic/sources
765
+ export interface TrafficSourcesResponse {
766
+ cluster: TrafficClusterInfo
767
+ active: string
768
+ detected: TrafficSourceStatus[]
769
+ notDetected: string[]
770
+ recommended?: TrafficRecommendation
771
+ }
772
+
773
+ // Response from GET /api/traffic/flows
774
+ export interface TrafficFlowsResponse {
775
+ source: string
776
+ timestamp: string
777
+ flows: TrafficFlow[]
778
+ aggregated: AggregatedFlow[]
779
+ warning?: string // Non-fatal warning (e.g., query errors)
780
+ }
781
+
782
+ // Wizard state for traffic setup
783
+ export type TrafficWizardState = 'detecting' | 'not_found' | 'wizard' | 'checking' | 'ready'
784
+
785
+ // Traffic view filter options
786
+ export interface TrafficFilters {
787
+ hideSystem: boolean
788
+ hideExternal: boolean
789
+ minConnections: number
790
+ focusedNamespaces: Set<string>
791
+ showNamespaceGroups: boolean
792
+ aggregateExternal: boolean
793
+ timeRange: string
794
+ }
795
+
796
+ // Main view type now includes 'traffic' and 'cost'
797
+ export type ExtendedMainView = MainView | 'traffic' | 'cost'
798
+
799
+ // ============================================================================
800
+ // Image Filesystem Types
801
+ // ============================================================================
802
+
803
+ // File or directory node in image filesystem
804
+ export interface FileNode {
805
+ name: string
806
+ path: string
807
+ type: 'file' | 'dir' | 'symlink'
808
+ size?: number
809
+ permissions?: string
810
+ mode?: number
811
+ modTime?: string
812
+ linkTarget?: string
813
+ children?: FileNode[]
814
+ }
815
+
816
+ // Image layer information
817
+ export interface LayerInfo {
818
+ digest: string
819
+ size: number
820
+ mediaType: string
821
+ }
822
+
823
+ // Complete image filesystem response
824
+ export interface ImageFilesystem {
825
+ image: string
826
+ digest?: string
827
+ platform?: string
828
+ root: FileNode
829
+ totalFiles: number
830
+ totalSize: number
831
+ layers?: LayerInfo[]
832
+ error?: string
833
+ }
834
+
835
+ // Lightweight image metadata (for pre-download check)
836
+ export interface ImageMetadata {
837
+ image: string
838
+ digest: string
839
+ platform: string
840
+ totalSize: number // Total compressed size of all layers
841
+ layerCount: number
842
+ cached: boolean // Whether filesystem is already cached
843
+ filesystem?: ImageFilesystem // Included if cached
844
+ authMethod: string // "anonymous", "google", "credentials", etc.
845
+ }
846
+
847
+ // ============================================================================
848
+ // Workload Logs Types
849
+ // ============================================================================
850
+
851
+ // Pod info returned from workload pods endpoint
852
+ export interface WorkloadPodInfo {
853
+ name: string
854
+ containers: string[]
855
+ ready: boolean
856
+ }
857
+
858
+ // SSE event types for workload log streaming
859
+ export type WorkloadLogEventType =
860
+ | 'connected'
861
+ | 'log'
862
+ | 'pod_added'
863
+ | 'pod_removed'
864
+ | 'end'
865
+ | 'error'
866
+
867
+ // Workload revision (for rollback)
868
+ export interface WorkloadRevision {
869
+ number: number
870
+ createdAt: string
871
+ image: string
872
+ isCurrent: boolean
873
+ replicas: number
874
+ template?: string // Pod template spec as YAML (for revision diff)
875
+ }
876
+
877
+ // Workload log stream event data
878
+ export interface WorkloadLogStreamEvent {
879
+ event: WorkloadLogEventType
880
+ // connected event
881
+ workload?: string
882
+ namespace?: string
883
+ kind?: string
884
+ pods?: WorkloadPodInfo[]
885
+ // log event
886
+ pod?: string
887
+ container?: string
888
+ timestamp?: string
889
+ content?: string
890
+ // pod_added/pod_removed events
891
+ reason?: string
892
+ // error event
893
+ message?: string
894
+ }