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.
The Tauri v2 IPC layer expects camelCase parameter names. The frontend
was sending cluster_type (snake_case), causing the deserialization
failure with error 'command add_proxmox_cluster missing required key
clusterType'.
Changed proxmoxClient.ts line 28 from:
cluster_type: clusterType
to:
clusterType
This aligns with the project's convention where all multi-word
parameters use camelCase (clusterId, nodeId, vmId, etc.).
Fixes the 'Failed to add remote' error when adding new Proxmox remotes.
- Change password parameter from &str to String in add_proxmox_cluster
so Tauri v2 IPC can deserialize it (requires DeserializeOwned + Send)
- Construct full https:// URL with port in ProxmoxClient::get_api_url()
and authenticate() since the frontend strips the protocol before
sending the hostname
- Show actual error string in AddRemoteForm instead of generic fallback
(Tauri errors are plain strings, not Error instances)
- Update client tests to reflect bare-hostname input from the frontend
compile("memset_shim") produces libmemset_shim.a, not memset_shim.o, so the
previous cargo:rustc-link-arg pointed at a file that never exists. Switching to
get_compiler().to_command() compiles memset_s_shim.c directly to a .o file at
a known OUT_DIR path and passes it as a positional linker arg. A positional .o
is always included unconditionally, which also resolves the archive-extraction
ordering issue where -l flags only pull symbols that are already undefined at
that point in the link command.
- Use rustc-link-arg to directly link memset_shim.o object file
instead of -l flag, ensuring symbol is available regardless of
link order with libsodium_sys
- Add #[allow(dead_code)] to find_ollama_binary() which is only
used inside cfg(target_os = "macos") and cfg(target_os = "linux")
blocks, causing false positive warning when cross-compiling for Windows
- Add __MINGW32__ detection in memset_s_shim.c for proper EXPORT macro
- Add WIN32 and __WIN32__ defines when compiling the shim in build.rs
- The memset_explicit symbol is required by libsodium-sys-stable but not
available in MinGW runtime
- The shim is compiled as a static library and linked before libsodium
- Add __declspec(dllexport) to memset_explicit in memset_s_shim.c
- Explicitly link memset_shim library in build.rs for Windows MinGW target
- Fixes undefined reference to memset_explicit when building for x86_64-pc-windows-gnu
Cargo injects [env] entries directly into build script environments,
bypassing shell-level unset and env -u entirely. SODIUM_USE_PKG_CONFIG
was set to "0" in [env], which libsodium-sys-stable build.rs treats as
"pkg-config enabled" (env::var().is_ok() returns true for any value
including "0"). Combined with SODIUM_LIB_DIR set in the workflow, this
triggered the incompatibility panic on every build.
The original comment claiming this "avoids memset_explicit on Windows"
was incorrect — SODIUM_USE_PKG_CONFIG controls detection strategy, not
link behaviour. The actual Windows memset_explicit fix is handled via
SODIUM_LIB_DIR pointing to pre-built MinGW sodium.
bash unset modifies the current shell's environment but the act_runner
at 172.0.0.29 re-injects runner-level environment variables before each
cargo invocation, making unset ineffective. env -u removes the variable
from the child process's environment at the exec() level, bypassing any
runner re-injection entirely.
Applies to all three non-macOS platforms (linux-amd64, windows-amd64,
linux-arm64) in both release-beta.yml and auto-tag.yml.
The libsodium-sys-stable build.rs panics if both SODIUM_LIB_DIR and
SODIUM_USE_PKG_CONFIG are set simultaneously. The runner infrastructure
at 172.0.0.29 has SODIUM_USE_PKG_CONFIG in its container environment
(not traceable to any workflow file or Docker image ENV layer), which
conflicts with the SODIUM_LIB_DIR approach used for cross-compilation.
Explicitly unset SODIUM_USE_PKG_CONFIG in the shell before npm/cargo
runs on all three platforms (linux-amd64, windows-amd64, linux-arm64)
in both release-beta.yml and auto-tag.yml. This is a defensive no-op
when the variable is absent, and a clean fix when it is present.
Master added `unset SODIUM_USE_PKG_CONFIG` to the linux-amd64 and
linux-arm64 build steps in auto-tag.yml (PR #111). Beta's copy of
auto-tag.yml was already ahead of master via the previous sync but
lacked those two unset lines, causing a line-level conflict.
Resolution: take master's version in both conflict regions, adding the
unset to both linux build steps. All three platforms (amd64, Windows,
arm64) now have consistent SODIUM_LIB_DIR + unset configuration.
The libsodium-sys-stable build.rs panics when both SODIUM_LIB_DIR and
SODIUM_USE_PKG_CONFIG are set simultaneously. The runner environment at
172.0.0.29 has SODIUM_USE_PKG_CONFIG set (not traceable to any workflow
file or Docker image ENV layer), which conflicts with any step that sets
SODIUM_LIB_DIR.
For all three platform builds (linux-amd64, windows-amd64, linux-arm64):
- Add `unset SODIUM_USE_PKG_CONFIG` to the shell before cargo runs
- Switch Linux builds from inline apt-get to SODIUM_LIB_DIR (Docker
images already include libsodium-dev, removing the redundant install)
- Extend arm64 PKG_CONFIG_PATH to include /usr/aarch64-linux-gnu/lib/pkgconfig
(matching the beta workflow for consistency)
The unset is a no-op when the variable is absent; it cleanly clears any
ambient value injected by the runner infrastructure.
Tested locally with Ubuntu 22.04 + libsodium-sys-stable 1.24.0:
- No env vars → install_from_source() needs 'make', fails in slim containers
- SODIUM_LIB_DIR alone → works when libsodium is installed in the image
- SODIUM_LIB_DIR + SODIUM_USE_PKG_CONFIG → immediate panic (incompatible by design)
Fixes three broken build targets introduced by the merge conflict resolution:
- linux-amd64: was missing all sodium config, add SODIUM_LIB_DIR
- windows: had SODIUM_LIB_DIR + SODIUM_USE_PKG_CONFIG (incompatible), remove the latter
- linux-arm64: was missing sodium config, add SODIUM_LIB_DIR
Resolves conflicts in auto-tag.yml and release-beta.yml caused by two
independent libsodium fixes landing on separate branches (PR #105 on beta
via SODIUM_LIB_DIR, PR #106 on master via apt-get install).
Resolution keeps beta's approach throughout: SODIUM_LIB_DIR env vars
pointing at pre-installed system libraries, with no runtime apt-get install.
Also carries forward master's Dockerfile.linux-arm64 libsodium addition and
CHANGELOG.md update.
tauri-plugin-stronghold pulls in libsodium-sys-stable which panics at
build time if libsodium is not found via pkg-config — it does not compile
from source. All builder images and the test job inline apt installs were
missing libsodium-dev, breaking every Rust compilation step.
- Add libsodium-dev to Dockerfile.linux-amd64
- Add libsodium-dev (host) + libsodium-dev:arm64 (cross target) to
Dockerfile.linux-arm64
- Add libsodium-dev to all three Rust jobs in test.yml
- Add inline apt-get install to linux-amd64 and linux-arm64 Build steps
in auto-tag.yml and release-beta.yml (bridges the timing race between
build-images and auto-tag triggering on the same push)
- Add SODIUM_LIB_DIR + SODIUM_STATIC to Windows Build env (Dockerfile
already pre-builds libsodium; this tells the crate where to find it)
Moved SODIUM_LIB_DIR from per-step env blocks to job-level env for all
three Rust test jobs (rust-fmt-check, rust-clippy, rust-tests).
Benefits:
- Applies to ALL cargo commands in the job, including generate-lockfile
- More maintainable - single declaration per job
- Consistent with best practices for job-wide environment variables
Addresses automated review feedback.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
The use-pkg-config feature was added in the previous PR and conflicts
with SODIUM_LIB_DIR. The build script errors with:
"SODIUM_LIB_DIR is incompatible with SODIUM_USE_PKG_CONFIG.
Set the only one env variable"
Removed the explicit libsodium-sys-stable dependency since we're using
the SODIUM_LIB_DIR environment variable approach instead.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Directly specify libsodium library paths via SODIUM_LIB_DIR environment
variable instead of relying on pkg-config detection. This is the highest
priority method in libsodium-sys-stable's build.rs and bypasses all
pkg-config/vcpkg logic.
Platform-specific paths:
- Linux x86_64: /usr/lib/x86_64-linux-gnu
- Linux aarch64: /usr/lib/aarch64-linux-gnu
- Windows MinGW: /usr/x86_64-w64-mingw32/lib
Changes:
- test.yml: Add SODIUM_LIB_DIR to all cargo commands
- auto-tag.yml: Add SODIUM_LIB_DIR to all build jobs
This resolves "libsodium not found via pkg-config or vcpkg" by telling
the build script exactly where libsodium is installed.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>