platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
72
docs/phase-c/C1_WEB_READINESS.md
Normal file
72
docs/phase-c/C1_WEB_READINESS.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# C1 Подготовка ядра к веб-совместимости
|
||||
|
||||
Дата: 2026-02-27
|
||||
Статус: draft
|
||||
Владелец: Engineering
|
||||
|
||||
## 1) Цель
|
||||
- Зафиксировать, какие компоненты Go-ядра уже готовы к внешнему доступу (SSE, REST, локальный API) и что нужно изменить/документировать для будущего веб-прототипа.
|
||||
- Убедиться, что веб-интерфейс сможет работать с ядром через ожидаемые договоренности (binding, CORS, авторизация, long-polling/SSE).
|
||||
- Зафиксировать архитектурный принцип повторного использования одного API-контракта для `web + iOS + Android`, без форков бизнес-логики по платформам.
|
||||
- Выбор UI-стека вынесен в `docs/phase-c/C2_WEB_STACK_DECISION.md` (принято: `Vite + React + TypeScript` для MVP).
|
||||
|
||||
## 2) Критерии завершения
|
||||
- Описан binding (`127.0.0.1:8080`), механизм SSE (`/api/v1/events/stream`), стандартные ответы (e.g. `CmdResult`, dataclasses) и авторизация через `vpn_login_session`.
|
||||
- Зафиксированы необходимые изменения инфраструктуры (proxy/unix socket, CORS/CSRF, дополнительная аутентификация или токены).
|
||||
- Собраны критические endpoint’ы для веба (routes service/update/rollback, traffic mode/appmarks/profiles, DNS/SmartDNS, VPN, trace) и их характеристики (async операции, payload, ответы).
|
||||
- Для мобильных клиентов описаны условия transport/auth/retry (TLS, токены, refresh, polling fallback к SSE, device session control).
|
||||
|
||||
## 3) Задачи
|
||||
- Подтвердить, что SSE поток (`events/stream`) предоставляет status/login/trace/autoloop updates и определить, какие события нужно визуализировать (policy route, unit state, autoloop, SmartDNS, routes progress).
|
||||
- Задокументировать payload/методы/JSON форматы для ключевых endpoint’ов (`routes/service`, `routes/update`, `traffic/mode`, `dns/benchmark`, `smartdns/prewarm`, `vpn/login/session`), чтобы новый фронт мог повторить вызовы.
|
||||
- Определить ограничения текущего binding (`127.0.0.1:8080`) и описать безопасный путь для проксирования (unix socket + nginx/systemd socket/reverse proxy).
|
||||
- Проработать механизм авторизации: как web UI вызывает `/api/v1/vpn/login/session/start`, получает `login_state`, делает action, и как `/api/v1/auth/status`/`login/session/state` поддерживают health.
|
||||
- Уточнить, какие операции требуют async-статуса (например, `routes update`, `routes/service restart`) и как отображать прогресс (SSE event `routes_nft_progress`, `status_changed`).
|
||||
- Задокументировать headers/CORS (`allowed origin`, `Authorization`, `Content-Type`, `X-Requested-With`, `GET/POST`) и сценарии CSRF/preflight при использовании cookie.
|
||||
- Утвердить единый API-versioning подход (`/api/v1`) и правила обратной совместимости для всех клиентов (веб и мобильных).
|
||||
- Зафиксировать контракт ошибок (`ok`, `message`, `exitCode`, `stderr`) и политику idempotency/retry для мобильных сетевых условий.
|
||||
|
||||
## 4) SSE, watchers, trace
|
||||
- `events_bus.go` собирает события `{ID, Kind, Ts, Data}` и поддерживает replay по `Last-Event-ID`/`since`. Web должен подписаться на `status_changed`, `login_state_changed`, `routes_nft_progress`, `unit_state_changed`, `autoloop_status_changed` и восстанавливать соединение при reconnect.
|
||||
- `watchers.go` poll-ит `status.json`, `login_state.json`, `trace.log`, `autoloop.log`, state traffic appmarks TTL и systemd unit’ы (`routes_service`, `routes_timer`, `vpn_unit`, `smartdns_unit`). Эти события идут в SSE и дают realtime-статус на UI (health, trace, unit status).
|
||||
- `trace_handlers.go` предоставляет `GET /api/v1/trace` (tail), `/trace-json` (structured), `/trace/append`. Убедиться, что web ограничивает JSON size (1<<20) и отображает `CmdResult` (stdout/stderr) при append.
|
||||
- Нужно описать, какие watcher-события и trace-последствия критичны для UI (policy route check, SmartDNS runtime, traffic appmarks TTL) и как SSE clients обрабатывают disconnect/replay.
|
||||
|
||||
## 5) Проксирование и безопасность
|
||||
- API должен быть доступен через безопасный proxy (unix socket + nginx, systemd socket или reverse proxy) и/или на изолированном интерфейсе, чтобы не экспонировать `127.0.0.1:8080` наружу.
|
||||
- Proxy configuration:
|
||||
- Systemd socket unit (`selective-vpn-api.socket`) слушает `/run/selective-vpn.sock`; nginx проксирует `location /api/` → `proxy_pass http://unix:/run/selective-vpn.sock:`.
|
||||
- В nginx включаете `proxy_buffering off`, `proxy_http_version 1.1`, `proxy_set_header Connection keep-alive`, `proxy_set_header Host $host`, `proxy_set_header X-Real-IP $remote_addr`, чтобы SSE `/api/v1/events/stream` работал без задержек.
|
||||
- Альтернатива — nginx на localhost:8080 с firewall, разрешающий соединения только от веб-интерфейса; при этом добавляется `allow 127.0.0.1` и `deny all`.
|
||||
- CORS/CSRF:
|
||||
- `Access-Control-Allow-Origin: https://selective-ui.local` (или переменная окружения). `Access-Control-Allow-Credentials: true` при использовании cookie.
|
||||
- `Access-Control-Allow-Headers: Authorization, Content-Type, X-Requested-With`, `Access-Control-Allow-Methods: GET, POST`, `Access-Control-Expose-Headers: X-Request-Id`.
|
||||
- Preflight (`OPTIONS`) обрабатывается proxy (nginx) или Go кодом, возвращая нужные заголовки и `204`.
|
||||
- Авторизация:
|
||||
- Web UI вызывает `POST /api/v1/vpn/login/session/start`, backend пишет `login_state.json` и возвращает `LoginState` (включая `state`/`msg`/`email`).
|
||||
- Web сохраняет `login_state_id`, прикладывает его как `Authorization: Bearer $login_state_id` либо использует session cookie от proxy. Go middleware проверяет токен перед вызовом критичных endpoint’ов.
|
||||
- `/api/v1/auth/status` (или расширение `/api/v1/vpn/login/session/state`) сообщают, активна ли сессия; если нет, UI перенаправляет пользователя к login modal.
|
||||
- `CmdResult` с `ok=false`, SSE `login_state_changed` или события `status_error` должна отображаться как alert и давать кнопку retry.
|
||||
- Async операции и прогресс:
|
||||
- `routes update` и `routes/service restart` занимают до 60 секунд. Web запускает POST `/api/v1/routes/update`, включает бесперебойный SSE и показывает progress bar, пока не придёт `CmdResult.ok=true` + event `routes_nft_progress`/`status_changed`.
|
||||
- `dns/benchmark`, `smartdns/prewarm` и `traffic/mode/test` тоже могут длиться минуты — UI ожидает SSE `progress`/`status` и отключает повторные вызовы до завершения.
|
||||
- Trace append (`/api/v1/trace/append`) возвращает `CmdResult`; UI показывает `stderr`/`exitCode` и ограничивает длину payload (<=1<<20).
|
||||
|
||||
## 6) Кросс-платформенная переиспользуемость (Web + iOS + Android)
|
||||
- Backend-слой остается единым: бизнес-логика только в Go-ядре, клиенты используют одинаковые endpoint’ы и payload-контракты.
|
||||
- DTO/модели (`Status`, `CmdResult`, `TrafficModeStatus`, `LoginState`, `TrafficAppMarkItem`) считаются каноничными; изменение полей только с backward-compatible стратегией.
|
||||
- Реaltime:
|
||||
- Web: SSE как основной канал.
|
||||
- Mobile: SSE при активном приложении + fallback polling для background/нестабильной сети.
|
||||
- Авторизация:
|
||||
- Веб-клиент может использовать cookie/token через proxy.
|
||||
- Мобильные клиенты используют bearer access token + refresh token, хранят секреты в secure storage (iOS Keychain / Android Keystore).
|
||||
- Надежность:
|
||||
- Для mutating POST операций вводить `Idempotency-Key`, чтобы избежать дублей при ретраях на мобильной сети.
|
||||
- Добавить request correlation (`X-Request-Id`) в ответы/логи для расследования инцидентов на всех клиентах.
|
||||
- Транспорт:
|
||||
- Только HTTPS, поддержка certificate pinning для мобильных приложений.
|
||||
- Никаких прямых подключений к `127.0.0.1:8080` с клиентов; только через контролируемый gateway/proxy.
|
||||
- Transport backends:
|
||||
- Поддержать модель pluggable backend-клиентов (`sing-box`, `dnstt-client`, `phoenix->slipstream`) с единым API-контрактом ядра.
|
||||
- UI-слой (web/iOS/Android) не должен зависеть от конкретного transport backend; различия покрываются capability endpoint/матрицей в Go.
|
||||
37
docs/phase-c/C2_WEB_STACK_DECISION.md
Normal file
37
docs/phase-c/C2_WEB_STACK_DECISION.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# C2 Решение по стеку web prototype
|
||||
|
||||
Дата: 2026-03-07
|
||||
Статус: approved
|
||||
Владелец: Engineering
|
||||
|
||||
## 1) Принятое решение
|
||||
- Для web prototype используется `Vite + React + TypeScript` (SPA).
|
||||
- Бэкенд-ядро остаётся в Go (`/api/v1` + SSE `/api/v1/events/stream`).
|
||||
- `Next.js` на MVP-этапе не используется.
|
||||
|
||||
## 2) Почему так
|
||||
- В проекте уже есть готовый Go API-контракт; отдельный Node/SSR-слой не обязателен.
|
||||
- Цель текущего этапа: рабочая control-plane панель, а не SEO-публичный сайт.
|
||||
- `Vite` даёт быстрый старт, простой билд и минимальные операционные риски.
|
||||
|
||||
## 3) Базовый frontend stack
|
||||
- `react` + `typescript`
|
||||
- `vite`
|
||||
- `react-router`
|
||||
- `@tanstack/react-query` для REST
|
||||
- `EventSource` (SSE) для realtime
|
||||
- lightweight UI state (например, `zustand`) только для локального состояния интерфейса
|
||||
|
||||
## 4) Когда рассматривать переход на Next.js
|
||||
- Появляется требование SSR/SEO.
|
||||
- Нужен встроенный BFF/edge middleware в самом фронтенд-проекте.
|
||||
- Требуется server-side session orchestration, которую нецелесообразно держать в Go gateway.
|
||||
|
||||
## 5) Архитектурный инвариант
|
||||
- Независимо от UI-фреймворка, источник истины остаётся в Go-ядре.
|
||||
- UI не дублирует бизнес-логику маршрутизации/transport/policy.
|
||||
- Контракт для web/iOS/Android остаётся единым: `/api/v1`.
|
||||
|
||||
## 6) Статус внедрения
|
||||
- Создан модуль `selective-vpn-web/` (foundation level).
|
||||
- На текущем этапе включены read-only проверки и SSE connectivity; mutating controls будут подключаться по фазам P1/E4.
|
||||
Reference in New Issue
Block a user