platform: modularize api/gui, add docs-tests-web foundation, and refresh root config

This commit is contained in:
beckline
2026-03-26 22:40:54 +03:00
parent 0e2d7f61ea
commit 6a56d734c2
562 changed files with 70151 additions and 16423 deletions

View File

@@ -0,0 +1,140 @@
# F1 План рефакторинга и модульности
Дата: 2026-03-07
Статус: planned
Владелец: Engineering
## 1) Цель
- Уменьшить размер и связность крупных файлов без изменения поведения приложения.
- Подготовить кодовую базу к быстрому развитию desktop/web/mobile поверх одного Go API.
## 2) Текущие "горячие" файлы
- `selective-vpn-gui/vpn_dashboard_qt.py``6103` строк (до старта F1.4; после текущего разреза: `116` + `main_window/ui_shell_mixin.py` + `main_window/singbox/*` + `main_window/runtime_actions_mixin.py`).
- `selective-vpn-gui/api_client.py``2220` строк.
- `selective-vpn-gui/dashboard_controller.py``1430` строк.
- `selective-vpn-api/app/transport_handlers.go``1984` строки.
- `selective-vpn-api/app/server.go` (legacy) — центральная связка entrypoints/bootstrap/routes, высокий риск регрессий при точечных изменениях.
## 3) Принципы разрезания
- Поведение не меняем: сначала вынос кода, потом точечные улучшения.
- Модули режем по domain-границам, а не "по 500 строк".
- Сохраняем один публичный entrypoint (facade) для UI и для backend-router.
- После каждого шага прогоняем существующие smoke/e2e (без новых требований к тестам от пользователя).
## 4) План разрезания GUI
### 4.1 `vpn_dashboard_qt.py` -> `gui/main_window/*`
- Цель: вынести табы и event-обвязку в отдельные модули.
- Разделение:
- `main_window.py` — сборка окна и общий lifecycle.
- `tabs/status_tab.py`
- `tabs/vpn_tab.py`
- `tabs/routes_tab.py`
- `tabs/dns_tab.py`
- `tabs/domains_tab.py`
- `tabs/trace_tab.py`
- `services/events_bridge.py` (`EventThread`, dispatch)
- `services/locations_loader.py` (`LocationsThread`, SWR-ui orchestration)
- Критерий: исходный файл `vpn_dashboard_qt.py` становится thin-bootstrap.
- Статус: выполнено (`2026-03-10`).
- Уже сделано:
- добавлены `main_window/constants.py` и `main_window/workers.py` (shared constants + `EventThread`/`LocationsThread`);
- вынесен UI shell (`build tabs + helpers + locations/egress`) в `main_window/ui_shell_mixin.py`;
- `ui_tabs_singbox_mixin.py` дополнительно разрезан на `ui_tabs_singbox_layout_mixin.py` и `ui_tabs_singbox_editor_mixin.py`;
- SingBox-контур дополнительно разрезан на подпакет `main_window/singbox/*` (`editor`, `cards`, `links`, `runtime`) с фасадом `main_window/singbox_mixin.py`;
- вынесен runtime/refresh/actions контур в `main_window/runtime_actions_mixin.py`;
- проведён второй проход декомпозиции: `ui_tabs_*`, `runtime_{state,refresh,auth,ops}`, `singbox/{links_*,runtime_*}`; фасады оставлены для совместимости;
- `MainWindow` переведён на наследование mixin-классов, поведение сохранено; в итоге крупные GUI-модули уложены в читаемые размеры (максимум `~633` строк).
### 4.2 `dashboard_controller.py` -> `controllers/*`
- Разделение:
- `controllers/status_controller.py`
- `controllers/vpn_controller.py`
- `controllers/routes_controller.py`
- `controllers/dns_controller.py`
- `controllers/domains_controller.py`
- `controllers/transport_controller.py`
- `controllers/trace_controller.py`
- Сохраняется фасад `DashboardController` (совместимость с текущим UI-кодом).
- Статус: выполнено (`2026-03-10`).
- Что сделано:
- добавлен пакет `selective-vpn-gui/controllers/` (`core + views + domain mixin-модули`);
- `selective-vpn-gui/dashboard_controller.py` переведён в thin-facade с прежней точкой входа;
- `py_compile` и импорты UI-модулей (`vpn_dashboard_qt.py`, `traffic_mode_dialog.py`, `dns_benchmark_dialog.py`) проходят.
### 4.3 `api_client.py` -> `api/*`
- Разделение:
- `api/client.py` (HTTP/SSE base + shared helpers)
- `api/models.py` (dataclasses)
- `api/status.py`, `api/vpn.py`, `api/routes.py`, `api/traffic.py`, `api/dns.py`, `api/domains.py`, `api/trace.py`
- `api/transport.py` facade + `api/transport_clients.py`, `api/transport_policy.py`, `api/transport_singbox.py`
- Сохраняется фасад `ApiClient` (старая точка импорта для UI).
- Статус: выполнено (`2026-03-10`).
- Что сделано:
- добавлен пакет `selective-vpn-gui/api/` с доменными mixin-модулями;
- `api_client.py` переведён в backward-compatible facade (legacy imports сохранены);
- `api/client.py` сокращён до base-слоя, доменные методы вынесены по подпапкам;
- `api/transport.py` разрезан на subdomain-модули с сохранением класса `TransportApiMixin`.
## 5) План разрезания Go-ядра
### 5.1 `transport_handlers.go` -> `app/transport_*`
- Разделение:
- `transport_handlers_clients.go` (CRUD/lifecycle/health/metrics)
- `transport_handlers_policy.go` (validate/apply/rollback/conflicts)
- `transport_validator.go` (normalize + conflict detection)
- `transport_confirm_token.go` (token lifecycle)
- `transport_state_store.go` (load/save state/snapshots)
- Сохраняем текущие endpoint-path и response-контракт без изменений.
### 5.2 `server.go` -> `app/entrypoints.go + api_bootstrap.go + api_routes.go`
- Цель: развязать entrypoint-логику (`Run*CLI`), bootstrap API-сервера и registry маршрутов.
- Статус: выполнено (`2026-03-10`).
- Состав:
- `entrypoints.go``Run`, `RunAPIServer`, `RunRoutesUpdateCLI`, `RunRoutesClearCLI`, `RunAutoloopCLI`, legacy-dispatch;
- `api_bootstrap.go` — bootstrap и lifecycle HTTP-сервера (`runAPIServerAtAddr`);
- `api_routes.go` — thin-facade `registerAPIRoutes`;
- `api_routes_*.go` — доменные registrars (`core`, `traffic`, `transport`, `trace`, `dns`, `vpn`) без изменения endpoint-path.
### 5.3 `app/*` -> подпакеты runtime (`app/cli`, `app/bootstrap`)
- Цель: убрать "кучу" в корне `app` и перенести исполнимые runner-модули в отдельные папки, сохранив фасады в `app`.
- Статус: выполнено (`2026-03-10`).
- Состав:
- `app/cli/*``routes-update`, `routes-clear`, `autoloop` раннеры с dependency-injection (callback deps);
- `app/bootstrap/server_runner.go` — единый HTTP server runner;
- `app/entrypoints.go` и `app/api_bootstrap.go` оставлены thin-facade слоями.
### 5.4 `transport_handlers.go` -> модульные transport файлы
- Цель: убрать крупнейший монолит transport control-plane без изменения endpoint-контракта.
- Статус: выполнено (`2026-03-10`).
- Состав:
- `transport_shared.go` — state/version constants, mutex, общие типы;
- `transport_handlers_clients.go` — clients CRUD/lifecycle/netns toggle handlers;
- `transport_handlers_policy.go` — policy validate/apply/rollback/conflicts/capabilities handlers;
- `transport_policy_validate.go` — normalize/validate/diff/conflict helpers;
- `transport_client_runtime.go` — runtime/health/lifecycle/allocation helpers;
- `transport_tokens_state.go` — confirm-token и state persistence.
### 5.5 Подпакеты transport (без циклических зависимостей)
- Цель: выносить переиспользуемые части transport-логики в подпапки только там, где не возникает import-cycle с `app`.
- Статус: in_progress (`2026-03-10`).
- Уже вынесено:
- `app/transporttoken/store.go` — confirm-token store (`issue/consume/ttl cleanup`) и token generator.
- Дальше:
- выделить в подпакеты часть stateless helper-функций (при сохранении фасадов в `app`).
## 6) Порядок выполнения (безопасный)
1. `api_client.py` (минимальный риск для UI, проще ревьюить).
2. `dashboard_controller.py`.
3. `vpn_dashboard_qt.py` (таб за табом).
4. `transport_handlers.go` в Go.
## 7) Definition of Done
- Все текущие smoke/e2e проходят:
- `./tests/run_all.sh`
- плюс ручная проверка пользователем в desktop приложении.
- Нет изменений API-контракта (`/api/v1/*`) и event-kind.
- В каждом крупном модуле остаётся читаемый размер (ориентир `< 700` строк; предпочтительно `< 500`).
## 8) Дополнительно (после F1)
- Добавить settings-механику видимости вкладок протоколов (`SingBox`, `DNSTT`, `Phoenix`) через `QSettings`/profile, чтобы включать только нужные модули UI.

