Context
failproofaid (the persistent Rust background daemon that keeps policy
evaluation warm, added in #632) is Linux + macOS only by explicit design
decision — see the plan and isDaemonSupportedPlatform() in
src/hooks/daemon-service.ts, which is a single
process.platform === "linux" || process.platform === "darwin" check.
A machine on Windows (or any platform where isDaemonSupportedPlatform()
returns false) stays entirely on today's full in-process evaluation —
failproofai config skips the daemon install/start step, and
daemon-client.ts's tryDaemonHook() never attempts a socket connection at
all. This is a deliberate scoping decision to keep the initial implementation
simple, not a limitation anyone is currently blocked on.
What Windows support would need
- Service lifecycle: a Windows equivalent of the systemd
--user unit /
launchd LaunchAgent install in daemon-service.ts — likely a Windows
Service (sc.exe/New-Service) or a Scheduled Task running at logon,
since failproofaid must start without requiring elevation (same
no-elevation constraint as the Linux/macOS install).
- IPC transport: Unix domain sockets (
crates/fpai-ipc,
~/.failproofai/run/failproofaid.sock) don't exist pre-Windows 10 1803;
even on newer Windows, std::os::unix::net::UnixStream isn't available —
this would need a named pipe transport (or Windows' newer AF_UNIX
support) in crates/failproofaid/src/server.rs and
crates/failproofaid/src/worker.rs, plus a matching client in
src/hooks/daemon-client.ts (currently node:net's createConnection({ path }), which assumes a filesystem-path socket).
- Process group / signal handling:
worker.rs's kill_process_group()
uses .process_group(0) + libc::kill(-pgid, SIGKILL) to reliably kill a
sh -c "..." worker child that may fork rather than exec. Windows has no
process groups or POSIX signals — this needs a Job Object–based
equivalent, and the worker spawn command itself (sh -c in
WorkerCommand::spawn) needs a Windows shell equivalent.
- Peer credential verification:
crates/fpai-ipc/src/peer.rs uses
SO_PEERCRED/getpeereid-style verification over the Unix socket to
confirm the connecting client is the same OS user — needs a named-pipe
equivalent (e.g. GetNamedPipeClientProcessId + a token/SID check).
resolveFailproofaidBinaryPath() in daemon-service.ts would need a
windows-x64/windows-arm64 entry in platformKey(), a
@failproofai/failproofaid-windows-* npm package, and a Windows leg in
.github/workflows/build-daemon.yml's cross-compile matrix (binary name
failproofaid.exe).
Out of scope for this issue
This issue tracks the idea and the known shape of the work — it is not a
commitment to a specific design. Whoever picks this up should re-verify the
above against whatever Windows APIs/crates are current at the time (this was
written from a Linux+macOS-only implementation with no live Windows testing).
Context
failproofaid(the persistent Rust background daemon that keeps policyevaluation warm, added in #632) is Linux + macOS only by explicit design
decision — see the plan and
isDaemonSupportedPlatform()insrc/hooks/daemon-service.ts, which is a singleprocess.platform === "linux" || process.platform === "darwin"check.A machine on Windows (or any platform where
isDaemonSupportedPlatform()returns false) stays entirely on today's full in-process evaluation —
failproofai configskips the daemon install/start step, anddaemon-client.ts'stryDaemonHook()never attempts a socket connection atall. This is a deliberate scoping decision to keep the initial implementation
simple, not a limitation anyone is currently blocked on.
What Windows support would need
--userunit /launchd
LaunchAgentinstall indaemon-service.ts— likely a WindowsService (
sc.exe/New-Service) or a Scheduled Task running at logon,since failproofaid must start without requiring elevation (same
no-elevation constraint as the Linux/macOS install).
crates/fpai-ipc,~/.failproofai/run/failproofaid.sock) don't exist pre-Windows 10 1803;even on newer Windows,
std::os::unix::net::UnixStreamisn't available —this would need a named pipe transport (or Windows' newer
AF_UNIXsupport) in
crates/failproofaid/src/server.rsandcrates/failproofaid/src/worker.rs, plus a matching client insrc/hooks/daemon-client.ts(currentlynode:net'screateConnection({ path }), which assumes a filesystem-path socket).worker.rs'skill_process_group()uses
.process_group(0)+libc::kill(-pgid, SIGKILL)to reliably kill ash -c "..."worker child that may fork rather than exec. Windows has noprocess groups or POSIX signals — this needs a Job Object–based
equivalent, and the worker spawn command itself (
sh -cinWorkerCommand::spawn) needs a Windows shell equivalent.crates/fpai-ipc/src/peer.rsusesSO_PEERCRED/getpeereid-style verification over the Unix socket toconfirm the connecting client is the same OS user — needs a named-pipe
equivalent (e.g.
GetNamedPipeClientProcessId+ a token/SID check).resolveFailproofaidBinaryPath()indaemon-service.tswould need awindows-x64/windows-arm64entry inplatformKey(), a@failproofai/failproofaid-windows-*npm package, and a Windows leg in.github/workflows/build-daemon.yml's cross-compile matrix (binary namefailproofaid.exe).Out of scope for this issue
This issue tracks the idea and the known shape of the work — it is not a
commitment to a specific design. Whoever picks this up should re-verify the
above against whatever Windows APIs/crates are current at the time (this was
written from a Linux+macOS-only implementation with no live Windows testing).