# Netrunner Control Plane Бэкенд VPN-сервиса «Netrunner»: авторизация (Telegram / анонимный «Ghost Protocol»), биллинг подписок через TON, реферальная программа, оркестрация VPN-нод по SSH, Telegram-бот как второй канал входа и встроенная раздача SPA-фронтенда. Стек: Rust (axum, sqlx/Postgres, teloxide, tokio) + React/TypeScript (Vite) фронтенд, собранные в единый Docker-образ. ## Структура репозитория | Путь | Что там | Подробнее | |---|---|---| | [`src/`](src) | Rust-бэкенд (control plane) | см. ниже | | [`src/modules/`](src/modules/README.md) | Бизнес-модули (auth, billing, nodes, referrals, users) | [README](src/modules/README.md) | | [`src/db/`](src/db/README.md) | Модели и репозиторий (доступ к Postgres) | [README](src/db/README.md) | | [`frontend/`](frontend/README.md) | React/Vite SPA (личный кабинет, игра, админка нод) | [README](frontend/README.md) | | [`migrations/`](migrations) | SQL-миграции (sqlx) | — | | [`templates/init_node.sh`](templates/init_node.sh) | Bash-скрипт инициализации новой VPN-ноды, исполняется по SSH | — | | [`tests/`](tests) | Интеграционные тесты репозитория (`sqlx::test`, требуют Postgres) | — | Инфраструктура и процесс деплоя подробно описаны в [`DEPLOYMENT.md`](DEPLOYMENT.md); список закрытых и остаточных угроз безопасности — в [`SECURITY_AUDIT.md`](SECURITY_AUDIT.md). ## Архитектура бэкенда Слоями, сверху вниз: 1. **`main.rs`** — точка входа: поднимает пул Postgres, собирает `ApiState` (репозиторий + сервисы всех модулей) и параллельно запускает HTTP API, Telegram-бота и фоновые задачи биллинга до общего сигнала остановки (Ctrl+C / SIGTERM). 2. **`api.rs`** — сборка axum-роутера: монтирует контроллеры модулей, rate-limiting (`tower_governor`), CORS, Prometheus-метрики (`/metrics`), health-пробы (`/health`, `/health/ready`) и раздачу статики фронтенда как SPA-фолбэк. 3. **`modules/*/controller.rs`** — HTTP-контракты (axum-роуты, JSON DTO), тонкий слой без бизнес-логики. 4. **`modules/*/service.rs`** — бизнес-логика модуля. 5. **`db::repository::AppRepository`** — трейт доступа к БД; единственная реализация — `PgRepository` (Postgres/sqlx). Сервисы знают только о трейте, поэтому теоретически подменяемы в тестах без реальной БД. 6. **`bot.rs`** — Telegram-бот (teloxide), использует те же сервисы, что и HTTP API; кнопки «Личный Кабинет»/«Тарифы»/«Синдикат» ведут в ЛК через общий WebApp-мост (короткоживущий bootstrap-токен в URL, фронт меняет его на cookie-сессию через `POST /auth/exchange`). 7. **`tasks.rs`** — два фоновых цикла: сброс просроченных подписок + сверка блокчейна на предмет потерянных платежей, и health-check VPN-нод (TCP-пинг раз в 60с, переоценка `online`/`offline`). 8. **`error.rs`** — единый `AppError` с `IntoResponse`: маппинг в HTTP-статус, безопасное сообщение наружу и подробности только в логи/метрики. ## Авторизация: единая cookie-сессия для лендинга и ЛК Один способ входа (Telegram Login Widget / анонимный Ghost Protocol / bootstrap-мост из бота) выдаёт одну и ту же пару cookie: короткий access-JWT (`nrxp_token`, 15 мин) и ротируемый непрозрачный refresh-токен (`nrxp_refresh`, 30 дней, хеш хранится в `refresh_sessions`, путь строго `/api/v1/auth/refresh`). Обе — `HttpOnly; Secure; SameSite=Lax`; в проде дополнительно `Domain=.netrunner-vpn.com`, поэтому одна и та же сессия работает и на лендинге (`netrunner-vpn.com`), и на ЛК (`account.netrunner-vpn.com`) без единого байта в `localStorage` или JS-читаемых cookie. Подробности — в [`src/modules/auth/README.md`](src/modules/auth/README.md). ## Быстрый старт (локальная разработка) ```bash cp .env.example .env # заполнить секреты (JWT_SECRET, ARGON_SALT, TELOXIDE_TOKEN, ...) make dev # docker compose: db + redis + app с hot-reload (cargo watch) ``` Приложение поднимется на `http://localhost:8080` (`/health`, `/health/ready`). Остальные команды — `make help`. ## Nodes, Cyberhack, биллинг — текущее состояние - **`GET /nodes/routing`** отдаёт полный `TunnelConfig`: `tunnel_*`-поля, `public_key`/`sni_domain` ноды и одноразовый (60с) session-токен, который выдаётся только при активной подписке юзера. - **Health-check VPN-нод** — фоновая задача (`src/tasks.rs`, TCP-пинг раз в 60с) переоценивает `online`/`offline` сама; ручной `POST /admin/nodes/{id}/restart` перезапускает прокси-контейнер на ноде по SSH-ключу. - **Провижининг ноды асинхронный:** `POST /admin/nodes` сразу отвечает `202 Accepted` со статусом `provisioning`, SSH-деплой идёт в фоне. - **Курс TON кешируется в Redis** (`ton_rate:`, TTL 60с) — `BillingService::initiate_payment` бьёт TonAPI только на промах кеша. - **Cyberhack — server-authoritative.** Доску генерирует и хранит сервер (`src/modules/users/cyberhack.rs`, порт алгоритма из `Cyberhack/src/lib.rs`); клиент присылает не итоговый счёт, а сырой путь кликов, который сервер сам реплеит и валидирует (`POST /users/hack/start` → `POST /users/hack/result`). - **Telegram-бот:** «Тарифы» и «Синдикат» ведут в тот же ЛК, что и «Личный Кабинет» — единый WebApp-мост (см. выше). - **`AdminDashboard.tsx`:** кнопки «Force Restart» и удаления ноды подключены к соответствующим ручкам бэкенда.