View File

@@ -0,0 +1,36 @@
# F3 План: библиотека модулей Go-ядра (deferred)
Дата: 2026-03-14
Статус: deferred
Владелец: Engineering
## 1) Цель
- Подготовить ядро к формату внутренней библиотеки модулей, чтобы backend собирался из чётких переиспользуемых пакетов.
- Снизить связность `app/*` и закрепить стабильные интерфейсы orchestration/PBR/transport/resolver.
## 2) Принцип scope
- `linux-first`: библиотека ориентирована на Linux runtime backend.
- `netns` — отладочный/инфраструктурный модуль для backend/desktop тестового контура.
- `mobile (iOS/Android)` не является целью для `netns`-модуля.
- Для mobile не планируется `netns` слой: только вызовы backend API (control-plane), без platform-specific system hooks.
- GUI/Web/Mobile должны использовать только API control-plane, а не прямые системные модули.
## 3) Целевые пакеты
- `pkg/orchestrator` — lifecycle orchestration (`prepare/start/stop/restart/rollback`) и locking.
- `pkg/transport` — shared transport-модели/валидация/runtime helpers.
- `pkg/pbr` — marks/tables/prefs allocator + compiler.
- `pkg/resolver` — resolver policy/execution primitives.
- `pkg/netnsdebug` (или `pkg/netns`) — Linux-only netns setup/cleanup helpers для debug/test-contour.
## 4) Шаги реализации (будущий этап)
1. Выделить публичные интерфейсы зависимостей (runner, nft/ip adapters, state store, logger).
2. Перенести код в `pkg/*` без изменения поведения.
3. Оставить `app/*` как thin-facade + HTTP слой.
4. Добавить compile/runtime guardrails для Linux-only модулей.
5. Обновить runbook миграции и интеграционные чеклисты.
## 5) Критерии готовности
- Backend-сборка не зависит от монолитных `app/*` helper-блоков.
- `netns` модуль чётко помечен как Linux-only и debug/test-oriented.
- Внешние API (`/api/v1/*`) не меняются.
- `go test ./...` зелёный после миграции.