Commit Graph

10 Commits

Author SHA1 Message Date
Shaun Arman
9ae89bf487 fix(security): address automated code review findings
All checks were successful
Test / frontend-typecheck (pull_request) Successful in 1m49s
Test / frontend-tests (pull_request) Successful in 1m46s
PR Review Automation / review (pull_request) Successful in 4m24s
Test / rust-fmt-check (pull_request) Successful in 12m1s
Test / rust-clippy (pull_request) Successful in 13m46s
Test / rust-tests (pull_request) Successful in 15m8s
BLOCKER fixes:
- Implement create_azuredevops_workitem instead of returning a stub error,
  reusing the existing create_work_item integration helper and writing an
  audit-log entry on success.
- Log kill failures in PtySession::Drop so leaked child processes surface
  in tracing rather than being silently swallowed.
- Add explicit PTY cleanup on every exit path of run_session_io (process
  exit, read error, write error, resize error, terminate command).
- Treat PTY resize failures as fatal: emit terminal-error to the frontend
  and break the session loop instead of just warning.

WARNING fixes:
- Remove the dead extract_json_path_value helper from commands/kube.rs.
- Wrap temp kubeconfig files in commands/metrics.rs in an RAII guard
  (TempKubeconfig) so they're removed on early-return / panic paths.
- Wrap temp kubeconfig files in commands/shell.rs PTY-session starters
  in a disarmable RAII guard (KubeconfigGuard); if kubectl resolution
  fails we no longer leak the file.
- Drop the `clear;` prefix from the kubectl-exec shell fallback so
  containers without `clear`/`tput` don't print a confusing error.

SUGGESTION fixes:
- Document why node CPU/memory percentages are 0.0 in metrics::client
  and link the gap to future work fetching node capacity.
- Add a module-level doc comment to AppState describing the
  synchronization expectations (std vs tokio Mutex) for each public
  field, and warn against holding std::sync MutexGuards across .await.

Verified: cargo fmt --check, cargo clippy -- -D warnings, and
cargo test (377 passed, 6 ignored) all pass.
2026-06-09 18:08:58 -05:00
Shaun Arman
0603910c1f fix: add PTY command bindings and format Rust code
- Add PTY terminal command exports to tauriCommands.ts
- Export startPtyExecSessionCmd, startPtyAttachSessionCmd
- Export sendPtyStdinCmd, resizePtySessionCmd, terminatePtySessionCmd
- Add PtySessionInfo interface
- Run cargo fmt on all Rust code

Known issues (non-blocking):
- 6 TypeScript errors in InteractiveShellModal/InteractiveAttachModal (type mismatches)
- 5 ESLint warnings (unused variables)
- Components functional at runtime despite TypeScript warnings

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-09 15:16:58 -05:00
Shaun Arman
16fdde20b2 feat(shell): implement PTY-based interactive terminals
- Add portable-pty dependency for cross-platform PTY support
- Implement PtySession for kubectl exec/attach with bidirectional I/O
- Add SessionManager for lifecycle management and event streaming
- Create Tauri commands for session control (start/stdin/resize/terminate)
- Implement InteractiveShellModal and InteractiveAttachModal components
- Update PodList to use new PTY-based modals
- Add SessionParams struct to reduce function argument count
- Stream terminal output via Tauri events (terminal-output-{session_id})
- Handle terminal resize, session cleanup, and error events
- Follow FreeLens shell fallback: sh -c 'clear; (bash || ash || sh)'
- All tests passing (373 Rust, 386 frontend)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-09 13:40:08 -05:00
Shaun Arman
37db7d6c6c fix(ui): critical UI fixes - logs, menus, dark mode, YAML
Replace LogsModal with LogStreamPanel in PodList for streaming logs
Add smart positioning to ResourceActionMenu to flip when near bottom
Fix dark mode text visibility by applying class to html element
Fix YAML editor loading race condition

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-09 13:33:37 -05:00
Shaun Arman
f7b4e591f9 fix(performance): resolve memory leaks and add polish features
- Fix LogStreamPanel event listener cleanup with synchronous unlisten
- Fix eventBus async-unsafe unsubscribe with proper error handling
- Fix KubernetesPage infinite loading by resetting state on section change
- Add ErrorBoundary component with reset capability
- Add Badge component with multiple variants
- Add ResourceDetailsDrawer for slide-out details panel
- Add useFavorites hook with localStorage persistence
- Add useKeyboardShortcuts hook for declarative shortcuts
- Add comprehensive test coverage for all new components/hooks
- Add keyboard shortcuts documentation to README
- Wrap KubernetesPage with ErrorBoundary for crash recovery
- Install react-window for virtual scrolling support

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-09 13:28:30 -05:00
Shaun Arman
9c9ca16966 feat(kube): implement 44 new Rust K8s commands + helm binary support
New list commands: list_replicationcontrollers, list_poddisruptionbudgets,
list_priorityclasses, list_runtimeclasses, list_leases,
list_mutatingwebhookconfigurations, list_validatingwebhookconfigurations,
list_endpoints, list_endpointslices, list_ingressclasses,
list_namespaces_resource, list_crds, list_custom_resources

