# Дейл (Deal) — архитектурный дизайн-док > Исторический документ (архитектурный дизайн-черновик, 2026-09-05). Актуальное состояние — `docs/superpowers/STATUS.md` и `docs/technical/Техническая-документация-Дейл.md`. > Версия: 0.1 (черновик для согласования) > Дата: 2026-09-05 > Статус: фиксирует согласованные решения по переписыванию LeadRadar в новый продукт «Дейл» --- ## 1. Контекст и цели **LeadRadar** — рабочий прототип (Python/FastAPI/DuckDB/Vue), проверенный на тестовых данных. **«Дейл»** — новая реализация: SaaS-продукт, который мониторит Telegram-каналы и группы клиентов, отсеивает рекламу/скам/дубликаты и показывает **реальные заказы и клиентов**, совпадающих с профилем пользователя (сфера, стек, бюджет). Клиенты подключают свои Telegram-аккаунты. ### Цели переписывания 1. Код, который владелец продукта может поддерживать сам (типизированный .NET вместо Python). 2. Стабильность и строгость типов, интерфейсов, слоёв — «как сеньор-архитектор». 3. Мультитенантный SaaS (схема на тенанта) — фундамент для роста до сотен/тысяч клиентов. 4. Безопасность «с первого дня» (публичный продукт). 5. Полная документация: ТЗ, инструкция пользователя, техдок — параллельно с кодом. ### Не-цели (сейчас) - Переписывание фронтенда (Vue остаётся как есть). - Kafka/кубер (отложены до реального масштаба; архитектура готова к ним). - Биллинг-провайдер (лимиты в ядре, биллинг — позже). - Саморегистрация тенантов (только инвайты). --- ## 2. Решения верхнего уровня (зафиксированы) | # | Решение | Выбор | |---|---|---| | 1 | Стратегия | Big Bang: пишем новый бэкенд целиком; старые данные не мигрируем (тестовые) | | 2 | Фронтенд | Vue не трогаем; HTTP-контракт `/api/...` — замороженная спецификация миграции | | 3 | Архитектура | Модульный монолит в `core` (один процесс, одно sln); сервисы — отдельные процессы/sln | | 4 | Стек | .NET (актуальная LTS), C# современный, Postgres | | 5 | Мультитенантность | Одна Postgres-БД, **схема на тенанта** (`tenant_.*`), системное в `public` | | 6 | Владение данными | Каждый модуль владеет своими таблицами; межмодульно — интерфейсы/доменные события | | 7 | Межпроцессно | gRPC + mTLS; шина событий за портом `IEventBus` (outbox → Kafka позже) | | 8 | Telegram | Отдельный `telegram-service`: ферма сессий, 1 аккаунт/тенант, анти-бан; исполняет команды ядра, ничего не знает о бизнес-логике | | 9 | ML | Отдельный `ml-service`: .NET + ONNX, пул моделей per-tenant, обучение на действиях | | 10 | AI (LLM) | Отдельный `ai-service`: фасад провайдеров, промпты, учёт токенов | | 11 | Клиенты SaaS | Подключают свои Telegram-аккаунты и настраивают обработку под свою сферу | | 12 | Доступ тенантов | Инвайты: тенанта создаёт оператор, клиент по ссылке задаёт пароль | | 13 | Аутентификация | Логин = email + пароль (email уникален глобально); `tenantId` в сессии/JWT | | 14 | Название | «Дейл» (бренд), namespace `Deal` | | 15 | Код-стайл | Документ пользователя + 5 адаптаций; 1 тип = 1 файл; `.editorconfig` + анализаторы | | 16 | Наблюдаемость | Serilog + OpenTelemetry → Grafana + Loki + Promtail | | 17 | Админка | Операторская (A): тенанты, лимиты, health, impersonation, аудит | | 18 | Бэкапы | Ежедневные: Postgres + minio + сессии | | 19 | Лимиты | Бюджет токенов на тенанта (LLM); fallback на ML/локальную обработку | | 20 | Деплой | docker compose на своём VPS; Cloudflare перед origin; k8s позже | --- ## 3. Структура репозитория ``` src/ core/ # МОДУЛЬНЫЙ МОНОЛИТ — один процесс, один sln Deal.sln Deal.Api/ # host: Web API (/api-контракт), gRPC-сервер, SSE, DI Deal.Modules.Pipeline/ # очередь → стоп-лист → дедуп → ML/ИИ → карточка Deal.Modules.Kanban/ # карточки, колонки, правила, архив/корзина Deal.Modules.Projects/ # «Выбранные» (проектный канбан) Deal.Modules.Discovery/ # поиск каналов, вступление, чёрный список Deal.Modules.Settings/ # настройки тенанта, промпты, валюты Deal.Modules.Tenants/ # тенанты, инвайты, лимиты, админка Deal.SharedKernel/ # Result, доменные события, время, tenant-контекст Deal.Infrastructure/ # Postgres, миграции, outbox, IEventBus, файлы (MinIO) Deal.Contracts/ # DTO для /api + gRPC-контракты наружу tests/ # Deal.Tests.* (unit/integration модулей) ml-service/ # Deal.Ml.sln — .NET + ONNX, обучение/предсказание per-tenant ai-service/ # Deal.Ai.sln — LLM-фасад, промпты, учёт токенов telegram-service/ # Deal.Telegram.sln — ферма сессий, анти-бан contracts/ # общие .proto (gRPC): ml.proto, ai.proto, telegram.proto frontend/ # Vue — переезжает как есть docker-compose.yml # dev-подъём всех процессов ``` Правила: - `core` — единственное место с бизнес-логикой и БД. - Каждый сервис самодостаточен: свой sln, свой контейнер. - `.proto` — единственный общий «язык» между процессами, лежит в `contracts/`. --- ## 4. Мультитенантность ### Модель БД - Одна Postgres-БД, **схема на тенанта**: `tenant_.*`. - Системные таблицы (реестр тенантов, пользователи, инвайты, глобальные настройки, ключи приложения Telegram) — в схеме `public`. - DAL получает схему из tenant-контекста (claim в JWT / gRPC-метаданные); пул соединений переключает `search_path`. - Миграции применяются ко всем схемам тенантов (специальный механизм, см. §10). - «Золотым» клиентам позже — выделенный инстанс: стратегия выбора схемы/БД в одном месте. ### Изоляция (критично) - `tenantId` **только из сессии/JWT**, никогда из тела запроса. - Каждый SQL-запрос исполняется в контексте схемы тенанта; модуль проверяет принадлежность объекта тенанту (IDOR-защита). - Интеграционные тесты на перекрёстный доступ тенантов — обязательны. ### Обработка per-tenant - Настройки обработки (стоп-фразы, промпты, колонки/правила, ключи) — per-tenant. - **ML-модель — per-tenant** (модель дизайнера не учится на действиях кровельщика): `ml-service` держит пул моделей, core передаёт `tenantId` в каждом вызове. --- ## 5. Модули core и их границы Модули заводятся сразу как отдельные проекты; **внутренние интерфейсы между ними не выдумываются заранее** — появляются в момент реальной зависимости. | Модуль | Ответственность | Владеет таблицами (в схеме тенанта) | |---|---|---| | Pipeline | очередь входящих → стоп-лист → дедуп → ML/ИИ → карточка; отсев; обработка | очередь, отсев, dedup | | Kanban | карточки, колонки, правила, архив/корзина, комментарии, файлы | карточки, колонки | | Projects | «Выбранные»: свой канбан, стадии, история, напоминания | проекты | | Discovery | задачи поиска каналов, кандидаты, чёрный список, квоты | discovery-таблицы | | Settings | настройки тенанта, промпты, валюты | настройки | | Tenants | тенанты, пользователи, инвайты, лимиты, аудит, операторская админка | tenant-реестр (в `public`) | Общие справочники (например, «колонки» нужны и Pipeline при создании карточки, и Kanban при отрисовке) живут в модуле-владельце (Kanban); доступ — через его публичный интерфейс. --- ## 6. Контракты ### 6.1 `/api` — замороженный контракт миграции - Фронтенд Vue продолжает ходить в `/api/...` без изменений. - Снимаем точную карту с работающего LeadRadar (эндпоинты + формы ответов, которые реально потребляет фронт) → фиксируем как OpenAPI-спецификацию. - Новый `Deal.Api` обязан воспроизводить её 1:1. - Ведём реестр «кривых мест»: если правка фронта на 1 строку убирает слой костылей — выносим на решение владельца по одному (не молча). ### 6.2 gRPC-контракты (`contracts/`) - `telegram.proto`: команды ядра (подключить аккаунт, слушать канал, перечитать, вступить/выйти) + поток сырых сообщений → ядро. - `ml.proto`: predict (текст → решение), train (действие → обучение), health. - `ai.proto`: classify/filter/generate (текст → структура), учёт токенов. - Каждый вызов несёт `tenantId`; сервисы проверяют принадлежность по своей модели (сессии/модели), не доверяя полю на слово. ### 6.3 Шина событий - Порт `IEventBus` в SharedKernel. - Реализация сейчас: outbox в Postgres (транзакционно событие + эффект, фоновый диспетчер). - Kafka — позже, сменой реализации без правки бизнес-логики. --- ## 7. Сервисы ### 7.1 telegram-service - Отдельный процесс, свой sln. Ничего не знает о данных и бизнес-логике. - **Сессии привязаны к тенанту** (`tenantId → session`, 1:1): команды исполняются только на сессии своего тенанта; нет сессии для tenantId → отказ. - Проверка принадлежности диалога: read/subscribe только для диалогов аккаунта тенанта. - Join — только от имени тенанта, под его квотами и анти-баном. - Исходящий поток сообщений помечен `tenantId` (источник определён на входе, в сервисе). - Сервисная аутентификация (mTLS) + аудит команд `(tenantId, действие, диалог, результат)`. - Один аккаунт на тенанта на старте (связь тенант→аккаунты уже таблицей — расширение позже). ### 7.2 ml-service - .NET + ONNX (не ML.NET для онлайн-обучения): пул моделей по тенантам, обучение на реальных действиях пользователя и результатах ИИ. - Ничего не знает о домене: получает текст, отдаёт решение; обучение — по контракту. - Экспорт/импорт моделей — по контракту (для переноса между инстансами). ### 7.3 ai-service - Фасад LLM-провайдеров (DeepSeek и др., включая локальные OpenAI-совместимые), библиотека промптов, классификация, генерация. - **Учёт токенов**: каждый вызов оценивается в токенах и списывается с бюджета тенанта. - При исчерпании бюджета — fallback на ML/локальную обработку + уведомление (приём сообщений не блокируется). --- ## 8. Безопасность ### Слой приложения (core) - SQL-инъекции: запрет конкатенации SQL; только параметризация (EF Core/Dapper); анализаторы; Postgres-роль без DDL. - Tenant-изоляция (IDOR): tenantId из сессии; проверка принадлежности; тесты. - Аутентификация: Argon2id, лимит попыток, одноразовые инвайты с expiry. - Сессии: httpOnly cookie + CSRF (не localStorage). - XSS: экранирование на фронте (renderSourceMessage), CSP, запрет v-html без санитайзера. - SSRF: ai/telegram не тянут произвольные URL от имени тенанта (allowlist). - Валидация входа: DTO + FluentValidation, лимиты размеров. - Аудит: входы, инвайты, impersonation, действия оператора — неизменяемый поток. ### Транспорт/сервисы - TLS везде; mTLS между сервисами; service-token второй фактор. ### Инфраструктура - Cloudflare (DDoS/WAF) → reverse proxy (TLS, rate limit по IP, security-заголовки). - Rate limiting в приложении по тенанту (защита от «шумного соседа»). - Docker: сервисы в изолированной сети, наружу — только прокси; non-root, read-only FS. - Секреты: env/secret-хранилище; шифрование (enc); ничего в коде/репозитории. ### Процессы - CI: сканирование зависимостей (NuGet/npm), SAST, trivy-скан образов. - Обновления и алерты на CVE. - Postgres: бэкапы ежедневные, тест восстановления. --- ## 9. Наблюдаемость, админка, бэкапы ### Observability - Serilog (структурированные логи) + OpenTelemetry (метрики/трейсы) → Promtail → **Grafana + Loki**. - Дашборды: health сервисов, pipeline, ML-качество, расход токенов по тенантам. - За абстракцией экспорта — смена стека без правки кода. ### Операторская админка (только оператору) - Создание тенантов и инвайтов, лимиты, health, impersonation (с полным аудитом), подозрительная активность. Отдельный защищённый вход (оператор ≠ тенант). ### Бэкапы - Ежедневно: Postgres (pg_dump), файлы MinIO, сессии telegram. - Retention и внешняя выгрузка — уточнить на этапе деплоя. --- ## 10. Деплой - docker compose на одном VPS: core, ml-service, ai-service, telegram-service, postgres, minio, grafana/loki/promtail, reverse proxy. - Сервисы compose = будущие k8s-деплойменты (никаких завязок на compose в коде). - Миграции схем тенантов: механизм «миграция ко всем схемам» (список схем в `public`, применение по очереди, версия миграции на схему) — детализировать в плане реализации. --- ## 11. Стандарты кода - Код-стайл: `C:\telbase\Стиль_кода.docx` + согласованные адаптации (без snake_case-хелперов и регионов, public-поля → свойства, XML-doc для public-контрактов, настройки через `IOptions`, комментарии на русском). - 1 тип = 1 файл (класс/record/struct/enum/interface — отдельный файл). - `.editorconfig` + Roslyn-анализаторы с ошибками на нарушения. - Второй слой правил: скилы `agent-rules-books` (Clean Code, DDD, DDIA). - .NET-эталоны: скил `dotnet-clean-architecture-skills` (адаптировать под проект). --- ## 12. Открытые вопросы / следующие шаги 1. **Карта `/api`**: снять точную спецификацию с работающего LeadRadar (отдельная задача). 2. **Детали лимитов**: механика «бюджет токенов» (период, пороги, уведомления) — спроектировать. 3. **Бэкапы**: точная схема retention/внешнего хранилища. 4. **Миграции на 1000 схем**: детальный механизм. 5. Порядок реализации: этап 0 (каркас) → Pipeline+Kanban → ai/ml/telegram → Projects/Discovery. --- ## Приложение: глоссарий - **Тенант** — клиент SaaS (одна организация/пользователь), владеет схемой БД и настройками. - **Канал/источник** — Telegram-канал/группа, который слушает аккаунт тенанта. - **Карточка** — структурированная заявка (заказ/вакансия), созданная пайплайном. - **Outbox** — паттерн надёжной доставки событий через таблицу в той же транзакции.