- Add Proxmox cluster management commands to tauriCommands.ts
- Fix RemotesPage.tsx to use actual IPC calls instead of mock data
- Add Proxmox settings section to App.tsx settings navigation
- Create ProxmoxSettings page with update management (stable/pre-release)
- Add Proxmox submenu navigation to sidebar with expandable section
- Update docs/RELEASE_NOTES.md to include v1.2.0 Proxmox features
This fixes critical bugs preventing cluster persistence and navigation.
Replace hardcoded light-mode Tailwind colors with dark: variants
across six components. Issues that broke readability:
- PiiDiffViewer / Security: toggle knob was bg-white (invisible on
bg-muted in dark mode) -> bg-background
- ImageGallery: thumbnail container, filename labels, alert banners,
and modal chrome all used hardcoded gray/white backgrounds with dark
text; added full dark: variants throughout
- ShellExecution TIER_CONFIG: tier cards used bg-green/yellow/red-50
(near-white) with dark text; added dark:bg-*-950/30 backgrounds and
light text for all three tiers
- ShellApprovalModal: tier 2 badge hardcoded bg-yellow-50/text-yellow-700;
added dark: variants
- LogUpload: PII warning alert used bg-amber-50/text-amber-800; added
dark:bg-amber-900/20 and lighter text for dark mode
Credential error persists: switch all 40 kubectl invocations from using
KUBECONFIG env var to the explicit --kubeconfig CLI flag. The flag has higher
precedence in kubectl's lookup order and is unambiguous regardless of any
inherited KUBECONFIG env var in the parent process environment.
Also adds test_kubectl_connection Tauri command (runs kubectl cluster-info
with the stored kubeconfig) and a Test button in Settings → Kubeconfig so
the exact kubectl output — context name, exit code, full stdout/stderr — is
visible without needing to inspect tracing logs. This output will reveal
whether the issue is expired certs, a missing exec-auth plugin, wrong context,
or something else entirely.
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).
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
Change plaintext_env input field from type='password' to type='text' since
this field is explicitly for non-sensitive values (DEBUG, LOG_LEVEL, etc.).
Using password type for plaintext config was misleading and prevented
copy/paste of legitimate non-sensitive configuration.
Only the encrypted_env and http_headers fields remain as type='password'
for sensitive values like API keys and tokens.
Add clearer placeholder and helper text to explain that encrypted environment
variables are never displayed for security reasons. When editing an existing
server, the encrypted_env field shows a placeholder explaining that leaving it
blank will preserve existing values.
Also apply cargo fmt formatting fixes to store.rs.
Add dual-mode environment variable support for stdio MCP servers and custom
HTTP headers for HTTP-based MCP servers to enable proper authentication and
configuration.
Backend changes (Rust):
- Add migration 023 for env_config column in mcp_servers table
- Add env_config field to McpServer, CreateMcpServerRequest, UpdateMcpServerRequest
- Encrypt env_config using AES-256-GCM on create/update in store.rs
- Add get_server_env_config() helper to decrypt and parse env vars
- Parse plaintext env from transport_config.env (stdio only)
- Parse custom headers from transport_config.headers (HTTP only)
- Merge plaintext and encrypted env vars (encrypted takes precedence)
- Update connect_stdio() to accept HashMap<String, String> for env vars
- Update connect_http() to accept HashMap<String, String> for headers
- Apply env vars to tokio::process::Command via .env() method
- Add warning for HTTP headers (rmcp v1.7.0 limitation - no .header() method)
- Add comprehensive tests for encryption, merging, and clearing
Frontend changes (TypeScript/React):
- Add env_config field to CreateMcpServerRequest and UpdateMcpServerRequest
- Add plaintext_env, encrypted_env, http_headers to ServerForm interface
- Add parsing helpers: parseEnvVars(), formatEnvVars(), parseHeaders(), formatHeaders()
- Update startEdit() to extract and format env vars/headers from transport_config
- Update handleSave() to build transport_config with env/headers and env_config JSON
- Add conditional UI fields: stdio (plaintext + encrypted env), HTTP (custom headers)
- Use password input type for all sensitive fields
Security:
- Encrypted env vars stored using AES-256-GCM (matching auth_value pattern)
- Plaintext env vars in transport_config for non-sensitive values
- UI masks all env/header fields with password input type
- Never display decrypted values when editing
Fixes inability to configure MCP servers that require environment variables
(e.g., GitHub MCP server with GITHUB_PERSONAL_ACCESS_TOKEN).
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixes two bugs identified in the AI code review:
1. INSERT OR REPLACE with a freshly generated UUID never matches the
existing primary key, so it appended rows instead of replacing.
Switch to DELETE-then-INSERT to guarantee exactly one row.
2. Username defaulted to empty string. Resolve it to the current OS
user (USER/LOGNAME env vars, fallback 'local') so credentials are
always bound to a specific user identity.
test_sudo_password now passes -u <username> to sudo so the test
runs scoped to the stored user, not an arbitrary one.
UI: show the configured username prominently in status; relabel the
field and add a scope hint below it.
Tests: test_set_sudo_singleton_delete_then_insert, three username
resolution tests.
The normalizeApiFormat helper (which mapped the legacy format identifier
to custom_rest) was removed but still referenced in 4 call sites.
Replace each call with the underlying value directly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Delete internal vendor API documentation and handoff docs
- Remove vendor-specific AI gateway URLs from CSP whitelist
- Replace vendor-specific log prefixes and comments with generic 'Custom REST'
- Remove vendor-specific default auth header from custom REST implementation
- Remove vendor-specific client header from HTTP requests
- Remove backward-compat vendor format identifier from is_custom_rest_format()
- Remove LEGACY_API_FORMAT constant and normalizeApiFormat() helper
- Update test to not reference legacy format identifier
- Update wiki docs to use generic enterprise gateway configuration
- Update architecture diagrams and ADR-003 to remove vendor references
- Add Buy Me A Coffee link to README
- Update .gitignore to exclude internal user guide and ticket files
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit implements two major features:
1. Integration Search as Primary AI Data Source
- Confluence, ServiceNow, and Azure DevOps searches execute before AI queries
- Search results injected as system context for AI providers
- Parallel search execution for performance
- Webview-based fetch for HttpOnly cookie support
- Persistent browser windows maintain authenticated sessions
2. AI Tool-Calling (Function Calling)
- Allows AI to automatically execute functions during conversation
- Implemented for OpenAI-compatible providers and Custom REST provider
- Created add_ado_comment tool for updating Azure DevOps tickets
- Iterative tool-calling loop supports multi-step workflows
- Extensible architecture for adding new tools
Key Files:
- src-tauri/src/ai/tools.rs (NEW) - Tool definitions
- src-tauri/src/integrations/*_search.rs (NEW) - Integration search modules
- src-tauri/src/integrations/webview_fetch.rs (NEW) - HttpOnly cookie workaround
- src-tauri/src/commands/ai.rs - Tool execution and integration search
- src-tauri/src/ai/openai.rs - Tool-calling for OpenAI and Custom REST provider
- All providers updated with tools parameter support
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- AIProviders: hide top model row when custom_rest active (dropdown lower in form handles it);
clear auth header prefill on format switch; rename User ID / CORE ID → Email Address
- Dashboard + Ollama: add border-border/bg-card classes to Refresh buttons for dark-bg contrast
- Security + settingsStore: wire PII toggle state to persisted Zustand store so pattern
selections survive app restarts
- App: add Sun/Moon theme toggle button to sidebar footer (always visible when collapsed)
- system.rs: add install_ollama_from_bundle command (copies bundled binary to /usr/local/bin)
- auto-tag.yml: add Download Ollama step to all 4 platform build jobs with SHA256 verification
- tauri.conf.json: add resources/ollama/* to bundle resources
- docs: add install_ollama_from_bundle to IPC-Commands wiki
Security: CI download steps verify SHA256 against Ollama's published sha256sums.txt before bundling.
Rename custom API format handling from custom_rest to custom_rest with backward compatibility, add guided model selection with custom entry in provider settings, and rebrand app naming to Troubleshooting and RCA Assistant across UI, metadata, and docs.
Made-with: Cursor
## Integration Settings Persistence
- Add database commands to save/load integration configs (base_url, username, project_name, space_key)
- Frontend now loads configs from DB on mount and saves changes automatically
- Fixes issue where settings were lost on app restart
## Persistent Browser Window Architecture
- Integration browser windows now stay open for user browsing and authentication
- Extract fresh cookies before each API call to handle token rotation
- Track open windows in app state (integration_webviews HashMap)
- Windows titled as "{Service} Browser (TFTSR)" for clarity
- Support easy navigation between app and browser windows (Cmd+Tab/Alt+Tab)
- Gracefully handle closed windows with automatic cleanup
## Bug Fixes
- Fix Rust formatting issues across 8 files
- Fix clippy warnings:
- Use is_some_and() instead of map_or() in openai.rs
- Use .to_string() instead of format!() in integrations.rs
- Add missing OptionalExtension import for .optional() method
## Tests
- Add test_integration_config_serialization
- Add test_webview_tracking
- Add test_token_auth_request_serialization
- All 6 integration tests passing
## Files Modified
- src-tauri/src/state.rs: Add integration_webviews tracking
- src-tauri/src/lib.rs: Register 3 new commands, initialize webviews HashMap
- src-tauri/src/commands/integrations.rs: Config persistence, fresh cookie extraction (+151 lines)
- src-tauri/src/integrations/webview_auth.rs: Persistent window behavior
- src/lib/tauriCommands.ts: TypeScript wrappers for new commands
- src/pages/Settings/Integrations.tsx: Load/save configs from DB
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Implement three authentication methods for Confluence, ServiceNow, and Azure DevOps:
1. **OAuth2** - Traditional OAuth flow for enterprise SSO environments
2. **Embedded Browser** - Webview-based login that captures session cookies/tokens
- Solves VPN constraints: users authenticate off-VPN via web UI
- Extracted credentials work on-VPN for API calls
- Based on confluence-publisher agent pattern
3. **Manual Token** - Direct API token/PAT input as fallback
**Changes:**
- Add webview_auth.rs module for embedded browser authentication
- Implement authenticate_with_webview and extract_cookies_from_webview commands
- Implement save_manual_token command with validation
- Add AuthMethod enum to support all three modes
- Add RadioGroup UI component for mode selection
- Complete rewrite of Integrations settings page with mode-specific UI
- Add secondary button variant for UI consistency
**VPN-friendly design:**
Users can authenticate via webview when off-VPN (web UI accessible), then use extracted cookies for API calls when on-VPN (API requires VPN). Addresses enterprise SSO limitations where OAuth app registration is blocked.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Fixes:
- Added shell:allow-open permission to fix OAuth integration flows
- Added user_id field to ProviderConfig for Custom REST provider CORE ID
- Added UI field for user_id when api_format is custom_rest
- Made userId optional in Custom REST provider requests (only sent if provided)
- Added X-msi-genai-client header to Custom REST provider requests
- Updated CSP to include Custom REST provider domains
- Bumped version to 0.2.6
This fixes:
- OAuth error: 'Command plugin:shell|open not allowed by ACL'
- Missing User ID field in Custom REST provider configuration UI
- Extended ProviderConfig with optional custom fields for non-OpenAI APIs
- Added custom_endpoint_path, custom_auth_header, custom_auth_prefix fields
- Added api_format field to distinguish between OpenAI and Custom REST provider formats
- Added session_id field for stateful conversation APIs
- Implemented chat_custom_rest() method in OpenAI provider
- Custom REST provider uses different request format (prompt+sessionId) and response (msg field)
- Updated TypeScript types to match Rust schema
- Added UI controls in Settings/AIProviders for custom provider configuration
- API format selector auto-populates appropriate defaults (OpenAI vs Custom REST provider)
- Backward compatible: existing providers default to OpenAI format
- Fix download icons (PDF/DOCX) not visible in dark theme by adding text-foreground class
- Fix "Read-only file system" error by using Downloads directory for exports with proper fallback
- Fix Search button visibility in History page by changing variant and adding icon
- Fix domain-only filtering in History page by adding missing filter.domain handling
- Enhance audit log to capture full transmitted data (provider details, messages, content previews)
- Add dirs crate dependency for cross-platform directory detection
- Add success/error feedback for document exports with file path display
- Update Security page to display pretty-printed JSON audit details
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- globals.css: remove button from WebKit -webkit-text-fill-color override that
was causing button text to be invisible (text color matched background in dark mode)
- Security.tsx: toggle enabled state uses bg-blue-500 instead of bg-primary;
in dark mode --primary is near-white making the white knob invisible
- tauriCommands.ts: fix createIssueCmd to pass flat args (not wrapped in newIssue),
map domain->category, and return Issue instead of IssueDetail
- NewIssue/index.tsx: update call site to use Issue return type directly
- release.yml: add ad-hoc codesign step for macOS .app so Gatekeeper shows
"unidentified developer" instead of "damaged" error