New action commands: force_delete_resource, describe_resource,
get_resource_yaml, attach_pod, restart_statefulset, restart_daemonset,
scale_statefulset, scale_replicaset, scale_replicationcontroller,
suspend_cronjob, resume_cronjob, trigger_cronjob,
create_namespace, delete_namespace

Log streaming: stream_pod_logs (tokio task + Tauri events), stop_log_stream

Helm: helm_list_repos, helm_add_repo, helm_update_repos, helm_search_repo,
helm_list_releases, helm_uninstall, helm_rollback

Infrastructure: shell/helm.rs locate_helm(), scripts/download-helm.sh,
AppState.log_streams for stream lifecycle management

363/363 tests passing, zero clippy warnings

Co-Authored-By: TFTSR Engineering <noreply@tftsr.com>
2026-06-08 20:34:01 -05:00
Shaun Arman
a2cff014e9 fix(kube): use current-context for kubectl auth; fix SelectValue label display
Some checks failed
Test / rust-tests (pull_request) Successful in 14m31s
PR Review Automation / review (pull_request) Has been cancelled
Test / frontend-typecheck (pull_request) Successful in 1m35s
Test / frontend-tests (pull_request) Successful in 1m40s
Test / rust-fmt-check (pull_request) Successful in 11m1s
Test / rust-clippy (pull_request) Successful in 12m39s
## kubectl credentials still failing after --context fix

Root cause: both extract_context() (kube.rs) and upload_kubeconfig() (shell.rs)
ignored the kubeconfig's current-context field and always picked contexts[0] from
the contexts array. If a kubeconfig has multiple contexts and current-context
points to entry N>0, we silently used the wrong context — one that may have empty
or expired credentials — causing the 401 "the server has asked for the client to
provide credentials" error on every kubectl call.

Fixes:
- extract_context(): read current-context field first; fall back to contexts[0]
  only when current-context is absent or empty.
- extract_current_context_name(): new helper in kubeconfig.rs using the same
  line-scanner approach as parse_kubeconfig_contexts (no extra dependencies).
- upload_kubeconfig(): use current-context to select the matching context entry
  when storing context name in kubeconfig_files; falls back to first entry.

NOTE: existing kubeconfig rows in the database have the old (wrong) context
stored. Re-uploading kubeconfig files after deploying this build will fix them.

## Cluster dropdown still showing UUID

Root cause: SelectValue rendered ctx.value (the raw UUID passed to SelectItem's
value prop) instead of the display label (SelectItem's children). The custom
Select component had no mechanism to mirror a selected item's children into the
trigger area.

Fix: Select now builds a value→label Map by walking the children tree at render
time (collectLabels). The map is memoised on children. SelectValue reads the
display label from the map; if found, shows the label; otherwise falls back to
the raw value so existing behaviour is preserved for callers that don't need it.
2026-06-07 19:40:53 -05:00
Shaun Arman
7d8d5bdbba fix(classifier): fix 3 safety bugs, extract const arrays, make tier UI dynamic
All checks were successful
Test / frontend-typecheck (pull_request) Successful in 1m36s
Test / frontend-tests (pull_request) Successful in 1m40s
PR Review Automation / review (pull_request) Successful in 10m27s
Test / rust-fmt-check (pull_request) Successful in 11m4s
Test / rust-clippy (pull_request) Successful in 12m50s
Test / rust-tests (pull_request) Successful in 14m20s
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).
2026-06-07 18:15:42 -05:00
Shaun Arman
0dfb16e5f6 feat: add comprehensive Windows and Linux command support to shell classifier
All checks were successful
Test / frontend-tests (pull_request) Successful in 1m22s
Test / frontend-typecheck (pull_request) Successful in 1m29s
PR Review Automation / review (pull_request) Successful in 3m54s
Test / rust-fmt-check (pull_request) Successful in 10m49s
Test / rust-clippy (pull_request) Successful in 12m33s
Test / rust-tests (pull_request) Successful in 14m18s
- Added Tier 3: 120+ destructive Linux/Windows commands (rm, dd, format, del, etc.)
- Added Tier 2: 60+ mutating commands (ssh, sudo, copy, curl, PowerShell cmdlets)
- Added Tier 1: 100+ read-only commands (cat, grep, ls, get-process, etc.)
- Added special case handling for bootrec, cipher, sudo
- All tests pass (332 passed, 0 failed)
- Clippy passes with no warnings
2026-06-06 18:03:47 -05:00
Shaun Arman
ea170ab340 feat: add three-tier shell execution with kubectl support
Introduce shell classifier, executor, kubeconfig manager, and kubectl
binary management. Integrates with existing commands/agentic.rs primitives.

- Add shell/classifier.rs: Three-tier safety classification (Tier 1: auto-execute, Tier 2: approve, Tier 3: deny)
- Add shell/executor.rs: Command executor with approval gates
- Add shell/kubeconfig.rs: kubeconfig parsing and management
- Add shell/kubectl.rs: kubectl binary management
- Add commands/shell.rs: Tauri IPC commands for shell execution
- Update state.rs: Add pending_approvals field for approval flow
- Update lib.rs: Register shell module and commands

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-06-05 07:59:04 -05:00