When running the tsunagi agent as an elevated Administrator or Windows Service,
unprivileged user-space processes (such as a system tray application, user-level
CLI commands, or status monitors) could not interact with the control socket.
This was due to two constraints on Windows:
1. The default control socket path was derived from the per-user %APPDATA%,
making an administrator's socket invisible or inaccessible to a non-elevated
standard user profile.
2. Even if pointed to the same named pipe, Windows Mandatory Integrity Control (MIC)
and default ACLs prevent a Medium-Integrity (unelevated) process from opening
a High-Integrity (elevated) pipe server for write access unless explicitly allowed.
Key changes:
- In crates/tsunagi/src/ipc/windows.rs, implement PipeSecurityAttributes using
Win32 ConvertStringSecurityDescriptorToSecurityDescriptorW with SDDL:
"D:(A;;GRGW;;;WD)(A;;GA;;;BA)(A;;GA;;;SY)S:(ML;;NW;;;ME)". This grants generic
read/write access to Everyone (WD), retains full control for Administrators (BA)
and LocalSystem (SY), and sets the Mandatory Label SACL to Medium Integrity (ME)
with No-Write-Up (NW).
- In crates/tsunagi/src/ipc/mod.rs, introduce default_control_socket_path() which
points to %ProgramData%\tsunagi\agent.sock on Windows (and default per-user
state directory on Unix).
- In crates/tsunagi-cli/src/main.rs, support TSUNAGI_CONTROL_SOCKET environment
variable across all commands, and use default_control_socket_path() on Windows
when running against the default state directory. Custom state directories (--state-dir)
or explicit sockets (--control-socket) continue to take precedence, allowing
multi-daemon setups to remain strictly isolated.
- In workspace Cargo.toml, set unsafe_code = "deny" so the workspace forbids unsafe
code while permitting explicit, documented unsafe Win32 API calls in windows.rs.
Validation on Linux:
- cargo fmt --all -- --check passed.
- cargo clippy --locked --workspace --all-targets -- -D warnings passed.
- cargo test --locked --workspace --all-targets --jobs 2 -- --test-threads=2 passed (349 tests passed).