17 KiB
Windows Local Sing-Box Implementation Plan
Intent: Add an optional Windows-client Local sing-box block that mirrors the ProxiFyre block, installs and controls a real sing-box service, imports a subscription/link, lets the user pick and ping servers, and routes selected apps through the chosen local outbound.
Current Behavior: The Windows client supports an existing external SOCKS5 proxy and a ProxiFyre component block with setup details, install/start/stop/uninstall actions, animation, and generated config apply. singbox exists as an optional component in the model, but install-singbox.ps1 is only a marker boundary, main.rs does not register sing-box commands, the frontend has no sing-box block, and subscription parsing lives only in the Node server.
Expected Outcome: A Windows user can keep using the external proxy path unchanged, or explicitly install optional Local sing-box, paste a subscription/VLESS link, fetch servers, ping them, choose one, generate a checked sing-box config, start/stop the sing-box service, and apply ProxiFyre routing to local-singbox.
Target-Perspective Output: In the Windows client, the user sees a second optional block styled and animated like ProxiFyre. It shows what will be installed, asks for clear confirmation before privileged work, displays subscription/server state, exposes server ping and selection, and makes it obvious whether selected apps route to an existing proxy or to Local sing-box.
Truth Owner: Rust/Tauri backend owns sing-box source state, subscription parsing/cache, generated sing-box config, component detection, and service operations. React owns only transient UI state. Generated configs and service files are derived artifacts.
Contract Boundary: React calls typed Tauri commands. Rust validates and persists source JSON under C:\ProgramData\VpnProxy, generates configs through the sing-box adapter, and invokes explicit elevated PowerShell only for install/uninstall/service actions. UI never parses raw PowerShell/stdout.
Cutover: Replace the current marker-only sing-box installer path with a real optional Local sing-box component while preserving ComponentId::Singbox and local-singbox target semantics. Keep external proxy as the default usable route when sing-box is absent.
Displaced Path: Displace apps/windows-client/scripts/install-singbox.ps1 marker behavior and the current direct-only adapters/singbox.rs output. Do not create a parallel Node/server subscription path for the Windows client.
Value Density: The smallest high-value slice is a controlled Local sing-box block that can fetch a subscription, select an outbound, generate checked local sing-box config, and expose service controls without making sing-box mandatory.
Evidence Gate: Evidence must include target-perspective UI proof plus generated config proof, not just tests. Privileged Windows service behavior must be manually verified or explicitly marked implemented but unproven.
Acceptance Evidence: Rust tests for parser/config/service-command boundaries; frontend build; app state or screenshot showing ProxiFyre and Local sing-box blocks; generated sing-box-config.json containing the selected outbound and local mixed inbound; generated ProxiFyre config pointing to 127.0.0.1:1080; Windows service checklist when elevated actions are run.
Evidence Lane: Record commands, selected app state, generated config summaries, and manual Windows results in docs/goals/windows-local-singbox/EVIDENCE.md.
Kill Criteria: No mandatory sing-box for external proxy flow; no hidden install during profile apply; no duplicate subscription source of truth in React or Node server; no raw PowerShell text as app logic; no permanent marker-only sing-box install path.
Architecture Slice: Extend apps/windows-client only: Rust domain/storage/commands/adapters/detection/scripts plus React UI/types/CSS. Avoid root src/server and root src/web except as read-only reference.
Plan Review Gate: Requires PRE review before execution.
Terminology
The user-facing feature name is Local sing-box / sing-box. Do not use alternate feature names in UI, commands, docs, or files.
Architecture Slice
Files to create:
apps/windows-client/src-tauri/src/subscription.rsapps/windows-client/src-tauri/src/singbox_service.rsapps/windows-client/src-tauri/tests/subscription_tests.rsapps/windows-client/src-tauri/tests/singbox_service_tests.rsapps/windows-client/src-tauri/tests/singbox_command_tests.rs
Files to modify:
apps/windows-client/src-tauri/Cargo.tomlapps/windows-client/src-tauri/src/main.rsapps/windows-client/src-tauri/src/models.rsapps/windows-client/src-tauri/src/storage.rsapps/windows-client/src-tauri/src/commands.rsapps/windows-client/src-tauri/src/component_detection.rsapps/windows-client/src-tauri/src/adapters/singbox.rsapps/windows-client/src-tauri/tests/singbox_adapter_tests.rsapps/windows-client/src-tauri/tests/command_tests.rsapps/windows-client/src/domain/types.tsapps/windows-client/src/api/tauriCommands.tsapps/windows-client/src/app/App.tsxapps/windows-client/src/styles/app.cssapps/windows-client/scripts/install-singbox.ps1apps/windows-client/README.mddocs/goals/windows-local-singbox/EVIDENCE.md
Files to avoid:
src/server/*except as read-only reference for subscription semantics.src/web/*- Docker, compose, gateway, and macOS installer files.
- Existing ProxiFyre behavior except where it must consume the
local-singboxtarget.
Source of truth:
C:\ProgramData\VpnProxy\config\profiles.jsonC:\ProgramData\VpnProxy\config\targets.jsonC:\ProgramData\VpnProxy\config\local-singbox.jsonC:\ProgramData\VpnProxy\state\singbox-subscription-cache.jsonC:\ProgramData\VpnProxy\state\activity.json
Derived artifacts:
C:\ProgramData\VpnProxy\generated\sing-box-config.jsonC:\ProgramData\VpnProxy\generated\proxifyre-app-config.json- Installed
sing-box.exeand WinSW wrapper underC:\Program Files\VpnProxy\sing-box - Windows service
VpnProxySingBox
Read path:
- React calls
get_components,get_singbox_status,get_singbox_setup_status, and subscription/server commands. - Rust reads source Local sing-box config and cache, detects installed
sing-box/service/wrapper, and returns redacted DTOs.
Write path:
- React sends typed mutations for subscription URL, selected server, local endpoint, and service actions.
- Rust validates input, writes source JSON atomically, fetches/cache subscription data, generates
sing-box-config.json, and runssing-box checkbefore service start/restart.
Contract boundary:
subscription.rsowns fetch/parse/link normalization.adapters/singbox.rsowns conversion from selected outbound to local runtime config.singbox_service.rsowns install/service script generation and structured command parsing.commands.rsowns Tauri DTOs and activity entries.App.tsxowns layout/state orchestration only.
Integration points:
- ProxiFyre route remains
selected apps -> ProxiFyre -> target. - Local sing-box route uses target
local-singbox,kind=local,protocol=socks5,host=127.0.0.1,port=1080,requiresComponent=singbox. - Server ping uses TCP connect to the selected outbound host/port, like the existing server ping semantics.
- Install flow downloads/installs
sing-boxplus a WinSW Windows service wrapper, then writes machine-readable result JSON.
Migration/cutover:
- On first sing-box save/start, ensure
local-singboxtarget exists or is updated from Local sing-box listen settings. - Do not switch the user's profile target automatically unless the user chooses Local sing-box.
- Existing external proxy input remains the default path and must still build/apply without sing-box.
Displaced path:
install-singbox.ps1must stop being a marker-only script.- The old direct-only sing-box config in
adapters/singbox.rsmust be replaced by selected-subscription-outbound config generation. - No Windows-client code should import or call the root Node server for subscription parsing.
Acceptance evidence gate:
- Automated evidence proves parser/config/ping/service-command boundaries.
- App-visible evidence proves the optional block, setup details, server selection, and route mode.
- Generated config evidence proves selected server is used by sing-box and ProxiFyre points to the local endpoint.
Task Board
Task 1: Add Local Sing-Box Domain And Storage Contract
Allowed files:
apps/windows-client/src-tauri/src/models.rsapps/windows-client/src-tauri/src/storage.rsapps/windows-client/src/domain/types.tsapps/windows-client/src-tauri/tests/storage_tests.rs
Expected output:
LocalSingBoxConfigsource model with subscription URL, redacted display URL, selected server tag, listen host/port, service name, install root, and timestamps.SubscriptionCachemodel with parsed config, server summaries, user info, and fetched timestamp.- Storage paths for
config/local-singbox.jsonandstate/singbox-subscription-cache.json.
Verification:
cd apps/windows-client/src-tauri && cargo test storage
Acceptance evidence:
- Tests prove atomic roundtrip, default optional empty state, redacted URL DTO, and invalid cache fallback.
Parallel safe: no.
Task 2: Port Subscription Parsing And Fetching To Rust
Allowed files:
apps/windows-client/src-tauri/Cargo.tomlapps/windows-client/src-tauri/src/subscription.rsapps/windows-client/src-tauri/tests/subscription_tests.rs
Expected output:
- Parser supports sing-box JSON configs, base64 subscription bodies, and VLESS REALITY links with the same supported outbound types as
src/server/subscription.js. - Fetch command support is implemented in Rust with HTTP/HTTPS only and structured errors.
- Subscription URL is never echoed unredacted in diagnostics or normal status DTOs.
Verification:
cd apps/windows-client/src-tauri && cargo test subscription
Acceptance evidence:
- Tests cover JSON config, base64 VLESS list, invalid URL, unsupported outbound, and redaction.
Parallel safe: yes after Task 1 model names are stable.
Task 3: Replace Sing-Box Adapter With Selected-Outbound Config Generation
Allowed files:
apps/windows-client/src-tauri/src/adapters/singbox.rsapps/windows-client/src-tauri/tests/singbox_adapter_tests.rs
Expected output:
- Adapter builds local mixed inbound on the configured listen host/port.
- Adapter selects the cached outbound by tag, clones it, ensures a stable outbound tag, and adds
direct/block. - Adapter runs
sing-box checkwhen a binary path is available.
Verification:
cd apps/windows-client/src-tauri && cargo test singbox_adapter
Acceptance evidence:
- Tests show selected VLESS outbound appears in generated config, missing selected tag blocks generation, and external-target ProxiFyre flow remains independent from Local sing-box.
Parallel safe: yes after Task 1.
Task 4: Implement Sing-Box Detection, Setup Status, And Service Scripts
Allowed files:
apps/windows-client/src-tauri/src/component_detection.rsapps/windows-client/src-tauri/src/singbox_service.rsapps/windows-client/scripts/install-singbox.ps1apps/windows-client/src-tauri/tests/component_detection_tests.rsapps/windows-client/src-tauri/tests/singbox_service_tests.rs
Expected output:
- Detection finds installed
sing-box.exe, serviceVpnProxySingBox, service running state, version/path, and problems. - Setup status lists exactly what will be installed: sing-box binary, WinSW service wrapper, service name, install root, generated config/log paths.
- Install script performs a real idempotent install/repair boundary using WinSW and returns structured JSON; uninstall is safe-scoped to the configured install root.
Verification:
cd apps/windows-client/src-tauri && cargo test component_detection singbox_service- Windows parser check for
install-singbox.ps1when running on Windows.
Acceptance evidence:
- Tests prove missing/installed/running component merge and PowerShell result parsing. Manual service install/start evidence is recorded later.
Parallel safe: yes, but integrate with Task 6 before UI.
Task 5: Add Tauri Sing-Box Commands
Allowed files:
apps/windows-client/src-tauri/src/commands.rsapps/windows-client/src-tauri/src/main.rsapps/windows-client/src/api/tauriCommands.tsapps/windows-client/src-tauri/tests/command_tests.rsapps/windows-client/src-tauri/tests/singbox_command_tests.rs
Expected output:
- Commands:
get_singbox_status,get_singbox_setup_status,save_singbox_subscription,fetch_singbox_subscription,forget_singbox_subscription,select_singbox_server,ping_singbox_server,ping_all_singbox_servers,generate_singbox_config,start_singbox_service,stop_singbox_service,install_singbox,uninstall_singbox. - Commands update activity with structured entries.
generate_singbox_configensures/updates thelocal-singboxtarget but does not change profile targets without user choice.start_singbox_serviceregenerates and checks config from current source state before starting the service.
Verification:
cd apps/windows-client/src-tauri && cargo test command singbox_command
Acceptance evidence:
- Tests prove fetch/cache/select/generate flow and ProxiFyre apply blocks only when a profile actually targets missing/stopped Local sing-box.
Parallel safe: no; depends on Tasks 1-4.
Task 6: Build The Optional Local Sing-Box UI Block
Allowed files:
apps/windows-client/src/app/App.tsxapps/windows-client/src/domain/types.tsapps/windows-client/src/api/tauriCommands.tsapps/windows-client/src/styles/app.css
Expected output:
- A second block appears beside/under ProxiFyre, visually matching
finder-card, setup details, action menu, status light, and border animation behavior. - UI shows Local sing-box as optional, not an error, when missing.
- User can paste subscription/link, fetch servers, select server, ping one/all, generate config, install/start/stop/uninstall Local sing-box, and choose whether the main profile uses existing proxy or Local sing-box.
- Loading/error/success states are visible and controlled by user action.
Verification:
cd apps/windows-client && npm run build
Acceptance evidence:
- Screenshot or app state shows ProxiFyre block and Local sing-box block, expanded setup details, fetched server list with ping state, and route target toggle.
Parallel safe: no; depends on Task 5 DTOs.
Task 7: Integrate Route Choice And ProxiFyre Apply
Allowed files:
apps/windows-client/src/app/App.tsxapps/windows-client/src-tauri/src/commands.rsapps/windows-client/src-tauri/src/adapters/proxifyre.rsapps/windows-client/src-tauri/tests/command_tests.rsapps/windows-client/src-tauri/tests/proxifyre_adapter_tests.rs
Expected output:
- Main profile can target either external proxy or
local-singbox. - Switching to Local sing-box writes
targetId=local-singbox; switching back writes external target. - ProxiFyre generated config points to
127.0.0.1:1080when Local sing-box is selected and still points to the entered external proxy otherwise.
Verification:
cd apps/windows-client/src-tauri && cargo test proxifyre_adapter commandcd apps/windows-client && npm run build
Acceptance evidence:
- Generated ProxiFyre config samples for both external proxy and Local sing-box routes are recorded.
Parallel safe: no.
Task 8: Documentation, Evidence, And Windows Manual Gate
Allowed files:
apps/windows-client/README.mddocs/goals/windows-local-singbox/EVIDENCE.mddocs/goals/windows-modular-client/EVIDENCE.md
Expected output:
- README explains separate ProxiFyre and Local sing-box install flows, data paths, service name, and rollback.
- Evidence file records tests/builds/UI proof/generated configs/manual Windows service checks.
- If elevated service install cannot be run in the current environment, record
implemented but unprovenfor that lane with exact remaining manual steps.
Verification:
git status --short- Evidence commands listed in
EVIDENCE.md.
Acceptance evidence:
- A target-perspective checklist proves the external proxy path still works and Local sing-box path works or is explicitly unproven only at the privileged Windows service lane.
Parallel safe: no.
PRE Review Prompt
Use C:\Users\PC\.agents\skills\krypton-planning\plan-reviewer-prompt.md with:
- Plan file:
docs/goals/windows-local-singbox/PLAN.md - Original request: add an optional Windows-client Local sing-box block like ProxiFyre, with install/service management, connection link/subscription import, server selection, ping, animations, and user-controlled visibility of what will be installed.
- Unsafe paths or layers: root
src/server, rootsrc/web, hidden installer calls inside apply, raw PowerShell parsing in React, duplicate subscription state.