Remove obsolete VPN proxy code
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 40 KiB |
@@ -1,188 +0,0 @@
|
||||
# UX/UI-аудит Windows-клиента
|
||||
|
||||
Дата: 2026-07-08
|
||||
|
||||
## Область аудита
|
||||
|
||||
Проверен текущий React UI `apps/windows-client` для Vite/Tauri как компактная Windows-утилита управления proxy-маршрутизацией приложений. Аудит выполнялся в browser-preview на `http://127.0.0.1:5174/`, поэтому нативные Tauri-команды были недоступны, а интерфейс показывал preview/runtime-ошибки. Все выводы ниже привязаны к скриншотам, снятым в этом прогоне.
|
||||
|
||||
## Цель пользователя
|
||||
|
||||
Главная задача пользователя - быстро управлять службами и понять:
|
||||
|
||||
- какие компоненты установлены;
|
||||
- какие службы запущены, остановлены или отсутствуют;
|
||||
- какое действие доступно прямо сейчас: установить, удалить, запустить, остановить, обновить, добавить или применить;
|
||||
- что сейчас маршрутизируется;
|
||||
- через какую цепочку компонентов идет трафик;
|
||||
- готовы ли ProxiFyre и опциональный Local sing-box;
|
||||
- можно ли безопасно применить изменения;
|
||||
- что делать дальше, если что-то сломано.
|
||||
|
||||
Цель по доступности: интерфейс должен быть управляемым с клавиатуры, с понятными статусами, читаемым восстановлением после ошибок, предсказуемыми focus states и устойчивой адаптацией к узким размерам Windows-окна.
|
||||
|
||||
## Доказательства
|
||||
|
||||
1. `01-summary-desktop.png` - панель "Сводка", desktop-ширина. Состояние: смешанное. Главный статус виден, но примененное состояние еще "загружается", а рядом уже показан бейдж "Совпадает".
|
||||
2. `02-proxifyre-desktop.png` - панель ProxiFyre, desktop-ширина. Состояние: в целом рабочее. Состав компонента и список приложений компактны, но главное действие apply доступно даже при отсутствующих prerequisites.
|
||||
3. `03-proxy-desktop.png` - панель "VPN / Прокси", desktop-ширина. Состояние: рабочее. Настройка маршрута понятна, но route path выглядит как вторичный текст, а apply-action выглядит валидным до того, как маршрут может успешно примениться.
|
||||
4. `04-proxy-validation-desktop.png` - невалидный proxy input. Состояние: хорошая база. Inline-валидация находится рядом с полем и отключает действие проверки.
|
||||
5. `05-summary-narrow.png` - панель "Сводка", узкая ширина. Состояние: напряженное. Контент перестраивается, но нижний log dock и длинные сообщения обрезают важную информацию.
|
||||
6. `06-proxifyre-narrow.png` - панель ProxiFyre, узкая ширина. Состояние: напряженное. Контролы складываются неплохо, но setup chips переполняются по горизонтали, а нижний dock конкурирует с основной задачей.
|
||||
|
||||
## Доменное направление
|
||||
|
||||
Ключевые понятия домена: цепочка маршрута, здоровье компонентов, локальный runtime, внешний endpoint, выбранные приложения, сгенерированный конфиг, граница apply/restart, диагностика.
|
||||
|
||||
Цветовой мир: темная Windows-оболочка, терминальный черный, зеленый для driver/service ready, amber для предупреждений, красный для блокеров/firewall, синий для links/actions, slate для config-файлов.
|
||||
|
||||
Сигнатурный элемент, который стоит усилить: `Service Control Row` - повторяемая строка компонента, где слева состояние службы, в центре человекочитаемый статус, справа одно главное действие и меню дополнительных действий. Route-chain readout тоже нужен, но как объяснение эффекта этих служб: `Apps -> ProxiFyre -> target -> VPN/server`.
|
||||
|
||||
Дефолты, которые стоит отбрасывать:
|
||||
|
||||
- generic dashboard cards -> service-control utility;
|
||||
- большая зеленая apply-кнопка всегда видна -> apply gated by readiness + inline blockers;
|
||||
- raw logs как главный error surface -> сначала человеческое recovery-сообщение, raw details вторым уровнем.
|
||||
- разрозненные кнопки и анимации -> shared component base с едиными variants/states/motion tokens.
|
||||
|
||||
## Сильные стороны
|
||||
|
||||
- Приложение уже ощущается как компактная desktop-утилита, а не как сайт. Фиксированный header, tabs, плотные панели и темная системная палитра подходят задаче.
|
||||
- Продуктовая модель сильная: ProxiFyre и Local sing-box разделены, sing-box не сделан обязательным.
|
||||
- Inline-валидация SOCKS5-поля расположена рядом с полем и отключает "Проверить", когда формат неверный.
|
||||
- Зона добавления приложения использует иконки с доступными labels и tooltip, поэтому плотный workflow остается сканируемым.
|
||||
- Для основных анимаций есть `prefers-reduced-motion`.
|
||||
- UI использует настоящие `button` и tab roles, а не click-only divs. Это хорошая база для доступности.
|
||||
|
||||
## UX-риски
|
||||
|
||||
1. Apply выглядит доступным, когда маршрут еще не actionable.
|
||||
- Доказательства: `02-proxifyre-desktop.png`, `03-proxy-desktop.png`.
|
||||
- ProxiFyre отсутствует и список приложений пуст, но "Обновить конфиг" / "Обновить маршрут" ярко-зеленые. Это провоцирует failed action вместо направленного setup.
|
||||
|
||||
2. Главная цепочка маршрута не является визуальным фокусом.
|
||||
- Доказательства: `01-summary-desktop.png`, `03-proxy-desktop.png`.
|
||||
- Самая важная mental model - путь трафика, но сейчас он показан plain text в таблице или вторичном блоке. Пользователь вынужден читать фрагменты статуса вместо того, чтобы сразу увидеть цепочку.
|
||||
|
||||
3. В "Сводке" есть противоречивое состояние.
|
||||
- Доказательство: `01-summary-desktop.png`.
|
||||
- "Состояние загружается" показано рядом с "Совпадает", а система одновременно говорит "Не настроено". Это может создать ощущение, что действий не требуется.
|
||||
|
||||
4. Preview/native command failures слишком сырые.
|
||||
- Доказательства: все скриншоты.
|
||||
- Dock показывает `Cannot read properties of undefined (reading 'invoke')`. Для разработчика это полезно, но как первичный пользовательский error surface это шум.
|
||||
|
||||
5. Bottom log dock конфликтует с узкой компоновкой.
|
||||
- Доказательства: `05-summary-narrow.png`, `06-proxifyre-narrow.png`.
|
||||
- Важные сообщения обрезаются до "Компонен..." и "Cannot read prop..."; dock постоянно занимает вертикальное место в и так коротком окне.
|
||||
|
||||
6. ProxiFyre setup chips плохо перестраиваются.
|
||||
- Доказательство: `06-proxifyre-narrow.png`.
|
||||
- Горизонтальная chip-лента скрывает третий dependency и ухудшает диагностическую ясность.
|
||||
|
||||
7. Терминология немного смешана.
|
||||
- Доказательства: `01-summary-desktop.png`, `03-proxy-desktop.png`.
|
||||
- `config`, `TCP check`, `VPN сервер`, `Local sing-box`, `ProxiFyre` - все эти термины допустимы, но нужен единый принцип: сначала пользовательский русский, технический идентификатор вторым уровнем.
|
||||
|
||||
8. Компонентная база пока не выражена как система.
|
||||
- Доказательства: `02-proxifyre-desktop.png`, `03-proxy-desktop.png`, `06-proxifyre-narrow.png`.
|
||||
- Кнопки "Обновить", "Установить", "Открыть", "Проверить", add-icon buttons и service actions выглядят близко, но пока не читаются как строгая система variants. Из-за этого сложно гарантировать одинаковые hover/loading/disabled/focus states и одинаковую motion-модель.
|
||||
|
||||
## Риски доступности
|
||||
|
||||
- Tablist использует `role="tab"`, но не видно поддержки ожидаемого arrow-key behavior и roving tab index. Пользователю с клавиатурой, вероятно, придется проходить все tabs через Tab вместо Left/Right.
|
||||
- Focus visibility есть через browser defaults, но визуально она тяжелая и не согласована со стилем приложения. Нужен отдельный `:focus-visible` token для buttons, tabs, inputs и icon controls.
|
||||
- Status dots сильно полагаются на цвет. Стоит дублировать состояние видимым текстом или `aria-label`/screen-reader text там, где текст рядом не объясняет статус.
|
||||
- Footer использует `aria-live`, но повторяющиеся raw runtime errors могут быть шумными для assistive tech. Сначала стоит объявлять короткий статус, а подробный error text держать за "Посмотреть".
|
||||
- На узкой ширине truncation может скрывать actionable-часть сообщений и button labels.
|
||||
- Скриншоты не доказывают полный keyboard order, screen-reader output или contrast ratios. Для этого нужен интерактивный accessibility pass.
|
||||
|
||||
## План улучшений
|
||||
|
||||
### P0 - Сделать service-control flow заслуживающим доверия
|
||||
|
||||
1. Ввести shared component base:
|
||||
- `Button` с variants: `primary`, `neutral`, `add`, `danger`, `icon`;
|
||||
- `Tabs` с единым keyboard behavior и animation contract;
|
||||
- `ServiceControlRow` для ProxiFyre, Local sing-box и будущих служб;
|
||||
- `StatusPill`, `Field`, `ActionMenu`, `LogDock`;
|
||||
- единые states: default, hover, active, focus-visible, disabled, loading.
|
||||
|
||||
2. Нормализовать motion tokens:
|
||||
- button press: 100-140ms;
|
||||
- tab switch: 180-240ms, только `opacity` + `transform`;
|
||||
- popover/menu: 150-180ms;
|
||||
- service operation: видимый loading state, чтобы интерфейс не ощущался зависшим;
|
||||
- не использовать `transition: all`.
|
||||
|
||||
3. Заменить raw preview/native invocation failures на дружелюбное состояние:
|
||||
- "Desktop-команды недоступны в browser preview. Запусти через Tauri для управления службами."
|
||||
- Raw error оставить только в деталях лога.
|
||||
|
||||
4. Заблокировать primary apply actions до готовности:
|
||||
- disabled + explanation, когда список приложений пуст;
|
||||
- disabled + explanation, когда ProxiFyre отсутствует;
|
||||
- disabled + explanation, когда выбран local route без установленного/запущенного sing-box или выбранного сервера;
|
||||
- "Открыть конфиг" оставить вторичным действием, не равным apply по весу.
|
||||
|
||||
5. Исправить язык summary-state:
|
||||
- использовать взаимоисключающие состояния: "Проверяю", "Не готово", "Готово к применению", "Применено", "Есть черновик";
|
||||
- не показывать "Совпадает", пока saved/applied state реально не загружен.
|
||||
|
||||
### P1 - Пересобрать главную mental model
|
||||
|
||||
6. Вынести route-chain component как объясняющий элемент:
|
||||
- узел `Apps` с количеством;
|
||||
- узел `ProxiFyre` со статусом installed/running;
|
||||
- узел `Target`: external SOCKS5 или Local sing-box;
|
||||
- узел `Server`, когда активен local sing-box;
|
||||
- каждый сломанный узел показывает одно следующее действие.
|
||||
|
||||
7. Переработать "Сводку" в command center:
|
||||
- сверху: route-chain и readiness системы;
|
||||
- посередине: applied vs draft diff, только если есть отличие;
|
||||
- снизу: максимум два next actions;
|
||||
- длинные config paths и подробный состав компонентов убрать из первого взгляда.
|
||||
|
||||
8. Разделить "настроить маршрут" и "применить маршрут":
|
||||
- Proxy panel отвечает за endpoint choice и connection check;
|
||||
- ProxiFyre panel отвечает за app selection и service readiness;
|
||||
- Summary подтверждает объединенный маршрут и применяет только при готовности.
|
||||
|
||||
### P2 - Усилить responsive и component craft
|
||||
|
||||
7. Превратить setup chips в wrapping checklist на узких ширинах.
|
||||
|
||||
8. Сделать log dock адаптивным:
|
||||
- desktop: persistent compact dock подходит;
|
||||
- narrow: collapsed toast/details sheet вместо постоянного full-width footer.
|
||||
|
||||
9. Определить design tokens:
|
||||
- surfaces: canvas, panel, inset, elevated;
|
||||
- text: primary, secondary, muted, disabled;
|
||||
- status: ready, warning, blocked, checking;
|
||||
- focus ring и border intensities.
|
||||
|
||||
10. Стандартизировать copy:
|
||||
- последовательно использовать "конфиг" или "конфигурация";
|
||||
- заменить "TCP check" на "TCP-проверка";
|
||||
- `Local sing-box` оставить техническим именем компонента, но в user-facing headings связывать с "локальный прокси".
|
||||
|
||||
### P3 - Verification pass
|
||||
|
||||
11. Добавить focused interaction QA:
|
||||
- keyboard tab order;
|
||||
- arrow-key tab navigation;
|
||||
- focus return из menus/popovers;
|
||||
- disabled-action explanations;
|
||||
- empty, loading, error, missing-component, ready и unapplied-change states.
|
||||
|
||||
12. Добавить responsive visual snapshots:
|
||||
- 1280x720 desktop;
|
||||
- 800x600 compact desktop;
|
||||
- 420x720 narrow window;
|
||||
- длинные proxy/server names и длинные Windows paths.
|
||||
|
||||
## Рекомендуемый первый redesign slice
|
||||
|
||||
Сначала стоит сделать shared UI foundation: `Button`, `Tabs`, `ServiceControlRow`, `StatusPill`, `Field`, `ActionMenu`, `LogDock` и motion tokens. После этого собрать ProxiFyre и Local sing-box через один `ServiceControlRow`, а route-chain использовать как объясняющий компонент в "Сводке" и "VPN / Прокси". Такой порядок сначала стабилизирует поведение кнопок/табы/анимации, затем улучшит ориентацию и recovery без переписывания всего UI.
|
||||
@@ -1,82 +0,0 @@
|
||||
# Windows Client Service-Control UI System Evidence
|
||||
|
||||
## Acceptance Evidence
|
||||
|
||||
- Desktop Summary screenshot: `docs/goals/windows-client-service-control-ui-system/evidence/01-summary-desktop.png`
|
||||
- Shows shared tabs, shared refresh button, and friendly preview error: `Desktop-команды недоступны`.
|
||||
- Desktop ProxiFyre screenshot: `docs/goals/windows-client-service-control-ui-system/evidence/02-proxifyre-desktop.png`
|
||||
- Shows ProxiFyre rendered through the shared service-control row pattern.
|
||||
- Shows apply blocker: `ProxiFyre не установлен`.
|
||||
- Shows `Обновить конфиг` disabled instead of green/ready.
|
||||
- Desktop VPN / Proxy screenshot: `docs/goals/windows-client-service-control-ui-system/evidence/03-proxy-desktop.png`
|
||||
- Shows route mode buttons through shared button variants.
|
||||
- Shows apply blocker before route apply.
|
||||
- Narrow ProxiFyre screenshot: `docs/goals/windows-client-service-control-ui-system/evidence/04-proxifyre-narrow.png`
|
||||
- Shows service row and setup checklist reflow at 420px.
|
||||
- Shows compact log dock title instead of long raw runtime error text.
|
||||
|
||||
Captured DOM state from Browser preview:
|
||||
|
||||
```json
|
||||
{
|
||||
"proxState": {
|
||||
"disabledApply": true,
|
||||
"blockerText": true,
|
||||
"friendlyError": true,
|
||||
"rawInvokeCurrent": false
|
||||
},
|
||||
"routeState": {
|
||||
"externalButtonClass": "ui-button ui-button--primary ui-button--md",
|
||||
"externalAriaPressed": "true"
|
||||
},
|
||||
"narrowState": {
|
||||
"width": 420,
|
||||
"hasHorizontalOverflow": false,
|
||||
"setupStripOverflow": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Native/elevated install/start/stop/uninstall service actions were not executed in this evidence pass. They are implemented through the existing handlers and shared callbacks, but real elevated service execution remains `implemented but unproven`.
|
||||
|
||||
## Verification
|
||||
|
||||
Build was run with bundled Node because system `npm` is not in PATH in this Codex shell.
|
||||
|
||||
```powershell
|
||||
& 'C:\Users\PC\.cache\codex-runtimes\codex-primary-runtime\dependencies\node\bin\node.exe' '.\node_modules\typescript\bin\tsc'
|
||||
& 'C:\Users\PC\.cache\codex-runtimes\codex-primary-runtime\dependencies\node\bin\node.exe' '.\node_modules\vite\bin\vite.js' build
|
||||
```
|
||||
|
||||
Relevant output:
|
||||
|
||||
```text
|
||||
vite v7.3.6 building client environment for production...
|
||||
✓ 1800 modules transformed.
|
||||
✓ built in 1.14s
|
||||
```
|
||||
|
||||
Cutover check:
|
||||
|
||||
```powershell
|
||||
rg -n 'transition:\s*all|className=.*(apply-button|service-button|ghost-button|add-tile|open-config-button)' apps\windows-client\src
|
||||
```
|
||||
|
||||
Relevant output:
|
||||
|
||||
```text
|
||||
no legacy className or transition: all matches
|
||||
```
|
||||
|
||||
Notes:
|
||||
- `pnpm run build` was attempted through the bundled runtime, but it began reinstalling `node_modules` because dependencies were originally installed by another package manager. The process was stopped; no package or lockfile changes were recorded by git.
|
||||
- Browser preview was served from `http://127.0.0.1:5174/`.
|
||||
|
||||
## Review Notes
|
||||
|
||||
- Visual self-review found that active route mode lost its active styling after switching to shared `Button`; CSS was corrected with `.route-switch .ui-button--primary`.
|
||||
- Visual self-review found setup chips still horizontally scrolled at 420px; narrow CSS was corrected to wrap `.setup-strip-items`.
|
||||
- Residual product issue from the earlier audit remains: Summary still has `Состояние загружается` beside `Совпадает`. That state language was outside the implemented high-value slice and should be handled in a follow-up Summary view-model cleanup.
|
||||
- POST plan review: aligned. Implementation stayed inside the approved ownership and contract boundaries: shared UI components are presentational, `App.tsx` still owns orchestration, and Tauri wrappers remain the command boundary.
|
||||
- Correctness review: no blocker found. Real elevated service actions were not executed, so that lane remains `implemented but unproven`.
|
||||
- Maintainability review: no blocker found. Old dominant `className` paths for apply/service/ghost/add/open buttons were displaced from `App.tsx`; stale legacy CSS selectors remain in `app.css` as non-dominant compatibility residue and should be removed in a follow-up CSS pruning pass if desired.
|
||||
@@ -1,11 +0,0 @@
|
||||
# Goal: Windows Client Service-Control UI System
|
||||
|
||||
Use Krypton Execution to execute `docs/goals/windows-client-service-control-ui-system/PLAN.md`.
|
||||
|
||||
Core rules:
|
||||
- Treat PLAN.md as the source plan.
|
||||
- Preserve intent, ownership, contract, cutover, evidence, and kill criteria.
|
||||
- Do not add a new dominant path without deleting, redirecting, demoting, or shimming the displaced path.
|
||||
- Capture acceptance evidence from the target perspective and record it in EVIDENCE.md.
|
||||
- Say "implemented but unproven" if that evidence cannot be captured.
|
||||
|
||||
@@ -1,503 +0,0 @@
|
||||
# Windows Client Service-Control UI System Implementation Plan
|
||||
|
||||
**Intent:** Превратить текущий Windows-клиент в простую service-control утилиту с единой компонентной базой, предсказуемыми состояниями кнопок/табов/служебных строк, readiness-блокерами и аккуратными motion tokens.
|
||||
**Current Behavior:** `apps/windows-client/src/app/App.tsx` и `apps/windows-client/src/styles/app.css` остаются крупным монолитом. Кнопки, табы, service cards, add controls, apply/open actions, log dock, validation и анимации задаются ad hoc через локальные JSX-блоки и классы вроде `service-button`, `apply-button`, `ghost-button`, `add-tile`, `route-switch`, `finder-card`, `log-dock`.
|
||||
**Expected Outcome:** Пользователь видит плотную Windows-утилиту, где ProxiFyre и Local sing-box управляются через один повторяемый service-control паттерн, все кнопки имеют понятные variants/states, apply недоступен до готовности prerequisites, ошибки preview/native команд показываются человечески, а вкладки/меню/loading состояния двигаются одинаково и не создают ощущения зависшего UI.
|
||||
**Target-Perspective Output:** Пользователь открывает клиент и за несколько секунд понимает, какие компоненты установлены, какие службы запущены/остановлены/отсутствуют, какую одну кнопку можно нажать дальше, почему apply заблокирован, и где посмотреть детали. На desktop и узкой ширине интерфейс не обрезает ключевые действия и не показывает raw runtime errors как основной текст.
|
||||
**Truth Owner:** Источник правды для профилей, targets, компонентов, Local sing-box, generated config и apply остается в Rust/Tauri командах и JSON-файлах под `C:\ProgramData\VpnProxy`. Источник правды для UI-паттернов и визуальных контрактов после этого плана: `.interface-design/system.md` и shared UI components под `apps/windows-client/src/ui`.
|
||||
**Contract Boundary:** React UI вызывает typed wrappers из `apps/windows-client/src/api/tauriCommands.ts`. Shared UI components не вызывают Tauri напрямую и не владеют persistent state; они получают props, emit callbacks и отображают states. `App.tsx`/panel containers владеют orchestration, draft state, loading state, readiness blockers и вызовами существующих handlers.
|
||||
**Cutover:** Старые ad hoc JSX/CSS paths для кнопок, табов, service cards, log dock, fields и menus постепенно заменяются shared components. После cutover в `App.tsx` не должно оставаться нового прямого `<button className="apply-button|service-button|ghost-button|add-tile|open-config-button">` как доминирующего паттерна; старые классы либо удалены, либо превращены в internal classes shared components.
|
||||
**Displaced Path:** Вытесняется путь "каждый render-блок сам рисует свою кнопку/таб/service card/loading/error". Также демотируется route-chain-first направление: route chain остается объясняющим элементом, но основная модель UI - управление службами и их состояниями.
|
||||
**Value Density:** Самый ценный срез: `Button`/`IconButton`, `Tabs`, `ServiceControlRow`, `LogDock`, readiness blockers для apply, friendly preview error. Это сразу исправляет доверие к действиям и закладывает базу для дальнейшего разбиения панелей.
|
||||
**Evidence Gate:** Приемка требует `npm run build` плюс пользовательские доказательства: desktop и narrow screenshots для Summary, ProxiFyre, VPN/Proxy; screenshot или DOM-state, что apply disabled с explanation при missing ProxiFyre/empty apps; screenshot, что raw `invoke` preview error не показывается как главный текст.
|
||||
**Acceptance Evidence:** Build проходит; visual evidence показывает единые button variants/states, tabs с keyboard/active behavior, ServiceControlRow для ProxiFyre и Local sing-box, disabled apply blockers, adaptive log dock, friendly preview/native error. Если реальная elevated Tauri установка/удаление служб не проверялась, service execution lane помечается как `implemented but unproven`.
|
||||
**Evidence Lane:** Доказательства исполнения записывать в `docs/goals/windows-client-service-control-ui-system/EVIDENCE.md`.
|
||||
**Kill Criteria:** Нет второго источника UI truth вне shared components; нет прямой записи generated config из UI; нет скрытой установки компонентов при apply/open/refresh; нет новых изменений в root `src/web/*` или `src/server/*`; нет raw preview `Cannot read properties...invoke` как основного user-facing сообщения; нет зеленого primary apply без readiness.
|
||||
**Architecture Slice:** Создать shared UI layer под `apps/windows-client/src/ui`; при необходимости создать view-model helpers под `apps/windows-client/src/app`; модифицировать `apps/windows-client/src/app/App.tsx` и `apps/windows-client/src/styles/app.css`; не менять backend, кроме точечных type/import изменений, если вскроется compile-only необходимость.
|
||||
**Plan Review Gate:** Requires PRE review before execution.
|
||||
|
||||
## Outcome Contract
|
||||
|
||||
Plan title: Windows Client Service-Control UI System
|
||||
|
||||
Intent: стабилизировать UI как простую утилиту управления службами, а не dashboard.
|
||||
|
||||
Current behavior: большие участки JSX и CSS повторяют однотипные buttons, service status cards, tabs, fields, menus и log surfaces без общего контракта.
|
||||
|
||||
Expected outcome: shared UI foundation контролирует внешний вид, states, motion и accessibility для повторяемых элементов; ProxiFyre и Local sing-box отображаются через один service-control паттерн; apply actions gated by readiness.
|
||||
|
||||
Target-perspective output: пользователь видит понятные состояния "установлено/не установлено/запущено/остановлено/проверяю/ошибка", одну главную кнопку на службу, объяснение блокеров и одинаковые transitions при переключении вкладок/меню/loading.
|
||||
|
||||
Truth owner:
|
||||
- Data truth: Rust/Tauri commands + `C:\ProgramData\VpnProxy`.
|
||||
- UI pattern truth: `.interface-design/system.md` + `apps/windows-client/src/ui/*`.
|
||||
- Orchestration truth: `apps/windows-client/src/app/App.tsx` and extracted app-level helpers.
|
||||
|
||||
Contract boundary:
|
||||
- `src/ui/*` is presentational and callback-driven.
|
||||
- `src/app/*` containers compose view models, draft state and command handlers.
|
||||
- `src/api/tauriCommands.ts` remains the typed command boundary.
|
||||
|
||||
Cutover:
|
||||
- First introduce shared components without changing backend behavior.
|
||||
- Then migrate existing render functions to shared components.
|
||||
- Then remove/demote old CSS selectors so new work cannot keep using ad hoc paths.
|
||||
|
||||
Displaced path:
|
||||
- Direct ad hoc buttons/tabs/service-card styles in `App.tsx`/`app.css`.
|
||||
- Raw runtime error text as primary user-facing status.
|
||||
- Always-green apply actions regardless of prerequisites.
|
||||
|
||||
Value density:
|
||||
- Strongest first slice is shared component layer + apply blockers + friendly preview error.
|
||||
- Panel extraction is valuable only after component contracts exist.
|
||||
|
||||
Evidence gate:
|
||||
- Build proof.
|
||||
- Visual proof at desktop and narrow widths.
|
||||
- Interaction proof for disabled apply reasons, tab focus/keyboard behavior, service action loading state and log dock behavior.
|
||||
|
||||
Acceptance evidence:
|
||||
- `cd apps/windows-client && npm run build`.
|
||||
- Browser/Tauri screenshots saved under this goal's evidence folder or linked from `EVIDENCE.md`.
|
||||
- Notes of any unverified elevated service operations.
|
||||
|
||||
Evidence lane:
|
||||
- `docs/goals/windows-client-service-control-ui-system/EVIDENCE.md`.
|
||||
|
||||
Kill criteria:
|
||||
- If old button classes remain public and newly used after migration, the cutover is incomplete.
|
||||
- If `App.tsx` grows with more ad hoc JSX instead of shrinking or delegating to shared components, stop and refactor the slice.
|
||||
- If summary/route work starts before shared buttons/tabs/service rows, stop and restore priority.
|
||||
|
||||
Non-goals:
|
||||
- No backend service rewrite.
|
||||
- No new route modes.
|
||||
- No new installer behavior.
|
||||
- No root web/server redesign.
|
||||
- No full visual rebrand.
|
||||
- No dependency-heavy component library unless explicitly approved.
|
||||
|
||||
Risk if wrong:
|
||||
- The UI may look slightly cleaner but remain structurally unmaintainable, with duplicated states and inconsistent actions. The user will still see green buttons that fail, raw preview errors, and inconsistent loading/disabled/motion states.
|
||||
|
||||
## Architecture Slice
|
||||
|
||||
Files to create:
|
||||
- `apps/windows-client/src/ui/Button.tsx`
|
||||
- `apps/windows-client/src/ui/IconButton.tsx`
|
||||
- `apps/windows-client/src/ui/Tabs.tsx`
|
||||
- `apps/windows-client/src/ui/ServiceControlRow.tsx`
|
||||
- `apps/windows-client/src/ui/StatusPill.tsx`
|
||||
- `apps/windows-client/src/ui/Field.tsx`
|
||||
- `apps/windows-client/src/ui/ActionMenu.tsx`
|
||||
- `apps/windows-client/src/ui/LogDock.tsx`
|
||||
- `apps/windows-client/src/ui/index.ts`
|
||||
- `apps/windows-client/src/app/readiness.ts`
|
||||
- `apps/windows-client/src/app/viewModel.ts` or smaller helpers if they reduce `App.tsx` without creating duplicate truth.
|
||||
|
||||
Files to modify:
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
- `apps/windows-client/src/api/tauriCommands.ts` only for compile-safe preview/error wrapper changes if needed.
|
||||
- `apps/windows-client/src/domain/types.ts` only if component/view-model types need shared aliases.
|
||||
- `docs/goals/windows-client-service-control-ui-system/EVIDENCE.md` during execution.
|
||||
|
||||
Files to avoid:
|
||||
- `src/web/*`
|
||||
- `src/server/*`
|
||||
- Docker/compose/entrypoint files.
|
||||
- Installer scripts.
|
||||
- Rust backend files unless a compile break proves a tiny typed-boundary fix is necessary.
|
||||
- Existing goal packages, except cross-reference notes in evidence.
|
||||
|
||||
Source of truth:
|
||||
- UI system: `.interface-design/system.md`.
|
||||
- Profiles/targets/components/subscription/activity/generated config: Rust/Tauri commands and `C:\ProgramData\VpnProxy`.
|
||||
- Current draft state: React state in app containers only.
|
||||
|
||||
Read path:
|
||||
- `App.tsx` calls `getSavedState`, `getComponents`, `getProxiFyreSetupStatus`, `getSingBoxStatus`, `getSingBoxSetupStatus`.
|
||||
- View-model helpers derive service states, button readiness, route summary and blocker copy from existing state.
|
||||
- Shared components receive already-derived props and do no data fetching.
|
||||
|
||||
Write path:
|
||||
- Existing handlers remain the only write path: install/start/stop/uninstall service handlers, app add/remove handlers, route mode/proxy/subscription/server handlers, `updateConfig`, `openConfig`.
|
||||
- Shared components only call callbacks passed by containers.
|
||||
- Apply actions call `updateConfig` only when readiness says they are actionable.
|
||||
|
||||
Contract boundary:
|
||||
- `Button` owns variants/states/loading/disabled look, not business readiness.
|
||||
- `ServiceControlRow` owns layout for a service, not installing/starting logic.
|
||||
- `Tabs` owns keyboard behavior and active styling, not panel content.
|
||||
- `LogDock` owns display/collapse/history behavior, not logging policy.
|
||||
- `readiness.ts` owns blocker computation and copy.
|
||||
|
||||
Integration points:
|
||||
- ProxiFyre row uses existing `proxyfier`, `setupStatus`, `serviceAction`, `installProxiFyrePackage`, `setProxiFyreServiceRunning`, `uninstallProxiFyrePackage`.
|
||||
- Local sing-box row uses existing `singbox`, `singBoxSetupStatus`, `singBoxStatus`, `singBoxAction`, `installSingBoxPackage`, `setSingBoxServiceRunning`, `uninstallSingBoxPackage`.
|
||||
- App list uses existing `items`, `addItem`, `removeItem`, `pickAndAddItem`, `isProcessInputOpen`, `processInput`.
|
||||
- Route panel uses existing `routeMode`, `proxyInput`, `proxyPing`, `pingExternalProxy`, subscription/server handlers.
|
||||
- Log dock uses existing `logEntries`, `activeLog`, `isLogOpen`.
|
||||
|
||||
Migration/cutover:
|
||||
- Introduce shared components alongside old CSS.
|
||||
- Migrate one component family at a time.
|
||||
- After migration, delete or privatize old selectors from `app.css`.
|
||||
- Keep build green after each task.
|
||||
- Do not split backend concerns into UI components.
|
||||
|
||||
Displaced path:
|
||||
- `renderTabs` local tab button markup.
|
||||
- `renderProxiFyreCard` and `renderSingBoxCard` duplicated finder/service-card markup.
|
||||
- `renderApplyActions` always-green apply command row.
|
||||
- `log-dock` raw error display.
|
||||
- Direct CSS button families: `.ghost-button`, `.service-button`, `.apply-button`, `.open-config-button`, `.add-tile`, `.route-switch button`.
|
||||
|
||||
Acceptance evidence gate:
|
||||
- Visual proof is required because this is UI/system work.
|
||||
- Build proof alone is not enough.
|
||||
- If Browser preview cannot prove native service actions, capture preview proof and mark native actions `implemented but unproven`.
|
||||
|
||||
## UI Contract
|
||||
|
||||
### Button Variants
|
||||
|
||||
`Button` must support:
|
||||
- `primary`: one main ready action; green only when action is safe and ready.
|
||||
- `neutral`: refresh/open/cancel/secondary.
|
||||
- `add`: add process/EXE/folder/target; icon-first.
|
||||
- `danger`: stop/delete/uninstall/destructive.
|
||||
- `icon`: square icon-only action with `aria-label` and `title`/tooltip.
|
||||
|
||||
Required states:
|
||||
- default
|
||||
- hover
|
||||
- active
|
||||
- focus-visible
|
||||
- disabled
|
||||
- loading
|
||||
|
||||
Loading text should name the action: `Проверяю`, `Устанавливаю`, `Запускаю`, `Останавливаю`, `Применяю`, not only `...`.
|
||||
|
||||
### Tabs
|
||||
|
||||
`Tabs` must support:
|
||||
- `role="tablist"`, `role="tab"`, `role="tabpanel"`.
|
||||
- Left/Right arrow navigation.
|
||||
- Enter/Space activation if focus and selection are separated.
|
||||
- Active underline.
|
||||
- 180-240ms panel transition using only `opacity` and `transform`.
|
||||
- Reduced motion support.
|
||||
|
||||
### ServiceControlRow
|
||||
|
||||
`ServiceControlRow` props should express:
|
||||
- service name.
|
||||
- state: `checking | missing | installed | running | stopped | error`.
|
||||
- title and detail.
|
||||
- primary action label/loading/disabled.
|
||||
- optional secondary menu actions.
|
||||
- optional expanded details/checklist.
|
||||
- optional inline actions/details toggle.
|
||||
|
||||
It must be generic enough for both ProxiFyre and Local sing-box.
|
||||
|
||||
### Readiness Blockers
|
||||
|
||||
Apply readiness must be computed before rendering the action:
|
||||
- no apps -> blocked with `Добавь хотя бы одно приложение`.
|
||||
- ProxiFyre missing -> blocked with `Установи ProxiFyre`.
|
||||
- local route + sing-box missing -> blocked with `Установи Local sing-box`.
|
||||
- local route + no selected server -> blocked with `Выбери сервер Local sing-box`.
|
||||
- external route + invalid proxy -> blocked with accepted format copy.
|
||||
- pending service action/apply -> loading and disabled.
|
||||
|
||||
Blocked apply must not be bright green.
|
||||
|
||||
### Friendly Preview Error
|
||||
|
||||
Browser-preview/native command errors should render as:
|
||||
- title: `Desktop-команды недоступны`
|
||||
- text: `Запусти клиент через Tauri, чтобы управлять службами и применять конфиг.`
|
||||
- raw error only inside log details/history.
|
||||
|
||||
### Motion Tokens
|
||||
|
||||
CSS variables:
|
||||
- `--motion-fast: 120ms`
|
||||
- `--motion-standard: 180ms`
|
||||
- `--motion-panel: 220ms`
|
||||
- `--ease-out: cubic-bezier(0.23, 1, 0.32, 1)`
|
||||
- `--ease-standard: cubic-bezier(0.22, 0.72, 0.18, 1)`
|
||||
|
||||
Do not use `transition: all`.
|
||||
|
||||
## Tasks
|
||||
|
||||
### Task 1: Create Shared UI Foundation
|
||||
|
||||
Allowed files:
|
||||
- `apps/windows-client/src/ui/Button.tsx`
|
||||
- `apps/windows-client/src/ui/IconButton.tsx`
|
||||
- `apps/windows-client/src/ui/Tabs.tsx`
|
||||
- `apps/windows-client/src/ui/StatusPill.tsx`
|
||||
- `apps/windows-client/src/ui/Field.tsx`
|
||||
- `apps/windows-client/src/ui/index.ts`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
|
||||
Scope:
|
||||
- Create presentational components only.
|
||||
- Add CSS tokens/classes for button variants, tab states, focus-visible, loading and reduced motion.
|
||||
- Do not wire business handlers yet beyond simple props.
|
||||
|
||||
Expected output:
|
||||
- Components compile under strict TypeScript.
|
||||
- No backend or app state behavior changes.
|
||||
|
||||
Verification command:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
|
||||
Acceptance evidence:
|
||||
- Build output recorded in `EVIDENCE.md`.
|
||||
- Short note listing component contracts and CSS tokens/classes.
|
||||
|
||||
Parallel-safe: no. This establishes shared write scope.
|
||||
|
||||
### Task 2: Replace Tabs And Basic Buttons
|
||||
|
||||
Allowed files:
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
- `apps/windows-client/src/ui/*`
|
||||
|
||||
Scope:
|
||||
- Replace local `renderTabs` markup with `Tabs`.
|
||||
- Replace header refresh, summary navigation buttons, route switch buttons, neutral/open buttons and add icon buttons with shared `Button`/`IconButton`.
|
||||
- Preserve active panel state and current handlers.
|
||||
|
||||
Expected output:
|
||||
- Tabs have consistent ARIA and keyboard behavior.
|
||||
- Buttons share variants and loading labels.
|
||||
- No behavior regression in panel switching or refresh.
|
||||
|
||||
Verification command:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
|
||||
Acceptance evidence:
|
||||
- Screenshot or DOM note showing tab ARIA/active state.
|
||||
- Desktop screenshot showing migrated button variants.
|
||||
|
||||
Parallel-safe: no. Touches `App.tsx` and shared UI.
|
||||
|
||||
### Task 3: Add Readiness Model And Gate Apply Actions
|
||||
|
||||
Allowed files:
|
||||
- `apps/windows-client/src/app/readiness.ts`
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
|
||||
Scope:
|
||||
- Create pure helper functions for apply blockers and action labels.
|
||||
- Replace always-green `renderApplyActions` behavior with readiness-aware disabled/loading/blocker UI.
|
||||
- Keep `updateConfig` validation as backend/handler safety, but do not let obviously blocked actions look ready.
|
||||
|
||||
Expected output:
|
||||
- Apply disabled with explanation when ProxiFyre is missing, apps empty, external proxy invalid, local route lacks sing-box/server, or service/apply action is running.
|
||||
- Primary green appears only when action is ready.
|
||||
|
||||
Verification command:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
|
||||
Acceptance evidence:
|
||||
- Screenshot/state showing disabled apply + blocker copy in missing ProxiFyre/empty apps preview state.
|
||||
- Note that `updateConfig` still validates at action time.
|
||||
|
||||
Parallel-safe: no. Depends on shared buttons and touches core apply behavior.
|
||||
|
||||
### Task 4: Implement ServiceControlRow And Migrate ProxiFyre
|
||||
|
||||
Allowed files:
|
||||
- `apps/windows-client/src/ui/ServiceControlRow.tsx`
|
||||
- `apps/windows-client/src/ui/ActionMenu.tsx`
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
|
||||
Scope:
|
||||
- Create generic `ServiceControlRow`.
|
||||
- Migrate `renderProxiFyreCard` and setup strip/details into this pattern.
|
||||
- Preserve install/start/stop/uninstall confirm boundary and loading states.
|
||||
- Keep ProxiFyre setup checklist readable on narrow widths.
|
||||
|
||||
Expected output:
|
||||
- ProxiFyre service state row uses the generic component.
|
||||
- The old ProxiFyre-specific button/card markup is removed or demoted.
|
||||
|
||||
Verification command:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
|
||||
Acceptance evidence:
|
||||
- Desktop and narrow screenshots of ProxiFyre panel.
|
||||
- Note showing one primary service action plus overflow menu.
|
||||
|
||||
Parallel-safe: no. Touches `App.tsx`, service UI and CSS.
|
||||
|
||||
### Task 5: Migrate Local Sing-box To ServiceControlRow
|
||||
|
||||
Allowed files:
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
- `apps/windows-client/src/ui/ServiceControlRow.tsx`
|
||||
- `apps/windows-client/src/ui/ActionMenu.tsx`
|
||||
|
||||
Scope:
|
||||
- Reuse `ServiceControlRow` for Local sing-box.
|
||||
- Preserve setup details, info popover/actions, subscription workspace, server list and install note.
|
||||
- Keep Local sing-box controls only in VPN/Proxy context, unless already present by selected route.
|
||||
|
||||
Expected output:
|
||||
- Local sing-box service controls visually and behaviorally match ProxiFyre.
|
||||
- No duplicate service-control patterns remain for sing-box.
|
||||
|
||||
Verification command:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
|
||||
Acceptance evidence:
|
||||
- Screenshot of VPN/Proxy local route state or preview missing state.
|
||||
- Note confirming ProxiFyre and sing-box share the same component.
|
||||
|
||||
Parallel-safe: no. Depends on Task 4.
|
||||
|
||||
### Task 6: Friendly LogDock And Preview Error Handling
|
||||
|
||||
Allowed files:
|
||||
- `apps/windows-client/src/ui/LogDock.tsx`
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
- `apps/windows-client/src/api/tauriCommands.ts` only if a tiny safe error-normalization helper is required.
|
||||
|
||||
Scope:
|
||||
- Move log dock rendering into shared `LogDock`.
|
||||
- Collapse/adapt it on narrow widths.
|
||||
- Normalize preview/native `invoke` failure to friendly title/text while preserving raw details in history.
|
||||
- Keep `aria-live` concise.
|
||||
|
||||
Expected output:
|
||||
- Main footer no longer shows raw `Cannot read properties of undefined (reading 'invoke')` as primary text.
|
||||
- Narrow width does not hide the primary app task behind long raw error text.
|
||||
|
||||
Verification command:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
|
||||
Acceptance evidence:
|
||||
- Browser-preview screenshot showing friendly desktop-command message.
|
||||
- Narrow screenshot showing adaptive/collapsed log behavior.
|
||||
|
||||
Parallel-safe: no. Touches global app surface.
|
||||
|
||||
### Task 7: Extract Panel/View Helpers Without Moving Truth
|
||||
|
||||
Allowed files:
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/app/viewModel.ts`
|
||||
- Optional pure panel files under `apps/windows-client/src/app/panels/*` if and only if prop boundaries are clear.
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
|
||||
Scope:
|
||||
- Extract pure view-model helpers for summary/system state, route labels, service labels and display copy.
|
||||
- Optionally split large panel JSX into pure components that receive props/callbacks.
|
||||
- Do not move Tauri command calls into presentational components.
|
||||
- Do not create duplicate React state for profiles/targets/components.
|
||||
|
||||
Expected output:
|
||||
- `App.tsx` becomes smaller and more orchestration-focused.
|
||||
- UI components stay reusable and business state remains in containers/helpers.
|
||||
|
||||
Verification command:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
|
||||
Acceptance evidence:
|
||||
- Note listing extracted helpers/components and confirming no duplicate truth path.
|
||||
|
||||
Parallel-safe: no. Refactor touches core composition.
|
||||
|
||||
### Task 8: Motion, Responsive And CSS Cutover Cleanup
|
||||
|
||||
Allowed files:
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/ui/*`
|
||||
|
||||
Scope:
|
||||
- Replace one-off transitions with motion variables.
|
||||
- Remove or privatize old selectors after migration.
|
||||
- Ensure setup checklists wrap on narrow widths.
|
||||
- Ensure text/path/server names wrap or truncate intentionally.
|
||||
- Ensure no `transition: all`.
|
||||
|
||||
Expected output:
|
||||
- Consistent animation durations/easing.
|
||||
- No layout overlap on 1280x720, 800x600, 420x720.
|
||||
- Old ad hoc public selector families are not the dominant styling path.
|
||||
|
||||
Verification command:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
- `rg -n "transition:\\s*all|className=\"(apply-button|service-button|ghost-button|add-tile|open-config-button)" apps/windows-client/src`
|
||||
|
||||
Acceptance evidence:
|
||||
- Desktop + narrow screenshots.
|
||||
- `rg` output or note proving no new ad hoc button paths remain.
|
||||
|
||||
Parallel-safe: no. Final CSS integration pass.
|
||||
|
||||
### Task 9: Final Verification And Evidence
|
||||
|
||||
Allowed files:
|
||||
- `docs/goals/windows-client-service-control-ui-system/EVIDENCE.md`
|
||||
|
||||
Scope:
|
||||
- Record final build/test commands and outputs.
|
||||
- Capture visual evidence for Summary, ProxiFyre, VPN/Proxy at desktop and narrow widths.
|
||||
- Record interactive evidence for tabs keyboard behavior, disabled apply blocker, service action loading state and friendly preview error.
|
||||
- Record any unverified native/elevated service operations as residual risk.
|
||||
|
||||
Expected output:
|
||||
- `EVIDENCE.md` is sufficient for a reviewer to judge the user-facing outcome.
|
||||
|
||||
Verification command:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
- If Rust/backend changed: `cd apps/windows-client/src-tauri && cargo test`
|
||||
|
||||
Acceptance evidence:
|
||||
- Evidence file filled with commands, screenshots/state notes and residual risks.
|
||||
|
||||
Parallel-safe: no.
|
||||
|
||||
## PRE Review Prompt
|
||||
|
||||
Use `C:\Users\PC\.agents\skills\krypton-planning\plan-reviewer-prompt.md` with:
|
||||
|
||||
```text
|
||||
MODE: PRE
|
||||
|
||||
Plan file:
|
||||
docs/goals/windows-client-service-control-ui-system/PLAN.md
|
||||
|
||||
Original request:
|
||||
Составить план на основании UX/UI-аудита и уточнения, что Windows-клиент должен быть максимально простой service-control утилитой: управлять состояниями служб, устанавливать/удалять их, иметь нормальную компонентную базу для кнопок, табов, добавления, обновления, анимаций и loading states.
|
||||
|
||||
Outcome contract:
|
||||
Windows-клиент становится service-control utility с shared UI foundation, readiness-gated actions, едиными tabs/buttons/service rows/log dock/motion tokens и evidence from target perspective.
|
||||
|
||||
Architecture slice:
|
||||
Create `apps/windows-client/src/ui/*`, optional pure helpers under `apps/windows-client/src/app`, modify `App.tsx` and `app.css`, avoid backend/root web/server unless compile-only boundary fix is necessary.
|
||||
|
||||
Acceptance evidence requirement:
|
||||
Build plus desktop/narrow visual proof of Summary, ProxiFyre and VPN/Proxy; disabled apply blocker; friendly preview error; shared service rows; keyboard/active tab behavior.
|
||||
|
||||
Known non-goals:
|
||||
No backend rewrite, no installer changes, no root web/server changes, no full visual rebrand, no hidden component installation, no route-mode expansion.
|
||||
|
||||
Unsafe paths or layers:
|
||||
Duplicating truth in React, putting Tauri calls in UI components, leaving old ad hoc button paths as dominant, showing raw invoke errors, making apply green while blocked, changing generated config directly.
|
||||
```
|
||||
|
Before Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 75 KiB |
|
Before Width: | Height: | Size: 38 KiB |
@@ -1,85 +0,0 @@
|
||||
# Доказательства трехпанельного интерфейса Windows Client
|
||||
|
||||
## Приемочные доказательства
|
||||
|
||||
Записать реальный артефакт, который доказывает результат с точки зрения пользователя.
|
||||
|
||||
Обязательные доказательства:
|
||||
- `summary-panel.png`: read-only `Сводка` показывает статус системы, ProxiFyre, подключение, маршрут, активный сервер, количество приложений, config path state, dirty state и последнее событие.
|
||||
- Browser state для `Сводка`: `summaryInputs = 0`, `summaryForbiddenButtons = []`, активная вкладка `panel-summary`.
|
||||
- `proxifyre-panel.png`: панель `ProxiFyre` показывает статус компонента, setup action, service install action, список приложений, add controls, dirty/apply command row.
|
||||
- `vpn-proxy-external-panel.png`: панель `VPN / Прокси` в режиме внешнего прокси показывает route switch, SOCKS5 input, TCP check state, route preview и apply/open actions.
|
||||
- `vpn-proxy-local-panel.png`: панель `VPN / Прокси` в режиме локального прокси показывает Local sing-box empty/install state, route preview и dirty/apply state.
|
||||
- `narrow-proxifyre-panel.png`: узкий viewport показывает tab bar, ProxiFyre card, app list controls и command area без overlap с log dock.
|
||||
- Browser overlap state после фикса: desktop `commandBottom = 705.1875`, `logTop = 815.1875`, `overlaps = false`; narrow `appListBottom = 701.1875`, `logTop = 1072.1875`, `overlaps = false`.
|
||||
- Root `src/web` и `src/server` не менялись.
|
||||
|
||||
Сервисные действия install/start/stop/uninstall проверены на уровне существующих handlers и сборки UI. Реальный elevated Windows service lane для ProxiFyre/Local sing-box в этой сессии не запускался: `implemented but unproven`.
|
||||
|
||||
## Проверка
|
||||
|
||||
Записать сфокусированные проверки, которые прошли, включая команды и важный вывод.
|
||||
|
||||
Ожидаемые команды:
|
||||
|
||||
```powershell
|
||||
cd apps/windows-client
|
||||
npm run build
|
||||
```
|
||||
|
||||
Результат:
|
||||
|
||||
```text
|
||||
tsc && vite build
|
||||
1789 modules transformed
|
||||
dist/index.html
|
||||
dist/assets/index-Oqrmqzau.css
|
||||
dist/assets/index-CJqhju7q.js
|
||||
built in 1.31s
|
||||
```
|
||||
|
||||
Если менялись Rust/Tauri commands:
|
||||
|
||||
```powershell
|
||||
cd apps/windows-client/src-tauri
|
||||
cargo test
|
||||
```
|
||||
|
||||
Результат:
|
||||
|
||||
```text
|
||||
command_tests: 10 passed, including ping_proxy_target_reports_open_tcp_endpoint
|
||||
component_detection_tests: 7 passed
|
||||
domain_tests: 5 passed
|
||||
helper_tests: 6 passed
|
||||
proxifyre_adapter_tests: 6 passed
|
||||
singbox_adapter_tests: 6 passed
|
||||
singbox_command_tests: 8 passed
|
||||
singbox_service_tests: 7 passed
|
||||
storage_tests: 8 passed
|
||||
subscription_tests: 7 passed
|
||||
doc-tests: 0 passed
|
||||
overall: passed, warnings only for existing dead-code/test module duplication
|
||||
```
|
||||
|
||||
Browser preview:
|
||||
|
||||
```text
|
||||
Opened http://127.0.0.1:5174/
|
||||
Tabs detected: Сводка, ProxiFyre, VPN / Прокси
|
||||
Summary activePanel: panel-summary
|
||||
ProxiFyre activePanel: panel-proxifyre
|
||||
VPN/Proxy activePanel: panel-proxy
|
||||
External route aria-pressed=true in external mode
|
||||
Local route aria-pressed=true in local mode
|
||||
```
|
||||
|
||||
## Заметки review
|
||||
|
||||
Записать PRE review, reviewer, maintainer или verifier findings, если они изменили результат.
|
||||
|
||||
- PRE review: aligned. No blockers. Main risk was weak UI evidence; resolved by browser screenshots and DOM state checks.
|
||||
- POST plan review: aligned. The displaced monolithic screen path is removed from the active render path and replaced by three panels.
|
||||
- Correctness review: summary has no mutating controls; ProxiFyre actions remain in ProxiFyre panel; route/proxy actions remain in VPN/Proxy panel; new `ping_proxy_target` is read-only and tested with a local TCP listener.
|
||||
- Maintainability review: backend source of truth unchanged; no direct generated config writes from React; no root `src/web` or `src/server` edits.
|
||||
- Residual risk: real elevated service actions were not manually executed in native Tauri/elevated Windows mode during this UI pass.
|
||||
@@ -1,12 +0,0 @@
|
||||
# Goal: Трехпанельный интерфейс Windows Client
|
||||
|
||||
Use Krypton Execution to execute `docs/goals/windows-client-three-panel-ui/PLAN.md`.
|
||||
|
||||
Core rules:
|
||||
- Treat `PLAN.md` as the source plan.
|
||||
- Preserve intent, ownership, contract, cutover, evidence, and kill criteria.
|
||||
- Summary panel must remain read-only: no apply, install, start, stop, delete, input, subscription, or route mutations there.
|
||||
- Keep Rust/Tauri storage and commands as the source of truth; React may hold only UI state and derived display models.
|
||||
- Do not add a new dominant path without deleting, redirecting, demoting, or shimming the displaced monolithic screen path.
|
||||
- Capture acceptance evidence from the target perspective and record it in `EVIDENCE.md`.
|
||||
- Say `implemented but unproven` if target-perspective or Windows service evidence cannot be captured.
|
||||
@@ -1,423 +0,0 @@
|
||||
# План реализации трехпанельного интерфейса Windows Client
|
||||
|
||||
**Intent:** Перестроить текущий монолитный экран Windows-клиента в три переключаемые панели: read-only сводка, настройки ProxiFyre и настройки VPN/прокси.
|
||||
**Current Behavior:** Сейчас `apps/windows-client/src/app/App.tsx` смешивает статус ProxiFyre, выбор маршрута, Local sing-box, список приложений, применение конфига и журнал событий на одном экране. Пользователь сразу видит все управляющие элементы, поэтому главная страница не отделяет состояние системы от действий.
|
||||
**Expected Outcome:** Пользователь открывает приложение и сначала видит чистую сводку без редактирования. Управление ProxiFyre, список приложений и диагностика компонента находятся во второй панели. Выбор локального или внешнего прокси, подписка, серверы, ping и генерация VPN/proxy-конфига находятся в третьей панели.
|
||||
**Target-Perspective Output:** Пользователь может за 5-10 секунд понять, работает ли система, запущен ли ProxiFyre, какой маршрут применен, локальный он или внешний, и какой файл конфига активен. Затем пользователь переключается во вкладку ProxiFyre для сервисных действий и списка приложений либо во вкладку VPN/Прокси для выбора маршрута и проверки соединения.
|
||||
**Truth Owner:** Rust/Tauri команды и JSON-файлы под `C:\ProgramData\VpnProxy` остаются источником правды. React хранит только состояние текущей вкладки, черновики полей, loading/error/success состояния и производные view model для отображения.
|
||||
**Contract Boundary:** UI вызывает существующие typed Tauri commands из `apps/windows-client/src/api/tauriCommands.ts`. Rust владеет профилями, targets, компонентами, local-singbox config/cache, generated config и применением ProxiFyre. Новые UI-панели не должны писать напрямую в derived/generated артефакты.
|
||||
**Cutover:** Текущий единый экран в `App.tsx` заменяется shell-layout с тремя вкладками. Существующие функции загрузки, установки, запуска, выбора сервера, ping, apply и notifications переиспользуются, но раскладываются по панелям.
|
||||
**Displaced Path:** Убирается доминирующий путь "все настройки на одной странице". Сводка не дублирует формы и кнопки apply; она только отображает состояние и ведет пользователя к нужной панели.
|
||||
**Value Density:** Самый ценный срез: верхняя навигация по трем панелям плюс read-only сводка, которая корректно собирает текущее состояние из уже загружаемых данных. После этого переносим существующие настройки без изменения backend-контракта.
|
||||
**Evidence Gate:** Приемка требует не только `npm run build`, но и доказательство глазами пользователя: скриншоты/состояния всех трех панелей, read-only поведение сводки, dirty/apply состояние на вкладках настроек, responsive-проверка.
|
||||
**Acceptance Evidence:** `npm run build` проходит; при необходимости Rust tests проходят для нового ping/target DTO; в `EVIDENCE.md` записаны скриншоты или browser/Tauri state для трех панелей, а также проверка, что сводка не содержит изменяющих controls.
|
||||
**Evidence Lane:** Доказательства исполнения будут фиксироваться в `docs/goals/windows-client-three-panel-ui/EVIDENCE.md`.
|
||||
**Kill Criteria:** Нет input/button apply на сводке; нет второго источника состояния маршрута; нет скрытой установки компонентов при открытии вкладок; нет изменения root `src/web` или root `src/server`; нет расхождения терминов ProxiFyre / Local sing-box / внешний прокси.
|
||||
**Architecture Slice:** Изменения сосредоточены в `apps/windows-client/src/app/App.tsx`, `apps/windows-client/src/styles/app.css`, при необходимости `apps/windows-client/src/api/tauriCommands.ts`, `apps/windows-client/src/domain/types.ts`, `apps/windows-client/src-tauri/src/commands.rs` и связанных tests для проверки внешнего target ping.
|
||||
**Plan Review Gate:** Требуется PRE review перед исполнением.
|
||||
|
||||
## Краткий дизайн-brief
|
||||
|
||||
Продукт: Windows desktop utility для маршрутизации выбранных приложений через ProxiFyre и внешний или локальный proxy path.
|
||||
|
||||
Визуальный источник: текущий темный utilitarian-стиль `apps/windows-client/src/styles/app.css`: компактные панели, 4px radius, статусные точки, lucide icons, сдержанные borders, без landing/hero.
|
||||
|
||||
Интерактивность: полная. Вкладки, меню, установка/запуск/остановка, добавление приложений, выбор маршрута, подписка, выбор сервера, ping, генерация и apply должны работать через реальные текущие команды.
|
||||
|
||||
## Архитектурный срез
|
||||
|
||||
Файлы для создания:
|
||||
- `docs/goals/windows-client-three-panel-ui/PLAN.md`
|
||||
- `docs/goals/windows-client-three-panel-ui/GOAL.md`
|
||||
- `docs/goals/windows-client-three-panel-ui/EVIDENCE.md`
|
||||
|
||||
Файлы для изменения:
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
- `apps/windows-client/src/api/tauriCommands.ts`, только если понадобится новый внешний proxy ping command.
|
||||
- `apps/windows-client/src/domain/types.ts`, только если понадобится новый DTO для внешнего proxy ping.
|
||||
- `apps/windows-client/src-tauri/src/commands.rs`, только если понадобится новый внешний proxy ping command.
|
||||
- `apps/windows-client/src-tauri/src/main.rs`, только для регистрации нового command.
|
||||
- `apps/windows-client/src-tauri/tests/*`, только для нового command или сохранения существующих контрактов.
|
||||
- `docs/goals/windows-client-three-panel-ui/EVIDENCE.md`, при исполнении.
|
||||
|
||||
Файлы, которых не касаться:
|
||||
- `src/web/*`
|
||||
- `src/server/*`
|
||||
- Docker/compose/entrypoint файлы.
|
||||
- Installer scripts, если UI-разрез не требует изменения install boundary.
|
||||
- Старые goal packages, кроме ссылок в evidence при необходимости.
|
||||
|
||||
Источник правды:
|
||||
- `C:\ProgramData\VpnProxy\config\profiles.json`
|
||||
- `C:\ProgramData\VpnProxy\config\targets.json`
|
||||
- `C:\ProgramData\VpnProxy\config\components.json`
|
||||
- `C:\ProgramData\VpnProxy\config\local-singbox.json`
|
||||
- `C:\ProgramData\VpnProxy\state\singbox-subscription-cache.json`
|
||||
- `C:\ProgramData\VpnProxy\state\activity.json`
|
||||
|
||||
Производные артефакты:
|
||||
- `C:\ProgramData\VpnProxy\generated\proxifyre-app-config.json`
|
||||
- `C:\ProgramData\VpnProxy\generated\sing-box-config.json`
|
||||
|
||||
Путь чтения:
|
||||
- React вызывает `get_saved_state`, `get_components`, `get_proxifyre_setup_status`, `get_singbox_status`, `get_singbox_setup_status`.
|
||||
- Summary panel строит производную view model из уже загруженных `profiles`, `targets`, `components`, `setupStatus`, `singBoxStatus`, `generatedConfigPath`, `serverPings` и `hasUnappliedChanges`.
|
||||
- ProxiFyre panel читает `proxyfier`, `setupStatus`, `items`, `loadedProfiles`, `generatedConfigPath`.
|
||||
- VPN/Proxy panel читает `routeMode`, `proxyInput`, `singBoxStatus`, `singBoxSetupStatus`, `serverPings`, selected server и target.
|
||||
|
||||
Путь записи:
|
||||
- ProxiFyre panel пишет только через существующие handlers: install/start/stop/uninstall ProxiFyre, add/remove app items, `updateConfig`.
|
||||
- VPN/Proxy panel пишет только через route/subscription/server/config handlers: `changeRouteMode`, `changeProxyInput`, `saveSingBoxSubscription`, `fetchSingBoxSubscription`, `forgetSingBoxSubscription`, `selectSingBoxServer`, `ping*`, `generateSingBoxConfig`, service actions, `updateConfig`.
|
||||
- Summary panel не пишет ничего, кроме глобального non-mutating refresh, если refresh остается в header.
|
||||
|
||||
Граница контракта:
|
||||
- `App.tsx` отвечает за orchestration и view composition.
|
||||
- Typed Tauri command wrappers отвечают за API shape.
|
||||
- Rust commands отвечают за validation, persistence, service/check actions и generated config.
|
||||
- CSS отвечает за layout, tab transitions, loading skeletons, menu/popover transitions и responsive behavior.
|
||||
|
||||
Точки интеграции:
|
||||
- `routeMode === 'external'` показывает внешний/глобальный proxy target.
|
||||
- `routeMode === 'local-singbox'` показывает Local sing-box path.
|
||||
- `hasUnappliedChanges` остается общим индикатором для вкладок настроек.
|
||||
- `log-dock` остается глобальным и не привязывается к одной вкладке.
|
||||
|
||||
Миграция и переключение:
|
||||
- Сначала добавить `activePanel` и shell-вкладки без изменения бизнес-логики.
|
||||
- Затем перенести JSX блоки в три render-функции или локальные компоненты в том же файле.
|
||||
- После стабилизации можно вынести панели в отдельные файлы, но только если это уменьшит размер `App.tsx` без изменения контрактов.
|
||||
|
||||
Гейт приемочных доказательств:
|
||||
- Доказательство должно показать каждую панель отдельно.
|
||||
- Должно быть видно, что summary read-only.
|
||||
- Должно быть видно, что actions доступны на вкладках настроек.
|
||||
- Должно быть видно, что mobile layout не ломает tab bar, app list, server list и bottom log dock.
|
||||
|
||||
## Детальное описание интерфейса
|
||||
|
||||
### Общая оболочка
|
||||
|
||||
Верхняя часть экрана остается компактной, но становится навигационной:
|
||||
- слева: `VPN Proxy` и заголовок `Прокси для приложений`;
|
||||
- справа: кнопка `Обновить`, которая запускает текущий `refresh`;
|
||||
- под заголовком: segmented tabs из трех пунктов: `Сводка`, `ProxiFyre`, `VPN / Прокси`.
|
||||
|
||||
Поведение вкладок:
|
||||
- активная вкладка имеет более яркий border/background и status underline;
|
||||
- при клике меняется только `activePanel`, данные не перезагружаются автоматически;
|
||||
- переход между панелями: fade + легкий slide по Y на 6-8px, длительность 140-180ms;
|
||||
- при `prefers-reduced-motion: reduce` transition отключается;
|
||||
- keyboard support: tabs работают как buttons с `aria-pressed` или `role="tablist"`/`role="tab"`/`role="tabpanel`.
|
||||
|
||||
Глобальные состояния:
|
||||
- `isLoading` показывает skeleton в содержимом активной панели;
|
||||
- `isDetectingComponents` показывает проверку компонентов без блокировки переключения вкладок;
|
||||
- `log-dock` остается закрепленным снизу и продолжает показывать success/error/info;
|
||||
- dirty/apply bar появляется только на вкладках `ProxiFyre` и `VPN / Прокси`, не на read-only сводке.
|
||||
|
||||
### Панель 1: `Сводка`
|
||||
|
||||
Назначение: главная read-only страница, которая отвечает на вопрос "что сейчас происходит с системой".
|
||||
|
||||
Содержимое:
|
||||
- `Статус системы`: одно агрегированное состояние `Работает`, `Требует внимания`, `Не настроено`, `Проверяю`.
|
||||
- `ProxiFyre`: установлен/не установлен, запущен/остановлен, путь или первая проблема.
|
||||
- `Подключение`: корректность текущего маршрута: ProxiFyre running, выбран target, для Local sing-box выбран сервер и служба запущена, для внешнего proxy валиден host/port и есть последний результат ping/check, если он уже запускался.
|
||||
- `Маршрут`: `Локальный прокси` или `Внешний прокси`; рядом человекочитаемый endpoint: `127.0.0.1:1080`, LAN адрес Local sing-box или внешний `host:port`.
|
||||
- `Активный сервер`: selected Local sing-box server tag, если применим; иначе `не используется`.
|
||||
- `Приложения в профиле`: количество настроенных process/folder/exe items.
|
||||
- `Примененный конфиг`: путь `generatedConfigPath` для ProxiFyre и, если есть, `singBoxStatus.generatedConfigPath`.
|
||||
- `Состояние изменений`: `Все применено` или `Есть непримененные изменения`, но без кнопки apply.
|
||||
- `Последнее событие`: последний элемент `logEntries` или activity, если он уже доступен на клиенте.
|
||||
|
||||
Визуально:
|
||||
- это не форма, а read-only dashboard;
|
||||
- вместо input используются value rows: label слева, value справа, status dot рядом;
|
||||
- важные значения не спрятаны в tooltip;
|
||||
- длинные пути переносятся через `overflow-wrap: anywhere`;
|
||||
- при широкой ширине блоки идут сеткой 2-3 колонки, на узком экране складываются в один столбец.
|
||||
|
||||
Действия при нажатии:
|
||||
- клик по строке `ProxiFyre` переключает на вкладку `ProxiFyre`;
|
||||
- клик по строке `Маршрут` или `Активный сервер` переключает на вкладку `VPN / Прокси`;
|
||||
- клик по `Приложения в профиле` переключает на вкладку `ProxiFyre` и фокусирует список приложений;
|
||||
- никаких input, add/remove, install/start/stop, apply или clear на этой панели нет.
|
||||
|
||||
Анимации:
|
||||
- при refresh status rows показывают мягкий shimmer/skeleton;
|
||||
- status dot для `Проверяю` использует текущий spinner pattern;
|
||||
- при смене агрегированного статуса value row подсвечивается на 400-600ms через background flash;
|
||||
- предупреждение `Есть непримененные изменения` может слегка проявляться fade-in, но без кнопки.
|
||||
|
||||
### Панель 2: `ProxiFyre`
|
||||
|
||||
Назначение: диагностика и настройка того, что относится именно к ProxiFyre и маршрутизируемым приложениям.
|
||||
|
||||
Содержимое:
|
||||
- главный статус ProxiFyre: найден/не найден, запущен/остановлен, path/problem;
|
||||
- setup/modules list из `setupStatus.items`: binary/service/install folder/config capability и все, что возвращает backend;
|
||||
- service controls: install, start, stop, uninstall через меню `MoreHorizontal`;
|
||||
- `Список приложений`: настроенные process/folder/exe items, сгруппированные или помеченные типом;
|
||||
- счетчик приложений и отдельные пустые состояния для "ничего не настроено";
|
||||
- generated ProxiFyre config path;
|
||||
- dirty/apply state для изменений списка приложений.
|
||||
|
||||
Визуально:
|
||||
- верхний status block сохраняет текущий `finder-card` pattern, status-light и animated border glow;
|
||||
- modules list разворачивается внутри панели через `Состав ProxiFyre` / `Что будет установлено`;
|
||||
- список приложений становится основной частью панели, а не хвостом общей страницы;
|
||||
- app rows имеют icon по типу: process, exe, folder;
|
||||
- add-toolbar остается с icon buttons: process, exe, folder, с tooltip/title.
|
||||
|
||||
Действия при нажатии:
|
||||
- `Установить`: вызывает текущий `installProxiFyrePackage`, показывает loading на кнопке и animated border;
|
||||
- `Запустить`/`Остановить`: вызывает `setProxiFyreServiceRunning`, блокирует повторный клик на время action;
|
||||
- `Еще` открывает popover с `Удалить ProxiFyre`; uninstall сохраняет текущий confirm boundary;
|
||||
- `Состав ProxiFyre`: раскрывает/скрывает setup details;
|
||||
- `Добавить процесс`: открывает inline input, Enter добавляет, Escape закрывает;
|
||||
- `Добавить EXE`: открывает file picker через Tauri dialog;
|
||||
- `Добавить папку`: открывает directory picker;
|
||||
- `Удалить` у app row удаляет item и выставляет `hasUnappliedChanges`;
|
||||
- `Применить в ProxiFyre`: валидирует items и текущий route, затем вызывает `updateConfig`;
|
||||
- `Открыть конфиг`: открывает generated config location, если эта кнопка остается в ProxiFyre panel.
|
||||
|
||||
Анимации:
|
||||
- поиск/установка/запуск используют существующий moving border glow;
|
||||
- раскрытие modules list: height/opacity transition 160-220ms;
|
||||
- добавление app row: fade/slide-in;
|
||||
- удаление app row: быстрый opacity collapse, если реализация не усложнит state;
|
||||
- dirty bar появляется slide-up/fade-in над command row;
|
||||
- меню `Еще`: fade + scale 0.98 -> 1.
|
||||
|
||||
### Панель 3: `VPN / Прокси`
|
||||
|
||||
Назначение: выбор маршрута и настройка самого proxy/VPN path.
|
||||
|
||||
Содержимое:
|
||||
- segmented control `Внешний прокси` / `Локальный прокси`;
|
||||
- для `Внешний прокси`: input адреса `socks5://host:port` или `host:port`, validation hint, кнопка проверки доступности;
|
||||
- для `Локальный прокси`: Local sing-box status, install/start/stop/uninstall, setup details, локальный и LAN endpoint, selected server, generated sing-box config path;
|
||||
- subscription input: paste URL/link, load/update, clear;
|
||||
- server list из `singBoxStatus.cache.servers`;
|
||||
- ping controls: `Ping все`, per-server ping action, отображение latency/error рядом с server row;
|
||||
- generate sing-box config action;
|
||||
- route preview: `Выбранные приложения -> ProxiFyre -> внешний proxy` или `Выбранные приложения -> ProxiFyre -> Local sing-box -> selected server`;
|
||||
- dirty/apply state для route/proxy/subscription/server changes.
|
||||
|
||||
Визуально:
|
||||
- mode switch остается заметным вверху панели;
|
||||
- внешний proxy block не должен выглядеть менее важным, потому что это полноценный route path;
|
||||
- Local sing-box block визуально похож на ProxiFyre status block, но расположен только в VPN/Proxy panel;
|
||||
- server list может оставаться grid, но row должен показывать selected dot, server name и ping badge;
|
||||
- для плохого ping row получает amber/red border, для хорошего ping зеленый badge;
|
||||
- route preview оформляется как read-only line/flow, без декоративной схемы.
|
||||
|
||||
Действия при нажатии:
|
||||
- `Внешний прокси`: меняет `routeMode` на `external`, выставляет dirty state;
|
||||
- ввод адреса proxy: обновляет `proxyInput`, выставляет dirty state, frontend validation показывает ошибки до apply;
|
||||
- `Проверить`: парсит внешний proxy и вызывает новый или переиспользованный backend TCP connect check; результат сохраняется в UI state и отображается на этой панели и в summary;
|
||||
- `Локальный прокси`: меняет `routeMode` на `local-singbox`, выставляет dirty state;
|
||||
- `Установить Local sing-box`: вызывает текущий install handler;
|
||||
- `Запустить`/`Остановить`: вызывает текущий service handler;
|
||||
- `Состав Local sing-box`: раскрывает setup details;
|
||||
- `Подробности`: показывает локальный endpoint, LAN, server, binary path, config path;
|
||||
- `Загрузить`/`Обновить` подписку: вызывает текущий subscription flow;
|
||||
- `Очистить`: вызывает forget flow, очищает server pings и selected server;
|
||||
- click по server row: вызывает `selectSingBoxServer`, выставляет dirty state;
|
||||
- `Ping все`: вызывает `pingAllSingBoxServers`;
|
||||
- per-server ping: вызывает существующий `pingSingBoxServer(tag)`, если добавляем кнопку/иконку в row;
|
||||
- `Конфиг`: вызывает `generateSingBoxConfig`;
|
||||
- `Применить маршрут`: вызывает общий `updateConfig`.
|
||||
|
||||
Анимации:
|
||||
- mode switch меняет активный segment без скачка высоты;
|
||||
- при смене mode panel content cross-fade;
|
||||
- ping badge показывает loading spinner только на проверяемых row;
|
||||
- server row после ping обновляет latency с короткой подсветкой;
|
||||
- subscription/server empty state появляется fade-in;
|
||||
- generated config success подсвечивает config path на 400-600ms.
|
||||
|
||||
## Задачи исполнения
|
||||
|
||||
### Задача 1: Ввести shell вкладок и производные view models
|
||||
|
||||
Разрешенные файлы:
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
|
||||
Ожидаемый результат:
|
||||
- `activePanel: 'summary' | 'proxifyre' | 'proxy'`.
|
||||
- Общий header с tab control.
|
||||
- Производные функции для summary: system status, route label, endpoint label, config labels, app count, issue list.
|
||||
- Старые JSX-блоки временно остаются, но render path начинает разделяться.
|
||||
|
||||
Проверка:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
|
||||
Приемочные доказательства:
|
||||
- Screenshot/state показывает три tab buttons и корректную активную вкладку.
|
||||
|
||||
Параллельное выполнение: нет, общий `App.tsx`.
|
||||
|
||||
### Задача 2: Реализовать read-only панель `Сводка`
|
||||
|
||||
Разрешенные файлы:
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
|
||||
Ожидаемый результат:
|
||||
- Summary panel без input/apply/install/start/stop/delete.
|
||||
- Статус системы, ProxiFyre, подключение, маршрут, активный server, apps count, config paths, dirty state.
|
||||
- Навигационные клики по read-only строкам переводят на соответствующие вкладки.
|
||||
|
||||
Проверка:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
- Manual DOM/visual check: на summary нет изменяющих controls.
|
||||
|
||||
Приемочные доказательства:
|
||||
- Screenshot summary panel.
|
||||
- Запись в evidence: какие элементы read-only и куда ведут navigation clicks.
|
||||
|
||||
Параллельное выполнение: нет.
|
||||
|
||||
### Задача 3: Перенести ProxiFyre и список приложений во вторую панель
|
||||
|
||||
Разрешенные файлы:
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
|
||||
Ожидаемый результат:
|
||||
- ProxiFyre panel содержит status card, setup details, service actions, app add/remove, generated config path и apply/open config actions.
|
||||
- Существующие handlers переиспользованы без изменения backend ownership.
|
||||
- `hasUnappliedChanges` продолжает работать после add/remove.
|
||||
|
||||
Проверка:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
|
||||
Приемочные доказательства:
|
||||
- Screenshot ProxiFyre panel с service status и apps list.
|
||||
- Проверка add/remove вызывает dirty state.
|
||||
|
||||
Параллельное выполнение: нет.
|
||||
|
||||
### Задача 4: Перенести VPN/Proxy route settings в третью панель
|
||||
|
||||
Разрешенные файлы:
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
- `apps/windows-client/src/api/tauriCommands.ts`, если нужен внешний target ping.
|
||||
- `apps/windows-client/src/domain/types.ts`, если нужен внешний target ping DTO.
|
||||
|
||||
Ожидаемый результат:
|
||||
- VPN/Proxy panel содержит route mode switch, external proxy editor, Local sing-box controls, subscription, server selection, ping, generate config, route preview и apply.
|
||||
- Внешний proxy path не зависит от Local sing-box.
|
||||
- Local sing-box UI не показывается на summary и не смешивается с ProxiFyre panel.
|
||||
|
||||
Проверка:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
|
||||
Приемочные доказательства:
|
||||
- Screenshot external proxy mode.
|
||||
- Screenshot local proxy mode с server list или empty state.
|
||||
|
||||
Параллельное выполнение: нет.
|
||||
|
||||
### Задача 5: Добавить или переиспользовать проверку доступности внешнего proxy target
|
||||
|
||||
Разрешенные файлы:
|
||||
- `apps/windows-client/src-tauri/src/commands.rs`
|
||||
- `apps/windows-client/src-tauri/src/main.rs`
|
||||
- `apps/windows-client/src/api/tauriCommands.ts`
|
||||
- `apps/windows-client/src/domain/types.ts`
|
||||
- `apps/windows-client/src-tauri/tests/command_tests.rs` или отдельный focused test.
|
||||
|
||||
Ожидаемый результат:
|
||||
- Если существующих данных недостаточно для "все ли окей с подключением" во внешнем proxy mode, добавить typed command наподобие `ping_proxy_target`.
|
||||
- Command делает TCP connect check к host/port с timeout, возвращает `{ ok, latency, error }`.
|
||||
- UI отображает результат в VPN/Proxy panel и summary.
|
||||
- Это не заменяет apply и не пишет source config.
|
||||
|
||||
Проверка:
|
||||
- `cd apps/windows-client/src-tauri && cargo test command`
|
||||
- `cd apps/windows-client && npm run build`
|
||||
|
||||
Приемочные доказательства:
|
||||
- Test или manual state показывает успешный/ошибочный result shape.
|
||||
|
||||
Параллельное выполнение: частично, если UI DTO names согласованы заранее; интеграция не parallel-safe.
|
||||
|
||||
### Задача 6: Привести CSS, анимации и responsive behavior
|
||||
|
||||
Разрешенные файлы:
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
- `apps/windows-client/src/app/App.tsx`, только className/ARIA adjustments.
|
||||
|
||||
Ожидаемый результат:
|
||||
- Tab bar, panel transitions, setup expand/collapse, ping badges, dirty/apply bar и responsive grids.
|
||||
- Нет перекрытия текста, длинные paths/servers переносятся.
|
||||
- Mobile layout: tabs не ломаются, server list минимум 2 колонки или 1 колонка на очень узком экране, command row складывается.
|
||||
- `prefers-reduced-motion` отключает декоративные transitions.
|
||||
|
||||
Проверка:
|
||||
- `cd apps/windows-client && npm run build`
|
||||
- Browser/Tauri visual check на desktop и узком viewport.
|
||||
|
||||
Приемочные доказательства:
|
||||
- Screenshots desktop + narrow viewport.
|
||||
|
||||
Параллельное выполнение: нет, потому что зависит от финальной разметки.
|
||||
|
||||
### Задача 7: Финальная проверка и evidence
|
||||
|
||||
Разрешенные файлы:
|
||||
- `docs/goals/windows-client-three-panel-ui/EVIDENCE.md`
|
||||
- При необходимости `apps/windows-client/README.md`, если нужно зафиксировать новую навигацию.
|
||||
|
||||
Ожидаемый результат:
|
||||
- Evidence содержит commands, результаты build/tests, screenshots/state checks и список остаточных рисков.
|
||||
- Если Tauri service actions не проверялись на реальной Windows elevated среде, это явно помечено как `implemented but unproven` только для service lane.
|
||||
|
||||
Проверка:
|
||||
- `git status --short`
|
||||
- `cd apps/windows-client && npm run build`
|
||||
- `cd apps/windows-client/src-tauri && cargo test`, если Rust command менялся.
|
||||
|
||||
Приемочные доказательства:
|
||||
- Summary read-only verified.
|
||||
- ProxiFyre actions verified.
|
||||
- VPN/Proxy route switch and ping states verified.
|
||||
- No root web/server changes.
|
||||
|
||||
Параллельное выполнение: нет.
|
||||
|
||||
## Prompt для PRE review
|
||||
|
||||
Использовать `C:\Users\PC\.agents\skills\krypton-planning\plan-reviewer-prompt.md` со следующими данными:
|
||||
|
||||
Файл плана:
|
||||
- `docs/goals/windows-client-three-panel-ui/PLAN.md`
|
||||
|
||||
Исходный запрос:
|
||||
- Разбить Windows client UI на три переключаемые панели: общая read-only сводка, настройки ProxiFyre, настройки VPN/proxy; подробно описать внешний вид, анимации и действия.
|
||||
|
||||
Контракт результата:
|
||||
- Пользователь сначала видит статус системы и примененный route/config без изменения данных, затем переходит в нужную панель для ProxiFyre или VPN/proxy действий.
|
||||
|
||||
Архитектурный срез:
|
||||
- Основной scope: `apps/windows-client/src/app/App.tsx` и `apps/windows-client/src/styles/app.css`; backend только для внешнего target ping, если текущих команд недостаточно.
|
||||
|
||||
Требование к приемочным доказательствам:
|
||||
- Build/tests плюс screenshots/state proof трех панелей и read-only summary.
|
||||
|
||||
Известные non-goals:
|
||||
- Не менять root `src/web`/`src/server`.
|
||||
- Не переписывать Tauri backend без нужды.
|
||||
- Не добавлять скрытую установку компонентов.
|
||||
- Не делать summary редактируемой.
|
||||
|
||||
Опасные пути или слои:
|
||||
- Дублирование source of truth в React.
|
||||
- Изменение generated config напрямую.
|
||||
- Смешивание Local sing-box controls обратно в ProxiFyre panel.
|
||||
- Потеря external proxy path как полноценного режима.
|
||||
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 87 KiB |
@@ -1,61 +0,0 @@
|
||||
# Windows Local Sing-Box Evidence
|
||||
|
||||
## Acceptance Evidence
|
||||
|
||||
Record the real artifact that proves the outcome from the Windows-client user's perspective.
|
||||
|
||||
- Windows client now has two independent component blocks:
|
||||
- `ProxiFyre` block remains the existing required app-routing layer.
|
||||
- `Local sing-box` block is optional, visually matches the ProxiFyre finder card, has setup details, install/start/stop/uninstall actions, subscription input, route switch, server list, ping, and config generation actions.
|
||||
- Route choice is explicit:
|
||||
- `Внешний прокси` keeps the existing external SOCKS5 flow.
|
||||
- `Local sing-box` generates `sing-box-config.json`, ensures target `local-singbox` at `127.0.0.1:1080`, and applies ProxiFyre to that local target.
|
||||
- Generated config proof is covered by `singbox_command_tests::generate_writes_config_and_local_singbox_target`:
|
||||
- generated config contains a local mixed inbound;
|
||||
- selected outbound is retagged to stable `vpn`;
|
||||
- persisted target is `local-singbox`, `kind=local`, `protocol=socks5`, `host=127.0.0.1`, `port=1080`, `requiresComponent=singbox`.
|
||||
- Browser visual proof:
|
||||
- Vite dev server: `http://127.0.0.1:5173/`
|
||||
- Playwright/system Chrome desktop screenshot showed ProxiFyre and Local sing-box blocks, route switch, subscription input, ping/config actions, and apply/open controls.
|
||||
- Mobile screenshot at `390px` width showed the same controls stacked without overlap.
|
||||
- Final mobile layout metric: `docScrollWidth=390`, `viewportWidth=390`, `overflow=[]`.
|
||||
- Privileged Windows service lane:
|
||||
- Implemented install/start/stop/uninstall paths and PowerShell parser checks.
|
||||
- Real elevated UAC install/start was not executed in this session, so this lane is `implemented but unproven` until manual Windows validation runs.
|
||||
|
||||
## Verification
|
||||
|
||||
Record focused checks that passed, including command and relevant output.
|
||||
|
||||
- `cd apps/windows-client && npm run build`
|
||||
- Passed: `tsc && vite build`.
|
||||
- `cd apps/windows-client/src-tauri && cargo test --test storage_tests --test subscription_tests --test singbox_adapter_tests --test component_detection_tests --test singbox_service_tests --test command_tests --test singbox_command_tests`
|
||||
- Passed:
|
||||
- `command_tests`: 8 passed
|
||||
- `component_detection_tests`: 7 passed
|
||||
- `singbox_adapter_tests`: 6 passed
|
||||
- `singbox_command_tests`: 7 passed
|
||||
- `singbox_service_tests`: 6 passed
|
||||
- `storage_tests`: 8 passed
|
||||
- `subscription_tests`: 7 passed
|
||||
- Total focused Local sing-box backend path: 49 passed.
|
||||
- `cd apps/windows-client/src-tauri && cargo test --test proxifyre_adapter_tests`
|
||||
- Passed: 6 passed.
|
||||
- Proves existing external SOCKS5 route still generates and `local-singbox` route is blocked when the required component is missing but works when it is running.
|
||||
- `cargo fmt`
|
||||
- Passed.
|
||||
- `apps/windows-client/scripts/install-singbox.ps1` parser check:
|
||||
- Covered by `singbox_service_tests::install_singbox_script_parses_as_powershell` on Windows.
|
||||
- Playwright/system Chrome visual check:
|
||||
- Desktop viewport `1280x1200`: main controls rendered.
|
||||
- Mobile viewport `390x900`: no horizontal overflow after CSS fix.
|
||||
|
||||
## Review Notes
|
||||
|
||||
Record PRE reviewer, maintainer, or verifier findings that changed the result.
|
||||
|
||||
- PRE self-review: aligned after tightening the service-wrapper contract to WinSW and requiring `start_singbox_service` to regenerate/check config before service start.
|
||||
- POST plan review: implementation stayed inside `apps/windows-client` and did not reuse root Node subscription parsing. External proxy remains default and does not require Local sing-box.
|
||||
- Correctness review: covered storage defaults, redacted subscription URL, HTTP/HTTPS validation, JSON/base64/VLESS subscription parsing, selected-outbound config generation, missing selected server errors, component detection, service command output parsing, Tauri command orchestration, route target generation, TypeScript build, and responsive UI.
|
||||
- Maintainability review: Rust owns subscription/cache/config/service state; React owns transient UI only. Tauri commands are typed and do not expose raw PowerShell/stdout to the UI.
|
||||
- Residual risk: real UAC install/start/stop/uninstall for `VpnProxySingBox` must be validated manually on a Windows machine with admin confirmation and network access to GitHub releases.
|
||||
@@ -1,13 +0,0 @@
|
||||
# Goal: Windows Local Sing-Box
|
||||
|
||||
Use Krypton Execution to execute `docs/goals/windows-local-singbox/PLAN.md`.
|
||||
|
||||
Core rules:
|
||||
- Treat PLAN.md as the source plan.
|
||||
- Preserve intent, ownership, contract, cutover, evidence, and kill criteria.
|
||||
- Implement the feature as the existing optional Local sing-box component, not as a new unrelated component id.
|
||||
- Keep external proxy flow working without Local sing-box.
|
||||
- Do not add hidden installation during profile apply.
|
||||
- Do not import or call the root Node server from the Windows client.
|
||||
- Capture acceptance evidence from the target perspective and record it in EVIDENCE.md.
|
||||
- Say "implemented but unproven" if elevated Windows service evidence cannot be captured.
|
||||
@@ -1,285 +0,0 @@
|
||||
# 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.rs`
|
||||
- `apps/windows-client/src-tauri/src/singbox_service.rs`
|
||||
- `apps/windows-client/src-tauri/tests/subscription_tests.rs`
|
||||
- `apps/windows-client/src-tauri/tests/singbox_service_tests.rs`
|
||||
- `apps/windows-client/src-tauri/tests/singbox_command_tests.rs`
|
||||
|
||||
Files to modify:
|
||||
- `apps/windows-client/src-tauri/Cargo.toml`
|
||||
- `apps/windows-client/src-tauri/src/main.rs`
|
||||
- `apps/windows-client/src-tauri/src/models.rs`
|
||||
- `apps/windows-client/src-tauri/src/storage.rs`
|
||||
- `apps/windows-client/src-tauri/src/commands.rs`
|
||||
- `apps/windows-client/src-tauri/src/component_detection.rs`
|
||||
- `apps/windows-client/src-tauri/src/adapters/singbox.rs`
|
||||
- `apps/windows-client/src-tauri/tests/singbox_adapter_tests.rs`
|
||||
- `apps/windows-client/src-tauri/tests/command_tests.rs`
|
||||
- `apps/windows-client/src/domain/types.ts`
|
||||
- `apps/windows-client/src/api/tauriCommands.ts`
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/styles/app.css`
|
||||
- `apps/windows-client/scripts/install-singbox.ps1`
|
||||
- `apps/windows-client/README.md`
|
||||
- `docs/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-singbox` target.
|
||||
|
||||
Source of truth:
|
||||
- `C:\ProgramData\VpnProxy\config\profiles.json`
|
||||
- `C:\ProgramData\VpnProxy\config\targets.json`
|
||||
- `C:\ProgramData\VpnProxy\config\local-singbox.json`
|
||||
- `C:\ProgramData\VpnProxy\state\singbox-subscription-cache.json`
|
||||
- `C:\ProgramData\VpnProxy\state\activity.json`
|
||||
|
||||
Derived artifacts:
|
||||
- `C:\ProgramData\VpnProxy\generated\sing-box-config.json`
|
||||
- `C:\ProgramData\VpnProxy\generated\proxifyre-app-config.json`
|
||||
- Installed `sing-box.exe` and WinSW wrapper under `C:\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 runs `sing-box check` before service start/restart.
|
||||
|
||||
Contract boundary:
|
||||
- `subscription.rs` owns fetch/parse/link normalization.
|
||||
- `adapters/singbox.rs` owns conversion from selected outbound to local runtime config.
|
||||
- `singbox_service.rs` owns install/service script generation and structured command parsing.
|
||||
- `commands.rs` owns Tauri DTOs and activity entries.
|
||||
- `App.tsx` owns 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-box` plus a WinSW Windows service wrapper, then writes machine-readable result JSON.
|
||||
|
||||
Migration/cutover:
|
||||
- On first sing-box save/start, ensure `local-singbox` target 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.ps1` must stop being a marker-only script.
|
||||
- The old direct-only sing-box config in `adapters/singbox.rs` must 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.rs`
|
||||
- `apps/windows-client/src-tauri/src/storage.rs`
|
||||
- `apps/windows-client/src/domain/types.ts`
|
||||
- `apps/windows-client/src-tauri/tests/storage_tests.rs`
|
||||
|
||||
Expected output:
|
||||
- `LocalSingBoxConfig` source model with subscription URL, redacted display URL, selected server tag, listen host/port, service name, install root, and timestamps.
|
||||
- `SubscriptionCache` model with parsed config, server summaries, user info, and fetched timestamp.
|
||||
- Storage paths for `config/local-singbox.json` and `state/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.toml`
|
||||
- `apps/windows-client/src-tauri/src/subscription.rs`
|
||||
- `apps/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.rs`
|
||||
- `apps/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 check` when 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.rs`
|
||||
- `apps/windows-client/src-tauri/src/singbox_service.rs`
|
||||
- `apps/windows-client/scripts/install-singbox.ps1`
|
||||
- `apps/windows-client/src-tauri/tests/component_detection_tests.rs`
|
||||
- `apps/windows-client/src-tauri/tests/singbox_service_tests.rs`
|
||||
|
||||
Expected output:
|
||||
- Detection finds installed `sing-box.exe`, service `VpnProxySingBox`, 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.ps1` when 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.rs`
|
||||
- `apps/windows-client/src-tauri/src/main.rs`
|
||||
- `apps/windows-client/src/api/tauriCommands.ts`
|
||||
- `apps/windows-client/src-tauri/tests/command_tests.rs`
|
||||
- `apps/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_config` ensures/updates the `local-singbox` target but does not change profile targets without user choice.
|
||||
- `start_singbox_service` regenerates 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.tsx`
|
||||
- `apps/windows-client/src/domain/types.ts`
|
||||
- `apps/windows-client/src/api/tauriCommands.ts`
|
||||
- `apps/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.tsx`
|
||||
- `apps/windows-client/src-tauri/src/commands.rs`
|
||||
- `apps/windows-client/src-tauri/src/adapters/proxifyre.rs`
|
||||
- `apps/windows-client/src-tauri/tests/command_tests.rs`
|
||||
- `apps/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:1080` when 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 command`
|
||||
- `cd 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.md`
|
||||
- `docs/goals/windows-local-singbox/EVIDENCE.md`
|
||||
- `docs/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 unproven` for 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`, root `src/web`, hidden installer calls inside apply, raw PowerShell parsing in React, duplicate subscription state.
|
||||
@@ -1,16 +0,0 @@
|
||||
# Goal: Windows Tauri Proxy Client
|
||||
|
||||
Use Krypton Execution to execute `docs/goals/windows-modular-client/PLAN.md`.
|
||||
|
||||
Core rules:
|
||||
- Treat `PLAN.md` as the source plan.
|
||||
- Preserve intent, ownership, contract, cutover, evidence, and kill criteria.
|
||||
- Build a separate Tauri 2 Windows desktop app under `apps/windows-client`.
|
||||
- Do not implement Windows by extending the current Node gateway/client server.
|
||||
- Keep Control App, Proxyfier Layer, and Local sing-box separately installable and operable.
|
||||
- Make external proxy target + ProxiFyre profile apply the MVP.
|
||||
- Keep Local sing-box optional; it must not be required for external target profiles.
|
||||
- Keep generated ProxiFyre and sing-box configs derived from source models.
|
||||
- Capture acceptance evidence from the target user's perspective and record it in `EVIDENCE.md`.
|
||||
- Say "implemented but unproven" if Windows-only privileged evidence cannot be captured.
|
||||
|
||||
@@ -1,506 +0,0 @@
|
||||
# Windows Tauri Proxy Client Implementation Plan
|
||||
|
||||
**Intent:** Build a separate Windows desktop proxy management app using Tauri 2, React, TypeScript, and Rust. The app manages three independent components: Control App, Proxyfier Layer, and optional Local sing-box.
|
||||
**Current Behavior:** The repo contains a gateway/client Node + React web application and planning documents for a Windows mode inside that app. A newer product/technology brief now targets a standalone Windows desktop utility instead of extending the existing web control panel.
|
||||
**Expected Outcome:** A compact Windows desktop utility lets the user configure app-level proxy routing through external SOCKS5/HTTP targets first, then optionally install and use local sing-box. The app remains useful when sing-box is absent.
|
||||
**Target-Perspective Output:** A Windows user opens the desktop app, sees Overview, Profiles, Targets, Components, and Logs, adds Discord or another process/folder/exe profile, selects an external proxy target, applies changes to the proxyfier layer, and sees component status plus recent activity. Later, installing Local sing-box adds a local target without changing the profile model.
|
||||
**Truth Owner:** Source configuration lives in the Tauri app's Rust domain model and JSON files under `C:\ProgramData\VpnProxy`. Generated ProxiFyre and sing-box configs are derived artifacts. Privileged install/service operations are owned by explicit helper/installer flows, not by React UI state.
|
||||
**Contract Boundary:** React UI calls typed Tauri commands. Tauri Rust backend validates and persists profiles/targets/components. Proxy routing is behind a `ProxyRouterAdapter` boundary, with ProxiFyre as the first adapter. Privileged operations go through explicit helper/install commands returning structured JSON.
|
||||
**Cutover:** Supersede the prior Node `APP_MODE=windows` implementation direction. Keep existing gateway/client code intact. New Windows work lives under a separate Tauri app slice.
|
||||
**Displaced Path:** The old plan to add Windows mode into `src/server`/`src/web` is demoted to historical context. Do not add a third app mode to the current Node server for this product.
|
||||
**Value Density:** The smallest high-value slice is the desktop app MVP with external SOCKS5 target + ProxiFyre profile apply. Local sing-box is optional and comes after the proxyfier MVP is proven.
|
||||
**Evidence Gate:** Evidence must include target-perspective app proof: built Tauri app or dev window screenshot/state, generated proxyfier config artifact, mocked or real helper response, and manual Windows checklist when privileged components are involved.
|
||||
**Acceptance Evidence:** Automated tests pass for Rust/TypeScript domain logic, app build succeeds, the MVP can create a profile and generate/apply ProxiFyre config against an external target, and Windows manual evidence proves independent component behavior.
|
||||
**Evidence Lane:** Record command output, app screenshots/state payloads, generated configs, and manual verification in `docs/goals/windows-modular-client/EVIDENCE.md`.
|
||||
**Kill Criteria:** No Windows implementation inside current Node gateway/client server; no mandatory sing-box dependency; no generated config as source truth; no hidden installation during profile apply; no direct UI parsing of raw PowerShell/stdout.
|
||||
**Architecture Slice:** New standalone Tauri app under `apps/windows-client`, plus docs updates that point from older Windows plans to this plan.
|
||||
**Plan Review Gate:** Requires PRE review before implementation execution.
|
||||
|
||||
## Source Brief
|
||||
|
||||
Product and technology source brief:
|
||||
|
||||
- `docs/windows-client-product-tech-brief.md`
|
||||
|
||||
This plan turns that brief into an execution-ready implementation sequence.
|
||||
|
||||
## Outcome Contract
|
||||
|
||||
Plan title: Windows Tauri Proxy Client
|
||||
|
||||
Intent: Build a native-feeling Windows utility that manages app-level proxy routing while keeping Control App, Proxyfier Layer, and Local sing-box separately installable and operable.
|
||||
|
||||
Current behavior:
|
||||
- Existing runtime code is a Node HTTP server and Vite/React web UI for gateway and Mac-style client modes.
|
||||
- Earlier Windows docs describe adding Windows mode to that existing app.
|
||||
- The selected direction is now Tauri 2 + React/TypeScript + Rust as a separate Windows desktop app.
|
||||
|
||||
Expected outcome:
|
||||
- `apps/windows-client` contains a Tauri 2 app.
|
||||
- The app has Overview, Profiles, Targets, Components, and Logs surfaces.
|
||||
- Profiles store process/folder/exe source items.
|
||||
- Targets store external proxy endpoints and optional local sing-box.
|
||||
- ProxiFyre is the first proxy router adapter.
|
||||
- Local sing-box is optional and never required for external target profiles.
|
||||
|
||||
Target-perspective output:
|
||||
- User can install/run only the Control App.
|
||||
- User can see Proxyfier and Local sing-box as separate components.
|
||||
- User can add an external SOCKS5 target.
|
||||
- User can add a Discord process profile.
|
||||
- User can apply the profile to generated ProxiFyre config.
|
||||
- User sees activity confirming whether apply succeeded or why it was blocked.
|
||||
|
||||
Truth owner:
|
||||
- Rust core domain crate owns normalized models and validation.
|
||||
- JSON source files under `C:\ProgramData\VpnProxy\config` own persisted profiles/targets/component preferences.
|
||||
- `ProxyRouterAdapter` owns conversion from source models to proxy-router generated config.
|
||||
- `SingBoxAdapter` owns generated local sing-box config and service contract.
|
||||
- React UI owns only transient UI state.
|
||||
|
||||
Contract boundary:
|
||||
- UI -> Tauri commands with typed request/response DTOs.
|
||||
- Tauri commands -> Rust core services.
|
||||
- Core services -> adapter traits.
|
||||
- Adapter traits -> helper/install/service commands when privileged operations are needed.
|
||||
- Helper/install commands return structured JSON, never unstructured text for app logic.
|
||||
|
||||
Cutover:
|
||||
- Add superseded notes to old Windows Node-mode docs.
|
||||
- Keep `docs/windows-client-product-tech-brief.md` as product brief.
|
||||
- Make this `PLAN.md` the execution plan.
|
||||
- Do not implement Windows by adding `APP_MODE=windows` to the current Node server.
|
||||
|
||||
Displaced path:
|
||||
- Displace old "Windows mode in current web app" implementation.
|
||||
- Displace "full install vs ProxiFyre-only" as dominant architecture; those become recipes composed from separate components.
|
||||
|
||||
Value density:
|
||||
- MVP must prove app-level routing with external proxy target and ProxiFyre before local sing-box work expands scope.
|
||||
|
||||
Evidence gate:
|
||||
- Tests and build are not enough.
|
||||
- Capture app-visible state and generated config.
|
||||
- Capture Windows manual evidence for service/helper actions when those tasks execute.
|
||||
|
||||
Acceptance evidence:
|
||||
- `cargo test` or equivalent Rust tests for domain/adapters.
|
||||
- frontend typecheck/test/build for React.
|
||||
- Tauri dev/build command result.
|
||||
- Screenshot or state dump showing Windows app surfaces.
|
||||
- Generated ProxiFyre config from a sample profile.
|
||||
- Manual Windows checklist when privileged components are present.
|
||||
|
||||
Non-goals:
|
||||
- No Electron.
|
||||
- No extension of the current Node gateway/client UI for Windows MVP.
|
||||
- No global Windows system proxy changes.
|
||||
- No transparent routing without a proxy router.
|
||||
- No mandatory local sing-box.
|
||||
- No direct coupling of UI to ProxiFyre-specific config shape.
|
||||
|
||||
Risk if wrong:
|
||||
- If built inside the current Node app, the product will inherit gateway/client assumptions and conflict with the selected Tauri direction.
|
||||
- If ProxiFyre is not behind an adapter, licensing or engine changes will force UI/data rewrites.
|
||||
- If privileged work is hidden behind apply, users lose control and failures become hard to diagnose.
|
||||
|
||||
## Architecture Slice
|
||||
|
||||
Files/directories to create:
|
||||
- `apps/windows-client/package.json`
|
||||
- `apps/windows-client/vite.config.ts`
|
||||
- `apps/windows-client/tsconfig.json`
|
||||
- `apps/windows-client/src/main.tsx`
|
||||
- `apps/windows-client/src/app/App.tsx`
|
||||
- `apps/windows-client/src/app/routes.tsx`
|
||||
- `apps/windows-client/src/api/tauriCommands.ts`
|
||||
- `apps/windows-client/src/domain/types.ts`
|
||||
- `apps/windows-client/src/features/overview/*`
|
||||
- `apps/windows-client/src/features/profiles/*`
|
||||
- `apps/windows-client/src/features/targets/*`
|
||||
- `apps/windows-client/src/features/components/*`
|
||||
- `apps/windows-client/src/features/logs/*`
|
||||
- `apps/windows-client/src/styles/*`
|
||||
- `apps/windows-client/src-tauri/Cargo.toml`
|
||||
- `apps/windows-client/src-tauri/tauri.conf.json`
|
||||
- `apps/windows-client/src-tauri/capabilities/default.json`
|
||||
- `apps/windows-client/src-tauri/src/main.rs`
|
||||
- `apps/windows-client/src-tauri/src/commands.rs`
|
||||
- `apps/windows-client/src-tauri/src/models.rs`
|
||||
- `apps/windows-client/src-tauri/src/storage.rs`
|
||||
- `apps/windows-client/src-tauri/src/activity.rs`
|
||||
- `apps/windows-client/src-tauri/src/adapters/proxy_router.rs`
|
||||
- `apps/windows-client/src-tauri/src/adapters/proxifyre.rs`
|
||||
- `apps/windows-client/src-tauri/src/adapters/singbox.rs`
|
||||
- `apps/windows-client/src-tauri/src/helper.rs`
|
||||
- `apps/windows-client/src-tauri/tests/*`
|
||||
- `apps/windows-client/scripts/install-control-app.ps1`
|
||||
- `apps/windows-client/scripts/install-proxyfier.ps1`
|
||||
- `apps/windows-client/scripts/install-singbox.ps1`
|
||||
|
||||
Files to modify:
|
||||
- `README.md`
|
||||
- `docs/roadmap.md`
|
||||
- `docs/superpowers/specs/2026-05-21-windows-client-design.md`
|
||||
- `docs/superpowers/plans/2026-05-21-windows-client.md`
|
||||
- `docs/goals/windows-modular-client/GOAL.md`
|
||||
- `docs/goals/windows-modular-client/EVIDENCE.md`
|
||||
|
||||
Files to avoid:
|
||||
- `src/server/*` except if a later explicit migration asks for shared code extraction.
|
||||
- `src/web/*` for Windows MVP.
|
||||
- Docker, entrypoint, and compose files.
|
||||
- macOS installer.
|
||||
|
||||
Source of truth:
|
||||
- `C:\ProgramData\VpnProxy\config\profiles.json`
|
||||
- `C:\ProgramData\VpnProxy\config\targets.json`
|
||||
- `C:\ProgramData\VpnProxy\config\components.json`
|
||||
- `C:\ProgramData\VpnProxy\state\activity.json`
|
||||
|
||||
Derived artifacts:
|
||||
- `C:\ProgramData\VpnProxy\generated\proxifyre-app-config.json`
|
||||
- `C:\ProgramData\VpnProxy\generated\sing-box-config.json`
|
||||
- ProxiFyre runtime config copied/backed up by helper/apply operation.
|
||||
|
||||
Read path:
|
||||
- React UI calls Tauri commands.
|
||||
- Tauri commands read JSON source via Rust storage service.
|
||||
- Component status combines source preferences, filesystem checks, service checks, and helper responses.
|
||||
|
||||
Write path:
|
||||
- React UI sends typed mutations.
|
||||
- Rust validates with domain models.
|
||||
- Rust writes source JSON atomically with backups.
|
||||
- Apply generates derived config and invokes adapter/helper.
|
||||
|
||||
Integration points:
|
||||
- ProxiFyre adapter emits `app-config.json` compatible output.
|
||||
- Local sing-box adapter emits `sing-box` JSON config and validates via `sing-box check` when binary exists.
|
||||
- Tauri sidecar/helper permissions are declared explicitly.
|
||||
- Installer scripts may be launched or displayed explicitly, never silently during apply.
|
||||
|
||||
Migration/cutover:
|
||||
- Older Windows docs point to this plan and source brief.
|
||||
- Existing Node app remains gateway/client only.
|
||||
- If shared subscription parsing is needed later, extract it intentionally into a shared package rather than importing server internals.
|
||||
|
||||
Acceptance evidence gate:
|
||||
- MVP evidence must show external-target flow works without local sing-box.
|
||||
- Optional sing-box evidence must show the same profile model can switch targets after installing sing-box.
|
||||
|
||||
## Task Board
|
||||
|
||||
### Task 1: Supersede Old Windows Node Plan
|
||||
|
||||
Owner: main agent
|
||||
|
||||
Input:
|
||||
- `docs/windows-client-product-tech-brief.md`
|
||||
- old Windows docs/plans
|
||||
|
||||
Files allowed:
|
||||
- `docs/superpowers/specs/2026-05-21-windows-client-design.md`
|
||||
- `docs/superpowers/plans/2026-05-21-windows-client.md`
|
||||
- `docs/roadmap.md`
|
||||
- `README.md`
|
||||
|
||||
Files forbidden:
|
||||
- Runtime source files.
|
||||
|
||||
Output:
|
||||
- Old Windows documents clearly point to this Tauri plan and no longer read as implementation authority.
|
||||
|
||||
Evidence:
|
||||
- `rg -n "Tauri|superseded|windows-client-product-tech-brief|apps/windows-client" README.md docs`
|
||||
|
||||
Depends on: none
|
||||
|
||||
Parallel safe: yes
|
||||
|
||||
### Task 2: Scaffold Tauri App Shell
|
||||
|
||||
Owner: main agent
|
||||
|
||||
Input:
|
||||
- Tauri 2 app structure
|
||||
- Product brief UI surfaces
|
||||
|
||||
Files allowed:
|
||||
- `apps/windows-client/package.json`
|
||||
- `apps/windows-client/vite.config.ts`
|
||||
- `apps/windows-client/tsconfig.json`
|
||||
- `apps/windows-client/index.html`
|
||||
- `apps/windows-client/src/*`
|
||||
- `apps/windows-client/src-tauri/*`
|
||||
|
||||
Files forbidden:
|
||||
- Current root `src/server/*`
|
||||
- Current root `src/web/*`
|
||||
|
||||
Output:
|
||||
- Tauri app starts with empty shell and five navigation surfaces.
|
||||
- No business logic yet.
|
||||
|
||||
Evidence:
|
||||
- `cd apps/windows-client && npm install && npm run build`
|
||||
- `cd apps/windows-client/src-tauri && cargo test` if Rust tests exist
|
||||
|
||||
Depends on: Task 1
|
||||
|
||||
Parallel safe: no
|
||||
|
||||
### Task 3: Define Domain Models And Validation
|
||||
|
||||
Owner: main agent
|
||||
|
||||
Input:
|
||||
- Profile/Target/Component models from brief
|
||||
|
||||
Files allowed:
|
||||
- `apps/windows-client/src-tauri/src/models.rs`
|
||||
- `apps/windows-client/src-tauri/src/validation.rs`
|
||||
- `apps/windows-client/src/domain/types.ts`
|
||||
- `apps/windows-client/src-tauri/tests/domain_tests.rs`
|
||||
|
||||
Files forbidden:
|
||||
- Adapter/helper code except trait references.
|
||||
|
||||
Output:
|
||||
- Typed Rust models for `Profile`, `ProfileItem`, `Target`, `ComponentStatus`, `ActivityEntry`.
|
||||
- TypeScript DTOs mirror Rust command responses.
|
||||
- Validation rejects malformed ports/protocols but allows missing local sing-box.
|
||||
|
||||
Evidence:
|
||||
- Rust tests showing process/folder/exe normalization and external target validation.
|
||||
|
||||
Depends on: Task 2
|
||||
|
||||
Parallel safe: no
|
||||
|
||||
### Task 4: Implement JSON Storage And Activity Log
|
||||
|
||||
Owner: main agent
|
||||
|
||||
Input:
|
||||
- Domain models from Task 3
|
||||
|
||||
Files allowed:
|
||||
- `apps/windows-client/src-tauri/src/storage.rs`
|
||||
- `apps/windows-client/src-tauri/src/activity.rs`
|
||||
- `apps/windows-client/src-tauri/tests/storage_tests.rs`
|
||||
|
||||
Files forbidden:
|
||||
- UI screens except command wiring stubs.
|
||||
|
||||
Output:
|
||||
- Atomic JSON read/write for profiles, targets, components, and activity.
|
||||
- Backups before overwriting source files.
|
||||
- Config root defaults to `C:\ProgramData\VpnProxy`, with test override.
|
||||
|
||||
Evidence:
|
||||
- Tests prove roundtrip, invalid JSON fallback behavior, backup creation, activity cap/sort.
|
||||
|
||||
Depends on: Task 3
|
||||
|
||||
Parallel safe: no
|
||||
|
||||
### Task 5: Add Proxy Router Adapter Boundary And ProxiFyre Adapter
|
||||
|
||||
Owner: main agent
|
||||
|
||||
Input:
|
||||
- Domain models and storage
|
||||
|
||||
Files allowed:
|
||||
- `apps/windows-client/src-tauri/src/adapters/proxy_router.rs`
|
||||
- `apps/windows-client/src-tauri/src/adapters/proxifyre.rs`
|
||||
- `apps/windows-client/src-tauri/tests/proxifyre_adapter_tests.rs`
|
||||
|
||||
Files forbidden:
|
||||
- Direct UI coupling to ProxiFyre config fields.
|
||||
|
||||
Output:
|
||||
- `ProxyRouterAdapter` trait.
|
||||
- `ProxiFyreAdapter` generates config from enabled profiles and targets.
|
||||
- External target flow does not require sing-box.
|
||||
|
||||
Evidence:
|
||||
- Test generates ProxiFyre config for Discord + external SOCKS5 target.
|
||||
- Test blocks local-singbox target only when target requires missing component.
|
||||
|
||||
Depends on: Task 4
|
||||
|
||||
Parallel safe: no
|
||||
|
||||
### Task 6: Add Tauri Commands
|
||||
|
||||
Owner: main agent
|
||||
|
||||
Input:
|
||||
- Storage and adapter services
|
||||
|
||||
Files allowed:
|
||||
- `apps/windows-client/src-tauri/src/commands.rs`
|
||||
- `apps/windows-client/src-tauri/src/main.rs`
|
||||
- `apps/windows-client/src/api/tauriCommands.ts`
|
||||
- `apps/windows-client/src-tauri/tests/command_tests.rs`
|
||||
|
||||
Files forbidden:
|
||||
- Full UI implementation beyond command call wrappers.
|
||||
|
||||
Output:
|
||||
- Commands for status, profiles, targets, components, scan/resolve preview, apply, logs.
|
||||
- Commands return structured responses only.
|
||||
|
||||
Evidence:
|
||||
- Command tests or integration tests prove apply generates derived config and records activity using a mock adapter/helper.
|
||||
|
||||
Depends on: Task 5
|
||||
|
||||
Parallel safe: no
|
||||
|
||||
### Task 7: Build MVP UI
|
||||
|
||||
Owner: main agent
|
||||
|
||||
Input:
|
||||
- Tauri command API
|
||||
- Product brief layout
|
||||
|
||||
Files allowed:
|
||||
- `apps/windows-client/src/app/*`
|
||||
- `apps/windows-client/src/features/overview/*`
|
||||
- `apps/windows-client/src/features/profiles/*`
|
||||
- `apps/windows-client/src/features/targets/*`
|
||||
- `apps/windows-client/src/features/components/*`
|
||||
- `apps/windows-client/src/features/logs/*`
|
||||
- `apps/windows-client/src/styles/*`
|
||||
|
||||
Files forbidden:
|
||||
- Rust adapter behavior except fixing DTO mismatches.
|
||||
|
||||
Output:
|
||||
- Compact utility UI with Overview, Profiles, Targets, Components, Logs.
|
||||
- User can create/edit profile, external target, and trigger apply.
|
||||
- Missing sing-box is shown as valid optional state.
|
||||
|
||||
Evidence:
|
||||
- `npm run build`
|
||||
- Screenshot or browser/app state showing missing sing-box and usable external target flow.
|
||||
|
||||
Depends on: Task 6
|
||||
|
||||
Parallel safe: no
|
||||
|
||||
### Task 8: Implement Helper And Explicit Installer Boundary
|
||||
|
||||
Owner: main agent
|
||||
|
||||
Input:
|
||||
- Component model
|
||||
- Security model from brief
|
||||
|
||||
Files allowed:
|
||||
- `apps/windows-client/src-tauri/src/helper.rs`
|
||||
- `apps/windows-client/src-tauri/capabilities/default.json`
|
||||
- `apps/windows-client/scripts/install-control-app.ps1`
|
||||
- `apps/windows-client/scripts/install-proxyfier.ps1`
|
||||
- `apps/windows-client/scripts/install-singbox.ps1`
|
||||
- `apps/windows-client/src-tauri/tests/helper_tests.rs`
|
||||
|
||||
Files forbidden:
|
||||
- Hidden installer invocation inside profile apply.
|
||||
|
||||
Output:
|
||||
- Helper command abstraction for status/service/apply.
|
||||
- Installer scripts are explicit and idempotent.
|
||||
- Tauri sidecar/shell permissions are narrow and documented.
|
||||
|
||||
Evidence:
|
||||
- Helper tests with mock command runner.
|
||||
- PowerShell parser checks for installer scripts.
|
||||
- Capability file shows limited sidecar permissions.
|
||||
|
||||
Depends on: Task 6
|
||||
|
||||
Parallel safe: partly, after command DTOs are stable
|
||||
|
||||
### Task 9: Add Optional Local Sing-Box Adapter
|
||||
|
||||
Owner: main agent
|
||||
|
||||
Input:
|
||||
- sing-box target model
|
||||
- service/helper boundary
|
||||
|
||||
Files allowed:
|
||||
- `apps/windows-client/src-tauri/src/adapters/singbox.rs`
|
||||
- `apps/windows-client/src-tauri/tests/singbox_adapter_tests.rs`
|
||||
- `apps/windows-client/src/features/components/*`
|
||||
- `apps/windows-client/src/features/targets/*`
|
||||
|
||||
Files forbidden:
|
||||
- Making sing-box mandatory for external targets.
|
||||
|
||||
Output:
|
||||
- Generate local sing-box config.
|
||||
- Validate via `sing-box check` when binary exists.
|
||||
- Local target appears only when installed/configured or as an explicit install prompt.
|
||||
|
||||
Evidence:
|
||||
- Tests show external target apply works without sing-box.
|
||||
- Tests show local-singbox target requires installed/running component.
|
||||
|
||||
Depends on: Tasks 5 and 8
|
||||
|
||||
Parallel safe: no
|
||||
|
||||
### Task 10: Package, Verify, And Record Evidence
|
||||
|
||||
Owner: main agent
|
||||
|
||||
Input:
|
||||
- Completed MVP implementation
|
||||
|
||||
Files allowed:
|
||||
- `apps/windows-client/*`
|
||||
- `README.md`
|
||||
- `docs/roadmap.md`
|
||||
- `docs/goals/windows-modular-client/EVIDENCE.md`
|
||||
|
||||
Files forbidden:
|
||||
- Unrelated app code.
|
||||
|
||||
Output:
|
||||
- Build/test commands documented.
|
||||
- README explains separate Control App, Proxyfier, and Local sing-box install flows.
|
||||
- Evidence file captures automated and target-perspective proof.
|
||||
|
||||
Evidence:
|
||||
- `npm run build`
|
||||
- Rust tests
|
||||
- Tauri build/dev proof
|
||||
- generated ProxiFyre config summary
|
||||
- UI screenshot/state
|
||||
- Windows manual checklist, or clearly mark `implemented but unproven` for Windows-only service behavior if not run on a Windows host.
|
||||
|
||||
Depends on: all previous tasks
|
||||
|
||||
Parallel safe: no
|
||||
|
||||
## Manual Windows Verification Checklist
|
||||
|
||||
1. Install/run only Control App.
|
||||
2. Verify Proxyfier and Local sing-box show missing as separate components.
|
||||
3. Add external SOCKS5 target.
|
||||
4. Add Discord process profile.
|
||||
5. Apply profile; verify generated ProxiFyre config and activity entry.
|
||||
6. Install Proxyfier separately; verify status changes.
|
||||
7. Apply profile to real Proxyfier service.
|
||||
8. Install Local sing-box separately.
|
||||
9. Import subscription or config, select outbound, and start Local sing-box.
|
||||
10. Switch existing profile from external target to Local sing-box and apply.
|
||||
11. Stop/restart Proxyfier and Local sing-box separately.
|
||||
12. Copy diagnostics and verify secrets are redacted.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
| --- | --- | --- | --- |
|
||||
| `gateway` | LXC/VPS как gateway для роутера и всей сети | Docker `network_mode: host` + TProxy | делаем первым |
|
||||
| `desktop-proxy` | Mac/Linux локальный HTTP/SOCKS proxy с fallback | Docker bridged ports | позже переносим из старой реализации |
|
||||
| `windows-gaming` | Windows для игр/Discord/Vesktop | standalone Tauri 2 app + ProxiFyre adapter + optional native `sing-box.exe` | активное направление: `docs/goals/windows-modular-client/PLAN.md` |
|
||||
| `windows-gaming` | Windows для игр/Discord/Vesktop | standalone Tauri 2 app + ProxiFyre adapter + optional native `sing-box.exe` | вынесено в `D:\repos\ProxyWarden` |
|
||||
|
||||
## Gateway mode
|
||||
|
||||
@@ -86,30 +86,7 @@
|
||||
|
||||
Цель: отдельное Windows desktop-приложение для Discord/Vesktop/игр, где Control App, Proxyfier Layer и Local sing-box являются независимыми компонентами.
|
||||
|
||||
Current checkpoint:
|
||||
|
||||
- MVP slice exists under `apps/windows-client`.
|
||||
- Frontend build passes with `npm run build`.
|
||||
- Rust/Tauri native verification requires installing Rust/rustup and Visual Studio Build Tools with MSVC/Windows SDK.
|
||||
- Local sing-box is optional; external SOCKS5 targets remain the first verified path.
|
||||
|
||||
Требования:
|
||||
|
||||
- Standalone Tauri 2 + React/TypeScript + Rust app under `apps/windows-client`.
|
||||
- Profiles for process/folder/exe app routing.
|
||||
- External SOCKS5/HTTP targets first; local `sing-box` is optional.
|
||||
- Proxyfier adapter boundary with ProxiFyre as the first engine.
|
||||
- Explicit installers for Control App, Proxyfier Layer, and Local sing-box.
|
||||
- Privileged helper/install operations return structured JSON.
|
||||
|
||||
Source docs:
|
||||
|
||||
- Product/tech brief: `docs/windows-client-product-tech-brief.md`.
|
||||
- Execution plan: `docs/goals/windows-modular-client/PLAN.md`.
|
||||
|
||||
Superseded:
|
||||
|
||||
- The old Node `APP_MODE=windows` plan in `docs/superpowers/plans/2026-05-21-windows-client.md` is historical context, not the active implementation path.
|
||||
Статус: вынесено в соседний репозиторий `D:\repos\ProxyWarden`. Этот репозиторий больше не содержит Tauri Windows app, Windows-specific планы/evidence или installer scripts.
|
||||
|
||||
## Рабочий порядок
|
||||
|
||||
@@ -119,4 +96,4 @@ Superseded:
|
||||
4. Реализовать Vite + React UI для subscription -> server select -> apply.
|
||||
5. Добавить gateway docs/install script.
|
||||
6. Потом переносить desktop-proxy.
|
||||
7. Потом реализовать standalone Windows Tauri client по `docs/goals/windows-modular-client/PLAN.md`.
|
||||
7. Windows desktop client развивать в `D:\repos\ProxyWarden`.
|
||||
|
||||
@@ -1,236 +0,0 @@
|
||||
# Windows Client Design
|
||||
|
||||
> Superseded: this document describes the earlier Node/web-control Windows direction.
|
||||
> The active Windows direction is a standalone Tauri 2 desktop app under
|
||||
> `apps/windows-client`, driven by `docs/windows-client-product-tech-brief.md`
|
||||
> and `docs/goals/windows-modular-client/PLAN.md`.
|
||||
> Content below is retained for historical context and may contradict the active
|
||||
> Tauri plan.
|
||||
|
||||
## Goal
|
||||
|
||||
Restore the old Windows workflow in a cleaner product shape: a one-command PowerShell installer can install either a full local `sing-box` + ProxiFyre setup or ProxiFyre-only routing to an existing proxy, then expose a small local web UI for profiles, folders, executable files, status, and logs.
|
||||
|
||||
## Product Shape
|
||||
|
||||
The Windows mode is script-first and UI-assisted. The installer remains the durable entrypoint because Windows driver/service setup needs administrator rights and must stay easy to debug from PowerShell. The web UI is a local control surface on top of the same scripts, not a separate desktop app in the first version.
|
||||
|
||||
The installer supports two paths:
|
||||
|
||||
- **Full install:** install native `sing-box.exe`, configure a local SOCKS/HTTP proxy on `127.0.0.1:1080`, install WinPacketFilter and ProxiFyre, then route selected Windows apps through the local proxy.
|
||||
- **ProxiFyre only:** install WinPacketFilter and ProxiFyre, then point selected Windows apps to an existing proxy target such as `127.0.0.1:8080`, `192.168.50.111:8080`, or another reachable SOCKS5 endpoint.
|
||||
|
||||
The default UI direction is the approved cleaner mockup: one route status, profiles as the main object, selected profile details on the right, and a short recent activity/log section below. The first screen should answer: what is the active proxy target, whether services are running, and which profiles are currently enabled.
|
||||
|
||||
## User Flows
|
||||
|
||||
### Install
|
||||
|
||||
The user opens PowerShell 7 as Administrator and runs:
|
||||
|
||||
```powershell
|
||||
irm https://git.dokops.ru/dokril/vpn-proxy/raw/branch/master/scripts/install-windows-client.ps1 | iex
|
||||
```
|
||||
|
||||
The installer checks administrator rights, PowerShell version, architecture, internet access, and required paths. It installs under `C:\Tools\vpn-proxy-windows` and keeps third-party runtime files in focused subdirectories:
|
||||
|
||||
- `C:\Tools\vpn-proxy-windows\app` for this project checkout or archive.
|
||||
- `C:\Tools\vpn-proxy-windows\runtime\node` for portable Node.js when no suitable Node is installed.
|
||||
- `C:\Tools\vpn-proxy-windows\runtime\sing-box` for `sing-box.exe`, config, and logs.
|
||||
- `C:\Tools\ProxiFyre` for ProxiFyre, matching the legacy script path.
|
||||
|
||||
If the user chooses Full install, the installer asks for a subscription or VLESS link, parses it through the existing subscription logic where possible, lets the user select a server, writes the native `sing-box` config, installs a scheduled task for `sing-box`, and starts it.
|
||||
|
||||
If the user chooses ProxiFyre only, the installer asks for a SOCKS5 proxy target and verifies TCP connectivity before writing ProxiFyre config.
|
||||
|
||||
After setup, the installer starts the local control UI on `http://127.0.0.1:3456` and prints recovery commands:
|
||||
|
||||
```powershell
|
||||
& "C:\Tools\vpn-proxy-windows\manage.ps1"
|
||||
& "C:\Tools\vpn-proxy-windows\manage.ps1" -OpenUi
|
||||
& "C:\Tools\vpn-proxy-windows\manage.ps1" -Status
|
||||
```
|
||||
|
||||
### Profile Management
|
||||
|
||||
Profiles are the central unit. A profile contains a name, enabled flag, proxy target, protocol list, and app items. Supported item types:
|
||||
|
||||
- `process`: process name such as `Discord`, `Update`, or `Vesktop`.
|
||||
- `folder`: folder path; the system scans `.exe` files and converts them to routable entries.
|
||||
- `exe`: explicit executable file path; the system resolves it to the executable name for ProxiFyre and keeps the full path for display and diagnostics.
|
||||
|
||||
Folder and exe entries are intentionally stored as user-facing source items, while the generated ProxiFyre config is derived. This keeps the UI understandable and makes future ProxiFyre/Proxifier adapter changes possible without changing the profile model.
|
||||
|
||||
When a profile changes, the UI marks it as pending. The user applies changes once. Apply regenerates ProxiFyre `app-config.json`, restarts the ProxiFyre service, then writes an activity entry showing what changed.
|
||||
|
||||
### Runtime Operations
|
||||
|
||||
The UI exposes these actions:
|
||||
|
||||
- start, stop, restart `sing-box` when local mode is installed;
|
||||
- start, stop, restart ProxiFyre;
|
||||
- switch a profile between `local-singbox` and an external proxy target;
|
||||
- add process, folder, or exe entries;
|
||||
- scan folder entries again;
|
||||
- copy diagnostics for support/debugging;
|
||||
- open logs.
|
||||
|
||||
The UI does not auto-change global Windows proxy settings. Routing happens only through ProxiFyre profiles.
|
||||
|
||||
## Architecture
|
||||
|
||||
The active project already has a plain Node API server, React/Vite UI, subscription parser, `sing-box` config generator, logs, traffic parsing, and client/gateway modes. Windows mode should reuse those pieces and add a Windows helper boundary.
|
||||
|
||||
### App Mode
|
||||
|
||||
Add `APP_MODE=windows`. In Windows mode:
|
||||
|
||||
- the HTTP server binds to `127.0.0.1`;
|
||||
- the UI uses Windows labels and hides gateway-only TProxy/device controls;
|
||||
- config generation is proxy-only like client mode, but it targets native `sing-box.exe` rather than Docker;
|
||||
- service and driver actions go through the PowerShell helper, not direct Node assumptions.
|
||||
|
||||
### Windows Helper Boundary
|
||||
|
||||
Create a PowerShell helper module that owns privileged Windows operations:
|
||||
|
||||
- install/update `sing-box.exe`;
|
||||
- install/start/stop scheduled tasks;
|
||||
- install/update WinPacketFilter;
|
||||
- install/update ProxiFyre;
|
||||
- write ProxiFyre config;
|
||||
- query service/task status;
|
||||
- read recent log files;
|
||||
- test proxy connectivity;
|
||||
- manage firewall rules for local proxy ports.
|
||||
|
||||
The Node server calls the helper with explicit command names and JSON input/output. The helper returns structured JSON for every operation:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"action": "proxies.apply",
|
||||
"changed": true,
|
||||
"message": "ProxiFyre config applied and service restarted"
|
||||
}
|
||||
```
|
||||
|
||||
Errors use the same shape with `success: false`, `error`, and optional `details`. The UI never parses raw PowerShell text.
|
||||
|
||||
### Data Files
|
||||
|
||||
Windows mode stores state under `C:\Tools\vpn-proxy-windows\data`:
|
||||
|
||||
- `windows-profiles.json` for profile source data.
|
||||
- `proxy-targets.json` for `local-singbox` and external proxy targets.
|
||||
- `windows-state.json` for last applied profile revision and UI status.
|
||||
- `subscription-cache.json` and `state.json` stay compatible with existing subscription/server selection logic.
|
||||
|
||||
Profile shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "discord-vesktop",
|
||||
"name": "Discord + Vesktop",
|
||||
"enabled": true,
|
||||
"proxyTargetId": "local-singbox",
|
||||
"protocols": ["TCP", "UDP"],
|
||||
"items": [
|
||||
{ "type": "process", "value": "Discord" },
|
||||
{ "type": "process", "value": "Update" },
|
||||
{
|
||||
"type": "folder",
|
||||
"value": "%LOCALAPPDATA%\\vesktop",
|
||||
"recursive": true
|
||||
},
|
||||
{
|
||||
"type": "exe",
|
||||
"value": "C:\\Games\\SomeGame\\game.exe"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Generated ProxiFyre config is not edited directly. It is derived from enabled profiles and proxy targets, then written to `C:\Tools\ProxiFyre\app-config.json`.
|
||||
|
||||
### API Surface
|
||||
|
||||
Add Windows-specific endpoints:
|
||||
|
||||
- `GET /api/windows/status`: returns install mode, `sing-box` status, ProxiFyre status, active target, pending changes, and recent activity.
|
||||
- `GET /api/windows/profiles`: returns profile source data with resolved executable counts.
|
||||
- `PUT /api/windows/profiles`: saves profiles without applying.
|
||||
- `POST /api/windows/profiles/apply`: generates ProxiFyre config and restarts service.
|
||||
- `POST /api/windows/profiles/scan`: resolves folder and exe entries for preview.
|
||||
- `GET /api/windows/targets`: returns `local-singbox` and external proxy targets.
|
||||
- `PUT /api/windows/targets`: saves external proxy targets after validation.
|
||||
- `POST /api/windows/service`: start, stop, or restart `sing-box`, ProxiFyre, or the UI service.
|
||||
- `GET /api/windows/logs`: returns recent helper, `sing-box`, and ProxiFyre logs.
|
||||
|
||||
Existing generic endpoints for subscription fetch, server selection, apply, logs, and config validation should be reused where the behavior matches Windows mode.
|
||||
|
||||
## UI Design
|
||||
|
||||
The approved direction is a restrained operational UI:
|
||||
|
||||
- top bar: product name, restart/stop/add profile actions;
|
||||
- left nav: Overview, Profiles, Targets, Logs, Settings;
|
||||
- main status panel: one sentence describing the active route, plus a compact route line such as `Selected apps -> ProxiFyre -> sing-box -> VPN`;
|
||||
- main workspace: profile list on the left, selected profile details on the right;
|
||||
- profile details: target selector, add process/folder/exe input, resolved items list, save/apply controls;
|
||||
- activity panel: recent traffic/service events, not a full noisy log dump.
|
||||
|
||||
Avoid duplicate status blocks. Avoid showing raw implementation concepts like WinPacketFilter unless the user is in diagnostics/settings. The primary terms should be `Profile`, `Proxy target`, `Local sing-box`, `Existing proxy`, `App/folder/exe`, and `Apply changes`.
|
||||
|
||||
## Safety And Constraints
|
||||
|
||||
The UI binds only to `127.0.0.1`. Windows actions that require elevation stay in the installer/helper path. The installer must not delete existing `C:\Tools\vpn-proxy` legacy folders without confirmation.
|
||||
|
||||
Folder and exe routing needs a clear diagnostic note: ProxiFyre routing ultimately depends on what the installed ProxiFyre version accepts. The first implementation should resolve folders and exe paths to executable names for compatibility, while preserving full paths in profile data and diagnostics. If direct path matching is verified in ProxiFyre, the adapter can emit full paths without changing the UI model.
|
||||
|
||||
The installer should be idempotent:
|
||||
|
||||
- re-running it updates project files;
|
||||
- existing subscriptions and profiles are preserved unless the user chooses reset;
|
||||
- existing ProxiFyre config is backed up before overwrite;
|
||||
- failed applies leave the previous generated config available for rollback.
|
||||
|
||||
## Testing And Verification
|
||||
|
||||
Use focused tests for pure logic:
|
||||
|
||||
- profile normalization;
|
||||
- folder/exe item resolution;
|
||||
- ProxiFyre config generation;
|
||||
- proxy target validation;
|
||||
- Windows helper JSON command contract;
|
||||
- `APP_MODE=windows` public state and config generation.
|
||||
|
||||
Use manual Windows verification for privileged operations:
|
||||
|
||||
- fresh Full install;
|
||||
- fresh ProxiFyre-only install;
|
||||
- re-run installer over existing install;
|
||||
- add process profile;
|
||||
- add folder profile;
|
||||
- add explicit exe profile;
|
||||
- switch a profile from local sing-box to external proxy;
|
||||
- restart ProxiFyre and verify service status;
|
||||
- copy diagnostics after a failed proxy target check.
|
||||
|
||||
Local non-Windows development should still run `npm test` and `npm run build`. Windows-only helper commands should have dry-run or mockable modes so logic can be tested without installing drivers on the development machine.
|
||||
|
||||
## Non-Goals For First Version
|
||||
|
||||
- No Electron or Tauri wrapper.
|
||||
- No global Windows system proxy changes.
|
||||
- No transparent routing without ProxiFyre.
|
||||
- No remote multi-device management.
|
||||
- No automatic uninstall of unrelated WinPacketFilter users.
|
||||
- No Proxifier support until ProxiFyre behavior is stable.
|
||||
|
||||
## Implementation Defaults
|
||||
|
||||
- The UI server runs when opened by `manage.ps1 -OpenUi` in the first version. An at-logon scheduled UI task can be added later after the helper and UI are stable.
|
||||
- Full install uses portable Node/npm when the machine has no suitable Node.js. The installer builds the React UI locally for MVP; a prebuilt release artifact can replace that later without changing user-facing behavior.
|
||||
- ProxiFyre generation emits process names in the first version for compatibility. Full folder and exe paths remain in profile data and diagnostics; the adapter can start emitting full paths later if ProxiFyre path matching is verified.
|
||||
@@ -1,635 +0,0 @@
|
||||
# Windows Proxy Client: Product And Technology Brief
|
||||
|
||||
Дата: 2026-07-03
|
||||
|
||||
Цель документа: описать, как должно выглядеть и работать Windows-приложение для управления proxy/VPN-маршрутизацией приложений, и какой стек лучше использовать для реализации.
|
||||
|
||||
Этот документ можно отдать другой модели или команде как исходное ТЗ.
|
||||
|
||||
## Коротко
|
||||
|
||||
Нужно Windows-приложение, которое разделяет систему на три независимые части:
|
||||
|
||||
1. **Control App**: маленькое desktop-приложение для настройки, статуса, профилей, логов и запуска операций.
|
||||
2. **Proxyfier Layer**: отдельный компонент, который заставляет выбранные Windows-приложения ходить через SOCKS5/HTTP proxy, даже если они сами не умеют proxy.
|
||||
3. **Local sing-box**: опциональный локальный VPN/proxy runtime. Его можно установить, не устанавливать, остановить, заменить внешним proxy target.
|
||||
|
||||
Главный принцип: пользователь не обязан ставить все сразу. Если у него уже есть proxy, ему нужны только Control App + Proxyfier. Если нужен локальный VPN-клиент, он отдельно ставит `sing-box`.
|
||||
|
||||
## Как это должно выглядеть
|
||||
|
||||
Приложение должно выглядеть как компактная системная утилита, а не как сайт.
|
||||
|
||||
Главный экран:
|
||||
|
||||
- верхняя строка: общий статус маршрута;
|
||||
- три карточки компонентов: `Control App`, `Proxyfier`, `Local sing-box`;
|
||||
- список активных профилей;
|
||||
- кнопка `Apply changes`;
|
||||
- короткая лента последних событий.
|
||||
|
||||
Пример главного статуса:
|
||||
|
||||
```text
|
||||
Selected apps -> ProxiFyre -> Local sing-box 127.0.0.1:1080 -> VPN
|
||||
```
|
||||
|
||||
или:
|
||||
|
||||
```text
|
||||
Selected apps -> ProxiFyre -> Existing proxy 192.168.50.111:8080
|
||||
```
|
||||
|
||||
Если `sing-box` не установлен, это не ошибка. Карточка должна показывать:
|
||||
|
||||
```text
|
||||
Local sing-box
|
||||
Not installed
|
||||
Install if you want this PC to run its own local VPN proxy.
|
||||
```
|
||||
|
||||
Если Proxyfier не установлен, профили можно редактировать, но apply должен быть заблокирован:
|
||||
|
||||
```text
|
||||
Proxyfier is required to route selected apps.
|
||||
Install Proxyfier
|
||||
```
|
||||
|
||||
## Основные экраны
|
||||
|
||||
### 1. Overview
|
||||
|
||||
Показывает:
|
||||
|
||||
- текущий route line;
|
||||
- статус Control App;
|
||||
- статус Proxyfier;
|
||||
- статус Local sing-box;
|
||||
- активный proxy target;
|
||||
- сколько приложений сейчас включено в routing;
|
||||
- последние 5-10 событий.
|
||||
|
||||
Действия:
|
||||
|
||||
- restart Proxyfier;
|
||||
- restart local sing-box, если установлен;
|
||||
- open logs;
|
||||
- copy diagnostics.
|
||||
|
||||
### 2. Profiles
|
||||
|
||||
Профиль - главный объект настройки.
|
||||
|
||||
Профиль содержит:
|
||||
|
||||
- название;
|
||||
- enabled/disabled;
|
||||
- proxy target;
|
||||
- протоколы: TCP, UDP;
|
||||
- список приложений.
|
||||
|
||||
Типы элементов:
|
||||
|
||||
- `process`: имя процесса, например `Discord`, `Telegram`, `Code`;
|
||||
- `folder`: папка, приложение сканирует `.exe` внутри;
|
||||
- `exe`: конкретный путь к `.exe`.
|
||||
|
||||
UI профиля:
|
||||
|
||||
- слева список профилей;
|
||||
- справа детали выбранного профиля;
|
||||
- поле выбора target;
|
||||
- кнопки добавления: `Process`, `Folder`, `EXE`;
|
||||
- preview resolved apps;
|
||||
- `Save`;
|
||||
- `Apply changes`.
|
||||
|
||||
Важно: пользователь должен видеть понятные исходные элементы, а не только сгенерированный конфиг Proxyfier.
|
||||
|
||||
### 3. Targets
|
||||
|
||||
Proxy target - это куда Proxyfier отправляет трафик выбранных приложений.
|
||||
|
||||
Типы targets:
|
||||
|
||||
- `Local sing-box`: `127.0.0.1:1080`, доступен только если local sing-box установлен и запущен;
|
||||
- `Existing SOCKS5 proxy`: например `127.0.0.1:8080` или `192.168.50.111:8080`;
|
||||
- `Existing HTTP proxy`, если выбранный proxyfier поддерживает HTTP.
|
||||
|
||||
На экране targets:
|
||||
|
||||
- список targets;
|
||||
- проверка соединения;
|
||||
- имя, host, port, protocol;
|
||||
- статус last checked;
|
||||
- кнопка set default.
|
||||
|
||||
### 4. Components
|
||||
|
||||
Отдельный экран или часть Overview.
|
||||
|
||||
Компоненты:
|
||||
|
||||
- Control App;
|
||||
- Proxyfier;
|
||||
- Local sing-box.
|
||||
|
||||
Для каждого:
|
||||
|
||||
- installed / not installed;
|
||||
- running / stopped;
|
||||
- version;
|
||||
- path;
|
||||
- service/task status;
|
||||
- actions.
|
||||
|
||||
Actions должны быть явными:
|
||||
|
||||
- `Install`;
|
||||
- `Repair`;
|
||||
- `Start`;
|
||||
- `Stop`;
|
||||
- `Restart`;
|
||||
- `Open folder`;
|
||||
- `View logs`.
|
||||
|
||||
Нельзя делать скрытую установку `sing-box` при сохранении профиля.
|
||||
|
||||
### 5. Logs / Diagnostics
|
||||
|
||||
Должно быть две зоны:
|
||||
|
||||
- activity: действия пользователя и результат apply;
|
||||
- runtime logs: proxyfier logs, sing-box logs, helper logs.
|
||||
|
||||
Кнопка `Copy diagnostics` должна собирать:
|
||||
|
||||
- версии компонентов;
|
||||
- paths;
|
||||
- running status;
|
||||
- активные profiles;
|
||||
- targets без секретов;
|
||||
- последние ошибки;
|
||||
- путь к сгенерированному proxyfier config.
|
||||
|
||||
## Пользовательские сценарии
|
||||
|
||||
### Сценарий A: у пользователя уже есть proxy
|
||||
|
||||
1. Пользователь устанавливает Control App.
|
||||
2. Открывает приложение.
|
||||
3. Видит, что Proxyfier не установлен, а sing-box отсутствует.
|
||||
4. Нажимает `Install Proxyfier`.
|
||||
5. Добавляет target `192.168.50.111:8080`.
|
||||
6. Создает профиль `Discord`.
|
||||
7. Добавляет process `Discord`.
|
||||
8. Нажимает `Apply changes`.
|
||||
9. Приложение генерирует config для Proxyfier и перезапускает proxyfier service.
|
||||
|
||||
Результат: Discord ходит через внешний proxy. Local sing-box не нужен.
|
||||
|
||||
### Сценарий B: пользователь хочет локальный VPN proxy
|
||||
|
||||
1. Пользователь устанавливает Control App.
|
||||
2. Устанавливает Proxyfier.
|
||||
3. Устанавливает Local sing-box.
|
||||
4. Вводит subscription/VLESS link.
|
||||
5. Выбирает сервер.
|
||||
6. Local sing-box поднимает SOCKS5/HTTP endpoint на `127.0.0.1:1080`.
|
||||
7. Профили используют target `Local sing-box`.
|
||||
|
||||
Результат: выбранные приложения ходят через локальный sing-box.
|
||||
|
||||
### Сценарий C: временно отключить VPN
|
||||
|
||||
1. Пользователь открывает профиль.
|
||||
2. Меняет target с `Local sing-box` на внешний proxy или `Direct/Disabled`.
|
||||
3. Нажимает `Apply changes`.
|
||||
|
||||
Результат: Proxyfier перегенерирован, local sing-box можно остановить отдельно.
|
||||
|
||||
## Рекомендуемый стек
|
||||
|
||||
### Desktop shell: Tauri 2
|
||||
|
||||
Рекомендация: **Tauri 2 + React + TypeScript + Rust backend**.
|
||||
|
||||
Почему:
|
||||
|
||||
- Tauri ориентирован на маленькие desktop-приложения и использует системный web renderer, поэтому приложение легче Electron.
|
||||
- Можно писать UI на обычном web stack: React/TypeScript/Vite.
|
||||
- Backend-часть на Rust хорошо подходит для Windows APIs, файлов, процессов, sidecar binaries и безопасных команд.
|
||||
- Tauri поддерживает sidecar binaries, но требует явно выдать permissions на запуск sidecar, что полезно для security boundary.
|
||||
|
||||
Frontend:
|
||||
|
||||
- React;
|
||||
- TypeScript;
|
||||
- Vite;
|
||||
- TanStack Query для загрузки/кэша status/API;
|
||||
- Zustand или Jotai для локального UI state;
|
||||
- Zod для валидации JSON-моделей;
|
||||
- CSS modules или Tailwind. Для этой утилиты лучше сдержанный Windows-like UI, без тяжелой дизайн-системы.
|
||||
|
||||
Backend внутри Tauri:
|
||||
|
||||
- Rust commands для простых операций;
|
||||
- отдельный `core` crate с доменной логикой;
|
||||
- отдельный `windows-helper` binary для elevated/privileged действий.
|
||||
|
||||
Не рекомендую начинать с Electron, если нет жесткой причины. Electron проще для web-команды, но тяжелее по размеру и памяти. Для маленькой системной утилиты Tauri подходит лучше.
|
||||
|
||||
### Privileged helper
|
||||
|
||||
Нужно отделить обычное приложение от операций администратора.
|
||||
|
||||
Рекомендуемая модель:
|
||||
|
||||
```text
|
||||
Tauri UI
|
||||
-> Rust app backend
|
||||
-> unprivileged status/read operations
|
||||
-> explicit elevated helper for install/repair/service operations
|
||||
```
|
||||
|
||||
Privileged helper может быть:
|
||||
|
||||
- Rust CLI, который запускается elevated только для конкретной операции;
|
||||
- Rust Windows service/helper, если нужен постоянный privileged agent;
|
||||
- PowerShell scripts только как thin installer layer, не как основная бизнес-логика.
|
||||
|
||||
Для MVP можно сделать проще:
|
||||
|
||||
- installers запускаются отдельно от имени администратора;
|
||||
- Control App работает обычным пользователем;
|
||||
- service start/stop/restart идет через helper command;
|
||||
- helper возвращает JSON, UI не парсит текст PowerShell.
|
||||
|
||||
Контракт helper:
|
||||
|
||||
```json
|
||||
{
|
||||
"action": "proxyfier.apply",
|
||||
"payload": {
|
||||
"configPath": "C:\\Tools\\ProxiFyre\\app-config.json",
|
||||
"config": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Ответ:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"action": "proxyfier.apply",
|
||||
"changed": true,
|
||||
"message": "Proxyfier config applied and service restarted"
|
||||
}
|
||||
```
|
||||
|
||||
Ошибки:
|
||||
|
||||
```json
|
||||
{
|
||||
"success": false,
|
||||
"action": "proxyfier.apply",
|
||||
"error": "Proxyfier service is not installed",
|
||||
"details": {}
|
||||
}
|
||||
```
|
||||
|
||||
### Service/runtime management
|
||||
|
||||
Для `sing-box` как background runtime:
|
||||
|
||||
- использовать `sing-box check` перед применением config;
|
||||
- хранить config отдельно;
|
||||
- запускать как Windows service или scheduled task;
|
||||
- для service wrapper можно использовать WinSW, если не хочется писать собственный Windows service wrapper.
|
||||
|
||||
Практичный вариант:
|
||||
|
||||
- v1: WinSW wraps `sing-box.exe`;
|
||||
- v2: собственный Rust service/helper, если понадобится полный контроль.
|
||||
|
||||
Control App не должен напрямую владеть процессом `sing-box`. Он должен управлять service/task через helper.
|
||||
|
||||
### Local sing-box
|
||||
|
||||
`sing-box` - опциональный runtime.
|
||||
|
||||
Его роль:
|
||||
|
||||
- принять subscription/VLESS/sing-box config;
|
||||
- поднять локальный mixed SOCKS/HTTP inbound;
|
||||
- слушать только `127.0.0.1`, например `127.0.0.1:1080`;
|
||||
- маршрутизировать трафик через выбранный outbound.
|
||||
|
||||
Config генерируется из source state приложения и проверяется:
|
||||
|
||||
```powershell
|
||||
sing-box check -c C:\Tools\VpnProxy\sing-box\config.json
|
||||
```
|
||||
|
||||
Local sing-box не должен быть обязательным. Если profile target указывает на внешний proxy, `sing-box` может отсутствовать.
|
||||
|
||||
### Proxyfier layer
|
||||
|
||||
Рекомендуемый стартовый backend: **ProxiFyre**.
|
||||
|
||||
Почему:
|
||||
|
||||
- open-source;
|
||||
- Windows-focused;
|
||||
- маршрутизирует TCP и UDP;
|
||||
- работает per-application;
|
||||
- использует `app-config.json`;
|
||||
- может работать как Windows Service.
|
||||
|
||||
Важное ограничение: ProxiFyre лицензируется как AGPL-3.0. Если продукт должен быть закрытым коммерческим приложением, нужно заранее решить юридический вопрос или сделать adapter layer, чтобы можно было заменить engine на:
|
||||
|
||||
- коммерческий Proxifier;
|
||||
- ProxyBridge;
|
||||
- собственный WinDivert/NDIS/WFP-based engine;
|
||||
- другой per-app proxy router.
|
||||
|
||||
Интерфейс должен называться не `ProxiFyreConfig`, а шире:
|
||||
|
||||
```text
|
||||
ProxyRouterAdapter
|
||||
```
|
||||
|
||||
Первый adapter:
|
||||
|
||||
```text
|
||||
ProxiFyreAdapter
|
||||
```
|
||||
|
||||
Это позволит поменять engine без переделки UI и профилей.
|
||||
|
||||
### Data storage
|
||||
|
||||
Для MVP лучше использовать простые JSON-файлы с schema validation.
|
||||
|
||||
Причина:
|
||||
|
||||
- настройки легко читать и бэкапить;
|
||||
- можно быстро отлаживать;
|
||||
- config portable;
|
||||
- подходит для profile/target/source state.
|
||||
|
||||
Рекомендуемые файлы:
|
||||
|
||||
```text
|
||||
C:\ProgramData\VpnProxy\config\profiles.json
|
||||
C:\ProgramData\VpnProxy\config\targets.json
|
||||
C:\ProgramData\VpnProxy\config\components.json
|
||||
C:\ProgramData\VpnProxy\state\activity.json
|
||||
C:\ProgramData\VpnProxy\state\last-status.json
|
||||
C:\ProgramData\VpnProxy\generated\proxifyre-app-config.json
|
||||
C:\ProgramData\VpnProxy\generated\sing-box-config.json
|
||||
```
|
||||
|
||||
Если нужна большая история событий, статистика трафика или сложные миграции, тогда добавить SQLite:
|
||||
|
||||
- `rusqlite` или `sqlx` в Rust;
|
||||
- миграции;
|
||||
- таблицы `activity`, `component_status`, `traffic_events`.
|
||||
|
||||
Но source of truth для профилей можно оставить JSON даже при наличии SQLite.
|
||||
|
||||
### Installer strategy
|
||||
|
||||
Нужны три явных installer entrypoints:
|
||||
|
||||
```text
|
||||
Install Control App
|
||||
Install Proxyfier Layer
|
||||
Install Local sing-box
|
||||
```
|
||||
|
||||
Они могут быть кнопками в UI, но каждая операция должна быть отдельной и понятной.
|
||||
|
||||
CLI/script names:
|
||||
|
||||
```text
|
||||
install-control-app.ps1
|
||||
install-proxyfier.ps1
|
||||
install-singbox.ps1
|
||||
```
|
||||
|
||||
Или в packaged app:
|
||||
|
||||
```text
|
||||
VpnProxySetup.exe /component control-app
|
||||
VpnProxySetup.exe /component proxyfier
|
||||
VpnProxySetup.exe /component sing-box
|
||||
```
|
||||
|
||||
Каждый installer:
|
||||
|
||||
- idempotent;
|
||||
- делает backup перед overwrite;
|
||||
- не удаляет чужие файлы без подтверждения;
|
||||
- проверяет admin rights;
|
||||
- пишет machine-readable install result;
|
||||
- не трогает остальные компоненты без явного выбора.
|
||||
|
||||
### Security model
|
||||
|
||||
Правила:
|
||||
|
||||
- UI работает без admin rights.
|
||||
- Admin elevation только для install/repair/service/config apply, если это реально нужно.
|
||||
- Local API, если будет, слушает только `127.0.0.1`.
|
||||
- Лучше использовать Tauri commands / named pipe, чем открытый HTTP port.
|
||||
- Если нужен loopback HTTP, включить token или origin check.
|
||||
- Секреты subscription URLs не показывать в diagnostics.
|
||||
- Generated configs не редактируются вручную из UI.
|
||||
- Every apply creates backup.
|
||||
|
||||
## Архитектура
|
||||
|
||||
```text
|
||||
+-------------------------------+
|
||||
| Tauri Control App |
|
||||
| React/TypeScript UI |
|
||||
+---------------+---------------+
|
||||
|
|
||||
v
|
||||
+-------------------------------+
|
||||
| Rust App Backend |
|
||||
| profiles, targets, validation |
|
||||
| component status aggregation |
|
||||
+-------+---------------+-------+
|
||||
| |
|
||||
v v
|
||||
+---------------+ +-------------------+
|
||||
| Proxy Router | | Local sing-box |
|
||||
| Adapter | | Adapter |
|
||||
| ProxiFyre v1 | | config + service |
|
||||
+-------+-------+ +---------+---------+
|
||||
| |
|
||||
v v
|
||||
+---------------+ +-------------------+
|
||||
| ProxiFyre | | sing-box.exe |
|
||||
| Windows svc | | Windows svc/task |
|
||||
+---------------+ +-------------------+
|
||||
```
|
||||
|
||||
## Модель данных
|
||||
|
||||
### Profile
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "discord",
|
||||
"name": "Discord",
|
||||
"enabled": true,
|
||||
"targetId": "local-singbox",
|
||||
"protocols": ["TCP", "UDP"],
|
||||
"items": [
|
||||
{ "type": "process", "value": "Discord" },
|
||||
{ "type": "folder", "value": "%LOCALAPPDATA%\\Discord", "recursive": true },
|
||||
{ "type": "exe", "value": "C:\\Games\\Game\\game.exe" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Target
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "local-singbox",
|
||||
"name": "Local sing-box",
|
||||
"type": "local",
|
||||
"protocol": "socks5",
|
||||
"host": "127.0.0.1",
|
||||
"port": 1080,
|
||||
"requiresComponent": "singbox"
|
||||
}
|
||||
```
|
||||
|
||||
External target:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "home-gateway",
|
||||
"name": "Home gateway",
|
||||
"type": "external",
|
||||
"protocol": "socks5",
|
||||
"host": "192.168.50.111",
|
||||
"port": 8080
|
||||
}
|
||||
```
|
||||
|
||||
### Component status
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "proxyfier",
|
||||
"name": "Proxyfier",
|
||||
"installed": true,
|
||||
"running": true,
|
||||
"version": "2.3.0",
|
||||
"path": "C:\\Tools\\ProxiFyre",
|
||||
"serviceName": "ProxiFyreService",
|
||||
"problems": [],
|
||||
"actions": ["restart", "repair", "openLogs"]
|
||||
}
|
||||
```
|
||||
|
||||
## Apply behavior
|
||||
|
||||
Apply должен делать одно понятное действие:
|
||||
|
||||
1. Прочитать profiles.
|
||||
2. Прочитать targets.
|
||||
3. Проверить, что выбранные targets доступны.
|
||||
4. Проверить, что Proxyfier установлен.
|
||||
5. Разрешить folder/exe в process names.
|
||||
6. Сгенерировать proxyfier config.
|
||||
7. Сделать backup старого config.
|
||||
8. Записать новый config.
|
||||
9. Перезапустить Proxyfier service.
|
||||
10. Записать activity entry.
|
||||
|
||||
Если profile использует `local-singbox`, дополнительно:
|
||||
|
||||
- проверить, что `sing-box` установлен;
|
||||
- проверить, что service running;
|
||||
- проверить, что `127.0.0.1:1080` отвечает.
|
||||
|
||||
Если `local-singbox` не установлен, но profile target внешний, apply должен работать.
|
||||
|
||||
## Что не делать
|
||||
|
||||
- Не делать глобальную смену Windows proxy settings.
|
||||
- Не делать `sing-box` обязательным.
|
||||
- Не смешивать installer и profile apply.
|
||||
- Не хранить generated ProxiFyre config как source of truth.
|
||||
- Не привязывать UI напрямую к ProxiFyre, нужен adapter layer.
|
||||
- Не запускать privileged операции без явного согласия пользователя.
|
||||
- Не делать большой dashboard с лишней статистикой в первой версии.
|
||||
|
||||
## MVP
|
||||
|
||||
Самый правильный первый slice:
|
||||
|
||||
1. Tauri app shell.
|
||||
2. Profiles UI.
|
||||
3. Targets UI.
|
||||
4. Component status UI.
|
||||
5. ProxiFyre adapter.
|
||||
6. External SOCKS5 target.
|
||||
7. Apply profile -> generate ProxiFyre config -> restart service.
|
||||
|
||||
В MVP `sing-box` может быть только карточкой `Not installed / Install`.
|
||||
|
||||
После этого добавить:
|
||||
|
||||
1. Local sing-box installer.
|
||||
2. Subscription import.
|
||||
3. Server selection.
|
||||
4. Generate sing-box config.
|
||||
5. Start/stop/restart local sing-box service.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
Приложение считается успешным, если:
|
||||
|
||||
- можно установить только Control App;
|
||||
- можно установить Proxyfier отдельно;
|
||||
- можно не устанавливать sing-box;
|
||||
- можно добавить внешний SOCKS5 target;
|
||||
- можно создать профиль для Discord;
|
||||
- можно применить профиль;
|
||||
- generated ProxiFyre config не редактируется пользователем вручную;
|
||||
- UI показывает, что local sing-box отсутствует, но это не ломает внешний proxy flow;
|
||||
- после установки sing-box появляется target `Local sing-box`;
|
||||
- пользователь может переключить профиль с внешнего target на local sing-box.
|
||||
|
||||
## Prompt For Another AI
|
||||
|
||||
Build a Windows desktop proxy management app.
|
||||
|
||||
Use Tauri 2 with React, TypeScript, Vite, and a Rust backend. The app must manage three independent components: the Control App, a proxyfier layer, and optional local sing-box. Do not make sing-box mandatory.
|
||||
|
||||
The UI must be a compact Windows utility with these screens: Overview, Profiles, Targets, Components, Logs. Profiles contain process/folder/exe entries and choose a proxy target. Targets can be local sing-box or external SOCKS5/HTTP proxies. Proxyfier is the layer that routes selected apps through the chosen target.
|
||||
|
||||
Start with ProxiFyre as the first proxy router adapter, but design an adapter boundary so it can later be replaced. Store source configuration as JSON with schema validation. Generated ProxiFyre and sing-box configs are derived artifacts, not source truth.
|
||||
|
||||
Privileged operations must be isolated in an explicit helper/installer flow. The main UI should run without admin rights. Install Control App, Install Proxyfier, and Install Local sing-box must be separate operations. Applying a profile must not silently install missing components.
|
||||
|
||||
MVP: external SOCKS5 target + ProxiFyre profile apply. Then add optional local sing-box installation, subscription import, server selection, and local sing-box service control.
|
||||
|
||||
## References
|
||||
|
||||
- Tauri 2: https://v2.tauri.app/
|
||||
- Tauri sidecar permissions: https://v2.tauri.app/develop/sidecar/
|
||||
- sing-box configuration: https://sing-box.sagernet.org/configuration/
|
||||
- ProxiFyre repository: https://github.com/wiresock/proxifyre
|
||||
- WinSW service wrapper: https://github.com/winsw/winsw
|
||||
- Microsoft Windows Service with Worker Service: https://learn.microsoft.com/en-us/dotnet/core/extensions/windows-service
|
||||
|
||||