platform: modularize api/gui, add docs-tests-web foundation, and refresh root config
This commit is contained in:
184
docs/phase-d/D1_GO_READINESS_DOCS.md
Normal file
184
docs/phase-d/D1_GO_READINESS_DOCS.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# D1 Документирование готовности ядра
|
||||
|
||||
Дата: 2026-03-02
|
||||
Статус: in-progress
|
||||
Владелец: Engineering
|
||||
|
||||
## 1) Цель
|
||||
- Дать точный endpoint-level срез: что уже можно подключать в веб, что требует инфраструктурных условий, и где нужен отдельный UX-поток.
|
||||
- Зафиксировать критерии перехода к веб-прототипу на базе фактического кода `selective-vpn-api`.
|
||||
|
||||
## 2) Легенда статусов
|
||||
- `ready-read` — готово для веба как read endpoint.
|
||||
- `ready-write` — готово для веба как write endpoint, но обязательно через auth/rbac/audit/proxy.
|
||||
- `ready-async` — write endpoint готов, но требуется async UX (SSE progress/polling).
|
||||
- `ready-interactive` — endpoint готов, но требует интерактивного flow (session state/action).
|
||||
|
||||
## 3) Глобальные условия для веба
|
||||
- API должен ходить через proxy (unix socket + nginx/systemd socket) и не быть публично открыт напрямую на `127.0.0.1:8080`.
|
||||
- Для всех mutating endpoints обязательны auth/rbac и аудит вызовов.
|
||||
- Для SSE (`/api/v1/events/stream`) нужен корректный proxy режим (`proxy_buffering off`).
|
||||
- Для async операций (`routes update`, `smartdns prewarm`, `dns benchmark`) веб должен слушать SSE/статусы и блокировать повторные конкурирующие действия.
|
||||
- Архитектурный инвариант: один контракт `/api/v1` для `web + iOS + Android`, без платформенных форков backend-логики.
|
||||
|
||||
## 4) Матрица endpoint -> web-ready
|
||||
|
||||
| Endpoint | Method | Handler | Статус | Комментарий для веба |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `/healthz` | GET | `handleHealthz` | `ready-read` | Базовый liveness probe. |
|
||||
| `/api/v1/events/stream` | GET | `handleEventsStream` | `ready-read` | SSE source для realtime UI. |
|
||||
| `/api/v1/status` | GET | `handleGetStatus` | `ready-read` | Карточка статуса маршрутов. |
|
||||
| `/api/v1/routes/status` | GET | `handleGetStatus` | `ready-read` | Алиас статуса. |
|
||||
| `/api/v1/vpn/login-state` | GET | `handleVPNLoginState` | `ready-read` | Текущий state логина VPN. |
|
||||
| `/api/v1/systemd/state` | GET | `handleSystemdState` | `ready-read` | Проверка unit state по query `unit`. |
|
||||
| `/api/v1/routes/service/start` | POST | `makeRoutesServiceActionHandler("start")` | `ready-write` | Чувствительная операция systemd. |
|
||||
| `/api/v1/routes/service/stop` | POST | `makeRoutesServiceActionHandler("stop")` | `ready-write` | Чувствительная операция systemd. |
|
||||
| `/api/v1/routes/service/restart` | POST | `makeRoutesServiceActionHandler("restart")` | `ready-write` | Чувствительная операция systemd. |
|
||||
| `/api/v1/routes/service` | POST | `handleRoutesService` | `ready-write` | Универсальный action endpoint. |
|
||||
| `/api/v1/routes/update` | POST | `handleRoutesUpdate` | `ready-async` | Запуск async job; прогресс через SSE/events. |
|
||||
| `/api/v1/routes/timer` | GET/POST | `handleRoutesTimer` | `ready-write` | GET состояние, POST переключение. |
|
||||
| `/api/v1/routes/timer/toggle` | POST | `handleRoutesTimerToggle` | `ready-write` | Legacy toggle для совместимости. |
|
||||
| `/api/v1/routes/rollback` | POST | `handleRoutesClear` | `ready-write` | Очистка nft/routes с риском влияния на трафик. |
|
||||
| `/api/v1/routes/clear` | POST | `handleRoutesClear` | `ready-write` | Алиас rollback. |
|
||||
| `/api/v1/routes/cache/restore` | POST | `handleRoutesCacheRestore` | `ready-write` | Восстановление из clear-cache. |
|
||||
| `/api/v1/routes/precheck/debug` | POST | `handleRoutesPrecheckDebug` | `ready-async` | Debug flow + опциональный async restart. |
|
||||
| `/api/v1/routes/fix-policy-route` | POST | `handleFixPolicyRoute` | `ready-write` | Ремонт policy route по status.json. |
|
||||
| `/api/v1/routes/fix-policy` | POST | `handleFixPolicyRoute` | `ready-write` | Алиас fix-policy-route. |
|
||||
| `/api/v1/traffic/mode` | GET/POST | `handleTrafficMode` | `ready-write` | Ключевой control-plane endpoint. |
|
||||
| `/api/v1/traffic/mode/test` | GET/POST | `handleTrafficModeTest` | `ready-read` | Проверка health/probe для UI. |
|
||||
| `/api/v1/traffic/advanced/reset` | POST | `handleTrafficAdvancedReset` | `ready-write` | Сброс advanced bypass state. |
|
||||
| `/api/v1/traffic/interfaces` | GET | `handleTrafficInterfaces` | `ready-read` | Список интерфейсов и active iface. |
|
||||
| `/api/v1/traffic/candidates` | GET | `handleTrafficCandidates` | `ready-read` | Подсказки subnet/unit/uid. |
|
||||
| `/api/v1/traffic/appmarks` | GET/POST | `handleTrafficAppMarks` | `ready-write` | Runtime app marking, требует RBAC. |
|
||||
| `/api/v1/traffic/appmarks/items` | GET | `handleTrafficAppMarksItems` | `ready-read` | Список текущих runtime marks. |
|
||||
| `/api/v1/traffic/app-profiles` | GET/POST/DELETE | `handleTrafficAppProfiles` | `ready-write` | CRUD профилей приложений. |
|
||||
| `/api/v1/traffic/audit` | GET | `handleTrafficAudit` | `ready-read` | Sanity-check и issues report. |
|
||||
| `/api/v1/trace` | GET | `handleTraceTailPlain` | `ready-read` | Plain tail trace. |
|
||||
| `/api/v1/trace-json` | GET | `handleTraceJSON` | `ready-read` | Structured trace view. |
|
||||
| `/api/v1/trace/append` | POST | `handleTraceAppend` | `ready-write` | Write в trace; ограничить доступ и размер body. |
|
||||
| `/api/v1/dns-upstreams` | GET/POST | `handleDNSUpstreams` | `ready-write` | Конфиг upstreams. |
|
||||
| `/api/v1/dns/upstream-pool` | GET/POST | `handleDNSUpstreamPool` | `ready-write` | Конфиг pool. |
|
||||
| `/api/v1/dns/status` | GET | `handleDNSStatus` | `ready-read` | Состояние DNS mode/runtime. |
|
||||
| `/api/v1/dns/mode` | POST | `handleDNSModeSet` | `ready-write` | Переключение DNS resolver mode. |
|
||||
| `/api/v1/dns/benchmark` | POST | `handleDNSBenchmark` | `ready-async` | Долгий бенчмарк; нужен UX ожидания. |
|
||||
| `/api/v1/dns/smartdns-service` | POST | `handleDNSSmartdnsService` | `ready-write` | Start/stop/restart smartdns unit. |
|
||||
| `/api/v1/smartdns/service` | GET/POST | `handleSmartdnsService` | `ready-write` | GET state + POST action. |
|
||||
| `/api/v1/smartdns/runtime` | GET/POST | `handleSmartdnsRuntime` | `ready-write` | Runtime nftset hook toggle. |
|
||||
| `/api/v1/smartdns/prewarm` | POST | `handleSmartdnsPrewarm` | `ready-async` | Потенциально долгий prewarm. |
|
||||
| `/api/v1/domains/table` | GET | `handleDomainsTable` | `ready-read` | Таблица nft/ipset dump. |
|
||||
| `/api/v1/domains/file` | GET/POST | `handleDomainsFile` | `ready-write` | File-backed editor; нужен ACL по name. |
|
||||
| `/api/v1/smartdns/wildcards` | GET/POST | `handleSmartdnsWildcards` | `ready-write` | CRUD wildcard list. |
|
||||
| `/api/v1/vpn/autoloop-status` | GET | `handleVPNAutoloopStatus` | `ready-read` | Статус autoloop parser. |
|
||||
| `/api/v1/vpn/status` | GET | `handleVPNStatus` | `ready-read` | VPN state + unit state. |
|
||||
| `/api/v1/vpn/autoconnect` | POST | `handleVPNAutoconnect` | `ready-write` | Управление adgvpn unit. |
|
||||
| `/api/v1/vpn/locations` | GET | `handleVPNListLocations` | `ready-read` | Список location options. |
|
||||
| `/api/v1/vpn/location` | POST | `handleVPNSetLocation` | `ready-write` | Смена desired location + unit restart. |
|
||||
| `/api/v1/vpn/login/session/start` | POST | `handleVPNLoginSessionStart` | `ready-interactive` | Старт интерактивной PTY login session. |
|
||||
| `/api/v1/vpn/login/session/state` | GET | `handleVPNLoginSessionState` | `ready-interactive` | Poll состояния и линий с `since`. |
|
||||
| `/api/v1/vpn/login/session/action` | POST | `handleVPNLoginSessionAction` | `ready-interactive` | Команды open/check/cancel. |
|
||||
| `/api/v1/vpn/login/session/stop` | POST | `handleVPNLoginSessionStop` | `ready-interactive` | Cleanup/stop interactive session. |
|
||||
| `/api/v1/vpn/logout` | POST | `handleVPNLogout` | `ready-write` | Logout + refresh login state. |
|
||||
|
||||
## 5) Скриптовые smoke-тесты
|
||||
- `tests/api_sanity.sh` — read endpoints + method guard + SSE headers.
|
||||
- `tests/trace_append.sh` — append + readback (`/trace`, `/trace-json`).
|
||||
- `tests/events_stream.py` — SSE stream + активный триггер `trace_append`.
|
||||
- `tests/vpn_login_flow.py` — start/state/action/stop для login session.
|
||||
- `tests/transport_flow_smoke.py` — API-flow `draft/validate/confirm/apply/rollback` для transport policy.
|
||||
- `tests/transport_platform_compatibility_smoke.py` — проверка кроссплатформенного transport-контракта (`web/iOS/Android`) через capabilities + policy endpoints.
|
||||
- `tests/transport_runbook_cli_smoke.sh` — smoke операционного runbook helper (`scripts/transport_runbook.py`) по lifecycle transport-клиента.
|
||||
- `tests/transport_recovery_runbook_smoke.sh` — smoke recovery runbook (`scripts/transport_recovery_runbook.py`) для сценария `health->restart->fallback->diagnostics`.
|
||||
- `tests/transport_systemd_real_e2e.py` — real-systemd e2e для `singbox/dnstt(+ssh)/phoenix` + проверка cleanup unit artifacts.
|
||||
- `tests/transport_production_like_e2e.py` — production-like e2e для template-команд и `packaging_profile=bundled` на `systemd` backend.
|
||||
- `tests/transport_singbox_e2e.py` — backend-first e2e для `singbox` lifecycle/guards.
|
||||
- `tests/transport_dnstt_e2e.py` — backend-first e2e для `dnstt` lifecycle/guards (`ssh overlay`, template checks).
|
||||
- `tests/transport_phoenix_e2e.py` — backend-first e2e для `phoenix` lifecycle/guards.
|
||||
- `tests/run_all.sh` — общий запуск набора.
|
||||
|
||||
## 6) Факт прогона (2026-03-02)
|
||||
- Команда: `API_URL=http://127.0.0.1:8080 ./tests/run_all.sh`.
|
||||
- Результат: `api_sanity`, `trace_append`, `events_stream`, `vpn_login_flow` — `passed`.
|
||||
- Дополнение (2026-03-07):
|
||||
- Расширенный `run_all` с transport smoke/e2e и packaging smoke проходит `passed`;
|
||||
- включён и проходит `tests/transport_platform_compatibility_smoke.py` (capabilities + policy contract);
|
||||
- при запуске старого backend-процесса `transport_*_e2e` могут завершаться `SKIP` (без `provision/metrics`);
|
||||
- после пересборки и перезапуска `selective-vpn-api` из текущего кода `transport_singbox_e2e`, `transport_dnstt_e2e`, `transport_phoenix_e2e` прошли без `SKIP`.
|
||||
- в `run_all` включены и проходят `transport_systemd_real_e2e` + `transport_production_like_e2e` (template-commands + packaging profile checks на `runner=systemd`).
|
||||
|
||||
## 7) Вывод для веб-прототипа
|
||||
- Срез по legacy-матрице (53 endpoint из Phase D):
|
||||
- `ready-read`: 18
|
||||
- `ready-write`: 27
|
||||
- `ready-async`: 4
|
||||
- `ready-interactive`: 4
|
||||
- Дополнение 2026-03-07:
|
||||
- В ядро добавлены `8` базовых mux-route `/api/v1/transport/*` + action-subpath `GET /api/v1/transport/clients/{id}/metrics` (контракт D4.1).
|
||||
- Их контракт и rollout описаны в `docs/phase-e/E2_TRANSPORT_API_CONTRACT.md`.
|
||||
- По API-ядру нет endpoint, который блокирует веб-прототип на уровне контракта.
|
||||
- Ограничения не в ручках, а в обвязке: auth/rbac, proxy/CORS/CSRF, и UX для async/interactive сценариев.
|
||||
- Практический старт веба можно делать сразу: read панели + write действия под admin scope + SSE realtime слой.
|
||||
|
||||
## 8) Условия переиспользования для смартфонов (iOS/Android)
|
||||
- Серверная обвязка:
|
||||
- gateway/proxy с TLS и токен-авторизацией;
|
||||
- refresh/access токены и управление device sessions;
|
||||
- аудит и rate-limit для mutating endpoints.
|
||||
- Контракт:
|
||||
- стабильные DTO и error contract (`ok`, `message`, `exitCode`, `stderr`);
|
||||
- versioning через `/api/v1` и backward-compatible изменения.
|
||||
- Realtime и фоновые ограничения:
|
||||
- веб использует SSE постоянно;
|
||||
- mobile использует SSE в foreground и polling fallback в background.
|
||||
- Надежность мобильной сети:
|
||||
- idempotency key для POST операций;
|
||||
- retry policy с экспоненциальной паузой;
|
||||
- correlation id для трассировки запросов.
|
||||
- Безопасность клиента:
|
||||
- iOS Keychain / Android Keystore для токенов;
|
||||
- certificate pinning для production приложений.
|
||||
|
||||
## 9) D3: Последовательность запуска multi-client
|
||||
- D3.1: Завершить gateway/auth слой (TLS, токены, RBAC, audit).
|
||||
- D3.2: Подключить web-клиент к уже готовой матрице endpoint и SSE.
|
||||
- D3.3: Ввести mobile transport profile (polling fallback + retry/idempotency).
|
||||
- D3.4: Запустить iOS/Android клиенты на том же `/api/v1` без изменения бизнес-логики ядра.
|
||||
|
||||
## 10) D4: Transport Integration Backlog
|
||||
- D4.1 `sing-box client`:
|
||||
- Роль: универсальный клиент-транспорт для сценариев proxy/tun.
|
||||
- Требование к ядру: запуск/остановка/health через backend-адаптер, без переноса логики в UI.
|
||||
- Статус: `in-progress` (2026-03-07: в API введён минимальный общий backend-контракт lifecycle/health/metrics/errors, добавлен `GET /api/v1/transport/clients/{id}/metrics`).
|
||||
- E2E шаг (backend-first): `tests/transport_singbox_e2e.py`:
|
||||
- проверяет успешный lifecycle на `runner=mock` (`provision/start/health/restart/stop/metrics`);
|
||||
- проверяет guard `runtime_mode=embedded` -> `TRANSPORT_BACKEND_RUNTIME_MODE_UNSUPPORTED`;
|
||||
- проверяет fail-fast `require_binary=true` для отсутствующего `singbox_bin`.
|
||||
- Примечание: если в рантайме запущен старый процесс API без `provision/metrics`, тест завершится `SKIP`; для полного прогона нужен перезапуск backend из актуального кода.
|
||||
- D4.2 `dnstt-client`:
|
||||
- Роль: отдельный клиент для DNSTT-протокола (как самостоятельный backend).
|
||||
- Требование к ядру: управление lifecycle + состояние/ошибки через общий API слой.
|
||||
- Уточнение: поддержать режим `dnstt + ssh overlay` (туннель поверх SSH как единая система, аналогично phoenix UX-модели).
|
||||
- Статус: `in-progress` (2026-03-07: в Go добавлены adapter foundation, `POST /api/v1/transport/clients/{id}/provision`, template-команды запуска, systemd restart/watchdog tuning, unit hardening-профили, `runtime_mode` foundation `exec|embedded|sidecar`, packaging profiles (`system|bundled`) и manual pinned updater/rollback scripts; `config.exec_start` работает как optional override).
|
||||
- E2E шаг (backend-first): `tests/transport_dnstt_e2e.py`:
|
||||
- проверяет успешный lifecycle на `runner=mock`;
|
||||
- проверяет guard `ssh_overlay` конфигурации (`ssh_host` обязателен, `ssh_unit` валидируется);
|
||||
- проверяет template-валидацию DNSTT при неполном config.
|
||||
- Примечание: как и для singbox, при старом API-процессе без `provision` тест завершится `SKIP`; нужен перезапуск backend из текущего кода.
|
||||
- D4.3 `phoenix -> slipstream`:
|
||||
- Роль: отдельный backend-клиент для подключения к удаленному `slipstream` серверу.
|
||||
- Требование к ядру: конфиг/статус/управление сессией через backend-адаптер и общий контракт.
|
||||
- Статус: `in-progress` (2026-03-07: добавлен backend-first e2e тест `tests/transport_phoenix_e2e.py` для lifecycle/guards на API-контракте).
|
||||
- E2E шаг (backend-first): `tests/transport_phoenix_e2e.py`:
|
||||
- проверяет успешный lifecycle на `runner=mock` (`provision/start/health/restart/stop/metrics`);
|
||||
- проверяет guard `runtime_mode=embedded` -> `TRANSPORT_BACKEND_RUNTIME_MODE_UNSUPPORTED`;
|
||||
- проверяет fail-fast `require_binary=true` для отсутствующего `phoenix_bin`.
|
||||
- Примечание: при старом API-процессе без `provision/metrics` тест завершится `SKIP`; для полного прогона нужен перезапуск backend из актуального кода.
|
||||
- D4.4 Общий инвариант:
|
||||
- Для `web + iOS + Android` UI не знает о внутренней реализации backend-клиента; он работает с единым API ядра.
|
||||
- Все transport-backend различия прячутся в Go-слое (feature flags, capability matrix, unified error contract).
|
||||
|
||||
## 11) D4.3: Матрица совместимости web + iOS + Android
|
||||
- Отдельный артефакт: `docs/phase-d/D4_PLATFORM_COMPATIBILITY_MATRIX.md`.
|
||||
- Зафиксировано:
|
||||
- единый control-plane контракт `/api/v1` для всех платформ;
|
||||
- transport-runtime работает только в backend (`exec`), UI работает через capabilities/policies flow;
|
||||
- mobile использует тот же API, с fallback `polling` при недоступном SSE в background.
|
||||
Reference in New Issue
Block a user