96 lines
8.0 KiB
Markdown
96 lines
8.0 KiB
Markdown
# 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).
|
||
Неструктурированный бэклог идей и задач — в [`things.txt`](things.txt).
|
||
|
||
## Архитектура бэкенда
|
||
|
||
Слоями, сверху вниз:
|
||
|
||
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.
|
||
7. **`tasks.rs`** — фоновый цикл: сброс просроченных подписок и сверка блокчейна на
|
||
предмет потерянных платежей.
|
||
8. **`error.rs`** — единый `AppError` с `IntoResponse`: маппинг в HTTP-статус,
|
||
безопасное сообщение наружу и подробности только в логи/метрики.
|
||
|
||
## Быстрый старт (локальная разработка)
|
||
|
||
```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`.
|
||
|
||
## Известные незавершённые места (недоделки)
|
||
|
||
Ниже — то, что явно недоделано или является временной заглушкой в текущем коде.
|
||
В самих файлах эти места помечены комментариями `// TODO:` — см. также
|
||
[`SECURITY_AUDIT.md`](SECURITY_AUDIT.md) для рисков безопасности отдельно.
|
||
|
||
- **Cyberhack без анти-чита.** `POST /users/hack/result` принимает `score` от клиента
|
||
и лишь клампит его в `0..=500` — сервер не проверяет, что игра реально была сыграна
|
||
честно. Пока не эксплуатируемо (баланс E$ нигде не тратится), но станет дырой, как
|
||
только появится трата баланса. См. `src/modules/users/controller.rs`.
|
||
- **`GET /nodes/routing` возвращает неполный конфиг.** Отдаёт только
|
||
`ip/port/region/supported_protocols` (последнее — статичная заглушка). Реальному
|
||
VPN-клиенту нужны ещё `tunnel_*`-поля (уже есть в модели `VpnNode`, но не
|
||
сериализуются), `public_key`/`sni_domain` (их нет даже в схеме БД) и одноразовый
|
||
session-токен. См. `src/modules/nodes/controller.rs`.
|
||
- **`GET /nodes/stats` отдаёт фейковый `uptime: "99.9%"`** для всех нод — не реальная
|
||
метрика.
|
||
- **Нет health-check воркера для VPN-нод.** Статус ноды в БД не переоценивается сам:
|
||
если физический сервер лёг, control plane продолжит считать его `online` и выдавать
|
||
клиентам. См. `src/tasks.rs`.
|
||
- **Провижининг ноды — синхронный.** `POST /admin/nodes` держит HTTP-запрос открытым
|
||
на всё время SSH-провижининга (может занимать минуты) вместо немедленного `202
|
||
Accepted` + фоновой задачи. См. `src/modules/nodes/service.rs`.
|
||
- **Курс TON запрашивается синхронно на каждый инвойс** (`BillingService::initiate_payment`)
|
||
— не кешируется, хотя Redis в проекте уже подключён.
|
||
- **Таблица `auth_sessions`** объявлена в миграции, но нигде не используется — заброшенный
|
||
черновик флоу авторизации через Magic Link из бота. Либо доделать, либо убрать из схемы.
|
||
- **Telegram-бот: разделы «Тарифы» и «Синдикат»** в inline-меню — заглушка
|
||
«В разработке...» (`src/bot.rs`, `handle_callbacks`).
|
||
- **Фронтенд, `AdminDashboard.tsx`:** кнопка «Force Restart» ничего не делает (нет
|
||
`onClick`); UI для удаления ноды тоже отсутствует, хотя бэкенд уже умеет
|
||
`DELETE /api/v1/admin/nodes/{id}`.
|
||
- **Фронтенд, `Auth.tsx`:** искусственные задержки (`setTimeout` 800мс/6000мс) чисто
|
||
ради вида терминала; при генерации Ghost-seed нет кнопки «скачать ключ» — если юзер
|
||
не успеет скопировать seed за 6 секунд до авто-редиректа, доступ к анонимному
|
||
аккаунту теряется безвозвратно (seed невосстановим).
|
||
- **`frontend/README.md`** был шаблоном Vite по умолчанию (сейчас заменён на
|
||
специфичный для проекта).
|