Portable Windows utility with a compact always-visible dashboard for desktop proxy/VPN clients.
The project started as a v2rayN TUN widget. It now uses explicit operational adapters so the same frontend and Tauri command layer can work with v2rayN, Happ and future clients.
| Client | Detection/status | Open app | Connect/disconnect | Profile/server selection | Subscriptions |
|---|---|---|---|---|---|
| v2rayN | Supported | Supported | Supported for Enable TUN | Experimental | Unsupported |
| Happ | Supported baseline; UI status experimental | Supported | Experimental opt-in UI Automation | Research required | Research required |
Preserved behind the compatibility adapter:
- installation/path detection;
- process, config and log signals;
- combined status resolution;
- external IP and latency checks;
- Enable TUN through Windows UI Automation;
- config toggle plus reload/restart fallback;
- profile list;
- experimental active profile switching;
- open/restart and privilege diagnostics;
- process, privilege and UI control scoped to the configured installation;
- serialized refresh/control operations and stale-context rejection;
- primary-only action confirmation with explicit desired-state fallback;
- non-mutating status reads and fail-closed, schema-preserving config updates;
- existing-process activation without duplicate launch.
Explicit limitations:
- subscription listing is not supported;
- subscription switching is not supported;
- subscription refresh/update is not supported;
- adding/removing subscriptions is not supported;
- profile selection is not subscription switching;
- generic Proxy/TUN/Mixed reporting is not implemented for v2rayN.
Safe baseline:
- detects known processes and PID;
- detects or validates the executable path;
- checks common Windows installation locations;
- opens Happ and retains launch ownership until the exact selected executable becomes observable;
- reports generic IP/latency diagnostics;
- never infers Connected from process existence alone;
- provides a dedicated Happ Setup and diagnostics window;
- scopes runtime operations to the configured executable and serializes refresh/control/setup actions;
- activates an exact running installation instead of launching a duplicate.
Experimental connection control:
- disabled by default;
- requires explicit consent in Happ Setup;
- scopes window discovery to the detected Happ PID;
- accepts only a high-confidence Connect/Disconnect action;
- rejects Auto connect, Reconnect and settings labels;
- supports English and Russian action labels;
- fails without clicking when the UI is ambiguous;
- can report an exact selected Proxy/TUN/Mixed label when the current UI exposes one.
The adapter does not modify Happ config, database or subscription files.
Still unavailable for Happ:
- stable official CLI/API/daemon IPC;
- server/profile list or selection;
- restart/reload;
- subscriptions.
- Select Happ in the widget.
- Open the adapter setup with the sliders button beside the selector.
- Detect the executable automatically or enter a path to
Happ.exe. - Run the Happ probe.
- Review the detected process, window, action and confidence score.
- Enable experimental Windows UI Automation only after the probe identifies the current installed UI correctly.
The connect button remains disabled until experimental control is explicitly enabled.
Four responsibility layers:
- frontend (
src/frontend) — shared UI, selected-client UX, setup/debug windows, capability gating, i18n and polling; - generic commands (
src/tauri/src/client_commands.rs) — resolve the selected adapter and invoke its contract; - adapters (
src/tauri/src/adapters) — client-specific operations and capability descriptors; - services (
src/tauri/src/services,src/tauri/src/utils) — health checks, persistence, window behavior and automation helpers.
ProxyClientAdapter owns:
- descriptor/capabilities;
- refresh;
- toggle;
- list/select items;
- open;
- diagnostics.
client_commands.rs has no v2rayN/Happ operation branching. Future adapters are registered in the adapter module and implement the same contract.
Legacy v2rayN commands remain registered during staged migration so existing debug/control workflows are not removed in this refactor.
Network diagnostics reject non-public literal and DNS-resolved targets, disable redirects and ambient proxy settings, and pin hostname requests to the exact public socket addresses that were validated before the request. Settings normalization bounds endpoint lists, polling and opacity values before persistence.
All four local windows expose explicit loading/error/retry or no-result behavior. Settings and Happ Setup protect unsaved draft-only changes on both custom and native close requests. Settings, Debug and Happ Setup close requests are routed through the backend rule that restores Main before hiding the source; if that cannot be proven, the source remains visible and a localized accessible alert explains the failure. Main mutations, Settings save/path/discard actions, Debug commands and Happ Setup actions reject duplicate same-frame dispatch before React rerenders. Administrator relaunch also has a process-wide backend claim, so concurrent requests from different windows cannot launch multiple elevated processes. Diagnostics opens are coalesced while native window creation is in flight, and Main auto-height writes are serialized so the newest measurement is applied last. Diagnostics opens without hiding Main and can therefore use its normal native close lifecycle. Local and Diagnostics windows are fitted to the active monitor work area when shown or resized by application commands. Native minimum sizes are temporarily capped when a small/RDP work area cannot contain them and restored before final size/position clamping when space returns. Async Tauri listeners are disposed even if registration finishes after React unmounts. Endpoint lists and loaded settings are normalized and bounded before use.
Read AGENTS.md before changing the project.
Planning and decisions:
project-tracking/roadmap/0013-proxy-client-adapter-roadmap.mdproject-tracking/tasks/0013-add-proxy-client-adapters-and-happ-mvp.mdproject-tracking/decisions/0013-multi-client-adapter-architecture.mdproject-tracking/reports/0013-add-proxy-client-adapters-and-happ-mvp-report.mdproject-tracking/tasks/0014-post-merge-deep-audit.mdproject-tracking/tasks/0015-final-main-tree-audit.mdproject-tracking/tasks/0016-post-merge-runtime-hardening.mdproject-tracking/reports/0016-post-merge-runtime-hardening-report.mdproject-tracking/tasks/0017-final-post-merge-audit.mdproject-tracking/reports/0017-final-post-merge-audit-report.mdproject-tracking/tasks/0018-full-project-screen-audit.mdproject-tracking/reports/0018-full-project-screen-audit-report.mdproject-tracking/tasks/0024-self-hosted-runner-and-full-audit.mdproject-tracking/decisions/0024-self-hosted-ci-runner.mdproject-tracking/reports/0024-self-hosted-runner-and-full-audit-report.mdproject-tracking/tasks/0025-disable-ci-system-installation.mdproject-tracking/decisions/0025-validation-only-self-hosted-ci.mdproject-tracking/reports/0025-disable-ci-system-installation-report.mdproject-tracking/tasks/0026-post-uac-fix-hardening.mdproject-tracking/decisions/0026-validation-only-release-toolchain.mdproject-tracking/reports/0026-post-uac-fix-hardening-report.mdproject-tracking/tasks/0029-close-and-small-work-area-hardening.mdproject-tracking/reports/0029-close-and-small-work-area-hardening-report.mdproject-tracking/tasks/0037-auxiliary-operation-ownership-and-reopen-state.mdproject-tracking/reports/0037-auxiliary-operation-ownership-and-reopen-state-report.mdproject-tracking/tasks/0039-settings-debug-operation-ownership.mdproject-tracking/reports/0039-settings-debug-operation-ownership-report.mdproject-tracking/tasks/0041-launch-and-window-operation-ownership.mdproject-tracking/reports/0041-launch-and-window-operation-ownership-report.md
The repository is public. Do not commit credentials, subscription URLs, private endpoints, real local paths, runtime configs/logs or personal data.
- Rust + Tauri
- React + TypeScript + Vite
- Tailwind CSS
- Zustand
- i18next
Frontend:
cd src/frontend
npm install
npm run devTauri:
cd src/tauri
cargo tauri devcd src/frontend
npm ci
npm audit --audit-level=high
npm test
npm run build./scripts/rust-env.ps1 -Bootstrap
./scripts/test-rust.ps1The permanent Release Quality workflow runs both jobs on the dedicated Windows self-hosted runner selected by [self-hosted, v2rayn-widget-ci]. It validates every non-draft same-repository PR revision on opened, reopened, ready_for_review and synchronize; PR-number concurrency cancels obsolete runs.
CI is validation-only. Node.js, npm, the stable x64 MSVC Rust toolchain, rustfmt, Clippy, the Visual Studio C++ toolchain and the exact Tauri NSIS cache must already exist on the runner. Workflow jobs never install or update system toolchains, request elevation, invoke package-manager installers or run generated setup executables. Missing or mismatched prerequisites fail immediately with a manual-provisioning message.
Frontend dependencies are restored only into the checkout with npm ci --ignore-scripts, process-scoped registry/cache settings and cleanup after artifact upload. Official Actions are pinned to immutable commit SHAs, and checkout credentials are not persisted in the repository. The PR quality gate does not package NSIS installers; it only validates that the locked Tauri CLI and exact NSIS cache are ready for a later trusted release build.
The Release Quality workflow additionally:
- verifies workflow runner, trigger, no-provisioning, credential, action-pinning and cleanup contracts;
- rejects high-severity frontend dependency advisories;
- validates the locked Tauri CLI and exact
%LOCALAPPDATA%\tauri\NSIScache without mutating it; - transfers the exact built frontend into the Tauri job;
- checks formatting for the complete Rust workspace;
- runs the Rust regression suite;
- runs strict
cargo clippy --locked --all-targets -- -D warnings; - runs strict release/no-default-features Clippy;
- executes
cargo check --locked; - performs a locked release build and verifies that the portable Windows executable is produced.
The trusted Build Release Assets workflow also uses v2rayn-widget-ci. It validates the exact Tauri NSIS 3.11 cache, fingerprints it before and after bundling, and fails if the cache changes. The NSIS installer is explicitly current-user only and skips WebView2 installation, so it does not request Administrator access or execute a dependency installer; WebView2 must already exist on the target Windows system. The generated installer is packaged and uploaded but never executed by CI. The only write-enabled release-publishing job remains on an isolated hosted Linux runner, does not check out project code, and uploads only checksum-verified allowlisted assets. See docs/release-process.md.
./scripts/build-portable.ps1Output: dist/portable/v2rayn-widget.exe or a timestamped file when the target executable is locked.
./scripts/build-installer.ps1The script requires the locked Tauri CLI and complete exact Tauri NSIS cache to be provisioned beforehand. It fingerprints the cache before and after packaging and fails if Tauri downloads, repairs or mutates bundler tooling.
Output: exactly one file under src/tauri/target/release/bundle/nsis/*.exe.
A configured v2rayN folder must contain:
v2rayN.exeguiConfigs/guiLogs/
The adapter reads:
guiConfigs/guiNConfig.jsonguiConfigs/guiNDB.db- the latest file in
guiLogs/
For v2rayN control, run the widget under the same Windows account and privilege level as v2rayN. Mixed privilege levels can block UI Automation.
Happ UI Automation is also affected by Windows privilege isolation. The setup probe fails safely when the current window cannot be inspected.
Widget logs are written to the application config directory under:
v2rayn-widget/logs/widget.log
- separate subscription abstraction and client-specific implementation;
- additional adapters using the existing operational contract;
- eventual compatibility-field and legacy-command cleanup;
- product/repository naming cleanup after release validation.
- 0030: active selected-adapter context consistency.
- 0031: Happ toggle lifecycle hardening.
- 0032: auxiliary settings consistency.
- 0033: tray/native runtime consistency.
- 0034: asynchronous native ownership and warning-free quality gates.
- 0035: declared-surface, accessibility, Settings close ownership and Node 24 Actions audit.
- 0036: verified audit evidence alignment.
- 0037: auxiliary operation ownership and hidden-window reopen state.
- 0038: verified auxiliary lifecycle evidence alignment.
- 0039: Main, Settings, Debug and administrator relaunch operation ownership.
- 0041: Happ launch, Diagnostics open and Main height operation ownership.