10 KiB
10 KiB
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 eventroutes_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.gopoll-ит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.
- Systemd socket unit (
- 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, SSElogin_state_changedили событияstatus_errorдолжна отображаться как alert и давать кнопку retry.
- Web UI вызывает
- Async операции и прогресс:
routes updateиroutes/service restartзанимают до 60 секунд. Web запускает POST/api/v1/routes/update, включает бесперебойный SSE и показывает progress bar, пока не придётCmdResult.ok=true+ eventroutes_nft_progress/status_changed.dns/benchmark,smartdns/prewarmиtraffic/mode/testтоже могут длиться минуты — UI ожидает SSEprogress/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) в ответы/логи для расследования инцидентов на всех клиентах.
- Для mutating POST операций вводить
- Транспорт:
- Только 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.
- Поддержать модель pluggable backend-клиентов (