# 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.
```
