Race condition in get_proxmox_client_for_cluster: two concurrent callers
for an uncached cluster could both authenticate and insert, with the second
overwriting the first. Re-check under write lock before inserting so the
later caller returns the already-stored client instead of overwriting it.
handleConnectRemote used getProxmoxCluster (a DB-only lookup) to set status
'connected', which passed even when the Proxmox API was unreachable. Replace
with pingProxmoxCluster, a new command that authenticates and calls
GET /api2/json/version, providing a real end-to-end connectivity test.
handleEditRemote used remove-then-add, leaving a gap where the record was
absent and silently lost if addProxmoxCluster failed. Replace with
updateProxmoxCluster, a new command that issues a single SQL UPDATE (plus
in-memory pool eviction) so the record is never transiently missing.
ActionsMenu useEffect added the mousedown listener only when open=true but
the dependency array contained open, causing ambiguity about cleanup timing.
Attach the listener unconditionally on mount (empty dep array) so there is
always exactly one add and one remove with no conditional branches.
New Rust tests cover update_proxmox_cluster not-found logic and ping error
message format (420 Rust + 386 frontend, zero failures).
Half-completed refactor left 68 Tauri command functions with orphaned
.ok_or_else() chains after the old clusters.get() pattern was removed
without inserting the replacement helper call. Also fixed two bugs in the
new get_proxmox_client_for_cluster helper: undeclared `clusters` variable
in the early-return check, and client_arc going out of scope before return.
fix(ai): enforce system-message-first ordering for strict LLM providers
Qwen3.5-122b (and other models via LiteLLM) reject requests where system
messages appear after user/assistant turns. Moved tool-calling format
and iteration-budget system messages to before history is appended.
Changed mid-loop iteration warning and forced-stop instruction from
system role to user role so they can safely appear mid-conversation.
fix(proxmox): Remotes actions menu and connect/disconnect behaviour
Replaced the non-functional "..." toast placeholder with a proper
ActionsMenu dropdown (Edit / Test Connection / Delete). Removed inline
emoji buttons folded into the menu. Connect now calls getProxmoxCluster
as a live connection test and reflects real status; disconnect marks the
remote disconnected locally. Remote status now maps correctly from the
backend ClusterInfoWithHealth.connected field instead of hardcoding
'connected' for every entry.
fix(proxmox): Ceph page no longer shows HEALTH_OK on non-Ceph clusters
Page now fetches real health data on mount. If getCephHealth fails the
page renders an informational notice rather than fake HEALTH_OK. When
Ceph is present, pools and OSDs are loaded and displayed live.
Address automated PR review feedback:
- Extract parseRemoteUrl() helper to eliminate code duplication in handleAddRemote and handleEditRemote
- Add JSDoc documentation for the helper function
- Document known architectural limitation in edit operation (remove-then-add pattern)
- Fix pre-existing issue: install missing node_modules dependencies (sonner, monaco-editor)
The edit operation uses remove-then-add because the backend lacks an atomic update command. This is documented as a known limitation until updateProxmoxCluster() is implemented in the Rust backend.
Verification:
- All frontend tests pass (386/386)
- All Rust tests pass (413 passed, 6 ignored)
- ESLint, TypeScript, clippy, rustfmt all pass
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
When adding a remote with a URL like https://172.0.0.18:8006, the code
was previously passing the port as part of the hostname
(172.0.0.18:8006) while also setting the port separately, causing
connection failures.
Now properly extracts the port from the URL if present, falling back
to default ports (8006 for PVE, 8007 for PBS) if not specified.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Replace hardcoded dummy data in VMs, Containers, Storage, Backup, and
Firewall pages with live API calls; show empty-state UI when no
clusters are configured
- Add list_proxmox_containers backend command (LXC via cluster/resources)
and register it in the Tauri handler and frontend proxmoxClient.ts
- Fix add_proxmox_cluster to store credentials without requiring a live
Proxmox connection; persist username in DB (migration 034); update
list/get queries to read username column from new schema
- Replace alert() in RemotesPage with toast.error() + rethrow so errors
surface correctly in Tauri WebView
- Replace tauri-plugin-updater with direct Gitea HTTP API call for
update checks; use tauri-plugin-opener for browser launch; Updater UI
now shows current/latest version and release notes
- Add gogs.tftsr.com to CSP connect-src
- Fix all 74 pre-existing ESLint no-explicit-any warnings in
proxmoxClient.ts; remove stale eslint-disable directive in ACLPage.tsx
- All checks pass: cargo fmt, clippy -D warnings, 411 Rust tests,
tsc --noEmit, eslint --max-warnings 0, 386 frontend tests
- ProxmoxSettings: load all six settings from localStorage on mount via
useEffect, wire Save button to write values and show a 2s confirmation,
wire Reset button to clear keys and restore defaults
- RemotesPage: attach loadRemotes() to the header Refresh button onClick
and replace the no-op onRefresh prop passed to RemotesList
- EditRemoteForm: add password field to RemoteConfig interface and form
so handleEditRemote receives a complete config; use DialogFooter for
consistent button layout
- 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.