1. kubectl credentials error (41 places in kube.rs)
Every kubectl invocation used .env("KUBERNETES_CONTEXT", context) which
is not a real kubectl environment variable — kubectl silently ignores it
and falls back to whatever current-context is set in the kubeconfig YAML.
If that context has expired or wrong credentials the auth failure occurs.
Replaced all 41 instances with .arg("--context").arg(context) so kubectl
always uses the correct context from the stored kubeconfig.
2. Cluster name still showed UUID (two causes)
a) Hotbar read from kubernetesStore.clusters (ClusterInfo[]) which is never
populated by the kubeconfig-based flow — always empty, so selectedCluster
was always undefined. Removed the Zustand cluster lookup from Hotbar and
added a clusterName prop passed from KubernetesPage.tsx (selectedConfig?.name).
b) ClusterOverview fell back to showing raw clusterId UUID when clusterName
was undefined. Changed subtitle to render conditionally so UUID never shows.
3. Bell dialog had no way to close
Custom DialogContent had no X button and no backdrop-click handler.
Added X close button (top-right) and backdrop-click-to-close.
4. Hotbar icons invisible in dark mode
variant="ghost" only styles hover state with no baseline text color.
Added className="text-foreground" to all icon-only ghost buttons.
Bug 1 — Dead multi-word tier3 entries / missing single-token commands
parse_single_command() extracts only the first token as `command`, so
multi-word entries like "kill -9", "init 0", "service stop" in the tier3
array never matched. Adding the single-token forms "kill", "pkill",
"killall", "init" to TIER3_COMMANDS ensures these commands are always
denied. Removed all dead multi-word entries.
Bug 2 — systemctl Tier 1 special case was dead code
systemctl was not in tier1_general, so the block that was supposed to
auto-execute `systemctl status` never ran. Moved systemctl handling into
its own block (TIER1_SYSTEMCTL_SUBCOMMANDS / TIER2_SYSTEMCTL_SUBCOMMANDS)
evaluated before the general tier checks. status, is-active, is-enabled,
list-units, list-unit-files → Tier 1; all others → Tier 2.
Bug 3 — ldapmodify / ldapdelete / ldapadd misclassified as Tier 1
Both appeared in the old tier1_general and tier2_general arrays; the tier1
check ran first, so LDAP write operations auto-executed. Removed them from
tier1. ldapsearch (read-only) remains Tier 1.
Dynamic Safety Architecture UI
Extracted all tier classification arrays to module-level pub const slices
(TIER3_COMMANDS, TIER1_KUBECTL_SUBCOMMANDS, etc.) so both the classifier
logic and a new get_classifier_rules() Tauri command share a single source
of truth. ShellExecution.tsx now calls getClassifierRulesCmd() on mount and
renders the actual command lists in collapsible per-tier cards — any change
to the const arrays is automatically reflected in the UI with no manual
documentation update needed.
Also fixes the cargo fmt CI failure introduced in the previous commit
(ClusterClient::new call reformatted to a single line).
Resolves four bugs in the Kubernetes management interface:
1. **Cluster not found error** - commands/kube.rs::list_nodes (and all other
kube resource commands) look up clusters from state.clusters (in-memory map)
which was never populated from the kubeconfig_files table. Add a new
connect_cluster_from_kubeconfig Tauri command that reads the encrypted
kubeconfig from the DB, decrypts it, and inserts a ClusterClient into
state.clusters. Wire it into KubernetesPage on initial load and cluster
change so the in-memory map is always populated before any kube command runs.
2. **Dropdown selection has no effect** - same root cause as #1; activating a
kubeconfig only updated the DB flag but never loaded the client into memory.
handleClusterChange now calls connectClusterFromKubeconfigCmd after activation.
3. **GUID shown instead of cluster name** - ClusterOverview displayed the raw
internal UUID as the page subtitle. Now accepts a clusterName prop (populated
from kubeconfig.context) and renders that instead. ClusterDetails similarly
changed to show kubeconfig.context in the header, not the UUID.
4. **Bell icon not clickable** - Hotbar bell button had no onClick handler. Add
optional onNotifications / notificationCount props; badge count is now dynamic
rather than hardcoded. KubernetesPage wires up a notifications dialog showing
active cluster context and a link to the Events section.
All changes follow TDD: failing tests written first, then implementation.
git-cliff's --tag flag sets the display label for unreleased commits;
it does not scope commits to a range. Passing a range string to --tag
caused git-cliff to emit the full cumulative history for every release.
Move the revision range from --tag to a positional argument so only
commits between PREV_TAG and CURRENT_TAG appear in each release body.
CHANGELOG.md generation is unaffected (still full history).
Complete overhaul of the Kubernetes management page from a basic config
panel into a full Lens-style IDE shell with 26 resource types, real-time
data, and a comprehensive test suite.
Layout & navigation:
- Rewrite KubernetesPage as a Lens v5-style shell: collapsible sidebar
(Workloads / Services & Networking / Config & Storage / Access Control /
Cluster), top hotbar with cluster+namespace selectors, Ctrl+K command
palette
- All 26 resource types now accessible via sidebar navigation (previously 5)
New resource types (Rust + TypeScript + React):
- StorageClasses, NetworkPolicies, ResourceQuotas, LimitRanges
- 4 new Tauri commands registered in generate_handler![]
Component implementations (replacing stubs with real IPC):
- Terminal: full xterm.js with multi-tab sessions and exec_pod IPC
- YamlEditor: Monaco editor with YAML syntax highlighting
- MetricsChart: recharts LineChart/BarChart
- ClusterOverview: live node/pod/deployment/namespace counts
- ClusterDetails: real kubeconfig + node data
- PodDetail, DeploymentDetail, ServiceDetail, ConfigMapDetail, SecretDetail:
all connected to real IPC data, zero hardcoded values
- CreateResourceModal, EditResourceModal: wired to createResourceCmd /
editResourceCmd
- RbacViewer: live data from 4 RBAC IPC commands
- RbacEditor: create roles/cluster-roles via YAML editor
- CommandPalette: 12 real navigation commands, keyboard nav
Dependencies added: xterm@5, xterm-addon-fit, xterm-addon-web-links,
@monaco-editor/react@4, recharts@2
Tooling:
- Replace eslint-plugin-react (incompatible with ESLint 10) with
@eslint-react/eslint-plugin; fix eslint.config.js for flat config
- Fix pre-existing hoisting lint errors in Security.tsx, PortForwardForm.tsx
- Fix eventBus.ts: replace all `any` generics with `unknown`
Tests: 251 passing across 35 test files (was 94/19)
- 16 new test files covering all new and fixed components (TDD)
- npx tsc --noEmit: 0 errors
- cargo clippy -- -D warnings: 0 warnings
- cargo fmt --check: passes
- eslint src/ --max-warnings 0: 0 issues
- Update handleActivateKubeconfig to call setSelectedCluster after activation
- ResourceBrowser now loads resources for the activated kubeconfig's cluster
- All tests passing, build successful
- Remove duplicate 'Add Cluster' button and modal
- Remove duplicate 'Start Port Forward' button and modal
- KubernetesPage now uses kubeconfig files from Settings → Kubeconfig
- Clusters section displays kubeconfig files with active indicator
- Port forwarding section shows active port forwards without duplicate controls
- All tests passing, build successful
Add a new 'Fetch PR comment history' step that pulls both review posts
and issue comments from the Gitea API before the LLM is called.
The full comment history is injected into the prompt with an explicit
instruction to silently discard any finding already marked as invalid,
acknowledged as intentional, or confirmed fixed in a prior round.
This prevents the reviewer from repeatedly raising refuted findings
across successive push events on the same PR.
- Remove duplicate state.inner() calls in subscribe_to_k8s_events and
subscribe_to_all_k8s_events (copy-paste error)
- Share all AppState Arc fields in OAuth callback task — clusters,
port_forwards, refresh_registry, and watchers were previously
constructed as fresh isolated instances instead of being cloned from
the live AppState
- Replace infinite sleep loop in Watcher::start with an immediate
warn-and-return, preventing Tokio thread leaks from stub watchers
- Document current status: 43 backend commands, 115 command wrappers, 10 frontend components
- Plan 16 resource discovery UIs (Nodes, Events, ConfigMaps, Secrets, etc.)
- Plan 6 advanced features (Terminal, YAML Editor, Metrics, Search, Context Switcher)
- Plan 3 enhanced workloads and cluster management features
- Plan 4 UX improvements and advanced management features
- Plan 3 phases for real-time updates, RBAC, and extension system
- 6-sprint implementation order with clear priorities
- Dependencies and architecture updates documented
- Success criteria and risk assessment included
The runner environment does not have Node.js in PATH, causing
actions/checkout@v4 and renovatebot/github-action@v41.0.0 (both JS
actions) to fail at startup.
Use renovate/renovate:latest as the job container and invoke the
renovate binary directly via run:, consistent with how all other
workflows in this repo handle checkout and tooling. The Checkout step
was also unnecessary — Renovate manages its own git operations.
- Replace take().expect() in background task with if let Some to handle
the race where stop_async/close takes the child before the task is
polled, preventing a task panic instead of a graceful exit
- Add temp kubeconfig cleanup to stop_async, close, and Drop since
taking the child out of the shared Arc causes the background task to
return early, skipping its own cleanup branch
- Backend: kube module with ClusterClient, PortForwardSession, RefreshRegistry
- 7 Tauri IPC commands: add_cluster, remove_cluster, list_clusters, start_port_forward, stop_port_forward, list_port_forwards, delete_port_forward, shutdown_port_forwards
- AppState extended with clusters, port_forwards, refresh_registry fields
- Version bumped to 1.1.0 in Cargo.toml and package.json
- Auto-tag workflow updated to mark releases as draft (pre-release)
- Buy Me A Coffee section added to README.md
- Fixed changelog workflow to only include current tag commits
- Proper kubeconfig YAML parsing with extract_context and extract_server_url
- Added kubeconfig content storage in ClusterClient
- Updated PortForwardSession to include cluster_name
- Frontend GUI components: ClusterList, PortForwardList, AddClusterModal, PortForwardForm, KubernetesPage
- TypeScript types and IPC commands for Kubernetes management
- Unit tests for Kubernetes IPC commands (6 tests)
- All 332 Rust tests passing
- All 98 frontend tests passing
- TypeScript type checks passing
- Project builds successfully in release mode
- Committed and pushed to feature/kubernetes-management branch
- Command injection vulnerability fixed with regex validation and max length check (253 chars)
- stop_port_forward and shutdown_port_forwards properly kill kubectl child processes via async child management
- Temp file cleanup implemented with RAII TempFileCleanup struct created before std::fs::write
- discover_pods now parses actual kubectl JSON output
- ChildWaitHandle implemented with background task for waiting on kubectl child
- PortForwardSession uses Arc<TokioMutex<Option<Child>>> for async-safe child management
- Port-forward uses kubectl's dynamic port binding (0) instead of TcpListener
- Added shutdown_port_forwards command for app shutdown cleanup
- Added cleanup effect in App.tsx to call shutdownPortForwardsCmd on unmount
- Database CRUD operations for clusters and port_forwards added to db.rs
- validate_resource_name uses lazy_static! for cached Regex to prevent ReDoS
- Cluster struct updated to store kubeconfig_content directly instead of kubeconfig_id
- Cluster model in db/models.rs updated to use kubeconfig_content field
- load_clusters and load_port_forwards commands registered in lib.rs
- Temp file cleanup moved to background task in ChildWaitHandle to ensure cleanup after kubectl completes
- Unused child_id field removed from ChildWaitHandle
- Command validation moved to beginning of start_port_forward before any operations
- Fixed lint errors: removed unused imports, fixed React hooks order, updated type annotations
- Updated eslint.config.js to properly configure file patterns
- Move command validation to beginning of start_port_forward before any operations
- Fix race condition: temp file cleanup now happens in background task after kubectl completes
- Remove unused child_id field from ChildWaitHandle
- Add comments explaining validation placement and cleanup timing
- Add load_clusters and load_port_forwards commands to db.rs
- Update remove_cluster to delete from database
- Update delete_port_forward to delete from database
- Add Cluster and PortForward imports to db.rs
- Add load commands to lib.rs generate_handler
- Fix formatting issues
- Add shutdown_port_forwards() Rust command to kill all child processes
- Add shutdownPortForwardsCmd() frontend command wrapper
- Add cleanup effect in App.tsx to call shutdown on unmount
- All port forward child processes now killed on app exit