Files
elmprodvpn/docs/phase-c/C1_WEB_READINESS.md

10 KiB
Raw Permalink Blame History

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.