Files
PnvPanel/docs/roadmap.md
T
Leonid Pershin 1452e5c4af
CI / Backend (build + test) (push) Successful in 1m23s
CI / Frontend (lint + typecheck + build) (push) Successful in 30s
Implement Telegram bot configuration updates and user messaging enhancements
- Added inline button functionality to the `/configs` command, allowing users to request connection strings for their configurations without displaying them in chat history.
- Introduced a constant message for unlinked Telegram accounts to improve user understanding of the linking process.
- Updated the handling of configuration messages to include inline buttons for better user interaction and experience.
2026-07-02 18:29:32 +03:00

15 KiB
Raw Blame History

Roadmap

MVP полностью реализован — все этапы M0–M8 закрыты. Ниже — ретроспектива по этапам (как было задумано → что реально сделано, с честными пометками о расхождениях) и раздел Backlog с тем, что осталось за рамками MVP осознанно.

M0 — Каркас и инфраструктура

  • Solution (PnvPanel.slnx) + 4 проекта (Domain/Application/Infrastructure/Api), ссылки по Clean Architecture.
  • Directory.Build.props, .editorconfig, nullable включены. dotnet format — локальная команда, в CI не запускается (CI гоняет только build/test).
  • EF Core + Npgsql, миграции.
  • Scaffolding фронта: Vite + React + TS + Tailwind + shadcn-стиль поверх Radix + TanStack Query/Router; тема light/dark/system (провайдер + переключатель); i18n (RU/EN); dev-прокси /api,/hubs на бэк.
  • Единый контейнер: multi-stage Dockerfile (node → dotnet publish → aspnet), Api раздаёт SPA из wwwroot (fallback на index.html); docker-compose app + db (PostgreSQL); ForwardedHeaders (TLS — внешним прокси); авто-применение миграций на старте.
  • Health-check /health, Serilog, нативный OpenAPI (Microsoft.AspNetCore.OpenApi) + Scalar (без Swashbuckle).
  • CI (GitHub Actions): dotnet build/test + pnpm build/lint/typecheck (без деплоя).
  • Готово, когда: единый образ поднимается в docker-compose рядом с postgres, отдаёт SPA и /health, есть миграции, CI зелёный. Достигнуто — включая полную проверку docker compose up end-to-end.

M1 — Аутентификация и сидинг

  • ASP.NET Core Identity (AppUser/AppRole c MaxConfigs); DbInitializer: системные роли admin/user и учётка админа из env (.env.example).
  • Вход по username (email не используется); JWT access + refresh (httpOnly cookie, ротация, Secure по факту HTTPS-запроса, хранение хэшей), Identity lockout, rate-limit на /auth/*; смена пароля. Явного анти-CSRF токена нет — обоснование в architecture.md.
  • Регистрация: новый пользователь → роль user, IsActivated = false.
  • Фронт: страницы login/register (username), стор авторизации, refresh-flow, guard-маршруты.
  • Готово, когда: регистрация/вход/refresh/logout по username работают, админ засидан, новый юзер неактивен. Достигнуто.

M2 — Роли и активация

  • Домен: динамические роли (CRUD, квота MaxConfigs), ActivationRequest.
  • Команды/запросы: CreateRole/UpdateRole/DeleteRole, ChangeUserRole (одна роль), RequestActivation (с комментарием), ApproveActivation/RejectActivation.
  • Эндпоинты активации (user + admin) и ролей; проверка активации/роли — inline в хендлерах и RequireAuthorization(...) на эндпоинте, без отдельных именованных policy.
  • Фронт: экран «запросить активацию» (с комментарием), админ-очередь запросов, управление ролями/назначением.
  • Готово, когда: юзер запрашивает активацию с комментарием, админ на сайте активирует; роли с квотами работают. Достигнуто.

M3 — Ноды и публикация inbounds (по ролям)

  • Домен Node/Inbound (+ AllowedRoles, DisplayName); порт IXuiPanelGateway + единственная реализация XuiPanelGateway (кэш клиента per-node внутри неё, ThreeXui.Net); шифрование секретов нод (ISecretProtector/ASP.NET Data Protection).
  • Команды/запросы: RegisterNode, UpdateNode, DeleteNode, SyncNode, ProbeNode, ListNodes, ListInbounds, PublishInbound (с выбором ролей).
  • Админка нод/инбаундов на фронте (публикация с displayName и allowedRoleIds).
  • Готово, когда: админ подключает реальную 3x-ui и публикует inbound для выбранных ролей. Достигнуто (удаление ноды с активными конфигами пока не блокируется — известный пробел, см. tech-stack.md).

M4 — Конфиги пользователя (ядро продукта)

  • Домен VpnConfig (создание, отзыв, ротация; инварианты: активирован + квота роли (грандфазеринг)
    • доступ роли к инбаунду; квота — под pg_advisory_xact_lock; схема ClientEmail).
  • CreateVpnConfig (с label/deviceLimitlimitIp), EditVpnConfig, RotateVpnConfig, RevokeVpnConfig, GetMyConfigs, GetConfigLink, ListAvailableInbounds; connection string по запросу (не сразу при создании), QR строится на фронте.
  • Подписка: один эндпоинт /sub/{token} — токен либо агрегированный (AppUser.SubscriptionToken, все конфиги), либо по одному конфигу (VpnConfig.SubscriptionToken); заголовки Subscription-Userinfo / Profile-Update-Interval.
  • Самоудаление аккаунта (DELETE /api/auth/me): отзыв всех активных конфигов + удаление AppUser.
  • Каталог приложений ClientApp (домен + GET /api/apps по ОС; сид из seed/client-apps.json) + страница инструкций на фронте.
  • Фронт: дашборд (метки, лимит устройств), создание/редактирование, страница инструкций, ссылка/QR по кнопке, отзыв, перевыпуск, настройки аккаунта.
  • Готово, когда: активированный юзер создаёт рабочий конфиг в доступном инбаунде в пределах квоты; работает подписка. Достигнуто. Лимиты трафика/срока конфига — не реализованы, backlog (см. domain-model.md).

M5 — Синхронизация трафика и realtime

  • TrafficSyncService (обход включённых нод, обновление трафика, TrafficSample) — только для отображения, без активной реконсиляции дрейфа (недоступная нода/незнакомый клиент — тихо пропускаются).
  • NodeHealthCheckService; TrafficRetentionService (TTL-чистка истории).
  • SignalR PanelHub + IRealtimeNotifier (реализован в Api/Hubs/, не в Infrastructure); события configTrafficUpdated/configStatusChanged/nodeStatusChanged/activationRequested/userActivated.
  • Фронт: живые обновления трафика/статусов без перезагрузки. Реакции на превышение лимита/срока нет — таких лимитов не существует (см. M4).
  • Готово, когда: трафик и статусы обновляются в UI без перезагрузки. Достигнуто.

M6 — Админ-статистика, управление пользователями, аудит

  • ListUsers, BlockUser (→ отключение конфигов в 3x-ui) / UnblockUser (два отдельных эндпоинта), ChangeUserRole, ResetUserPassword, GetUserConfigs, ForceRevokeConfig, GetStats.
  • AuditLog: запись значимых действий (активация, блокировка, смена роли, ноды/инбаунды — источник всегда Web, т.к. пишется из тех же хендлеров, что вызывает и бот) + эндпоинт /api/admin/audit.
  • Каталог приложений: админ-CRUD ClientApp (/api/admin/apps) — название, ссылка, ОС, порядок, вкл/выкл.
  • Фронт: таблицы пользователей/ролей/нод/приложений (обычные <table>, без TanStack Table), журнал аудита, статистика карточками (без графиков — recharts установлен, но не подключён).
  • Готово, когда: админ видит статистику и журнал, управляет пользователями/ролями/конфигами; блокировка гасит VPN. Достигнуто.

M7 — Telegram-бот

  • Библиотека Telegram.Bot, TelegramBotHostedService (long polling) в процессе Api, IOptions<TelegramOptions>.
  • Домен: поля Telegram у AppUser, TelegramLinkToken, TelegramLoginRequest.
  • Флоу привязки (LinkTelegramCommand) + эндпоинт link-token/unlink.
  • Passwordless-вход: login-request + подтверждение в боте (ApproveTelegramLoginCommand) → выпуск JWT; поллинг завершения на фронте (GET /api/auth/telegram/login-request/{id}).
  • Команды бота: /start (+ link_<token>/login_<requestId> deep-link payload), «Мои конфиги» (/configs — по сообщению на конфиг, с inline-кнопкой «🔗 Показать ссылку», раскрывающей connection string по запросу через тот же GetConfigLinkQuery, что и веб; ссылка не выводится сразу в списке, чтобы не светиться в истории чата без явного действия юзера), /unlink, /requests, /help.
  • Админ в боте: уведомления о запросах активации + inline «Активировать/Отклонить», /requests (по Telegram id из env).
  • DM-уведомления юзеру: активация (ApproveActivationCommandHandler), блокировка (BlockUserCommandHandler), принудительный отзыв конфига админом (ForceRevokeConfigCommandHandler) — если Telegram привязан. Бот — read-only по конфигам (только просмотр/показ ссылки, без создания/ротации/отзыва).
  • Готово, когда: юзер привязывает Telegram, входит без пароля, видит конфиги; админ активирует запросы прямо в боте. Достигнуто.
  • Перенесено в backlog (не реализовано в MVP): восстановление пароля через бота (/resetpassword с одноразовой ссылкой) — сейчас сброс пароля только через админа (ResetUserPasswordCommand); QR-картинкой в сообщениях бота (пока только текстовая ссылка). Фронтовые кнопки «Войти через Telegram»/«Привязать Telegram» реализованы в отдельной итерации (см. M0 фронт).

M8 — Закалка (hardening)

  • Тесты: PnvPanel.Domain.Tests (54, чистые unit-тесты инвариантов сущностей), PnvPanel.Application.Tests (71, CQRS-хендлеры на EF Core InMemory + NSubstitute-моки портов), PnvPanel.IntegrationTests (Testcontainers.PostgreSql + WebApplicationFactory<Program> — реальный HTTP-контракт, включая проверку pg_advisory_xact_lock под параллельной нагрузкой на квоту конфигов).
  • Rate-limiting, аудит-лог, единообразные ProblemDetails, ретеншн TrafficSample — сделаны в M5/M6.
  • CI (.github/workflows/ci.yml): dotnet build/test (backend, включая интеграционные — на ubuntu-latest Docker доступен) + pnpm lint/typecheck/build (frontend), без деплоя.
  • Прод-docker-compose.yml: env_file: .env прокидывает все секреты в контейнер app, том dp_keys для key-ring Data Protection (переживает пересоздание контейнера), healthcheck app через GET /health (curl добавлен в runtime-образ). TLS — внешним прокси (без изменений).
  • Готово, когда: зелёный CI, покрытие ключевых сценариев, готовность к деплою. Достигнуто (интеграционные тесты прогнаны локально через Testcontainers после появления Docker на машине разработки — 134/134 зелёных; там же впервые собран и проверен единый Docker-образ и docker-compose стек end-to-end).

Backlog (после MVP)

  • Полное самообслуживание в боте (создание/ротация/отзыв конфигов) — в MVP бот read-only.
  • Полная регистрация аккаунта через Telegram (в MVP — только привязка); Telegram Login Widget как альтернатива.
  • Тарифы/биллинг/платежи, автопродление, промокоды.
  • Реферальная программа; расширенные уведомления (через Telegram/веб — email в проекте не используется).
  • Балансировка/выбор оптимальной ноды, автоскейл.
  • OpenTelemetry-трейсинг, метрики, дашборды.
  • Вынос фоновых задач в Hangfire/Quartz; TimescaleDB для истории трафика.
  • Мультиязычность (RU/EN и далее).